summaryrefslogtreecommitdiff
path: root/agent/mibgroup/disman
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/disman')
-rw-r--r--agent/mibgroup/disman/event-mib.h2
-rw-r--r--agent/mibgroup/disman/event.h34
-rw-r--r--agent/mibgroup/disman/event/mteEvent.c492
-rw-r--r--agent/mibgroup/disman/event/mteEvent.h87
-rw-r--r--agent/mibgroup/disman/event/mteEventConf.c588
-rw-r--r--agent/mibgroup/disman/event/mteEventConf.h20
-rw-r--r--agent/mibgroup/disman/event/mteEventNotificationTable.c266
-rw-r--r--agent/mibgroup/disman/event/mteEventNotificationTable.h21
-rw-r--r--agent/mibgroup/disman/event/mteEventSetTable.c310
-rw-r--r--agent/mibgroup/disman/event/mteEventSetTable.h24
-rw-r--r--agent/mibgroup/disman/event/mteEventTable.c375
-rw-r--r--agent/mibgroup/disman/event/mteEventTable.h23
-rw-r--r--agent/mibgroup/disman/event/mteObjects.c433
-rw-r--r--agent/mibgroup/disman/event/mteObjects.h60
-rw-r--r--agent/mibgroup/disman/event/mteObjectsConf.c179
-rw-r--r--agent/mibgroup/disman/event/mteObjectsConf.h12
-rw-r--r--agent/mibgroup/disman/event/mteObjectsTable.c347
-rw-r--r--agent/mibgroup/disman/event/mteObjectsTable.h23
-rw-r--r--agent/mibgroup/disman/event/mteScalars.c135
-rw-r--r--agent/mibgroup/disman/event/mteScalars.h14
-rw-r--r--agent/mibgroup/disman/event/mteTrigger.c1200
-rw-r--r--agent/mibgroup/disman/event/mteTrigger.h199
-rw-r--r--agent/mibgroup/disman/event/mteTriggerBooleanTable.c315
-rw-r--r--agent/mibgroup/disman/event/mteTriggerBooleanTable.h25
-rw-r--r--agent/mibgroup/disman/event/mteTriggerConf.c1489
-rw-r--r--agent/mibgroup/disman/event/mteTriggerConf.h23
-rw-r--r--agent/mibgroup/disman/event/mteTriggerDeltaTable.c273
-rw-r--r--agent/mibgroup/disman/event/mteTriggerDeltaTable.h20
-rw-r--r--agent/mibgroup/disman/event/mteTriggerExistenceTable.c290
-rw-r--r--agent/mibgroup/disman/event/mteTriggerExistenceTable.h23
-rw-r--r--agent/mibgroup/disman/event/mteTriggerTable.c508
-rw-r--r--agent/mibgroup/disman/event/mteTriggerTable.h35
-rw-r--r--agent/mibgroup/disman/event/mteTriggerThresholdTable.c389
-rw-r--r--agent/mibgroup/disman/event/mteTriggerThresholdTable.h34
-rw-r--r--agent/mibgroup/disman/expr/expErrorTable.c120
-rw-r--r--agent/mibgroup/disman/expr/expErrorTable.h21
-rw-r--r--agent/mibgroup/disman/expr/expExpression.c365
-rw-r--r--agent/mibgroup/disman/expr/expExpression.h91
-rw-r--r--agent/mibgroup/disman/expr/expExpressionConf.c292
-rw-r--r--agent/mibgroup/disman/expr/expExpressionConf.h10
-rw-r--r--agent/mibgroup/disman/expr/expExpressionTable.c364
-rw-r--r--agent/mibgroup/disman/expr/expExpressionTable.h26
-rw-r--r--agent/mibgroup/disman/expr/expObject.c345
-rw-r--r--agent/mibgroup/disman/expr/expObject.h77
-rw-r--r--agent/mibgroup/disman/expr/expObjectConf.c185
-rw-r--r--agent/mibgroup/disman/expr/expObjectConf.h9
-rw-r--r--agent/mibgroup/disman/expr/expObjectTable.c461
-rw-r--r--agent/mibgroup/disman/expr/expObjectTable.h27
-rw-r--r--agent/mibgroup/disman/expr/expScalars.c97
-rw-r--r--agent/mibgroup/disman/expr/expScalars.h13
-rw-r--r--agent/mibgroup/disman/expr/expValue.c808
-rw-r--r--agent/mibgroup/disman/expr/expValue.h12
-rw-r--r--agent/mibgroup/disman/expr/expValueTable.c329
-rw-r--r--agent/mibgroup/disman/expr/expValueTable.h23
-rw-r--r--agent/mibgroup/disman/expr/exp_enum.h60
-rw-r--r--agent/mibgroup/disman/expression-mib.h21
-rw-r--r--agent/mibgroup/disman/expression.h13
-rw-r--r--agent/mibgroup/disman/expression/expErrorTable.c144
-rw-r--r--agent/mibgroup/disman/expression/expErrorTable.h49
-rw-r--r--agent/mibgroup/disman/expression/expExpressionTable.c1177
-rw-r--r--agent/mibgroup/disman/expression/expExpressionTable.h139
-rw-r--r--agent/mibgroup/disman/expression/expObjectTable.c1465
-rw-r--r--agent/mibgroup/disman/expression/expObjectTable.h92
-rw-r--r--agent/mibgroup/disman/expression/expValueTable.c873
-rw-r--r--agent/mibgroup/disman/expression/expValueTable.h63
-rw-r--r--agent/mibgroup/disman/mteEventNotificationTable.c110
-rw-r--r--agent/mibgroup/disman/mteEventNotificationTable.h23
-rw-r--r--agent/mibgroup/disman/mteEventTable.c345
-rw-r--r--agent/mibgroup/disman/mteEventTable.h30
-rw-r--r--agent/mibgroup/disman/mteObjectsTable.c995
-rw-r--r--agent/mibgroup/disman/mteObjectsTable.h71
-rw-r--r--agent/mibgroup/disman/mteTriggerBooleanTable.c852
-rw-r--r--agent/mibgroup/disman/mteTriggerBooleanTable.h47
-rw-r--r--agent/mibgroup/disman/mteTriggerDeltaTable.c443
-rw-r--r--agent/mibgroup/disman/mteTriggerDeltaTable.h39
-rw-r--r--agent/mibgroup/disman/mteTriggerExistenceTable.c782
-rw-r--r--agent/mibgroup/disman/mteTriggerExistenceTable.h41
-rw-r--r--agent/mibgroup/disman/mteTriggerTable.c3814
-rw-r--r--agent/mibgroup/disman/mteTriggerTable.h253
-rw-r--r--agent/mibgroup/disman/mteTriggerThresholdTable.c1700
-rw-r--r--agent/mibgroup/disman/mteTriggerThresholdTable.h48
-rw-r--r--agent/mibgroup/disman/nslookup-mib.h20
-rw-r--r--agent/mibgroup/disman/nslookup/lookupCtlTable.c1415
-rw-r--r--agent/mibgroup/disman/nslookup/lookupCtlTable.h87
-rw-r--r--agent/mibgroup/disman/nslookup/lookupResultsTable.c306
-rw-r--r--agent/mibgroup/disman/nslookup/lookupResultsTable.h39
-rw-r--r--agent/mibgroup/disman/old-event-mib.h33
-rw-r--r--agent/mibgroup/disman/ping-mib.h20
-rw-r--r--agent/mibgroup/disman/ping/pingCtlTable.c5829
-rw-r--r--agent/mibgroup/disman/ping/pingCtlTable.h437
-rw-r--r--agent/mibgroup/disman/ping/pingProbeHistoryTable.c342
-rw-r--r--agent/mibgroup/disman/ping/pingProbeHistoryTable.h36
-rw-r--r--agent/mibgroup/disman/ping/pingResultsTable.c425
-rw-r--r--agent/mibgroup/disman/ping/pingResultsTable.h42
-rw-r--r--agent/mibgroup/disman/schedule.h3
-rw-r--r--agent/mibgroup/disman/schedule/schedConf.c437
-rw-r--r--agent/mibgroup/disman/schedule/schedConf.h17
-rw-r--r--agent/mibgroup/disman/schedule/schedCore.c515
-rw-r--r--agent/mibgroup/disman/schedule/schedCore.h85
-rw-r--r--agent/mibgroup/disman/schedule/schedTable.c540
-rw-r--r--agent/mibgroup/disman/schedule/schedTable.h39
-rw-r--r--agent/mibgroup/disman/traceroute-mib.h21
-rw-r--r--agent/mibgroup/disman/traceroute/traceRouteCtlTable.c6198
-rw-r--r--agent/mibgroup/disman/traceroute/traceRouteCtlTable.h613
-rw-r--r--agent/mibgroup/disman/traceroute/traceRouteHopsTable.c420
-rw-r--r--agent/mibgroup/disman/traceroute/traceRouteHopsTable.h41
-rw-r--r--agent/mibgroup/disman/traceroute/traceRouteProbeHistoryTable.c417
-rw-r--r--agent/mibgroup/disman/traceroute/traceRouteProbeHistoryTable.h39
-rw-r--r--agent/mibgroup/disman/traceroute/traceRouteResultsTable.c421
-rw-r--r--agent/mibgroup/disman/traceroute/traceRouteResultsTable.h40
110 files changed, 44509 insertions, 0 deletions
diff --git a/agent/mibgroup/disman/event-mib.h b/agent/mibgroup/disman/event-mib.h
new file mode 100644
index 0000000..58c8391
--- /dev/null
+++ b/agent/mibgroup/disman/event-mib.h
@@ -0,0 +1,2 @@
+config_require(disman/event)
+
diff --git a/agent/mibgroup/disman/event.h b/agent/mibgroup/disman/event.h
new file mode 100644
index 0000000..e646975
--- /dev/null
+++ b/agent/mibgroup/disman/event.h
@@ -0,0 +1,34 @@
+config_add_mib(DISMAN-EVENT-MIB)
+
+/*
+ * wrapper for the new disman event mib implementation code files
+ */
+config_require(disman/event/mteScalars)
+config_require(disman/event/mteTrigger)
+config_require(disman/event/mteTriggerTable)
+config_require(disman/event/mteTriggerDeltaTable)
+config_require(disman/event/mteTriggerExistenceTable)
+config_require(disman/event/mteTriggerBooleanTable)
+config_require(disman/event/mteTriggerThresholdTable)
+config_require(disman/event/mteTriggerConf)
+config_require(disman/event/mteEvent)
+config_require(disman/event/mteEventTable)
+config_require(disman/event/mteEventSetTable)
+config_require(disman/event/mteEventNotificationTable)
+config_require(disman/event/mteEventConf)
+config_require(disman/event/mteObjects)
+config_require(disman/event/mteObjectsTable)
+config_require(disman/event/mteObjectsConf)
+
+/*
+ * conflicts with the previous implementation
+ */
+config_exclude(disman/mteTriggerTable)
+config_exclude(disman/mteTriggerDeltaTable)
+config_exclude(disman/mteTriggerExistenceTable)
+config_exclude(disman/mteTriggerBooleanTable)
+config_exclude(disman/mteTriggerThresholdTable)
+config_exclude(disman/mteObjectsTable)
+config_exclude(disman/mteEventTable)
+config_exclude(disman/mteEventNotificationTable)
+
diff --git a/agent/mibgroup/disman/event/mteEvent.c b/agent/mibgroup/disman/event/mteEvent.c
new file mode 100644
index 0000000..bc4ff0b
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteEvent.c
@@ -0,0 +1,492 @@
+/*
+ * DisMan Event MIB:
+ * Core implementation of the event handling behaviour
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "disman/event/mteEvent.h"
+#include "disman/event/mteTrigger.h"
+#include "disman/event/mteObjects.h"
+
+netsnmp_feature_child_of(disman_debugging, libnetsnmpmibs)
+netsnmp_feature_child_of(mteevent, libnetsnmpmibs)
+netsnmp_feature_child_of(mteevent_removeentry, mteevent)
+
+netsnmp_tdata *event_table_data;
+
+ /*
+ * Initialize the container for the (combined) mteEvent*Table,
+ * regardless of which table initialisation routine is called first.
+ */
+
+void
+init_event_table_data(void)
+{
+ DEBUGMSGTL(("disman:event:init", "init event container\n"));
+ if (!event_table_data) {
+ event_table_data = netsnmp_tdata_create_table("mteEventTable", 0);
+ DEBUGMSGTL(("disman:event:init", "create event container (%p)\n",
+ event_table_data));
+ }
+}
+
+void _init_default_mteEvent( const char *event, const char *oname, int specific );
+void _init_link_mteEvent( const char *event, const char *oname, int specific );
+void _init_builtin_mteEvent( const char *event, const char *oname,
+ oid *trapOID, size_t trapOID_len );
+
+
+/** Initializes the mteEvent module */
+void
+init_mteEvent(void)
+{
+ static int _defaults_init = 0;
+ init_event_table_data();
+
+ /*
+ * Insert fixed events for the default trigger notifications
+ *
+ * NB: internal events (with an owner of "_snmpd") will not in
+ * fact refer to the mteObjectsTable for the payload varbinds.
+ * The routine mteObjects_internal_vblist() hardcodes the
+ * appropriate varbinds for these internal events.
+ * This routine will need to be updated whenever a new
+ * internal event is added.
+ */
+ if ( _defaults_init)
+ return;
+
+ _init_default_mteEvent( "mteTriggerFired", "_triggerFire", 1 );
+ _init_default_mteEvent( "mteTriggerRising", "_triggerFire", 2 );
+ _init_default_mteEvent( "mteTriggerFalling", "_triggerFire", 3 );
+ _init_default_mteEvent( "mteTriggerFailure", "_triggerFail", 4 );
+
+ _init_link_mteEvent( "linkDown", "_linkUpDown", 3 );
+ _init_link_mteEvent( "linkUp", "_linkUpDown", 4 );
+ _defaults_init = 1;
+}
+
+void
+_init_builtin_mteEvent( const char *event, const char *oname, oid *trapOID, size_t trapOID_len )
+{
+ char ename[ MTE_STR1_LEN+1 ];
+ netsnmp_tdata_row *row;
+ struct mteEvent *entry;
+
+ memset(ename, 0, sizeof(ename));
+ ename[0] = '_';
+ memcpy(ename+1, event, strlen(event));
+
+ row = mteEvent_createEntry( "_snmpd", ename, 1 );
+ if (!row || !row->data)
+ return;
+ entry = (struct mteEvent *)row->data;
+
+ entry->mteEventActions = MTE_EVENT_NOTIFICATION;
+ entry->mteNotification_len = trapOID_len;
+ memcpy( entry->mteNotification, trapOID, trapOID_len*sizeof(oid));
+ memcpy( entry->mteNotifyOwner, "_snmpd", 6 );
+ memcpy( entry->mteNotifyObjects, oname, strlen(oname));
+ entry->flags |= MTE_EVENT_FLAG_ENABLED|
+ MTE_EVENT_FLAG_ACTIVE|
+ MTE_EVENT_FLAG_VALID;
+}
+
+void
+_init_default_mteEvent( const char *event, const char *oname, int specific )
+{
+ oid mteTrapOID[] = {1, 3, 6, 1, 2, 1, 88, 2, 0, 99 /* placeholder */};
+ size_t mteTrapOID_len = OID_LENGTH(mteTrapOID);
+
+ mteTrapOID[ mteTrapOID_len-1 ] = specific;
+ _init_builtin_mteEvent( event, oname, mteTrapOID, mteTrapOID_len );
+}
+
+
+void
+_init_link_mteEvent( const char *event, const char *oname, int specific )
+{
+ oid mteTrapOID[] = {1, 3, 6, 1, 6, 3, 1, 1, 5, 99 /* placeholder */};
+ size_t mteTrapOID_len = OID_LENGTH(mteTrapOID);
+
+ mteTrapOID[ mteTrapOID_len-1 ] = specific;
+ _init_builtin_mteEvent( event, oname, mteTrapOID, mteTrapOID_len );
+}
+
+
+ /* ===================================================
+ *
+ * APIs for maintaining the contents of the (combined)
+ * mteEvent*Table container.
+ *
+ * =================================================== */
+
+#ifndef NETSNMP_FEATURE_REMOVE_DISMAN_DEBUGGING
+void
+_mteEvent_dump(void)
+{
+ struct mteEvent *entry;
+ netsnmp_tdata_row *row;
+ int i = 0;
+
+ for (row = netsnmp_tdata_row_first(event_table_data);
+ row;
+ row = netsnmp_tdata_row_next(event_table_data, row)) {
+ entry = (struct mteEvent *)row->data;
+ DEBUGMSGTL(("disman:event:dump", "EventTable entry %d: ", i));
+ DEBUGMSGOID(("disman:event:dump", row->oid_index.oids, row->oid_index.len));
+ DEBUGMSG(("disman:event:dump", "(%s, %s)",
+ row->indexes->val.string,
+ row->indexes->next_variable->val.string));
+ DEBUGMSG(("disman:event:dump", ": %p, %p\n", row, entry));
+ i++;
+ }
+ DEBUGMSGTL(("disman:event:dump", "EventTable %d entries\n", i));
+}
+#endif /* NETSNMP_FEATURE_REMOVE_DISMAN_DEBUGGING */
+
+/*
+ * Create a new row in the event table
+ */
+netsnmp_tdata_row *
+mteEvent_createEntry(const char *mteOwner, const char *mteEName, int fixed)
+{
+ struct mteEvent *entry;
+ netsnmp_tdata_row *row;
+ size_t mteOwner_len = (mteOwner) ? strlen(mteOwner) : 0;
+ size_t mteEName_len = (mteEName) ? strlen(mteEName) : 0;
+
+ DEBUGMSGTL(("disman:event:table", "Create event entry (%s, %s)\n",
+ mteOwner, mteEName));
+ /*
+ * Create the mteEvent entry, and the
+ * (table-independent) row wrapper structure...
+ */
+ entry = SNMP_MALLOC_TYPEDEF(struct mteEvent);
+ 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 (mteOwner)
+ memcpy(entry->mteOwner, mteOwner, mteOwner_len);
+ netsnmp_table_row_add_index(row, ASN_OCTET_STR,
+ entry->mteOwner, mteOwner_len);
+ if (mteEName)
+ memcpy(entry->mteEName, mteEName, mteEName_len);
+ netsnmp_table_row_add_index(row, ASN_PRIV_IMPLIED_OCTET_STR,
+ entry->mteEName, mteEName_len);
+
+ entry->mteNotification_len = 2; /* .0.0 */
+ if (fixed)
+ entry->flags |= MTE_EVENT_FLAG_FIXED;
+
+ /*
+ * ... and insert the row into the (common) table container
+ */
+ netsnmp_tdata_add_row(event_table_data, row);
+ DEBUGMSGTL(("disman:event:table", "Event entry created\n"));
+ return row;
+}
+
+
+#ifndef NETSNMP_FEATURE_REMOVE_MTEEVENT_REMOVEENTRY
+/*
+ * Remove a row from the event table
+ */
+void
+mteEvent_removeEntry(netsnmp_tdata_row *row)
+{
+ struct mteEvent *entry;
+
+ if (!row)
+ return; /* Nothing to remove */
+ entry = (struct mteEvent *)
+ netsnmp_tdata_remove_and_delete_row(event_table_data, row);
+ SNMP_FREE(entry);
+}
+#endif /* NETSNMP_FEATURE_REMOVE_MTEEVENT_REMOVEENTRY */
+
+ /* ===================================================
+ *
+ * APIs for processing the firing of an event
+ *
+ * =================================================== */
+
+int
+_mteEvent_fire_notify( struct mteEvent *event,
+ struct mteTrigger *trigger,
+ oid *suffix, size_t sfx_len );
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+int
+_mteEvent_fire_set( struct mteEvent *event,
+ struct mteTrigger *trigger,
+ oid *suffix, size_t sfx_len );
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+int
+mteEvent_fire( char *owner, char *event, /* Event to invoke */
+ struct mteTrigger *trigger, /* Trigger that fired */
+ oid *suffix, size_t s_len ) /* Matching instance */
+{
+ struct mteEvent *entry;
+ int fired = 0;
+ netsnmp_variable_list owner_var, event_var;
+
+ DEBUGMSGTL(("disman:event:fire", "Event fired (%s, %s)\n",
+ owner, event));
+
+ /*
+ * Retrieve the entry for the specified event
+ */
+ memset( &owner_var, 0, sizeof(owner_var));
+ memset( &event_var, 0, sizeof(event_var));
+ snmp_set_var_typed_value(&owner_var, ASN_OCTET_STR, owner, strlen(owner));
+ snmp_set_var_typed_value(&event_var, ASN_PRIV_IMPLIED_OCTET_STR,
+ event, strlen(event));
+ owner_var.next_variable = &event_var;
+ entry = (struct mteEvent *)
+ netsnmp_tdata_row_entry(
+ netsnmp_tdata_row_get_byidx( event_table_data, &owner_var ));
+ if (!entry) {
+ DEBUGMSGTL(("disman:event:fire", "No matching event\n"));
+ return -1;
+ }
+
+ if (entry->mteEventActions & MTE_EVENT_NOTIFICATION) {
+ DEBUGMSGTL(("disman:event:fire", "Firing notification event\n"));
+ _mteEvent_fire_notify( entry, trigger, suffix, s_len );
+ fired = 1;
+ }
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ if (entry->mteEventActions & MTE_EVENT_SET) {
+ DEBUGMSGTL(("disman:event:fire", "Firing set event\n"));
+ _mteEvent_fire_set( entry, trigger, suffix, s_len );
+ fired = 1;
+ }
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+ if (!fired)
+ DEBUGMSGTL(("disman:event:fire", "Matched event is empty\n"));
+
+ return fired;
+}
+
+
+#ifdef __NOT_NEEDED
+void
+_insert_internal_objects( netsnmp_variable_list *vblist, char *oname,
+ struct mteTrigger *trigger)
+{
+ 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};
+
+ /*
+ * Construct the varbinds for this (internal) event...
+ */
+ if ((!strcmp(oname, "_mteTriggerFired" )) ||
+ (!strcmp(oname, "_mteTriggerRising" )) ||
+ (!strcmp(oname, "_mteTriggerFalling")) ||
+ (!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 {
+ DEBUGMSGTL(("disman:event:fire",
+ "Unknown internal objects tag (%s)\n", oname));
+ return;
+ }
+
+ /*
+ * ... 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;
+}
+#endif /* __NOT_NEEDED */
+
+int
+_mteEvent_fire_notify( struct mteEvent *entry, /* The event to fire */
+ struct mteTrigger *trigger, /* Trigger that fired */
+ oid *suffix, size_t sfx_len ) /* Matching instance */
+{
+ netsnmp_variable_list *var, *v2;
+ extern const oid snmptrap_oid[];
+ extern const size_t snmptrap_oid_len;
+ netsnmp_session *s;
+
+ /*
+ * The Event-MIB specification says that objects from the
+ * mteEventTable should come after those from the trigger,
+ * but things actually work better if these come first.
+ * Allow the agent to be configured either way.
+ */
+ int strictOrdering = netsnmp_ds_get_boolean(
+ NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_STRICT_DISMAN);
+
+ var = (netsnmp_variable_list *)SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ if (!var)
+ return -1;
+
+ /*
+ * Set the basic notification OID...
+ */
+ memset(var, 0, sizeof(netsnmp_variable_list));
+ snmp_set_var_objid( var, snmptrap_oid, snmptrap_oid_len );
+ snmp_set_var_typed_value( var, ASN_OBJECT_ID,
+ (u_char *)entry->mteNotification,
+ entry->mteNotification_len*sizeof(oid));
+
+ /*
+ * ... then add the specified objects from the Objects Table.
+ *
+ * Strictly speaking, the objects from the EventTable are meant
+ * to be listed last (after the various trigger objects).
+ * But logically things actually work better if the event objects
+ * are placed first. So this code handles things either way :-)
+ */
+
+ if (!strictOrdering) {
+ DEBUGMSGTL(("disman:event:fire", "Adding event objects (first)\n"));
+ if (strcmp(entry->mteNotifyOwner, "_snmpd") != 0)
+ mteObjects_vblist( var, entry->mteNotifyOwner,
+ entry->mteNotifyObjects,
+ suffix, sfx_len );
+ }
+
+ DEBUGMSGTL(("disman:event:fire", "Adding trigger objects (general)\n"));
+ mteObjects_vblist( var, trigger->mteTriggerOOwner,
+ trigger->mteTriggerObjects,
+ suffix, sfx_len );
+ DEBUGMSGTL(("disman:event:fire", "Adding trigger objects (specific)\n"));
+ mteObjects_vblist( var, trigger->mteTriggerXOwner,
+ trigger->mteTriggerXObjects,
+ suffix, sfx_len );
+
+ if (strictOrdering) {
+ DEBUGMSGTL(("disman:event:fire", "Adding event objects (last)\n"));
+ if (strcmp(entry->mteNotifyOwner, "_snmpd") != 0)
+ mteObjects_vblist( var, entry->mteNotifyOwner,
+ entry->mteNotifyObjects,
+ suffix, sfx_len );
+ }
+
+ /*
+ * Query the agent to retrieve the necessary values...
+ * (skipping the initial snmpTrapOID varbind)
+ */
+ v2 = var->next_variable;
+ if (entry->session)
+ s = entry->session;
+ else
+ s = trigger->session;
+ netsnmp_query_get( v2, s );
+
+ /*
+ * ... add any "internal" objects...
+ * (skipped by the processing above, and best handled directly)
+ */
+ if (strcmp(entry->mteNotifyOwner, "_snmpd") == 0) {
+ DEBUGMSGTL(("disman:event:fire", "Adding event objects (internal)\n"));
+ if ( !strictOrdering ) {
+ mteObjects_internal_vblist(var, entry->mteNotifyObjects, trigger, s);
+ } else {
+ for (v2 = var; v2 && v2->next_variable; v2=v2->next_variable)
+ ;
+ mteObjects_internal_vblist(v2, entry->mteNotifyObjects, trigger, s);
+ }
+ }
+
+ /*
+ * ... and send the resulting varbind list as a notification
+ */
+ send_v2trap( var );
+ snmp_free_varbind( var );
+ return 0;
+}
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+int
+_mteEvent_fire_set( struct mteEvent *entry, /* The event to fire */
+ struct mteTrigger *trigger, /* Trigger that fired */
+ oid *suffix, size_t sfx_len ) /* Matching instance */
+{
+ netsnmp_variable_list var;
+ oid set_oid[ MAX_OID_LEN ];
+ size_t set_len;
+
+ /*
+ * Set the basic assignment OID...
+ */
+ memset(set_oid, 0, sizeof(set_oid));
+ memcpy(set_oid, entry->mteSetOID, entry->mteSetOID_len*sizeof(oid));
+ set_len = entry->mteSetOID_len;
+
+ /*
+ * ... if the trigger value is wildcarded (sfx_len > 0),
+ * *and* the SET event entry is wildcarded,
+ * then add the supplied instance suffix...
+ */
+ if (sfx_len &&
+ entry->flags & MTE_SET_FLAG_OBJWILD) {
+ memcpy( &set_oid[set_len], suffix, sfx_len*sizeof(oid));
+ set_len += sfx_len;
+ }
+
+ /*
+ * ... finally build the assignment varbind,
+ * and pass it to be acted on.
+ *
+ * XXX: Need to handle (remote) targets and non-default contexts
+ */
+ memset( &var, 0, sizeof(var));
+ snmp_set_var_objid( &var, set_oid, set_len );
+ snmp_set_var_typed_integer( &var, ASN_INTEGER, entry->mteSetValue );
+ if (entry->session)
+ return netsnmp_query_set( &var, entry->session );
+ else
+ return netsnmp_query_set( &var, trigger->session );
+
+ /* XXX - Need to check result */
+}
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
diff --git a/agent/mibgroup/disman/event/mteEvent.h b/agent/mibgroup/disman/event/mteEvent.h
new file mode 100644
index 0000000..3be5c6e
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteEvent.h
@@ -0,0 +1,87 @@
+#ifndef MTEEVENT_H
+#define MTEEVENT_H
+
+#include "disman/event/mteTrigger.h"
+
+ /*
+ * Values for mteEventActions field
+ */
+#define MTE_EVENT_NOTIFICATION 0x80 /* mteEventActions values */
+#define MTE_EVENT_SET 0x40
+
+ /*
+ * Flags relating to the mteEventTable....
+ */
+#define MTE_EVENT_FLAG_ENABLED 0x01 /* for mteEventEnabled */
+#define MTE_EVENT_FLAG_ACTIVE 0x02 /* for mteEventEntryStatus */
+#define MTE_EVENT_FLAG_FIXED 0x04 /* for snmpd.conf persistence */
+#define MTE_EVENT_FLAG_VALID 0x08 /* for row creation/undo */
+
+ /*
+ * ...and to the mteEventSetTable
+ */
+#define MTE_SET_FLAG_OBJWILD 0x10 /* for mteEventSetObjectWildcard */
+#define MTE_SET_FLAG_CTXWILD 0x20 /* for mteEventSetContextNameWildcard */
+
+
+ /*
+ * All Event-MIB OCTET STRING objects are either short (32-character)
+ * tags, or SnmpAdminString/similar values (i.e. 255 characters)
+ */
+#define MTE_STR1_LEN 32
+#define MTE_STR2_LEN 255
+
+/*
+ * Data structure for a (combined) event row
+ * Covers both Notification and Set events
+ */
+struct mteEvent {
+ /*
+ * Index values
+ */
+ char mteOwner[MTE_STR1_LEN+1];
+ char mteEName[MTE_STR1_LEN+1];
+
+ /*
+ * Column values for the main mteEventTable
+ */
+ char mteEventComment[MTE_STR2_LEN+1];
+ u_char mteEventActions;
+
+ /*
+ * Column values for Notification events (mteEventNotificationTable)
+ */
+ oid mteNotification[MAX_OID_LEN];
+ size_t mteNotification_len;
+ char mteNotifyOwner[ MTE_STR1_LEN+1];
+ char mteNotifyObjects[MTE_STR1_LEN+1];
+
+ /*
+ * Column values for Set events (mteEventSetTable)
+ */
+ oid mteSetOID[MAX_OID_LEN];
+ size_t mteSetOID_len;
+ long mteSetValue;
+ char mteSetTarget[ MTE_STR2_LEN+1];
+ char mteSetContext[MTE_STR2_LEN+1];
+
+ netsnmp_session *session;
+ long flags;
+};
+
+ /*
+ * Container structure for the (combined) mteEvent*Tables,
+ * and routine to create this.
+ */
+extern netsnmp_tdata *event_table_data;
+extern void init_event_table_data(void);
+
+void init_mteEvent(void);
+void mteEvent_removeEntry(netsnmp_tdata_row *row);
+netsnmp_tdata_row *mteEvent_createEntry(const char *mteOwner,
+ const char *mteEventName, int fixed);
+int mteEvent_fire( char *owner, char *event,
+ struct mteTrigger *trigger,
+ oid *suffix, size_t s_len );
+
+#endif /* MTEEVENT_H */
diff --git a/agent/mibgroup/disman/event/mteEventConf.c b/agent/mibgroup/disman/event/mteEventConf.c
new file mode 100644
index 0000000..24192a6
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteEventConf.c
@@ -0,0 +1,588 @@
+/*
+ * DisMan Event MIB:
+ * Implementation of the event table configure handling
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/agent_callbacks.h>
+#include "disman/event/mteObjects.h"
+#include "disman/event/mteEvent.h"
+#include "disman/event/mteEventConf.h"
+
+netsnmp_feature_require(iquery)
+
+/** Initializes the mteEventsConf module */
+void
+init_mteEventConf(void)
+{
+ init_event_table_data();
+
+ /*
+ * Register config handlers for user-level (fixed) events....
+ */
+ snmpd_register_config_handler("notificationEvent",
+ parse_notificationEvent, NULL,
+ "eventname notifyOID [-m] [-i OID|-o OID]*");
+ snmpd_register_config_handler("setEvent",
+ parse_setEvent, NULL,
+ "eventname [-I] OID = value");
+
+ netsnmp_ds_register_config(ASN_BOOLEAN,
+ netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
+ NETSNMP_DS_LIB_APPTYPE),
+ "strictDisman", NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_STRICT_DISMAN);
+
+ /*
+ * ... and for persistent storage of dynamic event table entries.
+ *
+ * (The previous implementation didn't store these entries,
+ * so we don't need to worry about backwards compatability)
+ */
+ snmpd_register_config_handler("_mteETable",
+ parse_mteETable, NULL, NULL);
+ snmpd_register_config_handler("_mteENotTable",
+ parse_mteENotTable, NULL, NULL);
+ snmpd_register_config_handler("_mteESetTable",
+ parse_mteESetTable, NULL, NULL);
+
+ /*
+ * Register to save (non-fixed) entries when the agent shuts down
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_mteETable, NULL);
+ snmp_register_callback(SNMP_CALLBACK_APPLICATION,
+ SNMPD_CALLBACK_PRE_UPDATE_CONFIG,
+ clear_mteETable, NULL);
+}
+
+
+/* ==============================
+ *
+ * utility routines
+ *
+ * ============================== */
+
+ /*
+ * Find or create the specified event entry
+ */
+static struct mteEvent *
+_find_mteEvent_entry( const char *owner, const char *ename )
+{
+ netsnmp_variable_list owner_var, ename_var;
+ netsnmp_tdata_row *row;
+ /*
+ * If there's already an existing entry,
+ * then use that...
+ */
+ memset(&owner_var, 0, sizeof(netsnmp_variable_list));
+ memset(&ename_var, 0, sizeof(netsnmp_variable_list));
+ snmp_set_var_typed_value(&owner_var, ASN_OCTET_STR, owner, strlen(owner));
+ snmp_set_var_typed_value(&ename_var, ASN_PRIV_IMPLIED_OCTET_STR,
+ ename, strlen(ename));
+ owner_var.next_variable = &ename_var;
+ row = netsnmp_tdata_row_get_byidx( event_table_data, &owner_var );
+ /*
+ * ... otherwise, create a new one
+ */
+ if (!row)
+ row = mteEvent_createEntry( owner, ename, 0 );
+ if (!row)
+ return NULL;
+
+ /* return (struct mteEvent *)netsnmp_tdata_row_entry( row ); */
+ return (struct mteEvent *)row->data;
+}
+
+static struct mteEvent *
+_find_typed_mteEvent_entry( const char *owner, const char *ename, int type )
+{
+ struct mteEvent *entry = _find_mteEvent_entry( owner, ename );
+ if (!entry)
+ return NULL;
+
+ /*
+ * If this is an existing (i.e. valid) entry of the
+ * same type, then throw an error and discard it.
+ * But allow combined Set/Notification events.
+ */
+ if ( entry &&
+ (entry->flags & MTE_EVENT_FLAG_VALID) &&
+ (entry->mteEventActions & type )) {
+ config_perror("error: duplicate event name");
+ return NULL;
+ }
+ return entry;
+}
+
+
+/* ==============================
+ *
+ * User-configured (static) events
+ *
+ * ============================== */
+
+void
+parse_notificationEvent( const char *token, char *line )
+{
+ char ename[MTE_STR1_LEN+1];
+ char buf[SPRINT_MAX_LEN];
+ oid name_buf[MAX_OID_LEN];
+ size_t name_buf_len;
+ struct mteEvent *entry;
+ struct mteObject *object;
+ int wild = 1;
+ int idx = 0;
+ char *cp;
+#ifndef NETSNMP_DISABLE_MIB_LOADING
+ struct tree *tp;
+#endif
+ struct varbind_list *var;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing notificationEvent config\n"));
+
+ /*
+ * The event name could be used directly to index the mteObjectsTable.
+ * But it's quite possible that the same name could also be used to
+ * set up a mteTriggerTable entry (with trigger-specific objects).
+ *
+ * To avoid such a clash, we'll add a prefix ("_E").
+ */
+ memset(ename, 0, sizeof(ename));
+ ename[0] = '_';
+ ename[1] = 'E';
+ cp = copy_nword(line, ename+2, MTE_STR1_LEN-2);
+ if (!cp || ename[2] == '\0') {
+ config_perror("syntax error: no event name");
+ return;
+ }
+
+ /*
+ * Parse the notification OID field ...
+ */
+ cp = copy_nword(cp, buf, SPRINT_MAX_LEN);
+ if ( buf[0] == '\0' ) {
+ config_perror("syntax error: no notification OID");
+ return;
+ }
+ name_buf_len = MAX_OID_LEN;
+ if (!snmp_parse_oid(buf, name_buf, &name_buf_len)) {
+ snmp_log(LOG_ERR, "notificationEvent OID: %s\n", buf);
+ config_perror("unknown notification OID");
+ return;
+ }
+
+ /*
+ * ... and the relevant object/instances.
+ */
+ if ( cp && *cp=='-' && *(cp+1)=='m' ) {
+#ifdef NETSNMP_DISABLE_MIB_LOADING
+ config_perror("Can't use -m if MIB loading is disabled");
+ return;
+#else
+ /*
+ * Use the MIB definition to add the standard
+ * notification payload to the mteObjectsTable.
+ */
+ cp = skip_token( cp );
+ tp = get_tree( name_buf, name_buf_len, get_tree_head());
+ if (!tp) {
+ config_perror("Can't locate notification payload info");
+ return;
+ }
+ for (var = tp->varbinds; var; var=var->next) {
+ idx++;
+ object = mteObjects_addOID( "snmpd.conf", ename, idx,
+ var->vblabel, wild );
+ idx = object->mteOIndex;
+ }
+#endif
+ }
+ while (cp) {
+ if ( *cp == '-' ) {
+ switch (*(cp+1)) {
+ case 'm':
+ config_perror("-m option must come first");
+ return;
+ case 'i': /* exact instance */
+ case 'w': /* "not-wild" (backward compatability) */
+ wild = 0;
+ break;
+ case 'o': /* wildcarded object */
+ wild = 1;
+ break;
+ default:
+ config_perror("unrecognised option");
+ return;
+ }
+ cp = skip_token( cp );
+ if (!cp) {
+ config_perror("missing parameter");
+ return;
+ }
+ }
+ idx++;
+ cp = copy_nword(cp, buf, SPRINT_MAX_LEN);
+ object = mteObjects_addOID( "snmpd.conf", ename, idx, buf, wild );
+ idx = object->mteOIndex;
+ wild = 1; /* default to wildcarded objects */
+ }
+
+ /*
+ * If the entry has parsed successfully, then create,
+ * populate and activate the new event entry.
+ */
+ entry = _find_typed_mteEvent_entry("snmpd.conf", ename+2,
+ MTE_EVENT_NOTIFICATION);
+ if (!entry) {
+ mteObjects_removeEntries( "snmpd.conf", ename );
+ return;
+ }
+ entry->mteNotification_len = name_buf_len;
+ memcpy( entry->mteNotification, name_buf, name_buf_len*sizeof(oid));
+ memcpy( entry->mteNotifyOwner, "snmpd.conf", 10 );
+ memcpy( entry->mteNotifyObjects, ename, MTE_STR1_LEN );
+ entry->mteEventActions |= MTE_EVENT_NOTIFICATION;
+ entry->flags |= MTE_EVENT_FLAG_ENABLED |
+ MTE_EVENT_FLAG_ACTIVE |
+ MTE_EVENT_FLAG_FIXED |
+ MTE_EVENT_FLAG_VALID;
+ return;
+}
+
+void
+parse_setEvent( const char *token, char *line )
+{
+ char ename[MTE_STR1_LEN+1];
+ char buf[SPRINT_MAX_LEN];
+ oid name_buf[MAX_OID_LEN];
+ size_t name_buf_len;
+ long value;
+ int wild = 1;
+ struct mteEvent *entry;
+ char *cp;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing setEvent config... "));
+
+ memset( ename, 0, sizeof(ename));
+ cp = copy_nword(line, ename, MTE_STR1_LEN);
+ if (!cp || ename[0] == '\0') {
+ config_perror("syntax error: no event name");
+ return;
+ }
+
+ if (cp && *cp=='-' && *(cp+1)=='I') {
+ wild = 0; /* an instance assignment */
+ cp = skip_token( cp );
+ }
+
+ /*
+ * Parse the SET assignment in the form "OID = value"
+ */
+ cp = copy_nword(cp, buf, SPRINT_MAX_LEN);
+ if ( buf[0] == '\0' ) {
+ config_perror("syntax error: no set OID");
+ return;
+ }
+ name_buf_len = MAX_OID_LEN;
+ if (!snmp_parse_oid(buf, name_buf, &name_buf_len)) {
+ snmp_log(LOG_ERR, "setEvent OID: %s\n", buf);
+ config_perror("unknown set OID");
+ return;
+ }
+ if (cp && *cp == '=') {
+ cp = skip_token( cp ); /* skip the '=' assignment character */
+ }
+ if (!cp) {
+ config_perror("syntax error: missing set value");
+ return;
+ }
+
+ value = strtol( cp, NULL, 0);
+
+ /*
+ * If the entry has parsed successfully, then create,
+ * populate and activate the new event entry.
+ */
+ entry = _find_typed_mteEvent_entry("snmpd.conf", ename, MTE_EVENT_SET);
+ if (!entry) {
+ return;
+ }
+ memcpy( entry->mteSetOID, name_buf, name_buf_len*sizeof(oid));
+ entry->mteSetOID_len = name_buf_len;
+ entry->mteSetValue = value;
+ if (wild)
+ entry->flags |= MTE_SET_FLAG_OBJWILD;
+ entry->mteEventActions |= MTE_EVENT_SET;
+ entry->flags |= MTE_EVENT_FLAG_ENABLED |
+ MTE_EVENT_FLAG_ACTIVE |
+ MTE_EVENT_FLAG_FIXED |
+ MTE_EVENT_FLAG_VALID;
+ return;
+}
+
+
+/* ==============================
+ *
+ * Persistent (dynamic) configuration
+ *
+ * ============================== */
+
+void
+parse_mteETable(const char *token, char *line )
+{
+ char owner[MTE_STR1_LEN+1];
+ char ename[MTE_STR1_LEN+1];
+ void *vp;
+ size_t tmp;
+ size_t len;
+ struct mteEvent *entry;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing mteEventTable config... "));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( ename, 0, sizeof(ename));
+ len = MTE_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = ename;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ entry = _find_mteEvent_entry( owner, ename );
+
+ DEBUGMSG(("disman:event:conf", "(%s, %s) ", owner, ename));
+
+ /*
+ * Read in the accessible (event-independent) column values.
+ */
+ len = MTE_STR2_LEN; vp = entry->mteEventComment;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ /*
+ * Skip the mteEventAction field, and note that the
+ * boolean values are combined into a single field.
+ */
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ entry->flags |= (tmp &
+ (MTE_EVENT_FLAG_ENABLED|MTE_EVENT_FLAG_ACTIVE));
+ /*
+ * XXX - Will need to read in the 'iquery' access information
+ */
+ entry->flags |= MTE_EVENT_FLAG_VALID;
+
+ DEBUGMSG(("disman:event:conf", "\n"));
+}
+
+
+void
+parse_mteENotTable(const char *token, char *line)
+{
+ char owner[MTE_STR1_LEN+1];
+ char ename[MTE_STR1_LEN+1];
+ void *vp;
+ size_t len;
+ struct mteEvent *entry;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing mteENotifyTable config... "));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( ename, 0, sizeof(ename));
+ len = MTE_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = ename;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ entry = _find_mteEvent_entry( owner, ename );
+
+ DEBUGMSG(("disman:event:conf", "(%s, %s) ", owner, ename));
+
+ /*
+ * Read in the accessible column values.
+ */
+ vp = entry->mteNotification;
+ line = read_config_read_data(ASN_OBJECT_ID, line, &vp,
+ &entry->mteNotification_len);
+ len = MTE_STR1_LEN; vp = entry->mteNotifyOwner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteNotifyObjects;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+
+ entry->mteEventActions |= MTE_EVENT_NOTIFICATION;
+ entry->flags |= MTE_EVENT_FLAG_VALID;
+
+ DEBUGMSG(("disman:event:conf", "\n"));
+}
+
+
+void
+parse_mteESetTable(const char *token, char *line)
+{
+ char owner[MTE_STR1_LEN+1];
+ char ename[MTE_STR1_LEN+1];
+ void *vp;
+ size_t len;
+ struct mteEvent *entry;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing mteESetTable config... "));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( ename, 0, sizeof(ename));
+ len = MTE_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = ename;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ entry = _find_mteEvent_entry( owner, ename );
+
+ DEBUGMSG(("disman:event:conf", "(%s, %s) ", owner, ename));
+
+ /*
+ * Read in the accessible column values.
+ */
+ vp = entry->mteSetOID;
+ line = read_config_read_data(ASN_OBJECT_ID, line, &vp,
+ &entry->mteSetOID_len);
+ line = read_config_read_data(ASN_UNSIGNED, line,
+ &entry->mteSetValue, &len);
+ len = MTE_STR2_LEN; vp = entry->mteSetTarget;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR2_LEN; vp = entry->mteSetContext;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+
+ entry->mteEventActions |= MTE_EVENT_SET;
+ entry->flags |= MTE_EVENT_FLAG_VALID;
+
+ DEBUGMSG(("disman:event:conf", "\n"));
+}
+
+
+
+int
+store_mteETable(int majorID, int minorID, void *serverarg, void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr, *cp;
+ void *vp;
+ size_t tint;
+ netsnmp_tdata_row *row;
+ struct mteEvent *entry;
+
+
+ DEBUGMSGTL(("disman:event:conf", "Storing mteEventTable config:\n"));
+
+ for (row = netsnmp_tdata_row_first( event_table_data );
+ row;
+ row = netsnmp_tdata_row_next( event_table_data, row )) {
+
+ /*
+ * Skip entries that were set up via static config directives
+ */
+ entry = (struct mteEvent *)netsnmp_tdata_row_entry( row );
+ if ( entry->flags & MTE_EVENT_FLAG_FIXED )
+ continue;
+
+ DEBUGMSGTL(("disman:event:conf", " Storing (%s %s)\n",
+ entry->mteOwner, entry->mteEName));
+
+ /*
+ * Save the basic mteEventTable entry...
+ */
+ memset(line, 0, sizeof(line));
+ strcat(line, "_mteETable ");
+ cptr = line + strlen(line);
+
+ cp = entry->mteOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteEName; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteEventComment; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ /* ... (but skip the mteEventAction field)... */
+ tint = entry->flags & (MTE_EVENT_FLAG_ENABLED|MTE_EVENT_FLAG_ACTIVE);
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+ /* XXX - Need to store the 'iquery' access information */
+ snmpd_store_config(line);
+
+ /*
+ * ... then save Notify and/or Set entries separately
+ * (The mteEventAction bits will be set when these are read in).
+ */
+ if ( entry->mteEventActions & MTE_EVENT_NOTIFICATION ) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "_mteENotTable ");
+ cptr = line + strlen(line);
+
+ cp = entry->mteOwner; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteEName; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ vp = entry->mteNotification;
+ cptr = read_config_store_data(ASN_OBJECT_ID, cptr, &vp,
+ &entry->mteNotification_len);
+ cp = entry->mteNotifyOwner; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteNotifyObjects; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ snmpd_store_config(line);
+ }
+
+ if ( entry->mteEventActions & MTE_EVENT_SET ) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "_mteESetTable ");
+ cptr = line + strlen(line);
+
+ cp = entry->mteOwner; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteEName; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ vp = entry->mteSetOID;
+ cptr = read_config_store_data(ASN_OBJECT_ID, cptr, &vp,
+ &entry->mteSetOID_len);
+ tint = entry->mteSetValue;
+ cptr = read_config_store_data(ASN_INTEGER, cptr, &tint, NULL);
+ cp = entry->mteSetTarget; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteSetContext; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ tint = entry->flags & (MTE_SET_FLAG_OBJWILD|MTE_SET_FLAG_CTXWILD);
+ cptr = read_config_store_data(ASN_UNSIGNED, cptr, &tint, NULL);
+ snmpd_store_config(line);
+ }
+ }
+
+ DEBUGMSGTL(("disman:event:conf", " done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+int
+clear_mteETable(int majorID, int minorID, void *serverarg, void *clientarg)
+{
+ netsnmp_tdata_row *row;
+ netsnmp_variable_list owner_var;
+
+ /*
+ * We're only interested in entries set up via the config files
+ */
+ memset( &owner_var, 0, sizeof(netsnmp_variable_list));
+ snmp_set_var_typed_value( &owner_var, ASN_OCTET_STR,
+ "snmpd.conf", strlen("snmpd.conf"));
+ while (( row = netsnmp_tdata_row_next_byidx( event_table_data,
+ &owner_var ))) {
+ /*
+ * XXX - check for owner of "snmpd.conf"
+ * and break at the end of these
+ */
+ netsnmp_tdata_remove_and_delete_row( event_table_data, row );
+ }
+ return SNMPERR_SUCCESS;
+}
diff --git a/agent/mibgroup/disman/event/mteEventConf.h b/agent/mibgroup/disman/event/mteEventConf.h
new file mode 100644
index 0000000..47001f0
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteEventConf.h
@@ -0,0 +1,20 @@
+#ifndef MTEEVENTCONF_H
+#define MTEEVENTCONF_H
+
+config_require(utilities/iquery)
+
+/*
+ * function declarations
+ */
+void init_mteEventConf(void);
+
+void parse_notificationEvent(const char *, char *);
+void parse_setEvent( const char *, char *);
+
+void parse_mteETable( const char *, char *);
+void parse_mteENotTable(const char *, char *);
+void parse_mteESetTable(const char *, char *);
+SNMPCallback store_mteETable;
+SNMPCallback clear_mteETable;
+
+#endif /* MTEEVENTCONF_H */
diff --git a/agent/mibgroup/disman/event/mteEventNotificationTable.c b/agent/mibgroup/disman/event/mteEventNotificationTable.c
new file mode 100644
index 0000000..7d2c94a
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteEventNotificationTable.c
@@ -0,0 +1,266 @@
+/*
+ * DisMan Event MIB:
+ * Implementation of the mteEventNotificationTable MIB interface
+ * See 'mteEvent.c' for active behaviour of this table.
+ *
+ * (based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "disman/event/mteEvent.h"
+#include "disman/event/mteEventNotificationTable.h"
+
+netsnmp_feature_require(table_tdata)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(check_vb_type_and_max_size)
+netsnmp_feature_require(check_vb_oid)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+static netsnmp_table_registration_info *table_info;
+
+/* Initializes the mteEventNotificationTable module */
+void
+init_mteEventNotificationTable(void)
+{
+ static oid mteEventNotificationTable_oid[] = { 1, 3, 6, 1, 2, 1, 88, 1, 4, 3 };
+ size_t mteEventNotificationTable_oid_len = OID_LENGTH(mteEventNotificationTable_oid);
+ netsnmp_handler_registration *reg;
+
+ /*
+ * Ensure the (combined) table container is available...
+ */
+ init_event_table_data();
+
+ /*
+ * ... then set up the MIB interface to the mteEventNotificationTable slice
+ */
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ reg = netsnmp_create_handler_registration("mteEventNotificationTable",
+ mteEventNotificationTable_handler,
+ mteEventNotificationTable_oid,
+ mteEventNotificationTable_oid_len,
+ HANDLER_CAN_RWRITE);
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+ reg = netsnmp_create_handler_registration("mteEventNotificationTable",
+ mteEventNotificationTable_handler,
+ mteEventNotificationTable_oid,
+ mteEventNotificationTable_oid_len,
+ HANDLER_CAN_RONLY);
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_OCTET_STR, /* index: mteOwner */
+ /* index: mteEventName */
+ ASN_PRIV_IMPLIED_OCTET_STR,
+ 0);
+
+ table_info->min_column = COLUMN_MTEEVENTNOTIFICATION;
+ table_info->max_column = COLUMN_MTEEVENTNOTIFICATIONOBJECTS;
+
+ /* Register this using the (common) event_table_data container */
+ netsnmp_tdata_register(reg, event_table_data, table_info);
+ DEBUGMSGTL(("disman:event:init", "Event Notify Table container (%p)\n",
+ event_table_data));
+}
+
+void
+shutdown_mteEventNotificationTable(void)
+{
+ if (table_info) {
+ netsnmp_table_registration_info_free(table_info);
+ table_info = NULL;
+ }
+}
+
+
+/** handles requests for the mteEventNotificationTable table */
+int
+mteEventNotificationTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ struct mteEvent *entry;
+ int ret;
+
+ DEBUGMSGTL(("disman:event:mib", "Notification Table handler (%d)\n", reqinfo->mode));
+
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteEvent *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ /*
+ * The mteEventNotificationTable should only contains entries
+ * for rows where the mteEventActions 'notification(0)' bit
+ * is set. So skip entries where this isn't the case.
+ */
+ if (!entry || !(entry->mteEventActions & MTE_EVENT_NOTIFICATION))
+ continue;
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEEVENTNOTIFICATION:
+ snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
+ (u_char *) entry->mteNotification,
+ entry->mteNotification_len*sizeof(oid));
+ break;
+ case COLUMN_MTEEVENTNOTIFICATIONOBJECTSOWNER:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteNotifyOwner,
+ strlen(entry->mteNotifyOwner));
+ break;
+ case COLUMN_MTEEVENTNOTIFICATIONOBJECTS:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteNotifyObjects,
+ strlen(entry->mteNotifyObjects));
+ break;
+ }
+ }
+ break;
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ /*
+ * Write-support
+ */
+ case MODE_SET_RESERVE1:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ /*
+ * Since the mteEventNotificationTable only contains entries
+ * for rows where the mteEventActions 'notification(0)'
+ * bit is set, strictly speaking we should reject
+ * assignments where this isn't the case.
+ * But SET requests that include an assignment of the
+ * 'notification(0)' bit at the same time are valid,
+ * so would need to be accepted. Unfortunately, this
+ * assignment is only applied in the COMMIT pass, so
+ * it's difficult to detect whether this holds or not.
+ *
+ * Let's fudge things for now, by processing assignments
+ * even if the 'notification(0)' bit isn't set.
+ */
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEEVENTNOTIFICATION:
+ ret = netsnmp_check_vb_oid( request->requestvb );
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTEEVENTNOTIFICATIONOBJECTSOWNER:
+ case COLUMN_MTEEVENTNOTIFICATIONOBJECTS:
+ ret = netsnmp_check_vb_type_and_max_size(
+ request->requestvb, ASN_OCTET_STR, MTE_STR1_LEN);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ default:
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOTWRITABLE);
+ return SNMP_ERR_NOERROR;
+ }
+
+ /*
+ * The Event MIB is somewhat ambiguous as to whether
+ * mteEventNotificationTable (and mteEventSetTable)
+ * entries can be modified once the main mteEventTable
+ * entry has been marked 'active'.
+ * But it's clear from discussion on the DisMan mailing
+ * list is that the intention is not.
+ *
+ * So check for whether this row is already active,
+ * and reject *all* SET requests if it is.
+ */
+ entry = (struct mteEvent *) netsnmp_tdata_extract_entry(request);
+ if (entry &&
+ entry->flags & MTE_EVENT_FLAG_ACTIVE ) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_RESERVE2:
+ case MODE_SET_FREE:
+ case MODE_SET_UNDO:
+ break;
+
+ case MODE_SET_ACTION:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteEvent *) netsnmp_tdata_extract_entry(request);
+ if (!entry) {
+ /*
+ * New rows must be created via the RowStatus column
+ * (in the main mteEventTable)
+ */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ /* or inconsistentName? */
+ return SNMP_ERR_NOERROR;
+
+ }
+ }
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * All these assignments are "unfailable", so it's
+ * (reasonably) safe to apply them in the Commit phase
+ */
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteEvent *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEEVENTNOTIFICATION:
+ memset(entry->mteNotification, 0, sizeof(entry->mteNotification));
+ memcpy(entry->mteNotification, request->requestvb->val.objid,
+ request->requestvb->val_len);
+ entry->mteNotification_len = request->requestvb->val_len/sizeof(oid);
+ break;
+ case COLUMN_MTEEVENTNOTIFICATIONOBJECTSOWNER:
+ memset(entry->mteNotifyOwner, 0, sizeof(entry->mteNotifyOwner));
+ memcpy(entry->mteNotifyOwner, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTEEVENTNOTIFICATIONOBJECTS:
+ memset(entry->mteNotifyObjects, 0, sizeof(entry->mteNotifyObjects));
+ memcpy(entry->mteNotifyObjects, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ }
+ }
+ break;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ }
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/event/mteEventNotificationTable.h b/agent/mibgroup/disman/event/mteEventNotificationTable.h
new file mode 100644
index 0000000..abd6110
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteEventNotificationTable.h
@@ -0,0 +1,21 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.table_data.conf,v 1.8 2005/07/19 14:52:03 dts12 Exp $
+ */
+#ifndef MTEEVENTNOTIFICATIONTABLE_H
+#define MTEEVENTNOTIFICATIONTABLE_H
+
+/*
+ * function declarations
+ */
+void init_mteEventNotificationTable(void);
+void shutdown_mteEventNotificationTable(void);
+Netsnmp_Node_Handler mteEventNotificationTable_handler;
+
+/*
+ * column number definitions for table mteEventNotificationTable
+ */
+#define COLUMN_MTEEVENTNOTIFICATION 1
+#define COLUMN_MTEEVENTNOTIFICATIONOBJECTSOWNER 2
+#define COLUMN_MTEEVENTNOTIFICATIONOBJECTS 3
+#endif /* MTEEVENTNOTIFICATIONTABLE_H */
diff --git a/agent/mibgroup/disman/event/mteEventSetTable.c b/agent/mibgroup/disman/event/mteEventSetTable.c
new file mode 100644
index 0000000..ee696f1
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteEventSetTable.c
@@ -0,0 +1,310 @@
+/*
+ * DisMan Event MIB:
+ * Implementation of the mteEventSetTable MIB interface
+ * See 'mteEvent.c' for active behaviour of this table.
+ *
+ * (based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "disman/event/mteEvent.h"
+#include "disman/event/mteEventSetTable.h"
+
+netsnmp_feature_require(table_tdata)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(check_vb_type_and_max_size)
+netsnmp_feature_require(check_vb_oid)
+netsnmp_feature_require(check_vb_truthvalue)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+static netsnmp_table_registration_info *table_info;
+
+/* Initializes the mteEventSetTable module */
+void
+init_mteEventSetTable(void)
+{
+ static oid mteEventSetTable_oid[] = { 1, 3, 6, 1, 2, 1, 88, 1, 4, 4 };
+ size_t mteEventSetTable_oid_len = OID_LENGTH(mteEventSetTable_oid);
+ netsnmp_handler_registration *reg;
+
+ /*
+ * Ensure the (combined) table container is available...
+ */
+ init_event_table_data();
+
+ /*
+ * ... then set up the MIB interface to the mteEventSetTable slice
+ */
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ reg = netsnmp_create_handler_registration("mteEventSetTable",
+ mteEventSetTable_handler,
+ mteEventSetTable_oid,
+ mteEventSetTable_oid_len,
+ HANDLER_CAN_RWRITE);
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+ reg = netsnmp_create_handler_registration("mteEventSetTable",
+ mteEventSetTable_handler,
+ mteEventSetTable_oid,
+ mteEventSetTable_oid_len,
+ HANDLER_CAN_RONLY);
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_OCTET_STR, /* index: mteOwner */
+ /* index: mteEventName */
+ ASN_PRIV_IMPLIED_OCTET_STR,
+ 0);
+
+ table_info->min_column = COLUMN_MTEEVENTSETOBJECT;
+ table_info->max_column = COLUMN_MTEEVENTSETCONTEXTNAMEWILDCARD;
+
+ /* Register this using the (common) event_table_data container */
+ netsnmp_tdata_register(reg, event_table_data, table_info);
+ DEBUGMSGTL(("disman:event:init", "Event Set Table container (%p)\n",
+ event_table_data));
+}
+
+void
+shutdown_mteEventSetTable(void)
+{
+ if (table_info) {
+ netsnmp_table_registration_info_free(table_info);
+ table_info = NULL;
+ }
+}
+
+
+/** handles requests for the mteEventSetTable table */
+int
+mteEventSetTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ struct mteEvent *entry;
+ int ret;
+
+ DEBUGMSGTL(("disman:event:mib", "Set Table handler (%d)\n",
+ reqinfo->mode));
+
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteEvent *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ /*
+ * The mteEventSetTable should only contains entries for
+ * rows where the mteEventActions 'set(1)' bit is set.
+ * So skip entries where this isn't the case.
+ */
+ if (!entry || !(entry->mteEventActions & MTE_EVENT_SET))
+ continue;
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEEVENTSETOBJECT:
+ snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
+ (u_char *) entry->mteSetOID,
+ entry->mteSetOID_len*sizeof(oid));
+ break;
+ case COLUMN_MTEEVENTSETOBJECTWILDCARD:
+ ret = (entry->flags & MTE_SET_FLAG_OBJWILD ) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_MTEEVENTSETVALUE:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->mteSetValue);
+ break;
+ case COLUMN_MTEEVENTSETTARGETTAG:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteSetTarget,
+ strlen(entry->mteSetTarget));
+ break;
+ case COLUMN_MTEEVENTSETCONTEXTNAME:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteSetContext,
+ strlen(entry->mteSetContext));
+ break;
+ case COLUMN_MTEEVENTSETCONTEXTNAMEWILDCARD:
+ ret = (entry->flags & MTE_SET_FLAG_CTXWILD ) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ }
+ }
+ break;
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ /*
+ * Write-support
+ */
+ case MODE_SET_RESERVE1:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ /*
+ * Since the mteEventSetTable only contains entries for
+ * rows where the mteEventActions 'set(1)' bit is set,
+ * strictly speaking we should reject assignments where
+ * this isn't the case.
+ * But SET requests that include an assignment of the
+ * 'set(1)' bit at the same time are valid, so would
+ * need to be accepted. Unfortunately, this assignment
+ * is only applied in the COMMIT pass, so it's difficult
+ * to detect whether this holds or not.
+ *
+ * Let's fudge things for now, by processing assignments
+ * even if the 'set(1)' bit isn't set.
+ */
+ switch (tinfo->colnum) {
+ case COLUMN_MTEEVENTSETOBJECT:
+ ret = netsnmp_check_vb_oid( request->requestvb );
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTEEVENTSETOBJECTWILDCARD:
+ case COLUMN_MTEEVENTSETCONTEXTNAMEWILDCARD:
+ ret = netsnmp_check_vb_truthvalue( request->requestvb );
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTEEVENTSETVALUE:
+ ret = netsnmp_check_vb_int( request->requestvb );
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTEEVENTSETTARGETTAG:
+ case COLUMN_MTEEVENTSETCONTEXTNAME:
+ ret = netsnmp_check_vb_type_and_max_size(
+ request->requestvb, ASN_OCTET_STR, MTE_STR2_LEN);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ default:
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOTWRITABLE);
+ return SNMP_ERR_NOERROR;
+ }
+
+ /*
+ * The Event MIB is somewhat ambiguous as to whether
+ * mteEventSetTable (and mteEventNotificationTable)
+ * entries can be modified once the main mteEventTable
+ * entry has been marked 'active'.
+ * But it's clear from discussion on the DisMan mailing
+ * list is that the intention is not.
+ *
+ * So check for whether this row is already active,
+ * and reject *all* SET requests if it is.
+ */
+ entry = (struct mteEvent *) netsnmp_tdata_extract_entry(request);
+ if (entry &&
+ entry->flags & MTE_EVENT_FLAG_ACTIVE ) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_RESERVE2:
+ case MODE_SET_FREE:
+ case MODE_SET_UNDO:
+ break;
+
+ case MODE_SET_ACTION:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteEvent *) netsnmp_tdata_extract_entry(request);
+ if (!entry) {
+ /*
+ * New rows must be created via the RowStatus column
+ * (in the main mteEventTable)
+ */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ /* or inconsistentName? */
+ return SNMP_ERR_NOERROR;
+
+ }
+ }
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * All these assignments are "unfailable", so it's
+ * (reasonably) safe to apply them in the Commit phase
+ */
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteEvent *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEEVENTSETOBJECT:
+ memset(entry->mteSetOID, 0, sizeof(entry->mteSetOID));
+ memcpy(entry->mteSetOID, request->requestvb->val.objid,
+ request->requestvb->val_len);
+ entry->mteSetOID_len = request->requestvb->val_len/sizeof(oid);
+ break;
+ case COLUMN_MTEEVENTSETOBJECTWILDCARD:
+ if (*request->requestvb->val.integer == TV_TRUE)
+ entry->flags |= MTE_SET_FLAG_OBJWILD;
+ else
+ entry->flags &= ~MTE_SET_FLAG_OBJWILD;
+ break;
+ case COLUMN_MTEEVENTSETVALUE:
+ entry->mteSetValue = *request->requestvb->val.integer;
+ break;
+ case COLUMN_MTEEVENTSETTARGETTAG:
+ memset(entry->mteSetTarget, 0, sizeof(entry->mteSetTarget));
+ memcpy(entry->mteSetTarget, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTEEVENTSETCONTEXTNAME:
+ memset(entry->mteSetContext, 0, sizeof(entry->mteSetContext));
+ memcpy(entry->mteSetContext, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTEEVENTSETCONTEXTNAMEWILDCARD:
+ if (*request->requestvb->val.integer == TV_TRUE)
+ entry->flags |= MTE_SET_FLAG_CTXWILD;
+ else
+ entry->flags &= ~MTE_SET_FLAG_CTXWILD;
+ break;
+ }
+ }
+ break;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ }
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/event/mteEventSetTable.h b/agent/mibgroup/disman/event/mteEventSetTable.h
new file mode 100644
index 0000000..71ec09a
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteEventSetTable.h
@@ -0,0 +1,24 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.table_data.conf,v 1.8 2005/07/19 14:52:03 dts12 Exp $
+ */
+#ifndef MTEEVENTSETTABLE_H
+#define MTEEVENTSETTABLE_H
+
+/*
+ * function declarations
+ */
+void init_mteEventSetTable(void);
+void shutdown_mteEventSetTable(void);
+Netsnmp_Node_Handler mteEventSetTable_handler;
+
+/*
+ * column number definitions for table mteEventSetTable
+ */
+#define COLUMN_MTEEVENTSETOBJECT 1
+#define COLUMN_MTEEVENTSETOBJECTWILDCARD 2
+#define COLUMN_MTEEVENTSETVALUE 3
+#define COLUMN_MTEEVENTSETTARGETTAG 4
+#define COLUMN_MTEEVENTSETCONTEXTNAME 5
+#define COLUMN_MTEEVENTSETCONTEXTNAMEWILDCARD 6
+#endif /* MTEEVENTSETTABLE_H */
diff --git a/agent/mibgroup/disman/event/mteEventTable.c b/agent/mibgroup/disman/event/mteEventTable.c
new file mode 100644
index 0000000..c5b534e
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteEventTable.c
@@ -0,0 +1,375 @@
+/*
+ * DisMan Event MIB:
+ * Implementation of the mteEventTable MIB interface
+ * See 'mteEvent.c' for active behaviour of this table.
+ *
+ * (based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "utilities/iquery.h"
+#include "disman/event/mteEvent.h"
+#include "disman/event/mteEventTable.h"
+
+netsnmp_feature_require(iquery)
+netsnmp_feature_require(table_tdata)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(iquery_pdu_session)
+netsnmp_feature_require(check_vb_type_and_max_size)
+netsnmp_feature_require(mteevent_removeentry)
+netsnmp_feature_require(check_vb_truthvalue)
+netsnmp_feature_require(table_tdata_insert_row)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+static netsnmp_table_registration_info *table_info;
+
+/* Initializes the mteEventTable module */
+void
+init_mteEventTable(void)
+{
+ static oid mteEventTable_oid[] = { 1, 3, 6, 1, 2, 1, 88, 1, 4, 2 };
+ size_t mteEventTable_oid_len = OID_LENGTH(mteEventTable_oid);
+ netsnmp_handler_registration *reg;
+
+ /*
+ * Ensure the (combined) table container is available...
+ */
+ init_event_table_data();
+
+ /*
+ * ... then set up the MIB interface to the mteEventTable slice
+ */
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ reg = netsnmp_create_handler_registration("mteEventTable",
+ mteEventTable_handler,
+ mteEventTable_oid,
+ mteEventTable_oid_len,
+ HANDLER_CAN_RWRITE);
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+ reg = netsnmp_create_handler_registration("mteEventTable",
+ mteEventTable_handler,
+ mteEventTable_oid,
+ mteEventTable_oid_len,
+ HANDLER_CAN_RONLY);
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_OCTET_STR, /* index: mteOwner */
+ /* index: mteEventName */
+ ASN_PRIV_IMPLIED_OCTET_STR,
+ 0);
+
+ table_info->min_column = COLUMN_MTEEVENTCOMMENT;
+ table_info->max_column = COLUMN_MTEEVENTENTRYSTATUS;
+
+ /* Register this using the (common) event_table_data container */
+ netsnmp_tdata_register(reg, event_table_data, table_info);
+ DEBUGMSGTL(("disman:event:init", "Event Table container (%p)\n",
+ event_table_data));
+}
+
+void
+shutdown_mteEventTable(void)
+{
+ if (table_info) {
+ netsnmp_table_registration_info_free(table_info);
+ table_info = NULL;
+ }
+}
+
+/** handles requests for the mteEventTable table */
+int
+mteEventTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ netsnmp_tdata_row *row;
+ struct mteEvent *entry;
+ char mteOwner[MTE_STR1_LEN+1];
+ char mteEName[MTE_STR1_LEN+1];
+ long ret;
+
+ DEBUGMSGTL(("disman:event:mib", "Event Table handler (%d)\n",
+ reqinfo->mode));
+
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteEvent *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+ if (!entry || !(entry->flags & MTE_EVENT_FLAG_VALID))
+ continue;
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEEVENTCOMMENT:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ entry->mteEventComment,
+ strlen(entry->mteEventComment));
+ break;
+ case COLUMN_MTEEVENTACTIONS:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ &entry->mteEventActions, 1);
+ break;
+ case COLUMN_MTEEVENTENABLED:
+ ret = (entry->flags & MTE_EVENT_FLAG_ENABLED ) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_MTEEVENTENTRYSTATUS:
+ ret = (entry->flags & MTE_EVENT_FLAG_ACTIVE ) ?
+ RS_ACTIVE : RS_NOTINSERVICE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ }
+ }
+ break;
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ /*
+ * Write-support
+ */
+ case MODE_SET_RESERVE1:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteEvent *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEEVENTCOMMENT:
+ ret = netsnmp_check_vb_type_and_max_size(
+ request->requestvb, ASN_OCTET_STR, MTE_STR1_LEN);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ /*
+ * Can't modify the comment of an active row
+ * (No good reason for this, but that's what the MIB says!)
+ */
+ if (entry &&
+ entry->flags & MTE_EVENT_FLAG_ACTIVE ) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTEEVENTACTIONS:
+ ret = netsnmp_check_vb_type_and_size(
+ request->requestvb, ASN_OCTET_STR, 1);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ /*
+ * Can't modify the event types of an active row
+ * (A little more understandable perhaps,
+ * but still an unnecessary restriction IMO)
+ */
+ if (entry &&
+ entry->flags & MTE_EVENT_FLAG_ACTIVE ) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTEEVENTENABLED:
+ ret = netsnmp_check_vb_truthvalue(request->requestvb);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ /*
+ * The published version of the Event MIB forbids
+ * enabling (or disabling) an active row, which
+ * would make this object completely pointless!
+ * Fortunately this ludicrous decision has since been corrected.
+ */
+ break;
+
+ case COLUMN_MTEEVENTENTRYSTATUS:
+ ret = netsnmp_check_vb_rowstatus(request->requestvb,
+ (entry ? RS_ACTIVE : RS_NONEXISTENT));
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ /* An active row can only be deleted */
+ if (entry &&
+ entry->flags & MTE_EVENT_FLAG_ACTIVE &&
+ *request->requestvb->val.integer == RS_NOTINSERVICE ) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ default:
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOTWRITABLE);
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_RESERVE2:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEEVENTENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_CREATEANDGO:
+ case RS_CREATEANDWAIT:
+ /*
+ * Create an (empty) new row structure
+ */
+ memset(mteOwner, 0, sizeof(mteOwner));
+ memcpy(mteOwner, tinfo->indexes->val.string,
+ tinfo->indexes->val_len);
+ memset(mteEName, 0, sizeof(mteEName));
+ memcpy(mteEName,
+ tinfo->indexes->next_variable->val.string,
+ tinfo->indexes->next_variable->val_len);
+
+ row = mteEvent_createEntry(mteOwner, mteEName, 0);
+ if (!row) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_RESOURCEUNAVAILABLE);
+ return SNMP_ERR_NOERROR;
+ }
+ netsnmp_insert_tdata_row( request, row );
+ }
+ }
+ }
+ break;
+
+ case MODE_SET_FREE:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEEVENTENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_CREATEANDGO:
+ case RS_CREATEANDWAIT:
+ /*
+ * Tidy up after a failed row creation request
+ */
+ entry = (struct mteEvent *)
+ netsnmp_tdata_extract_entry(request);
+ if (entry &&
+ !(entry->flags & MTE_EVENT_FLAG_VALID)) {
+ row = (netsnmp_tdata_row *)
+ netsnmp_tdata_extract_row(request);
+ mteEvent_removeEntry( row );
+ }
+ }
+ }
+ }
+ break;
+
+ case MODE_SET_ACTION:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+ entry = (struct mteEvent *) netsnmp_tdata_extract_entry(request);
+ if (!entry) {
+ /*
+ * New rows must be created via the RowStatus column
+ */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ /* or inconsistentName? */
+ return SNMP_ERR_NOERROR;
+
+ }
+ }
+ break;
+
+ case MODE_SET_UNDO:
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * All these assignments are "unfailable", so it's
+ * (reasonably) safe to apply them in the Commit phase
+ */
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteEvent *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEEVENTCOMMENT:
+ memset(entry->mteEventComment, 0,
+ sizeof(entry->mteEventComment));
+ memcpy(entry->mteEventComment,
+ request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+
+ case COLUMN_MTEEVENTACTIONS:
+ entry->mteEventActions = request->requestvb->val.string[0];
+ break;
+
+ case COLUMN_MTEEVENTENABLED:
+ if (*request->requestvb->val.integer == TV_TRUE)
+ entry->flags |= MTE_EVENT_FLAG_ENABLED;
+ else
+ entry->flags &= ~MTE_EVENT_FLAG_ENABLED;
+ break;
+
+ case COLUMN_MTEEVENTENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_ACTIVE:
+ entry->flags |= MTE_EVENT_FLAG_ACTIVE;
+ break;
+ case RS_CREATEANDGO:
+ entry->flags |= MTE_EVENT_FLAG_ACTIVE;
+ /* fall-through */
+ case RS_CREATEANDWAIT:
+ entry->flags |= MTE_EVENT_FLAG_VALID;
+ entry->session =
+ netsnmp_iquery_pdu_session(reqinfo->asp->pdu);
+ break;
+
+ case RS_DESTROY:
+ row = (netsnmp_tdata_row *)
+ netsnmp_tdata_extract_row(request);
+ mteEvent_removeEntry(row);
+ }
+ }
+ }
+ break;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ }
+ DEBUGMSGTL(("disman:event:mib", "Table handler, done\n"));
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/event/mteEventTable.h b/agent/mibgroup/disman/event/mteEventTable.h
new file mode 100644
index 0000000..adc1c30
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteEventTable.h
@@ -0,0 +1,23 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.table_data.conf,v 1.8 2005/07/19 14:52:03 dts12 Exp $
+ */
+#ifndef MTEEVENTTABLE_H
+#define MTEEVENTTABLE_H
+
+/*
+ * function declarations
+ */
+void init_mteEventTable(void);
+void shutdown_mteEventTable(void);
+Netsnmp_Node_Handler mteEventTable_handler;
+
+/*
+ * column number definitions for mteEventTable
+ */
+#define COLUMN_MTEEVENTNAME 1
+#define COLUMN_MTEEVENTCOMMENT 2
+#define COLUMN_MTEEVENTACTIONS 3
+#define COLUMN_MTEEVENTENABLED 4
+#define COLUMN_MTEEVENTENTRYSTATUS 5
+#endif /* MTEEVENTTABLE_H */
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;
+}
diff --git a/agent/mibgroup/disman/event/mteObjects.h b/agent/mibgroup/disman/event/mteObjects.h
new file mode 100644
index 0000000..cdbf626
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteObjects.h
@@ -0,0 +1,60 @@
+#ifndef MTEOBJECTS_H
+#define MTEOBJECTS_H
+
+#include "disman/event/mteTrigger.h"
+
+ /*
+ * Flags relating to the mteObjectsTable
+ */
+#define MTE_OBJECT_FLAG_WILD 0x01 /* for mteObjectsIDWildcard */
+#define MTE_OBJECT_FLAG_ACTIVE 0x02 /* for mteObjectsEntryStatus */
+#define MTE_OBJECT_FLAG_FIXED 0x04 /* for snmpd.conf persistence */
+#define MTE_OBJECT_FLAG_VALID 0x08 /* for row creation/undo */
+#define MTE_OBJECT_FLAG_NEXT 0x10 /* for appending a new row */
+
+#define MTE_STR1_LEN 32
+
+/*
+ * Data structure for an object row
+ */
+struct mteObject {
+ /*
+ * Index values
+ */
+ char mteOwner[MTE_STR1_LEN+1];
+ char mteOName[MTE_STR1_LEN+1];
+ long mteOIndex;
+
+ /*
+ * Column values
+ */
+ oid mteObjectID[MAX_OID_LEN];
+ size_t mteObjectID_len;
+
+ long flags;
+};
+
+ /*
+ * Container structure for the mteObjectsTable,
+ * and routine to create this.
+ */
+extern netsnmp_tdata *objects_table_data;
+extern void init_objects_table_data(void);
+
+void init_mteObjects(void);
+void mteObjects_removeEntry(netsnmp_tdata_row *row);
+void mteObjects_removeEntries(const char *owner, char *oname);
+netsnmp_tdata_row *mteObjects_createEntry( const char *owner,
+ const char *oname,
+ int oindex, int flags);
+struct mteObject * mteObjects_addOID(const char *owner, const char *oname, int index,
+ const char *oid_name_buf, int wild );
+
+int mteObjects_vblist( netsnmp_variable_list *vblist,
+ char *owner, char *oname,
+ oid *suffix, size_t sfx_len );
+int mteObjects_internal_vblist( netsnmp_variable_list *vblist,
+ char *oname, struct mteTrigger *trigger,
+ netsnmp_session *s);
+
+#endif /* MTEOBJECTS_H */
diff --git a/agent/mibgroup/disman/event/mteObjectsConf.c b/agent/mibgroup/disman/event/mteObjectsConf.c
new file mode 100644
index 0000000..7679865
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteObjectsConf.c
@@ -0,0 +1,179 @@
+/*
+ * DisMan Event MIB:
+ * Implementation of the object table configure handling
+ */
+
+#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/agent_callbacks.h>
+#include "disman/event/mteObjects.h"
+#include "disman/event/mteObjectsConf.h"
+
+
+/** Initializes the mteObjectsConf module */
+void
+init_mteObjectsConf(void)
+{
+ init_objects_table_data();
+
+ /*
+ * Register config handlers for current and previous style
+ * persistent configuration directives
+ */
+ snmpd_register_config_handler("_mteOTable",
+ parse_mteOTable, NULL, NULL);
+ snmpd_register_config_handler("mteObjectsTable",
+ parse_mteOTable, NULL, NULL);
+ /*
+ * Register to save (non-fixed) entries when the agent shuts down
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_mteOTable, NULL);
+ snmp_register_callback(SNMP_CALLBACK_APPLICATION,
+ SNMPD_CALLBACK_PRE_UPDATE_CONFIG,
+ clear_mteOTable, NULL);
+}
+
+
+void
+parse_mteOTable(const char *token, char *line)
+{
+ char owner[MTE_STR1_LEN+1];
+ char oname[MTE_STR1_LEN+1];
+ void *vp;
+ u_long index;
+ size_t tmpint;
+ size_t len;
+ netsnmp_tdata_row *row;
+ struct mteObject *entry;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing mteObjectTable config... "));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( oname, 0, sizeof(oname));
+ len = MTE_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = oname;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ line = read_config_read_data(ASN_UNSIGNED, line, &index, &len);
+
+ DEBUGMSG(("disman:event:conf", "(%s, %s, %lu) ", owner, oname, index));
+
+ row = mteObjects_createEntry( owner, oname, index, 0 );
+ /* entry = (struct mteObject *)netsnmp_tdata_row_entry( row ); */
+ entry = (struct mteObject *)row->data;
+
+
+ /*
+ * Read in the accessible column values
+ */
+ entry->mteObjectID_len = MAX_OID_LEN;
+ vp = entry->mteObjectID;
+ line = read_config_read_data(ASN_OBJECT_ID, line, &vp,
+ &entry->mteObjectID_len);
+
+ if (!strcasecmp(token, "mteObjectsTable")) {
+ /*
+ * The previous Event-MIB implementation saved
+ * these fields as separate (integer) values
+ * Accept this (for backwards compatability)
+ */
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmpint, &len);
+ if (tmpint == TV_TRUE)
+ entry->flags |= MTE_OBJECT_FLAG_WILD;
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmpint, &len);
+ if (tmpint == RS_ACTIVE)
+ entry->flags |= MTE_OBJECT_FLAG_ACTIVE;
+ } else {
+ /*
+ * This implementation saves the (relevant) flag bits directly
+ */
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmpint, &len);
+ if (tmpint & MTE_OBJECT_FLAG_WILD)
+ entry->flags |= MTE_OBJECT_FLAG_WILD;
+ if (tmpint & MTE_OBJECT_FLAG_ACTIVE)
+ entry->flags |= MTE_OBJECT_FLAG_ACTIVE;
+ }
+
+ entry->flags |= MTE_OBJECT_FLAG_VALID;
+
+ DEBUGMSG(("disman:event:conf", "\n"));
+}
+
+
+
+int
+store_mteOTable(int majorID, int minorID, void *serverarg, void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr, *cp;
+ void *vp;
+ size_t tint;
+ netsnmp_tdata_row *row;
+ struct mteObject *entry;
+
+
+ DEBUGMSGTL(("disman:event:conf", "Storing mteObjectTable config:\n"));
+
+ for (row = netsnmp_tdata_row_first( objects_table_data );
+ row;
+ row = netsnmp_tdata_row_next( objects_table_data, row )) {
+
+ /*
+ * Skip entries that were set up via static config directives
+ */
+ entry = (struct mteObject *)netsnmp_tdata_row_entry( row );
+ if ( entry->flags & MTE_OBJECT_FLAG_FIXED )
+ continue;
+
+ DEBUGMSGTL(("disman:event:conf", " Storing (%s %s %ld)\n",
+ entry->mteOwner, entry->mteOName, entry->mteOIndex));
+ memset(line, 0, sizeof(line));
+ strcat(line, "_mteOTable ");
+ cptr = line + strlen(line);
+
+ cp = entry->mteOwner; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteOName; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ cptr = read_config_store_data(ASN_UNSIGNED, cptr,
+ &entry->mteOIndex, NULL);
+ vp = entry->mteObjectID;
+ cptr = read_config_store_data(ASN_OBJECT_ID, cptr, &vp,
+ &entry->mteObjectID_len);
+ tint = entry->flags & (MTE_OBJECT_FLAG_WILD|MTE_OBJECT_FLAG_ACTIVE);
+ cptr = read_config_store_data(ASN_UNSIGNED, cptr, &tint, NULL);
+ snmpd_store_config(line);
+ }
+
+ DEBUGMSGTL(("disman:event:conf", " done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+int
+clear_mteOTable(int majorID, int minorID, void *serverarg, void *clientarg)
+{
+ netsnmp_tdata_row *row;
+ netsnmp_variable_list owner_var;
+
+ /*
+ * We're only interested in entries set up via the config files
+ */
+ memset( &owner_var, 0, sizeof(netsnmp_variable_list));
+ snmp_set_var_typed_value( &owner_var, ASN_OCTET_STR,
+ "snmpd.conf", strlen("snmpd.conf"));
+ while (( row = netsnmp_tdata_row_next_byidx( objects_table_data,
+ &owner_var ))) {
+ /*
+ * XXX - check for owner of "snmpd.conf"
+ * and break at the end of these
+ */
+ netsnmp_tdata_remove_and_delete_row( objects_table_data, row );
+ }
+ return SNMPERR_SUCCESS;
+}
diff --git a/agent/mibgroup/disman/event/mteObjectsConf.h b/agent/mibgroup/disman/event/mteObjectsConf.h
new file mode 100644
index 0000000..d6649ff
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteObjectsConf.h
@@ -0,0 +1,12 @@
+#ifndef MTEOBJECTSCONF_H
+#define MTEOBJECTSCONF_H
+
+/*
+ * function declarations
+ */
+void init_mteObjectsConf(void);
+void parse_mteOTable(const char *, char *);
+SNMPCallback store_mteOTable;
+SNMPCallback clear_mteOTable;
+
+#endif /* MTEOBJECTSCONF_H */
diff --git a/agent/mibgroup/disman/event/mteObjectsTable.c b/agent/mibgroup/disman/event/mteObjectsTable.c
new file mode 100644
index 0000000..f7f6e02
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteObjectsTable.c
@@ -0,0 +1,347 @@
+/*
+ * DisMan Event MIB:
+ * Implementation of the mteObjectsTable MIB interface
+ * See 'mteObjects.c' for active behaviour of this table.
+ *
+ * (based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "disman/event/mteObjects.h"
+#include "disman/event/mteObjectsTable.h"
+
+netsnmp_feature_require(table_tdata)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(check_vb_oid)
+netsnmp_feature_require(check_vb_truthvalue)
+netsnmp_feature_require(table_tdata_insert_row)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+static netsnmp_table_registration_info *table_info;
+
+/** Initializes the mteObjectsTable module */
+void
+init_mteObjectsTable(void)
+
+{
+ static oid mteObjectsTable_oid[] = { 1, 3, 6, 1, 2, 1, 88, 1, 3, 1 };
+ size_t mteObjectsTable_oid_len = OID_LENGTH(mteObjectsTable_oid);
+ netsnmp_handler_registration *reg;
+
+ /*
+ * Ensure the object table container is available...
+ */
+ init_objects_table_data();
+
+ /*
+ * ... then set up the MIB interface to this table
+ */
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ reg = netsnmp_create_handler_registration("mteObjectsTable",
+ mteObjectsTable_handler,
+ mteObjectsTable_oid,
+ mteObjectsTable_oid_len,
+ HANDLER_CAN_RWRITE);
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+ reg = netsnmp_create_handler_registration("mteObjectsTable",
+ mteObjectsTable_handler,
+ mteObjectsTable_oid,
+ mteObjectsTable_oid_len,
+ HANDLER_CAN_RONLY);
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_OCTET_STR, /* index: mteOwner */
+ ASN_OCTET_STR, /* index: mteObjectsName */
+ ASN_UNSIGNED, /* index: mteObjectsIndex */
+ 0);
+
+ table_info->min_column = COLUMN_MTEOBJECTSID;
+ table_info->max_column = COLUMN_MTEOBJECTSENTRYSTATUS;
+
+
+ netsnmp_tdata_register(reg, objects_table_data, table_info);
+}
+
+void
+shutdown_mteObjectsTable(void)
+{
+ if (table_info) {
+ netsnmp_table_registration_info_free(table_info);
+ table_info = NULL;
+ }
+}
+
+
+/** handles requests for the mteObjectsTable table */
+int
+mteObjectsTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ netsnmp_tdata_row *row;
+ struct mteObject *entry;
+ char mteOwner[MTE_STR1_LEN+1];
+ char mteOName[MTE_STR1_LEN+1];
+ long ret;
+
+ DEBUGMSGTL(("disman:event:mib", "ObjTable handler (%d)\n", reqinfo->mode));
+
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteObject *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ if (!entry) {
+ netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
+ continue;
+ }
+ switch (tinfo->colnum) {
+ case COLUMN_MTEOBJECTSID:
+ snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
+ (u_char *) entry->mteObjectID,
+ entry->mteObjectID_len*sizeof(oid));
+ break;
+ case COLUMN_MTEOBJECTSIDWILDCARD:
+ ret = (entry->flags & MTE_OBJECT_FLAG_WILD ) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_MTEOBJECTSENTRYSTATUS:
+ ret = (entry->flags & MTE_OBJECT_FLAG_ACTIVE ) ?
+ RS_ACTIVE : RS_NOTINSERVICE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ }
+ }
+ break;
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ /*
+ * Write-support
+ */
+ case MODE_SET_RESERVE1:
+
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteObject *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEOBJECTSID:
+ ret = netsnmp_check_vb_oid( request->requestvb );
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ /*
+ * Can't modify the OID of an active row
+ * (an unnecessary restriction, IMO)
+ */
+ if (entry &&
+ entry->flags & MTE_OBJECT_FLAG_ACTIVE ) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTEOBJECTSIDWILDCARD:
+ ret = netsnmp_check_vb_truthvalue( request->requestvb );
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ /*
+ * Can't modify the wildcarding of an active row
+ * (an unnecessary restriction, IMO)
+ */
+ if (entry &&
+ entry->flags & MTE_OBJECT_FLAG_ACTIVE ) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTEOBJECTSENTRYSTATUS:
+ ret = netsnmp_check_vb_rowstatus(request->requestvb,
+ (entry ? RS_ACTIVE : RS_NONEXISTENT));
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ /* An active row can only be deleted */
+ if (entry &&
+ entry->flags & MTE_OBJECT_FLAG_ACTIVE &&
+ *request->requestvb->val.integer == RS_NOTINSERVICE ) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ default:
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOTWRITABLE);
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_RESERVE2:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEOBJECTSENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_CREATEANDGO:
+ case RS_CREATEANDWAIT:
+ /*
+ * Create an (empty) new row structure
+ */
+ memset(mteOwner, 0, sizeof(mteOwner));
+ memcpy(mteOwner, tinfo->indexes->val.string,
+ tinfo->indexes->val_len);
+ memset(mteOName, 0, sizeof(mteOName));
+ memcpy(mteOName,
+ tinfo->indexes->next_variable->val.string,
+ tinfo->indexes->next_variable->val_len);
+ ret = *tinfo->indexes->next_variable->next_variable->val.integer;
+
+ row = mteObjects_createEntry(mteOwner, mteOName, ret, 0);
+ if (!row) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_RESOURCEUNAVAILABLE);
+ return SNMP_ERR_NOERROR;
+ }
+ netsnmp_insert_tdata_row( request, row );
+ }
+ }
+ }
+ break;
+
+ case MODE_SET_FREE:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEOBJECTSENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_CREATEANDGO:
+ case RS_CREATEANDWAIT:
+ /*
+ * Tidy up after a failed row creation request
+ */
+ entry = (struct mteObject *)
+ netsnmp_tdata_extract_entry(request);
+ if (entry &&
+ !(entry->flags & MTE_OBJECT_FLAG_VALID)) {
+ row = (netsnmp_tdata_row *)
+ netsnmp_tdata_extract_row(request);
+ mteObjects_removeEntry( row );
+ }
+ }
+ }
+ }
+ break;
+
+ case MODE_SET_ACTION:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteObject *) netsnmp_tdata_extract_entry(request);
+ if (!entry) {
+ /*
+ * New rows must be created via the RowStatus column
+ */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ /* or inconsistentName? */
+ return SNMP_ERR_NOERROR;
+
+ }
+ }
+ break;
+
+ case MODE_SET_UNDO:
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * All these assignments are "unfailable", so it's
+ * (reasonably) safe to apply them in the Commit phase
+ */
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteObject *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTEOBJECTSID:
+ memset(entry->mteObjectID, 0, sizeof(entry->mteObjectID));
+ memcpy(entry->mteObjectID, request->requestvb->val.objid,
+ request->requestvb->val_len);
+ entry->mteObjectID_len = request->requestvb->val_len/sizeof(oid);
+ break;
+
+ case COLUMN_MTEOBJECTSIDWILDCARD:
+ if (*request->requestvb->val.integer == TV_TRUE)
+ entry->flags |= MTE_OBJECT_FLAG_WILD;
+ else
+ entry->flags &= ~MTE_OBJECT_FLAG_WILD;
+ break;
+
+ case COLUMN_MTEOBJECTSENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_ACTIVE:
+ entry->flags |= MTE_OBJECT_FLAG_ACTIVE;
+ break;
+ case RS_CREATEANDGO:
+ entry->flags |= MTE_OBJECT_FLAG_VALID;
+ entry->flags |= MTE_OBJECT_FLAG_ACTIVE;
+ break;
+ case RS_CREATEANDWAIT:
+ entry->flags |= MTE_OBJECT_FLAG_VALID;
+ break;
+
+ case RS_DESTROY:
+ row = (netsnmp_tdata_row *)
+ netsnmp_tdata_extract_row(request);
+ mteObjects_removeEntry(row);
+ }
+ }
+ }
+
+ /** set up to save persistent store */
+ snmp_store_needed(NULL);
+
+ break;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ }
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/event/mteObjectsTable.h b/agent/mibgroup/disman/event/mteObjectsTable.h
new file mode 100644
index 0000000..f5cd7bc
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteObjectsTable.h
@@ -0,0 +1,23 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.table_data.conf,v 1.8 2005/07/19 14:52:03 dts12 Exp $
+ */
+#ifndef MTEOBJECTSTABLE_H
+#define MTEOBJECTSTABLE_H
+
+/*
+ * function declarations
+ */
+void init_mteObjectsTable(void);
+void shutdown_mteObjectsTable(void);
+Netsnmp_Node_Handler mteObjectsTable_handler;
+
+/*
+ * column number definitions for table mteObjectsTable
+ */
+#define COLUMN_MTEOBJECTSNAME 1
+#define COLUMN_MTEOBJECTSINDEX 2
+#define COLUMN_MTEOBJECTSID 3
+#define COLUMN_MTEOBJECTSIDWILDCARD 4
+#define COLUMN_MTEOBJECTSENTRYSTATUS 5
+#endif /* MTEOBJECTSTABLE_H */
diff --git a/agent/mibgroup/disman/event/mteScalars.c b/agent/mibgroup/disman/event/mteScalars.c
new file mode 100644
index 0000000..769adc1
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteScalars.c
@@ -0,0 +1,135 @@
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "mteScalars.h"
+#include "mteTrigger.h"
+
+/** Initializes the mteScalars module */
+void
+init_mteScalars(void)
+{
+ static oid mteResource_oid[] = { 1, 3, 6, 1, 2, 1, 88, 1, 1 };
+ static oid mteTriggerFail_oid[] = { 1, 3, 6, 1, 2, 1, 88, 1, 2, 1 };
+
+ DEBUGMSGTL(("mteScalars", "Initializing\n"));
+
+ netsnmp_register_scalar_group(
+ netsnmp_create_handler_registration("mteResource", handle_mteResourceGroup,
+ mteResource_oid, OID_LENGTH(mteResource_oid),
+ HANDLER_CAN_RONLY),
+ MTE_RESOURCE_SAMPLE_MINFREQ, MTE_RESOURCE_SAMPLE_LACKS);
+
+ netsnmp_register_scalar(
+ netsnmp_create_handler_registration("mteTriggerFailures",
+ handle_mteTriggerFailures,
+ mteTriggerFail_oid, OID_LENGTH(mteTriggerFail_oid),
+ HANDLER_CAN_RONLY));
+}
+
+int
+handle_mteResourceGroup(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+ oid obj;
+ long value = 0;
+
+ switch (reqinfo->mode) {
+ case MODE_GET:
+ obj = requests->requestvb->name[ requests->requestvb->name_length-2 ];
+ switch (obj) {
+ case MTE_RESOURCE_SAMPLE_MINFREQ:
+ value = 1; /* Fixed minimum sample frequency */
+ snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
+ (u_char *)&value, sizeof(value));
+ break;
+
+ case MTE_RESOURCE_SAMPLE_MAX_INST:
+ value = 0; /* No fixed maximum */
+ snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
+ (u_char *)&value, sizeof(value));
+ break;
+
+ case MTE_RESOURCE_SAMPLE_INSTANCES:
+#ifdef USING_DISMAN_EVENT_MTETRIGGER_MODULE
+ value = mteTrigger_getNumEntries(0);
+#else
+ value = 0;
+#endif
+ snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE,
+ (u_char *)&value, sizeof(value));
+ break;
+
+ case MTE_RESOURCE_SAMPLE_HIGH:
+#ifdef USING_DISMAN_EVENT_MTETRIGGER_MODULE
+ value = mteTrigger_getNumEntries(1);
+#else
+ value = 0;
+#endif
+ snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE,
+ (u_char *)&value, sizeof(value));
+ break;
+
+ case MTE_RESOURCE_SAMPLE_LACKS:
+ value = 0; /* mteResSampleInstMax not used */
+ snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER,
+ (u_char *)&value, sizeof(value));
+ break;
+
+ default:
+ snmp_log(LOG_ERR,
+ "unknown object (%d) in handle_mteResourceGroup\n", (int)obj);
+ return SNMP_ERR_GENERR;
+ }
+ break;
+
+ default:
+ /*
+ * Although mteResourceSampleMinimum and mteResourceSampleInstanceMaximum
+ * are defined with MAX-ACCESS read-write, this version hardcodes
+ * these values, so doesn't need to implement write access.
+ */
+ snmp_log(LOG_ERR,
+ "unknown mode (%d) in handle_mteResourceGroup\n",
+ reqinfo->mode);
+ return SNMP_ERR_GENERR;
+ }
+
+ return SNMP_ERR_NOERROR;
+}
+
+int
+handle_mteTriggerFailures(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+#ifdef USING_DISMAN_EVENT_MTETRIGGER_MODULE
+ extern long mteTriggerFailures;
+#else
+ long mteTriggerFailures = 0;
+#endif
+
+ switch (reqinfo->mode) {
+ case MODE_GET:
+ snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER,
+ (u_char *)&mteTriggerFailures,
+ sizeof(mteTriggerFailures));
+ break;
+
+
+ default:
+ /*
+ * we should never get here, so this is a really bad error
+ */
+ snmp_log(LOG_ERR,
+ "unknown mode (%d) in handle_mteTriggerFailures\n",
+ reqinfo->mode);
+ return SNMP_ERR_GENERR;
+ }
+
+ return SNMP_ERR_NOERROR;
+}
+
diff --git a/agent/mibgroup/disman/event/mteScalars.h b/agent/mibgroup/disman/event/mteScalars.h
new file mode 100644
index 0000000..a6ade2e
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteScalars.h
@@ -0,0 +1,14 @@
+#ifndef MTESCALARS_H
+#define MTESCALARS_H
+
+void init_mteScalars(void);
+Netsnmp_Node_Handler handle_mteResourceGroup;
+Netsnmp_Node_Handler handle_mteTriggerFailures;
+
+#define MTE_RESOURCE_SAMPLE_MINFREQ 1
+#define MTE_RESOURCE_SAMPLE_MAX_INST 2
+#define MTE_RESOURCE_SAMPLE_INSTANCES 3
+#define MTE_RESOURCE_SAMPLE_HIGH 4
+#define MTE_RESOURCE_SAMPLE_LACKS 5
+
+#endif /* MTESCALARS_H */
diff --git a/agent/mibgroup/disman/event/mteTrigger.c b/agent/mibgroup/disman/event/mteTrigger.c
new file mode 100644
index 0000000..7fca1b0
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTrigger.c
@@ -0,0 +1,1200 @@
+/*
+ * DisMan Event MIB:
+ * Core implementation of the trigger handling behaviour
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "disman/event/mteTrigger.h"
+#include "disman/event/mteEvent.h"
+
+netsnmp_feature_child_of(disman_debugging, libnetsnmpmibs)
+netsnmp_feature_child_of(mtetrigger, libnetsnmpmibs)
+netsnmp_feature_child_of(mtetrigger_removeentry, mtetrigger)
+
+netsnmp_tdata *trigger_table_data;
+
+oid _sysUpTime_instance[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 };
+size_t _sysUpTime_inst_len = OID_LENGTH(_sysUpTime_instance);
+
+long mteTriggerFailures;
+
+ /*
+ * Initialize the container for the (combined) mteTrigger*Table,
+ * regardless of which table initialisation routine is called first.
+ */
+
+void
+init_trigger_table_data(void)
+{
+ DEBUGMSGTL(("disman:event:init", "init trigger container\n"));
+ if (!trigger_table_data) {
+ trigger_table_data = netsnmp_tdata_create_table("mteTriggerTable", 0);
+ if (!trigger_table_data) {
+ snmp_log(LOG_ERR, "failed to create mteTriggerTable");
+ return;
+ }
+ DEBUGMSGTL(("disman:event:init", "create trigger container (%p)\n",
+ trigger_table_data));
+ }
+ mteTriggerFailures = 0;
+}
+
+
+/** Initializes the mteTrigger module */
+void
+init_mteTrigger(void)
+{
+ init_trigger_table_data();
+
+}
+
+ /* ===================================================
+ *
+ * APIs for maintaining the contents of the (combined)
+ * mteTrigger*Table container.
+ *
+ * =================================================== */
+
+#ifndef NETSNMP_FEATURE_REMOVE_DISMAN_DEBUGGING
+void
+_mteTrigger_dump(void)
+{
+ struct mteTrigger *entry;
+ netsnmp_tdata_row *row;
+ int i = 0;
+
+ for (row = netsnmp_tdata_row_first(trigger_table_data);
+ row;
+ row = netsnmp_tdata_row_next(trigger_table_data, row)) {
+ entry = (struct mteTrigger *)row->data;
+ DEBUGMSGTL(("disman:event:dump", "TriggerTable entry %d: ", i));
+ DEBUGMSGOID(("disman:event:dump", row->oid_index.oids, row->oid_index.len));
+ DEBUGMSG(("disman:event:dump", "(%s, %s)",
+ row->indexes->val.string,
+ row->indexes->next_variable->val.string));
+ DEBUGMSG(("disman:event:dump", ": %p, %p\n", row, entry));
+ i++;
+ }
+ DEBUGMSGTL(("disman:event:dump", "TriggerTable %d entries\n", i));
+}
+#endif /* NETSNMP_FEATURE_REMOVE_DISMAN_DEBUGGING */
+
+/*
+ * Create a new row in the trigger table
+ */
+netsnmp_tdata_row *
+mteTrigger_createEntry(const char *mteOwner, char *mteTName, int fixed)
+{
+ struct mteTrigger *entry;
+ netsnmp_tdata_row *row;
+ size_t mteOwner_len = (mteOwner) ? strlen(mteOwner) : 0;
+ size_t mteTName_len = (mteTName) ? strlen(mteTName) : 0;
+
+ DEBUGMSGTL(("disman:event:table", "Create trigger entry (%s, %s)\n",
+ mteOwner, mteTName));
+ /*
+ * Create the mteTrigger entry, and the
+ * (table-independent) row wrapper structure...
+ */
+ entry = SNMP_MALLOC_TYPEDEF(struct mteTrigger);
+ 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 (mteOwner)
+ memcpy(entry->mteOwner, mteOwner, mteOwner_len);
+ netsnmp_table_row_add_index(row, ASN_OCTET_STR,
+ entry->mteOwner, mteOwner_len);
+ if (mteTName)
+ memcpy(entry->mteTName, mteTName, mteTName_len);
+ netsnmp_table_row_add_index(row, ASN_PRIV_IMPLIED_OCTET_STR,
+ entry->mteTName, mteTName_len);
+
+ /* entry->mteTriggerTest = MTE_TRIGGER_BOOLEAN; */
+ entry->mteTriggerValueID_len = 2; /* .0.0 */
+ entry->mteTriggerFrequency = 600;
+ memcpy(entry->mteDeltaDiscontID, _sysUpTime_instance,
+ sizeof(_sysUpTime_instance));
+ entry->mteDeltaDiscontID_len = _sysUpTime_inst_len;
+ entry->mteDeltaDiscontIDType = MTE_DELTAD_TTICKS;
+ entry->flags |= MTE_TRIGGER_FLAG_SYSUPT;
+ entry->mteTExTest = (MTE_EXIST_PRESENT | MTE_EXIST_ABSENT);
+ entry->mteTExStartup = (MTE_EXIST_PRESENT | MTE_EXIST_ABSENT);
+ entry->mteTBoolComparison = MTE_BOOL_UNEQUAL;
+ entry->flags |= MTE_TRIGGER_FLAG_BSTART;
+ entry->mteTThStartup = MTE_THRESH_START_RISEFALL;
+
+ if (fixed)
+ entry->flags |= MTE_TRIGGER_FLAG_FIXED;
+
+ /*
+ * ... and insert the row into the (common) table container
+ */
+ netsnmp_tdata_add_row(trigger_table_data, row);
+ DEBUGMSGTL(("disman:event:table", "Trigger entry created\n"));
+ return row;
+}
+
+#ifndef NETSNMP_FEATURE_REMOVE_MTETRIGGER_REMOVEENTRY
+/*
+ * Remove a row from the trigger table
+ */
+void
+mteTrigger_removeEntry(netsnmp_tdata_row *row)
+{
+ struct mteTrigger *entry;
+
+ if (!row)
+ return; /* Nothing to remove */
+ entry = (struct mteTrigger *)
+ netsnmp_tdata_remove_and_delete_row(trigger_table_data, row);
+ if (entry) {
+ mteTrigger_disable( entry );
+ SNMP_FREE(entry);
+ }
+}
+#endif /* NETSNMP_FEATURE_REMOVE_MTETRIGGER_REMOVEENTRY */
+
+ /* ===================================================
+ *
+ * APIs for evaluating a trigger,
+ * and firing the appropriate event
+ *
+ * =================================================== */
+const char *_ops[] = { "",
+ "!=", /* MTE_BOOL_UNEQUAL */
+ "==", /* MTE_BOOL_EQUAL */
+ "<", /* MTE_BOOL_LESS */
+ "<=", /* MTE_BOOL_LESSEQUAL */
+ ">", /* MTE_BOOL_GREATER */
+ ">=" /* MTE_BOOL_GREATEREQUAL */ };
+
+void
+_mteTrigger_failure( /* int error, */ const char *msg )
+{
+ /*
+ * XXX - Send an mteTriggerFailure trap
+ * (if configured to do so)
+ */
+ mteTriggerFailures++;
+ snmp_log(LOG_ERR, "%s\n", msg );
+ return;
+}
+
+void
+mteTrigger_run( unsigned int reg, void *clientarg)
+{
+ struct mteTrigger *entry = (struct mteTrigger *)clientarg;
+ netsnmp_variable_list *var, *vtmp;
+ netsnmp_variable_list *vp1, *vp1_prev;
+ netsnmp_variable_list *vp2, *vp2_prev;
+ netsnmp_variable_list *dvar = NULL;
+ netsnmp_variable_list *dv1 = NULL, *dv2 = NULL;
+ netsnmp_variable_list sysUT_var;
+ int cmp = 0, n, n2;
+ long value;
+ const char *reason;
+
+ if (!entry) {
+ snmp_alarm_unregister( reg );
+ return;
+ }
+ if (!(entry->flags & MTE_TRIGGER_FLAG_ENABLED ) ||
+ !(entry->flags & MTE_TRIGGER_FLAG_ACTIVE ) ||
+ !(entry->flags & MTE_TRIGGER_FLAG_VALID )) {
+ return;
+ }
+
+ {
+ extern netsnmp_agent_session *netsnmp_processing_set;
+ if (netsnmp_processing_set) {
+ /*
+ * netsnmp_handle_request will not be responsive to our efforts to
+ * Retrieve the requested MIB value(s)...
+ * so we will skip it.
+ * https://sourceforge.net/tracker/
+ * index.php?func=detail&aid=1557406&group_id=12694&atid=112694
+ */
+ DEBUGMSGTL(("disman:event:trigger:monitor",
+ "Skipping trigger (%s) while netsnmp_processing_set\n",
+ entry->mteTName));
+ return;
+ }
+ }
+
+ /*
+ * Retrieve the requested MIB value(s)...
+ */
+ DEBUGMSGTL(( "disman:event:trigger:monitor", "Running trigger (%s)\n", entry->mteTName));
+ var = (netsnmp_variable_list *)SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ if (!var) {
+ _mteTrigger_failure("failed to create mteTrigger query varbind");
+ return;
+ }
+ snmp_set_var_objid( var, entry->mteTriggerValueID,
+ entry->mteTriggerValueID_len );
+ if ( entry->flags & MTE_TRIGGER_FLAG_VWILD ) {
+ n = netsnmp_query_walk( var, entry->session );
+ } else {
+ n = netsnmp_query_get( var, entry->session );
+ }
+ if ( n != SNMP_ERR_NOERROR ) {
+ DEBUGMSGTL(( "disman:event:trigger:monitor", "Trigger query (%s) failed: %d\n",
+ (( entry->flags & MTE_TRIGGER_FLAG_VWILD ) ? "walk" : "get"), n));
+ _mteTrigger_failure( "failed to run mteTrigger query" );
+ snmp_free_varbind(var);
+ return;
+ }
+
+ /*
+ * ... canonicalise the results (to simplify later comparisons)...
+ */
+
+ vp1 = var; vp1_prev = NULL;
+ vp2 = entry->old_results; vp2_prev = NULL;
+ entry->count=0;
+ while (vp1) {
+ /*
+ * Flatten various missing values/exceptions into a single form
+ */
+ switch (vp1->type) {
+ case SNMP_NOSUCHINSTANCE:
+ case SNMP_NOSUCHOBJECT:
+ case ASN_PRIV_RETRY: /* Internal only ? */
+ vp1->type = ASN_NULL;
+ }
+ /*
+ * Keep track of how many entries have been retrieved.
+ */
+ entry->count++;
+
+ /*
+ * Ensure previous and current result match
+ * (with corresponding entries in both lists)
+ * and set the flags indicating which triggers are armed
+ */
+ if (vp2) {
+ cmp = snmp_oid_compare(vp1->name, vp1->name_length,
+ vp2->name, vp2->name_length);
+ if ( cmp < 0 ) {
+ /*
+ * If a new value has appeared, insert a matching
+ * dummy entry into the previous result list.
+ *
+ * XXX - check how this is best done.
+ */
+ vtmp = SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ if (!vtmp) {
+ _mteTrigger_failure(
+ "failed to create mteTrigger temp varbind");
+ snmp_free_varbind(var);
+ return;
+ }
+ vtmp->type = ASN_NULL;
+ snmp_set_var_objid( vtmp, vp1->name, vp1->name_length );
+ vtmp->next_variable = vp2;
+ if (vp2_prev) {
+ vp2_prev->next_variable = vtmp;
+ } else {
+ entry->old_results = vtmp;
+ }
+ vp2_prev = vtmp;
+ vp1->index = MTE_ARMED_ALL; /* XXX - plus a new flag */
+ vp1_prev = vp1;
+ vp1 = vp1->next_variable;
+ }
+ else if ( cmp == 0 ) {
+ /*
+ * If it's a continuing entry, just copy across the armed flags
+ */
+ vp1->index = vp2->index;
+ vp1_prev = vp1;
+ vp1 = vp1->next_variable;
+ vp2_prev = vp2;
+ vp2 = vp2->next_variable;
+ } else {
+ /*
+ * If a value has just disappeared, insert a
+ * matching dummy entry into the current result list.
+ *
+ * XXX - check how this is best done.
+ *
+ */
+ if ( vp2->type != ASN_NULL ) {
+ vtmp = SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ if (!vtmp) {
+ _mteTrigger_failure(
+ "failed to create mteTrigger temp varbind");
+ snmp_free_varbind(var);
+ return;
+ }
+ vtmp->type = ASN_NULL;
+ snmp_set_var_objid( vtmp, vp2->name, vp2->name_length );
+ vtmp->next_variable = vp1;
+ if (vp1_prev) {
+ vp1_prev->next_variable = vtmp;
+ } else {
+ var = vtmp;
+ }
+ vp1_prev = vtmp;
+ vp2_prev = vp2;
+ vp2 = vp2->next_variable;
+ } else {
+ /*
+ * But only if this entry has *just* disappeared. If the
+ * entry from the last run was a dummy too, then remove it.
+ * (leaving vp2_prev unchanged)
+ */
+ vtmp = vp2;
+ if (vp2_prev) {
+ vp2_prev->next_variable = vp2->next_variable;
+ } else {
+ entry->old_results = vp2->next_variable;
+ }
+ vp2 = vp2->next_variable;
+ vtmp->next_variable = NULL;
+ snmp_free_varbind( vtmp );
+ }
+ }
+ } else {
+ /*
+ * No more old results to compare.
+ * Either all remaining values have only just been created ...
+ * (and we need to create dummy 'old' entries for them)
+ */
+ if ( vp2_prev ) {
+ vtmp = SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ if (!vtmp) {
+ _mteTrigger_failure(
+ "failed to create mteTrigger temp varbind");
+ snmp_free_varbind(var);
+ return;
+ }
+ vtmp->type = ASN_NULL;
+ snmp_set_var_objid( vtmp, vp1->name, vp1->name_length );
+ vtmp->next_variable = vp2_prev->next_variable;
+ vp2_prev->next_variable = vtmp;
+ vp2_prev = vtmp;
+ }
+ /*
+ * ... or this is the first run through
+ * (and there were no old results at all)
+ *
+ * In either case, mark the current entry as armed and new.
+ * Note that we no longer need to maintain 'vp1_prev'
+ */
+ vp1->index = MTE_ARMED_ALL; /* XXX - plus a new flag */
+ vp1 = vp1->next_variable;
+ }
+ }
+
+ /*
+ * ... and then work through these result(s), deciding
+ * whether or not to trigger the corresponding event.
+ *
+ * Note that there's no point in evaluating Existence or
+ * Boolean tests if there's no corresponding event.
+ * (Even if the trigger matched, nothing would be done anyway).
+ */
+ if ((entry->mteTriggerTest & MTE_TRIGGER_EXISTENCE) &&
+ (entry->mteTExEvent[0] != '\0' )) {
+ /*
+ * If we don't have a record of previous results,
+ * this must be the first time through, so consider
+ * the mteTriggerExistenceStartup tests.
+ */
+ if ( !entry->old_results ) {
+ /*
+ * With the 'present(0)' test, the trigger should fire
+ * for each value in the varbind list returned
+ * (whether the monitored value is wildcarded or not).
+ */
+ if (entry->mteTExTest & entry->mteTExStartup & MTE_EXIST_PRESENT) {
+ for (vp1 = var; vp1; vp1=vp1->next_variable) {
+ DEBUGMSGTL(( "disman:event:trigger:fire",
+ "Firing initial existence test: "));
+ DEBUGMSGOID(("disman:event:trigger:fire",
+ vp1->name, vp1->name_length));
+ DEBUGMSG(( "disman:event:trigger:fire",
+ " (present)\n"));;
+ entry->mteTriggerXOwner = entry->mteTExObjOwner;
+ entry->mteTriggerXObjects = entry->mteTExObjects;
+ entry->mteTriggerFired = vp1;
+ n = entry->mteTriggerValueID_len;
+ mteEvent_fire(entry->mteTExEvOwner, entry->mteTExEvent,
+ entry, vp1->name+n, vp1->name_length-n);
+ }
+ }
+ /*
+ * An initial 'absent(1)' test only makes sense when
+ * monitoring a non-wildcarded OID (how would we know
+ * which rows of the table "ought" to exist, but don't?)
+ */
+ if (entry->mteTExTest & entry->mteTExStartup & MTE_EXIST_ABSENT) {
+ if (!(entry->flags & MTE_TRIGGER_FLAG_VWILD) &&
+ var->type == ASN_NULL ) {
+ DEBUGMSGTL(( "disman:event:trigger:fire",
+ "Firing initial existence test: "));
+ DEBUGMSGOID(("disman:event:trigger:fire",
+ var->name, var->name_length));
+ DEBUGMSG(( "disman:event:trigger:fire",
+ " (absent)\n"));;
+ entry->mteTriggerXOwner = entry->mteTExObjOwner;
+ entry->mteTriggerXObjects = entry->mteTExObjects;
+ /*
+ * It's unclear what value the 'mteHotValue' payload
+ * should take when a monitored instance does not
+ * exist on startup. The only sensible option is
+ * to report a NULL value, but this clashes with
+ * the syntax of the mteHotValue MIB object.
+ */
+ entry->mteTriggerFired = var;
+ n = entry->mteTriggerValueID_len;
+ mteEvent_fire(entry->mteTExEvOwner, entry->mteTExEvent,
+ entry, var->name+n, var->name_length-n);
+ }
+ }
+ } /* !old_results */
+ /*
+ * Otherwise, compare the current set of results with
+ * the previous ones, looking for changes. We can
+ * assume that the two lists match (see above).
+ */
+ else {
+ for (vp1 = var, vp2 = entry->old_results;
+ vp1;
+ vp1=vp1->next_variable, vp2=vp2->next_variable) {
+
+ /* Use this field to indicate that the trigger should fire */
+ entry->mteTriggerFired = NULL;
+ reason = NULL;
+
+ if ((entry->mteTExTest & MTE_EXIST_PRESENT) &&
+ (vp1->type != ASN_NULL) &&
+ (vp2->type == ASN_NULL)) {
+ /* A new instance has appeared */
+ entry->mteTriggerFired = vp1;
+ reason = "(present)";
+
+ } else if ((entry->mteTExTest & MTE_EXIST_ABSENT) &&
+ (vp1->type == ASN_NULL) &&
+ (vp2->type != ASN_NULL)) {
+
+ /*
+ * A previous instance has disappeared.
+ *
+ * It's unclear what value the 'mteHotValue' payload
+ * should take when this happens - the previous
+ * value (vp2), or a NULL value (vp1) ?
+ * NULL makes more sense logically, but clashes
+ * with the syntax of the mteHotValue MIB object.
+ */
+ entry->mteTriggerFired = vp2;
+ reason = "(absent)";
+
+ } else if ((entry->mteTExTest & MTE_EXIST_CHANGED) &&
+ ((vp1->val_len != vp2->val_len) ||
+ (memcmp( vp1->val.string, vp2->val.string,
+ vp1->val_len) != 0 ))) {
+ /*
+ * This comparison detects changes in *any* type
+ * of value, numeric or string (or even OID).
+ *
+ * Unfortunately, the default 'mteTriggerFired'
+ * notification payload can't report non-numeric
+ * changes properly (see syntax of 'mteHotValue')
+ */
+ entry->mteTriggerFired = vp1;
+ reason = "(changed)";
+ }
+ if ( entry->mteTriggerFired ) {
+ /*
+ * One of the above tests has matched,
+ * so fire the trigger.
+ */
+ DEBUGMSGTL(( "disman:event:trigger:fire",
+ "Firing existence test: "));
+ DEBUGMSGOID(("disman:event:trigger:fire",
+ vp1->name, vp1->name_length));
+ DEBUGMSG(( "disman:event:trigger:fire",
+ " %s\n", reason));;
+ entry->mteTriggerXOwner = entry->mteTExObjOwner;
+ entry->mteTriggerXObjects = entry->mteTExObjects;
+ n = entry->mteTriggerValueID_len;
+ mteEvent_fire(entry->mteTExEvOwner, entry->mteTExEvent,
+ entry, vp1->name+n, vp1->name_length-n);
+ }
+ }
+ } /* !old_results - end of else block */
+ } /* MTE_TRIGGER_EXISTENCE */
+
+
+ if (( entry->mteTriggerTest & MTE_TRIGGER_BOOLEAN ) ||
+ ( entry->mteTriggerTest & MTE_TRIGGER_THRESHOLD )) {
+ /*
+ * Although Existence tests can work with any syntax values,
+ * Boolean and Threshold tests are integer-only. Ensure that
+ * the returned value(s) are appropriate.
+ *
+ * Note that we only need to check the first value, since all
+ * instances of a given object should have the same syntax.
+ */
+ switch (var->type) {
+ case ASN_INTEGER:
+ case ASN_COUNTER:
+ case ASN_GAUGE:
+ case ASN_TIMETICKS:
+ case ASN_UINTEGER:
+ case ASN_COUNTER64:
+#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
+ case ASN_OPAQUE_COUNTER64:
+ case ASN_OPAQUE_U64:
+ case ASN_OPAQUE_I64:
+#endif
+ /* OK */
+ break;
+ default:
+ /*
+ * Other syntax values can't be used for Boolean/Theshold
+ * tests. Report this as an error, and then rotate the
+ * results ready for the next run, (which will presumably
+ * also detect this as an error once again!)
+ */
+ DEBUGMSGTL(( "disman:event:trigger:fire",
+ "Returned non-integer result(s): "));
+ DEBUGMSGOID(("disman:event:trigger:fire",
+ var->name, var->name_length));
+ DEBUGMSG(( "disman:event:trigger:fire",
+ " (boolean/threshold) %d\n", var->type));;
+ snmp_free_varbind( entry->old_results );
+ entry->old_results = var;
+ return;
+ }
+
+
+ /*
+ * Retrieve the discontinuity markers for delta-valued samples.
+ * (including sysUpTime.0 if not specified explicitly).
+ */
+ if ( entry->flags & MTE_TRIGGER_FLAG_DELTA ) {
+ /*
+ * We'll need sysUpTime.0 regardless...
+ */
+ DEBUGMSGTL(("disman:event:delta", "retrieve sysUpTime.0\n"));
+ memset( &sysUT_var, 0, sizeof( netsnmp_variable_list ));
+ snmp_set_var_objid( &sysUT_var, _sysUpTime_instance,
+ _sysUpTime_inst_len );
+ netsnmp_query_get( &sysUT_var, entry->session );
+
+ if (!(entry->flags & MTE_TRIGGER_FLAG_SYSUPT)) {
+ /*
+ * ... but only retrieve the configured discontinuity
+ * marker(s) if they refer to something different.
+ */
+ DEBUGMSGTL(( "disman:event:delta",
+ "retrieve discontinuity marker(s): "));
+ DEBUGMSGOID(("disman:event:delta", entry->mteDeltaDiscontID,
+ entry->mteDeltaDiscontID_len ));
+ DEBUGMSG(( "disman:event:delta", " %s\n",
+ (entry->flags & MTE_TRIGGER_FLAG_DWILD ? " (wild)" : "")));
+
+ dvar = (netsnmp_variable_list *)
+ SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ if (!dvar) {
+ _mteTrigger_failure(
+ "failed to create mteTrigger delta query varbind");
+ return;
+ }
+ snmp_set_var_objid( dvar, entry->mteDeltaDiscontID,
+ entry->mteDeltaDiscontID_len );
+ if ( entry->flags & MTE_TRIGGER_FLAG_DWILD ) {
+ n = netsnmp_query_walk( dvar, entry->session );
+ } else {
+ n = netsnmp_query_get( dvar, entry->session );
+ }
+ if ( n != SNMP_ERR_NOERROR ) {
+ _mteTrigger_failure( "failed to run mteTrigger delta query" );
+ snmp_free_varbind( dvar );
+ return;
+ }
+ }
+
+ /*
+ * We can't calculate delta values the first time through,
+ * so there's no point in evaluating the remaining tests.
+ *
+ * Save the results (and discontinuity markers),
+ * ready for the next run.
+ */
+ if ( !entry->old_results ) {
+ entry->old_results = var;
+ entry->old_deltaDs = dvar;
+ entry->sysUpTime = *sysUT_var.val.integer;
+ return;
+ }
+ /*
+ * If the sysUpTime marker has been reset (or strictly,
+ * has advanced by less than the monitor frequency),
+ * there's no point in trying the remaining tests.
+ */
+
+ if (*sysUT_var.val.integer < entry->sysUpTime) {
+ DEBUGMSGTL(( "disman:event:delta",
+ "single discontinuity: (sysUT)\n"));
+ snmp_free_varbind( entry->old_results );
+ snmp_free_varbind( entry->old_deltaDs );
+ entry->old_results = var;
+ entry->old_deltaDs = dvar;
+ entry->sysUpTime = *sysUT_var.val.integer;
+ return;
+ }
+ /*
+ * Similarly if a separate (non-wildcarded) discontinuity
+ * marker has changed, then there's no
+ * point in trying to evaluate these tests either.
+ */
+ if (!(entry->flags & MTE_TRIGGER_FLAG_DWILD) &&
+ !(entry->flags & MTE_TRIGGER_FLAG_SYSUPT) &&
+ (!entry->old_deltaDs ||
+ (entry->old_deltaDs->val.integer != dvar->val.integer))) {
+ DEBUGMSGTL(( "disman:event:delta", "single discontinuity: ("));
+ DEBUGMSGOID(( "disman:event:delta", entry->mteDeltaDiscontID,
+ entry->mteDeltaDiscontID_len));
+ DEBUGMSG(( "disman:event:delta", ")\n"));
+ snmp_free_varbind( entry->old_results );
+ snmp_free_varbind( entry->old_deltaDs );
+ entry->old_results = var;
+ entry->old_deltaDs = dvar;
+ entry->sysUpTime = *sysUT_var.val.integer;
+ return;
+ }
+
+ /*
+ * Ensure that the list of (wildcarded) discontinuity
+ * markers matches the list of monitored values
+ * (inserting/removing discontinuity varbinds as needed)
+ *
+ * XXX - An alternative approach would be to use the list
+ * of monitored values (instance subidentifiers) to build
+ * the exact list of delta markers to retrieve earlier.
+ */
+ if (entry->flags & MTE_TRIGGER_FLAG_DWILD) {
+ vp1 = var;
+ vp2 = dvar;
+ vp2_prev = NULL;
+ n = entry->mteTriggerValueID_len;
+ n2 = entry->mteDeltaDiscontID_len;
+ while (vp1) {
+ /*
+ * For each monitored instance, check whether
+ * there's a matching discontinuity entry.
+ */
+ cmp = snmp_oid_compare(vp1->name+n, vp1->name_length-n,
+ vp2->name+n2, vp2->name_length-n2 );
+ if ( cmp < 0 ) {
+ /*
+ * If a discontinuity entry is missing,
+ * insert a (dummy) varbind.
+ * The corresponding delta calculation will
+ * fail, but this simplifies the later code.
+ */
+ vtmp = (netsnmp_variable_list *)
+ SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ if (!vtmp) {
+ _mteTrigger_failure(
+ "failed to create mteTrigger discontinuity varbind");
+ snmp_free_varbind(dvar);
+ return;
+ }
+ snmp_set_var_objid(vtmp, entry->mteDeltaDiscontID,
+ entry->mteDeltaDiscontID_len);
+ /* XXX - append instance subids */
+ vtmp->next_variable = vp2;
+ vp2_prev->next_variable = vtmp;
+ vp2_prev = vtmp;
+ vp1 = vp1->next_variable;
+ } else if ( cmp == 0 ) {
+ /*
+ * Matching discontinuity entry - all OK.
+ */
+ vp2_prev = vp2;
+ vp2 = vp2->next_variable;
+ vp1 = vp1->next_variable;
+ } else {
+ /*
+ * Remove unneeded discontinuity entry
+ */
+ vtmp = vp2;
+ vp2_prev->next_variable = vp2->next_variable;
+ vp2 = vp2->next_variable;
+ vtmp->next_variable = NULL;
+ snmp_free_varbind( vtmp );
+ }
+ }
+ /*
+ * XXX - Now need to ensure that the old list of
+ * delta discontinuity markers matches as well.
+ */
+ }
+ } /* delta samples */
+ } /* Boolean/Threshold test checks */
+
+
+
+ /*
+ * Only run the Boolean tests if there's an event to be triggered
+ */
+ if ((entry->mteTriggerTest & MTE_TRIGGER_BOOLEAN) &&
+ (entry->mteTBoolEvent[0] != '\0' )) {
+
+ if (entry->flags & MTE_TRIGGER_FLAG_DELTA) {
+ vp2 = entry->old_results;
+ if (entry->flags & MTE_TRIGGER_FLAG_DWILD) {
+ dv1 = dvar;
+ dv2 = entry->old_deltaDs;
+ }
+ }
+ for ( vp1 = var; vp1; vp1=vp1->next_variable ) {
+ /*
+ * Determine the value to be monitored...
+ */
+ if ( !vp1->val.integer ) { /* No value */
+ if ( vp2 )
+ vp2 = vp2->next_variable;
+ continue;
+ }
+ if (entry->flags & MTE_TRIGGER_FLAG_DELTA) {
+ if (entry->flags & MTE_TRIGGER_FLAG_DWILD) {
+ /*
+ * We've already checked any non-wildcarded
+ * discontinuity markers (inc. sysUpTime.0).
+ * Validate this particular sample against
+ * the relevant wildcarded marker...
+ */
+ if ((dv1->type == ASN_NULL) ||
+ (dv1->type != dv2->type) ||
+ (*dv1->val.integer != *dv2->val.integer)) {
+ /*
+ * Bogus or changed discontinuity marker.
+ * Need to skip this sample.
+ */
+ DEBUGMSGTL(( "disman:event:delta", "discontinuity occurred: "));
+ DEBUGMSGOID(("disman:event:delta", vp1->name,
+ vp1->name_length ));
+ DEBUGMSG(( "disman:event:delta", " \n" ));
+ vp2 = vp2->next_variable;
+ continue;
+ }
+ }
+ /*
+ * ... and check there is a previous sample to calculate
+ * the delta value against (regardless of whether the
+ * discontinuity marker was wildcarded or not).
+ */
+ if (vp2->type == ASN_NULL) {
+ DEBUGMSGTL(( "disman:event:delta", "missing sample: "));
+ DEBUGMSGOID(("disman:event:delta", vp1->name,
+ vp1->name_length ));
+ DEBUGMSG(( "disman:event:delta", " \n" ));
+ vp2 = vp2->next_variable;
+ continue;
+ }
+ value = (*vp1->val.integer - *vp2->val.integer);
+ DEBUGMSGTL(( "disman:event:delta", "delta sample: "));
+ DEBUGMSGOID(("disman:event:delta", vp1->name,
+ vp1->name_length ));
+ DEBUGMSG(( "disman:event:delta", " (%ld - %ld) = %ld\n",
+ *vp1->val.integer, *vp2->val.integer, value));
+ vp2 = vp2->next_variable;
+ } else {
+ value = *vp1->val.integer;
+ }
+
+ /*
+ * ... evaluate the comparison ...
+ */
+ switch (entry->mteTBoolComparison) {
+ case MTE_BOOL_UNEQUAL:
+ cmp = ( value != entry->mteTBoolValue );
+ break;
+ case MTE_BOOL_EQUAL:
+ cmp = ( value == entry->mteTBoolValue );
+ break;
+ case MTE_BOOL_LESS:
+ cmp = ( value < entry->mteTBoolValue );
+ break;
+ case MTE_BOOL_LESSEQUAL:
+ cmp = ( value <= entry->mteTBoolValue );
+ break;
+ case MTE_BOOL_GREATER:
+ cmp = ( value > entry->mteTBoolValue );
+ break;
+ case MTE_BOOL_GREATEREQUAL:
+ cmp = ( value >= entry->mteTBoolValue );
+ break;
+ }
+ DEBUGMSGTL(( "disman:event:delta", "Bool comparison: (%ld %s %ld) %d\n",
+ value, _ops[entry->mteTBoolComparison],
+ entry->mteTBoolValue, cmp));
+
+ /*
+ * ... and decide whether to trigger the event.
+ * (using the 'index' field of the varbind structure
+ * to remember whether the trigger has already fired)
+ */
+ if ( cmp ) {
+ if (vp1->index & MTE_ARMED_BOOLEAN ) {
+ vp1->index &= ~MTE_ARMED_BOOLEAN;
+ /*
+ * NB: Clear the trigger armed flag even if the
+ * (starting) event dosn't actually fire.
+ * Otherwise initially true (but suppressed)
+ * triggers will fire on the *second* probe.
+ */
+ if ( entry->old_results ||
+ (entry->flags & MTE_TRIGGER_FLAG_BSTART)) {
+ DEBUGMSGTL(( "disman:event:trigger:fire",
+ "Firing boolean test: "));
+ DEBUGMSGOID(("disman:event:trigger:fire",
+ vp1->name, vp1->name_length));
+ DEBUGMSG(( "disman:event:trigger:fire", "%s\n",
+ (entry->old_results ? "" : " (startup)")));
+ entry->mteTriggerXOwner = entry->mteTBoolObjOwner;
+ entry->mteTriggerXObjects = entry->mteTBoolObjects;
+ /*
+ * XXX - when firing a delta-based trigger, should
+ * 'mteHotValue' report the actual value sampled
+ * (as here), or the delta that triggered the event ?
+ */
+ entry->mteTriggerFired = vp1;
+ n = entry->mteTriggerValueID_len;
+ mteEvent_fire(entry->mteTBoolEvOwner, entry->mteTBoolEvent,
+ entry, vp1->name+n, vp1->name_length-n);
+ }
+ }
+ } else {
+ vp1->index |= MTE_ARMED_BOOLEAN;
+ }
+ }
+ }
+
+
+ /*
+ * Only run the basic threshold tests if there's an event to
+ * be triggered. (Either rising or falling will do)
+ */
+ if (( entry->mteTriggerTest & MTE_TRIGGER_THRESHOLD ) &&
+ ((entry->mteTThRiseEvent[0] != '\0' ) ||
+ (entry->mteTThFallEvent[0] != '\0' ))) {
+
+ /*
+ * The same delta-sample validation from Boolean
+ * tests also applies here too.
+ */
+ if (entry->flags & MTE_TRIGGER_FLAG_DELTA) {
+ vp2 = entry->old_results;
+ if (entry->flags & MTE_TRIGGER_FLAG_DWILD) {
+ dv1 = dvar;
+ dv2 = entry->old_deltaDs;
+ }
+ }
+ for ( vp1 = var; vp1; vp1=vp1->next_variable ) {
+ /*
+ * Determine the value to be monitored...
+ */
+ if ( !vp1->val.integer ) { /* No value */
+ if ( vp2 )
+ vp2 = vp2->next_variable;
+ continue;
+ }
+ if (entry->flags & MTE_TRIGGER_FLAG_DELTA) {
+ if (entry->flags & MTE_TRIGGER_FLAG_DWILD) {
+ /*
+ * We've already checked any non-wildcarded
+ * discontinuity markers (inc. sysUpTime.0).
+ * Validate this particular sample against
+ * the relevant wildcarded marker...
+ */
+ if ((dv1->type == ASN_NULL) ||
+ (dv1->type != dv2->type) ||
+ (*dv1->val.integer != *dv2->val.integer)) {
+ /*
+ * Bogus or changed discontinuity marker.
+ * Need to skip this sample.
+ */
+ vp2 = vp2->next_variable;
+ continue;
+ }
+ }
+ /*
+ * ... and check there is a previous sample to calculate
+ * the delta value against (regardless of whether the
+ * discontinuity marker was wildcarded or not).
+ */
+ if (vp2->type == ASN_NULL) {
+ vp2 = vp2->next_variable;
+ continue;
+ }
+ value = (*vp1->val.integer - *vp2->val.integer);
+ vp2 = vp2->next_variable;
+ } else {
+ value = *vp1->val.integer;
+ }
+
+ /*
+ * ... evaluate the single-value comparisons,
+ * and decide whether to trigger the event.
+ */
+ cmp = vp1->index; /* working copy of 'armed' flags */
+ if ( value >= entry->mteTThRiseValue ) {
+ if (cmp & MTE_ARMED_TH_RISE ) {
+ cmp &= ~MTE_ARMED_TH_RISE;
+ cmp |= MTE_ARMED_TH_FALL;
+ /*
+ * NB: Clear the trigger armed flag even if the
+ * (starting) event dosn't actually fire.
+ * Otherwise initially true (but suppressed)
+ * triggers will fire on the *second* probe.
+ * Similarly for falling thresholds (see below).
+ */
+ if ( entry->old_results ||
+ (entry->mteTThStartup & MTE_THRESH_START_RISE)) {
+ DEBUGMSGTL(( "disman:event:trigger:fire",
+ "Firing rising threshold test: "));
+ DEBUGMSGOID(("disman:event:trigger:fire",
+ vp1->name, vp1->name_length));
+ DEBUGMSG(( "disman:event:trigger:fire", "%s\n",
+ (entry->old_results ? "" : " (startup)")));
+ /*
+ * If no riseEvent is configured, we need still to
+ * set the armed flags appropriately, but there's
+ * no point in trying to fire the (missing) event.
+ */
+ if (entry->mteTThRiseEvent[0] != '\0' ) {
+ entry->mteTriggerXOwner = entry->mteTThObjOwner;
+ entry->mteTriggerXObjects = entry->mteTThObjects;
+ entry->mteTriggerFired = vp1;
+ n = entry->mteTriggerValueID_len;
+ mteEvent_fire(entry->mteTThRiseOwner,
+ entry->mteTThRiseEvent,
+ entry, vp1->name+n, vp1->name_length-n);
+ }
+ }
+ }
+ }
+
+ if ( value <= entry->mteTThFallValue ) {
+ if (cmp & MTE_ARMED_TH_FALL ) {
+ cmp &= ~MTE_ARMED_TH_FALL;
+ cmp |= MTE_ARMED_TH_RISE;
+ /* Clear the trigger armed flag (see above) */
+ if ( entry->old_results ||
+ (entry->mteTThStartup & MTE_THRESH_START_FALL)) {
+ DEBUGMSGTL(( "disman:event:trigger:fire",
+ "Firing falling threshold test: "));
+ DEBUGMSGOID(("disman:event:trigger:fire",
+ vp1->name, vp1->name_length));
+ DEBUGMSG(( "disman:event:trigger:fire", "%s\n",
+ (entry->old_results ? "" : " (startup)")));
+ /*
+ * Similarly, if no fallEvent is configured,
+ * there's no point in trying to fire it either.
+ */
+ if (entry->mteTThRiseEvent[0] != '\0' ) {
+ entry->mteTriggerXOwner = entry->mteTThObjOwner;
+ entry->mteTriggerXObjects = entry->mteTThObjects;
+ entry->mteTriggerFired = vp1;
+ n = entry->mteTriggerValueID_len;
+ mteEvent_fire(entry->mteTThFallOwner,
+ entry->mteTThFallEvent,
+ entry, vp1->name+n, vp1->name_length-n);
+ }
+ }
+ }
+ }
+ vp1->index = cmp;
+ }
+ }
+
+ /*
+ * The same processing also works for delta-threshold tests (if configured)
+ */
+ if (( entry->mteTriggerTest & MTE_TRIGGER_THRESHOLD ) &&
+ ((entry->mteTThDRiseEvent[0] != '\0' ) ||
+ (entry->mteTThDFallEvent[0] != '\0' ))) {
+
+ /*
+ * Delta-threshold tests can only be used with
+ * absolute valued samples.
+ */
+ vp2 = entry->old_results;
+ if (entry->flags & MTE_TRIGGER_FLAG_DELTA) {
+ DEBUGMSGTL(( "disman:event:trigger",
+ "Delta-threshold on delta-sample\n"));
+ } else if ( vp2 != NULL ) {
+ for ( vp1 = var; vp1; vp1=vp1->next_variable ) {
+ /*
+ * Determine the value to be monitored...
+ * (similar to previous delta-sample processing,
+ * but without the discontinuity marker checks)
+ */
+ if (!vp2) {
+ break; /* Run out of 'old' values */
+ }
+ if (( !vp1->val.integer ) ||
+ (vp2->type == ASN_NULL)) {
+ vp2 = vp2->next_variable;
+ continue;
+ }
+ value = (*vp1->val.integer - *vp2->val.integer);
+ vp2 = vp2->next_variable;
+
+ /*
+ * ... evaluate the single-value comparisons,
+ * and decide whether to trigger the event.
+ */
+ cmp = vp1->index; /* working copy of 'armed' flags */
+ if ( value >= entry->mteTThDRiseValue ) {
+ if (vp1->index & MTE_ARMED_TH_DRISE ) {
+ DEBUGMSGTL(( "disman:event:trigger:fire",
+ "Firing rising delta threshold test: "));
+ DEBUGMSGOID(("disman:event:trigger:fire",
+ vp1->name, vp1->name_length));
+ DEBUGMSG(( "disman:event:trigger:fire", "\n"));
+ cmp &= ~MTE_ARMED_TH_DRISE;
+ cmp |= MTE_ARMED_TH_DFALL;
+ /*
+ * If no riseEvent is configured, we need still to
+ * set the armed flags appropriately, but there's
+ * no point in trying to fire the (missing) event.
+ */
+ if (entry->mteTThDRiseEvent[0] != '\0' ) {
+ entry->mteTriggerXOwner = entry->mteTThObjOwner;
+ entry->mteTriggerXObjects = entry->mteTThObjects;
+ entry->mteTriggerFired = vp1;
+ n = entry->mteTriggerValueID_len;
+ mteEvent_fire(entry->mteTThDRiseOwner,
+ entry->mteTThDRiseEvent,
+ entry, vp1->name+n, vp1->name_length-n);
+ }
+ }
+ }
+
+ if ( value <= entry->mteTThDFallValue ) {
+ if (vp1->index & MTE_ARMED_TH_DFALL ) {
+ DEBUGMSGTL(( "disman:event:trigger:fire",
+ "Firing falling delta threshold test: "));
+ DEBUGMSGOID(("disman:event:trigger:fire",
+ vp1->name, vp1->name_length));
+ DEBUGMSG(( "disman:event:trigger:fire", "\n"));
+ cmp &= ~MTE_ARMED_TH_DFALL;
+ cmp |= MTE_ARMED_TH_DRISE;
+ /*
+ * Similarly, if no fallEvent is configured,
+ * there's no point in trying to fire it either.
+ */
+ if (entry->mteTThDRiseEvent[0] != '\0' ) {
+ entry->mteTriggerXOwner = entry->mteTThObjOwner;
+ entry->mteTriggerXObjects = entry->mteTThObjects;
+ entry->mteTriggerFired = vp1;
+ n = entry->mteTriggerValueID_len;
+ mteEvent_fire(entry->mteTThDFallOwner,
+ entry->mteTThDFallEvent,
+ entry, vp1->name+n, vp1->name_length-n);
+ }
+ }
+ }
+ vp1->index = cmp;
+ }
+ }
+ }
+
+ /*
+ * Finally, rotate the results - ready for the next run.
+ */
+ snmp_free_varbind( entry->old_results );
+ entry->old_results = var;
+ if ( entry->flags & MTE_TRIGGER_FLAG_DELTA ) {
+ snmp_free_varbind( entry->old_deltaDs );
+ entry->old_deltaDs = dvar;
+ entry->sysUpTime = *sysUT_var.val.integer;
+ }
+}
+
+void
+mteTrigger_enable( struct mteTrigger *entry )
+{
+ if (!entry)
+ return;
+
+ if (entry->alarm) {
+ /* XXX - or explicitly call mteTrigger_disable ?? */
+ snmp_alarm_unregister( entry->alarm );
+ entry->alarm = 0;
+ }
+
+ if (entry->mteTriggerFrequency) {
+ /*
+ * register once to run ASAP, and another to run
+ * at the trigger frequency
+ */
+ snmp_alarm_register(0, 0, mteTrigger_run, entry );
+ entry->alarm = snmp_alarm_register(
+ entry->mteTriggerFrequency, SA_REPEAT,
+ mteTrigger_run, entry );
+ }
+}
+
+void
+mteTrigger_disable( struct mteTrigger *entry )
+{
+ if (!entry)
+ return;
+
+ if (entry->alarm) {
+ snmp_alarm_unregister( entry->alarm );
+ entry->alarm = 0;
+ /* XXX - perhaps release any previous results */
+ }
+}
+
+long _mteTrigger_MaxCount = 0;
+long _mteTrigger_countEntries(void)
+{
+ struct mteTrigger *entry;
+ netsnmp_tdata_row *row;
+ long count = 0;
+
+ for (row = netsnmp_tdata_row_first(trigger_table_data);
+ row;
+ row = netsnmp_tdata_row_next(trigger_table_data, row)) {
+ entry = (struct mteTrigger *)row->data;
+ count += entry->count;
+ }
+
+ return count;
+}
+
+long mteTrigger_getNumEntries(int max)
+{
+ long count;
+ /* XXX - implement some form of caching ??? */
+ count = _mteTrigger_countEntries();
+ if ( count > _mteTrigger_MaxCount )
+ _mteTrigger_MaxCount = count;
+
+ return ( max ? _mteTrigger_MaxCount : count);
+}
diff --git a/agent/mibgroup/disman/event/mteTrigger.h b/agent/mibgroup/disman/event/mteTrigger.h
new file mode 100644
index 0000000..19626b1
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTrigger.h
@@ -0,0 +1,199 @@
+#ifndef MTETRIGGER_H
+#define MTETRIGGER_H
+
+extern oid _sysUpTime_instance[];
+extern size_t _sysUpTime_inst_len;
+ /*
+ * Flags relating to the mteTriggerTable and related tables
+ */
+#define MTE_TRIGGER_FLAG_DELTA 0x01 /* for mteTriggerSampleType */
+#define MTE_TRIGGER_FLAG_VWILD 0x02 /* for mteTriggerValueIDWildcard */
+#define MTE_TRIGGER_FLAG_CWILD 0x04 /* for mteTriggerContextWildcard */
+#define MTE_TRIGGER_FLAG_DWILD 0x08 /* for mteTriggerDeltaDIDWildcard */
+#define MTE_TRIGGER_FLAG_SYSUPT 0x10 /* using default mteTriggerDeltaID */
+
+#define MTE_TRIGGER_FLAG_BSTART 0x20 /* for mteTriggerBooleanStartup */
+
+#define MTE_TRIGGER_FLAG_ENABLED 0x0100 /* for mteTriggerEnabled */
+#define MTE_TRIGGER_FLAG_ACTIVE 0x0200 /* for mteTriggerEntryStatus */
+#define MTE_TRIGGER_FLAG_FIXED 0x0400 /* for snmpd.conf persistence */
+#define MTE_TRIGGER_FLAG_VALID 0x0800 /* for row creation/undo */
+
+
+ /*
+ * Values for the mteTriggerTest field
+ */
+#define MTE_TRIGGER_EXISTENCE 0x80 /* mteTriggerTest values */
+#define MTE_TRIGGER_BOOLEAN 0x40
+#define MTE_TRIGGER_THRESHOLD 0x20
+
+ /*
+ * Values for the mteTriggerSampleType field
+ */
+#define MTE_SAMPLE_ABSOLUTE 1 /* mteTriggerSampleType values */
+#define MTE_SAMPLE_DELTA 2
+
+ /*
+ * Values for the mteTriggerDeltaDiscontinuityIDType field
+ */
+#define MTE_DELTAD_TTICKS 1
+#define MTE_DELTAD_TSTAMP 2
+#define MTE_DELTAD_DATETIME 3
+
+ /*
+ * Values for the mteTriggerExistenceTest
+ * and mteTriggerExistenceStartup fields
+ */
+#define MTE_EXIST_PRESENT 0x80
+#define MTE_EXIST_ABSENT 0x40
+#define MTE_EXIST_CHANGED 0x20
+
+ /*
+ * Values for the mteTriggerBooleanComparison field
+ */
+#define MTE_BOOL_UNEQUAL 1
+#define MTE_BOOL_EQUAL 2
+#define MTE_BOOL_LESS 3
+#define MTE_BOOL_LESSEQUAL 4
+#define MTE_BOOL_GREATER 5
+#define MTE_BOOL_GREATEREQUAL 6
+
+ /*
+ * Values for the mteTriggerThresholdStartup field
+ */
+#define MTE_THRESH_START_RISE 1
+#define MTE_THRESH_START_FALL 2
+#define MTE_THRESH_START_RISEFALL 3
+ /* Note that RISE and FALL values can be used for bit-wise
+ tests as well, since RISEFALL = RISE | FALL */
+
+
+ /*
+ * Flags to indicate which triggers are armed, and ready to fire.
+ */
+#define MTE_ARMED_TH_RISE 0x01
+#define MTE_ARMED_TH_FALL 0x02
+#define MTE_ARMED_TH_DRISE 0x04
+#define MTE_ARMED_TH_DFALL 0x08
+#define MTE_ARMED_BOOLEAN 0x10
+#define MTE_ARMED_ALL 0x1f
+
+ /*
+ * All Event-MIB OCTET STRING objects are either short (32-character)
+ * tags, or SnmpAdminString/similar values (i.e. 255 characters)
+ */
+#define MTE_STR1_LEN 32
+#define MTE_STR2_LEN 255
+
+/*
+ * Data structure for a (combined) trigger row. Covers delta samples,
+ * and all types (Existence, Boolean and Threshold) of trigger.
+ */
+struct mteTrigger {
+ /*
+ * Index values
+ */
+ char mteOwner[MTE_STR1_LEN+1];
+ char mteTName[MTE_STR1_LEN+1];
+
+ /*
+ * Column values for the main mteTriggerTable
+ */
+ char mteTriggerComment[MTE_STR2_LEN+1];
+ char mteTriggerTest;
+ oid mteTriggerValueID[MAX_OID_LEN];
+ size_t mteTriggerValueID_len;
+ char mteTriggerTarget[ MTE_STR2_LEN+1];
+ char mteTriggerContext[MTE_STR2_LEN+1];
+ u_long mteTriggerFrequency;
+ char mteTriggerOOwner[ MTE_STR1_LEN+1];
+ char mteTriggerObjects[MTE_STR1_LEN+1];
+
+ netsnmp_session *session;
+ long flags;
+
+ /*
+ * Column values for the mteTriggerDeltaTable
+ */
+ oid mteDeltaDiscontID[MAX_OID_LEN];
+ size_t mteDeltaDiscontID_len;
+ long mteDeltaDiscontIDType;
+
+ /*
+ * Column values for Existence tests (mteTriggerExistenceTable)
+ */
+ u_char mteTExTest;
+ u_char mteTExStartup;
+ char mteTExObjOwner[MTE_STR1_LEN+1];
+ char mteTExObjects[ MTE_STR1_LEN+1];
+ char mteTExEvOwner[ MTE_STR1_LEN+1];
+ char mteTExEvent[ MTE_STR1_LEN+1];
+
+ /*
+ * Column values for Boolean tests (mteTriggerBooleanTable)
+ */
+ long mteTBoolComparison;
+ long mteTBoolValue;
+ char mteTBoolObjOwner[MTE_STR1_LEN+1];
+ char mteTBoolObjects[ MTE_STR1_LEN+1];
+ char mteTBoolEvOwner[ MTE_STR1_LEN+1];
+ char mteTBoolEvent[ MTE_STR1_LEN+1];
+
+ /*
+ * Column values for Threshold tests (mteTriggerThresholdTable)
+ */
+ long mteTThStartup;
+ long mteTThRiseValue;
+ long mteTThFallValue;
+ long mteTThDRiseValue;
+ long mteTThDFallValue;
+ char mteTThObjOwner[ MTE_STR1_LEN+1];
+ char mteTThObjects[ MTE_STR1_LEN+1];
+ char mteTThRiseOwner[ MTE_STR1_LEN+1];
+ char mteTThRiseEvent[ MTE_STR1_LEN+1];
+ char mteTThFallOwner[ MTE_STR1_LEN+1];
+ char mteTThFallEvent[ MTE_STR1_LEN+1];
+ char mteTThDRiseOwner[MTE_STR1_LEN+1];
+ char mteTThDRiseEvent[MTE_STR1_LEN+1];
+ char mteTThDFallOwner[MTE_STR1_LEN+1];
+ char mteTThDFallEvent[MTE_STR1_LEN+1];
+
+ /*
+ * Additional fields for operation of the Trigger tables:
+ * monitoring...
+ */
+ unsigned int alarm;
+ long sysUpTime;
+ netsnmp_variable_list *old_results;
+ netsnmp_variable_list *old_deltaDs;
+
+ /*
+ * ... stats...
+ */
+ long count;
+
+ /*
+ * ... and firing.
+ */
+ char *mteTriggerXOwner;
+ char *mteTriggerXObjects;
+ netsnmp_variable_list *mteTriggerFired;
+};
+
+ /*
+ * Container structure for the (combined) mteTrigger*Tables,
+ * and routine to create this.
+ */
+extern netsnmp_tdata *trigger_table_data;
+extern void init_trigger_table_data(void);
+
+void init_mteTrigger(void);
+void mteTrigger_removeEntry(netsnmp_tdata_row *row);
+netsnmp_tdata_row *mteTrigger_createEntry(const char *mteOwner,
+ char *mteTriggerName, int fixed);
+void mteTrigger_enable( struct mteTrigger *entry );
+void mteTrigger_disable( struct mteTrigger *entry );
+
+long mteTrigger_getNumEntries(int max);
+
+#endif /* MTETRIGGER_H */
diff --git a/agent/mibgroup/disman/event/mteTriggerBooleanTable.c b/agent/mibgroup/disman/event/mteTriggerBooleanTable.c
new file mode 100644
index 0000000..ed1ec30
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTriggerBooleanTable.c
@@ -0,0 +1,315 @@
+/*
+ * DisMan Event MIB:
+ * Implementation of the mteTriggerBooleanTable MIB interface
+ * See 'mteTrigger.c' for active behaviour of this table.
+ *
+ * (based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "disman/event/mteTrigger.h"
+#include "disman/event/mteTriggerBooleanTable.h"
+
+netsnmp_feature_require(table_tdata)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(check_vb_type_and_max_size)
+netsnmp_feature_require(check_vb_truthvalue)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+static netsnmp_table_registration_info *table_info;
+
+/** Initializes the mteTriggerBooleanTable module */
+void
+init_mteTriggerBooleanTable(void)
+{
+ static oid mteTBoolTable_oid[] = { 1, 3, 6, 1, 2, 1, 88, 1, 2, 5 };
+ size_t mteTBoolTable_oid_len = OID_LENGTH(mteTBoolTable_oid);
+ netsnmp_handler_registration *reg;
+
+ /*
+ * Ensure the (combined) table container is available...
+ */
+ init_trigger_table_data();
+
+ /*
+ * ... then set up the MIB interface to the mteTriggerBooleanTable slice
+ */
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ reg = netsnmp_create_handler_registration("mteTriggerBooleanTable",
+ mteTriggerBooleanTable_handler,
+ mteTBoolTable_oid,
+ mteTBoolTable_oid_len,
+ HANDLER_CAN_RWRITE);
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+ reg = netsnmp_create_handler_registration("mteTriggerBooleanTable",
+ mteTriggerBooleanTable_handler,
+ mteTBoolTable_oid,
+ mteTBoolTable_oid_len,
+ HANDLER_CAN_RWRITE);
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_OCTET_STR, /* index: mteOwner */
+ /* index: mteTriggerName */
+ ASN_PRIV_IMPLIED_OCTET_STR,
+ 0);
+
+ table_info->min_column = COLUMN_MTETRIGGERBOOLEANCOMPARISON;
+ table_info->max_column = COLUMN_MTETRIGGERBOOLEANEVENT;
+
+ /* Register this using the (common) trigger_table_data container */
+ netsnmp_tdata_register(reg, trigger_table_data, table_info);
+ DEBUGMSGTL(("disman:event:init", "Trigger Bool Table\n"));
+}
+
+void
+shutdown_mteTriggerBooleanTable(void)
+{
+ if (table_info) {
+ netsnmp_table_registration_info_free(table_info);
+ table_info = NULL;
+ }
+}
+
+/** handles requests for the mteTriggerBooleanTable table */
+int
+mteTriggerBooleanTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ struct mteTrigger *entry;
+ int ret;
+
+ DEBUGMSGTL(("disman:event:mib", "Boolean Table handler (%d)\n",
+ reqinfo->mode));
+
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ /*
+ * The mteTriggerBooleanTable should only contains entries for
+ * rows where the mteTriggerTest 'boolean(1)' bit is set.
+ * So skip entries where this isn't the case.
+ */
+ if (!entry || !(entry->mteTriggerTest & MTE_TRIGGER_BOOLEAN )) {
+ netsnmp_request_set_error(request, SNMP_NOSUCHINSTANCE);
+ continue;
+ }
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERBOOLEANCOMPARISON:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->mteTBoolComparison);
+ break;
+ case COLUMN_MTETRIGGERBOOLEANVALUE:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->mteTBoolValue);
+ break;
+ case COLUMN_MTETRIGGERBOOLEANSTARTUP:
+ ret = (entry->flags & MTE_TRIGGER_FLAG_BSTART ) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_MTETRIGGERBOOLEANOBJECTSOWNER:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTBoolObjOwner,
+ strlen(entry->mteTBoolObjOwner));
+ break;
+ case COLUMN_MTETRIGGERBOOLEANOBJECTS:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTBoolObjects,
+ strlen(entry->mteTBoolObjects));
+ break;
+ case COLUMN_MTETRIGGERBOOLEANEVENTOWNER:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTBoolEvOwner,
+ strlen(entry->mteTBoolEvOwner));
+ break;
+ case COLUMN_MTETRIGGERBOOLEANEVENT:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTBoolEvent,
+ strlen(entry->mteTBoolEvent));
+ break;
+ }
+ }
+ break;
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ /*
+ * Write-support
+ */
+ case MODE_SET_RESERVE1:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ /*
+ * Since the mteTriggerBooleanTable only contains entries for
+ * rows where the mteTriggerTest 'boolean(1)' bit is set,
+ * strictly speaking we should reject assignments where
+ * this isn't the case.
+ * But SET requests that include an assignment of the
+ * 'boolean(1)' bit at the same time are valid, so would
+ * need to be accepted. Unfortunately, this assignment
+ * is only applied in the COMMIT pass, so it's difficult
+ * to detect whether this holds or not.
+ *
+ * Let's fudge things for now, by processing assignments
+ * even if the 'boolean(1)' bit isn't set.
+ */
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERBOOLEANCOMPARISON:
+ ret = netsnmp_check_vb_int_range(request->requestvb,
+ MTE_BOOL_UNEQUAL, MTE_BOOL_GREATEREQUAL);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGERBOOLEANVALUE:
+ ret = netsnmp_check_vb_int(request->requestvb);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGERBOOLEANSTARTUP:
+ ret = netsnmp_check_vb_truthvalue(request->requestvb);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGERBOOLEANOBJECTSOWNER:
+ case COLUMN_MTETRIGGERBOOLEANOBJECTS:
+ case COLUMN_MTETRIGGERBOOLEANEVENTOWNER:
+ case COLUMN_MTETRIGGERBOOLEANEVENT:
+ ret = netsnmp_check_vb_type_and_max_size(
+ request->requestvb, ASN_OCTET_STR, MTE_STR1_LEN);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ default:
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOTWRITABLE);
+ return SNMP_ERR_NOERROR;
+ }
+
+ /*
+ * The Event MIB is somewhat ambiguous as to whether the
+ * various trigger table entries can be modified once the
+ * main mteTriggerTable entry has been marked 'active'.
+ * But it's clear from discussion on the DisMan mailing
+ * list is that the intention is not.
+ *
+ * So check for whether this row is already active,
+ * and reject *all* SET requests if it is.
+ */
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ if (entry &&
+ entry->flags & MTE_TRIGGER_FLAG_ACTIVE ) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_RESERVE2:
+ case MODE_SET_FREE:
+ case MODE_SET_UNDO:
+ break;
+
+ case MODE_SET_ACTION:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ if (!entry) {
+ /*
+ * New rows must be created via the RowStatus column
+ * (in the main mteTriggerTable)
+ */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ /* or inconsistentName? */
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * All these assignments are "unfailable", so it's
+ * (reasonably) safe to apply them in the Commit phase
+ */
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERBOOLEANCOMPARISON:
+ entry->mteTBoolComparison = *request->requestvb->val.integer;
+ break;
+ case COLUMN_MTETRIGGERBOOLEANVALUE:
+ entry->mteTBoolValue = *request->requestvb->val.integer;
+ break;
+ case COLUMN_MTETRIGGERBOOLEANSTARTUP:
+ if (*request->requestvb->val.integer == TV_TRUE)
+ entry->flags |= MTE_TRIGGER_FLAG_BSTART;
+ else
+ entry->flags &= ~MTE_TRIGGER_FLAG_BSTART;
+ break;
+ case COLUMN_MTETRIGGERBOOLEANOBJECTSOWNER:
+ memset(entry->mteTBoolObjOwner, 0, sizeof(entry->mteTBoolObjOwner));
+ memcpy(entry->mteTBoolObjOwner, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERBOOLEANOBJECTS:
+ memset(entry->mteTBoolObjects, 0, sizeof(entry->mteTBoolObjects));
+ memcpy(entry->mteTBoolObjects, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERBOOLEANEVENTOWNER:
+ memset(entry->mteTBoolEvOwner, 0, sizeof(entry->mteTBoolEvOwner));
+ memcpy(entry->mteTBoolEvOwner, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERBOOLEANEVENT:
+ memset(entry->mteTBoolEvent, 0, sizeof(entry->mteTBoolEvent));
+ memcpy(entry->mteTBoolEvent, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ }
+ }
+ break;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ }
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/event/mteTriggerBooleanTable.h b/agent/mibgroup/disman/event/mteTriggerBooleanTable.h
new file mode 100644
index 0000000..f2ddd77
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTriggerBooleanTable.h
@@ -0,0 +1,25 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.table_data.conf,v 1.8 2005/07/19 14:52:03 dts12 Exp $
+ */
+#ifndef MTETRIGGERBOOLEANTABLE_H
+#define MTETRIGGERBOOLEANTABLE_H
+
+/*
+ * function declarations
+ */
+void init_mteTriggerBooleanTable(void);
+void shutdown_mteTriggerBooleanTable(void);
+Netsnmp_Node_Handler mteTriggerBooleanTable_handler;
+
+/*
+ * column number definitions for table mteTriggerBooleanTable
+ */
+#define COLUMN_MTETRIGGERBOOLEANCOMPARISON 1
+#define COLUMN_MTETRIGGERBOOLEANVALUE 2
+#define COLUMN_MTETRIGGERBOOLEANSTARTUP 3
+#define COLUMN_MTETRIGGERBOOLEANOBJECTSOWNER 4
+#define COLUMN_MTETRIGGERBOOLEANOBJECTS 5
+#define COLUMN_MTETRIGGERBOOLEANEVENTOWNER 6
+#define COLUMN_MTETRIGGERBOOLEANEVENT 7
+#endif /* MTETRIGGERBOOLEANTABLE_H */
diff --git a/agent/mibgroup/disman/event/mteTriggerConf.c b/agent/mibgroup/disman/event/mteTriggerConf.c
new file mode 100644
index 0000000..e7bb69b
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTriggerConf.c
@@ -0,0 +1,1489 @@
+/*
+ * DisMan Event MIB:
+ * Implementation of the trigger table configure handling
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/agent_callbacks.h>
+#include "utilities/iquery.h"
+#include "disman/event/mteObjects.h"
+#include "disman/event/mteTrigger.h"
+#include "disman/event/mteTriggerConf.h"
+
+#include <ctype.h>
+
+netsnmp_feature_require(iquery)
+
+/** Initializes the mteTriggerConf module */
+void
+init_mteTriggerConf(void)
+{
+ init_trigger_table_data();
+
+ /*
+ * Register config handler for user-level (fixed) triggers ...
+ */
+ snmpd_register_const_config_handler("monitor",
+ parse_mteMonitor,
+ NULL,
+ "triggername [-I] [-i OID | -o OID]* [-e event] expression ");
+ snmpd_register_const_config_handler("defaultMonitors",
+ parse_default_mteMonitors,
+ NULL, "yes|no");
+ snmpd_register_const_config_handler("linkUpDownNotifications",
+ parse_linkUpDown_traps,
+ NULL, "yes|no");
+
+ /*
+ * ... for persistent storage of various event table entries ...
+ */
+ snmpd_register_config_handler("_mteTTable",
+ parse_mteTTable, NULL, NULL);
+ snmpd_register_config_handler("_mteTDTable",
+ parse_mteTDTable, NULL, NULL);
+ snmpd_register_config_handler("_mteTExTable",
+ parse_mteTExTable, NULL, NULL);
+ snmpd_register_config_handler("_mteTBlTable",
+ parse_mteTBlTable, NULL, NULL);
+ snmpd_register_config_handler("_mteTThTable",
+ parse_mteTThTable, NULL, NULL);
+
+ /*
+ * ... and backwards compatability with the previous implementation.
+ */
+ snmpd_register_config_handler("mteTriggerTable",
+ parse_mteTriggerTable, NULL, NULL);
+
+ /*
+ * Register to save (non-fixed) entries when the agent shuts down
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_mteTTable, NULL);
+ snmp_register_callback(SNMP_CALLBACK_APPLICATION,
+ SNMPD_CALLBACK_PRE_UPDATE_CONFIG,
+ clear_mteTTable, NULL);
+}
+
+/* ==============================
+ *
+ * utility routines
+ *
+ * ============================== */
+
+ /*
+ * Find or create the specified trigger entry
+ */
+struct mteTrigger *
+_find_mteTrigger_entry( const char *owner, char *tname )
+{
+ netsnmp_variable_list owner_var, tname_var;
+ netsnmp_tdata_row *row;
+
+ /*
+ * If there's already an existing entry,
+ * then use that...
+ */
+ memset(&owner_var, 0, sizeof(netsnmp_variable_list));
+ memset(&tname_var, 0, sizeof(netsnmp_variable_list));
+ snmp_set_var_typed_value(&owner_var, ASN_OCTET_STR, owner, strlen(owner));
+ snmp_set_var_typed_value(&tname_var, ASN_PRIV_IMPLIED_OCTET_STR,
+ tname, strlen(tname));
+ owner_var.next_variable = &tname_var;
+ row = netsnmp_tdata_row_get_byidx( trigger_table_data, &owner_var );
+ /*
+ * ... otherwise, create a new one
+ */
+ if (!row)
+ row = mteTrigger_createEntry( owner, tname, 0 );
+ if (!row)
+ return NULL;
+
+ /* return (struct mteTrigger *)netsnmp_tdata_row_entry( row ); */
+ return (struct mteTrigger *)row->data;
+}
+
+struct mteTrigger *
+_find_typed_mteTrigger_entry( const char *owner, char *tname, int type )
+{
+ struct mteTrigger *entry = _find_mteTrigger_entry( owner, tname );
+ if (!entry)
+ return NULL;
+
+ /*
+ * If this is an existing (i.e. valid) entry of the
+ * same type, then throw an error and discard it.
+ * But allow combined Existence/Boolean/Threshold trigger.
+ */
+ if ( entry &&
+ (entry->flags & MTE_TRIGGER_FLAG_VALID) &&
+ (entry->mteTriggerTest & type )) {
+ config_perror("duplicate trigger name");
+ return NULL;
+ }
+ return entry;
+}
+
+
+/* ================================================
+ *
+ * Handlers for user-configured (static) triggers
+ *
+ * ================================================ */
+
+int
+_mteTrigger_callback_enable( int majorID, int minorID,
+ void *serverargs, void *clientarg)
+{
+ struct mteTrigger *entry = (struct mteTrigger *)clientarg;
+ mteTrigger_enable( entry );
+
+ return 0;
+}
+
+
+void
+parse_mteMonitor(const char *token, const char *line)
+{
+ char buf[ SPRINT_MAX_LEN];
+ char tname[MTE_STR1_LEN+1];
+ const char *cp;
+ long test = 0;
+
+ char ename[MTE_STR1_LEN+1];
+ long flags = MTE_TRIGGER_FLAG_ENABLED |
+ MTE_TRIGGER_FLAG_ACTIVE |
+ MTE_TRIGGER_FLAG_FIXED |
+ MTE_TRIGGER_FLAG_VWILD |
+ MTE_TRIGGER_FLAG_SYSUPT |
+ MTE_TRIGGER_FLAG_VALID;
+ long idx = 0;
+ long startup = 1; /* ??? or 0 */
+ long repeat = 600;
+ netsnmp_session *sess = NULL;
+
+ int seen_name = 0;
+ char oid_name_buf[SPRINT_MAX_LEN];
+ oid name_buf[MAX_OID_LEN];
+ size_t name_buf_len;
+ u_char op = 0;
+ long value = 0;
+
+ struct mteObject *object;
+ struct mteTrigger *entry;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing disman monitor config (%s)\n", line));
+
+ /*
+ * Before parsing the configuration fully, first
+ * skim through the config line in order to:
+ * a) locate the name for the trigger, and
+ * b) identify the type of trigger test
+ *
+ * This information will be used both for creating the trigger
+ * entry, and registering any additional payload objects.
+ */
+ memset( buf, 0, sizeof(buf));
+ memset( tname, 0, sizeof(tname));
+ memset( ename, 0, sizeof(ename));
+ for (cp = copy_nword_const(line, buf, SPRINT_MAX_LEN);
+ ;
+ cp = copy_nword_const(cp, buf, SPRINT_MAX_LEN)) {
+
+ if ( buf[0] == '-' ) {
+ switch (buf[1]) {
+ case 't':
+ /* No longer necessary */
+ break;
+ case 'd':
+ case 'e':
+ case 'o':
+ case 'r':
+ case 'u':
+ /* skip option parameter */
+ cp = skip_token_const( cp );
+ break;
+ case 'D':
+ case 'I':
+ case 's':
+ case 'S':
+ /* flag options */
+ break;
+ case 'i':
+ /*
+ * '-i' can act as a flag or take a parameter.
+ * Handle either case.
+ */
+ if (cp && *cp != '-')
+ cp = skip_token_const( cp );
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* accept negative values */
+ case '\0':
+ /* and '-' placeholder value */
+ break;
+ default:
+ config_perror("unrecognised option");
+ return;
+ }
+ } else {
+ /*
+ * Save the first non-option parameter as the trigger name.
+ *
+ * This name will also be used to register entries in the
+ * mteObjectsTable, so insert a distinguishing prefix.
+ * This will ensure combined trigger entries don't clash with
+ * each other, or with a similarly-named notification event.
+ */
+ if ( !tname[0] ) {
+ tname[0] = '_';
+ tname[1] = '_'; /* Placeholder */
+ memcpy( tname+2, buf, MTE_STR1_LEN-2 );
+ } else {
+ /*
+ * This marks the beginning of the monitor expression,
+ * so we don't need to scan any further
+ */
+ break;
+ }
+ }
+ if (!cp)
+ break;
+ }
+
+ /*
+ * Now let's examine the expression to determine the type of
+ * monitor being configured. There are four possible forms:
+ * != OID (or ! OID) (existence test)
+ * OID (existence test)
+ * OID op VALUE (boolean test)
+ * OID MIN MAX (threshold test)
+ */
+ if ( *buf == '!' ) {
+ /*
+ * If the expression starts with '!=' or '!', then
+ * it must be the first style of existence test.
+ */
+ test = MTE_TRIGGER_EXISTENCE;
+ } else {
+ /*
+ * Otherwise the first token is the OID to be monitored.
+ * Skip it and look at the next token (if any).
+ */
+ cp = copy_nword_const(cp, buf, SPRINT_MAX_LEN);
+ if (cp) {
+ /*
+ * If this is a numeric value, then it'll be the MIN
+ * field of a threshold test (the fourth form)
+ * Otherwise it'll be the operation field of a
+ * boolean test (the third form)
+ */
+ if ( isdigit((unsigned char)(buf[0])) || buf[0] == '-' )
+ test = MTE_TRIGGER_THRESHOLD;
+ else
+ test = MTE_TRIGGER_BOOLEAN;
+ } else {
+ /*
+ * If there isn't a "next token", then this
+ * must be the second style of existence test.
+ */
+ test = MTE_TRIGGER_EXISTENCE;
+ }
+ }
+
+ /*
+ * Use the type of trigger test to update the trigger name buffer
+ */
+ switch (test) {
+ case MTE_TRIGGER_BOOLEAN:
+ tname[1] = 'B'; break;
+ case MTE_TRIGGER_THRESHOLD:
+ tname[1] = 'T'; break;
+ case MTE_TRIGGER_EXISTENCE:
+ tname[1] = 'X'; break;
+ }
+
+
+
+ /*
+ * Now start parsing again at the beginning of the directive,
+ * extracting the various options...
+ */
+ for (cp = copy_nword_const(line, buf, SPRINT_MAX_LEN);
+ ;
+ cp = copy_nword_const(cp, buf, SPRINT_MAX_LEN)) {
+
+ if (buf[0] == '-' ) {
+ switch (buf[1]) {
+ case 'D': /* delta sample value */
+ flags |= MTE_TRIGGER_FLAG_DELTA;
+ break;
+
+ case 'd': /* discontinuity OID (implies delta sample) */
+ flags |= MTE_TRIGGER_FLAG_DELTA;
+ if (buf[2] != 'i')
+ flags |= MTE_TRIGGER_FLAG_DWILD;
+ memset( oid_name_buf, 0, sizeof(oid_name_buf));
+ memset( name_buf, 0, sizeof( name_buf));
+ name_buf_len = MAX_OID_LEN;
+ cp = copy_nword_const(cp, oid_name_buf, MTE_STR1_LEN);
+ if (!snmp_parse_oid(oid_name_buf, name_buf, &name_buf_len)) {
+ snmp_log(LOG_ERR, "discontinuity OID: %s\n", oid_name_buf);
+ config_perror("unknown discontinuity OID");
+ mteObjects_removeEntries( "snmpd.conf", tname );
+ return;
+ }
+ if ( snmp_oid_compare( name_buf, name_buf_len,
+ _sysUpTime_instance,
+ _sysUpTime_inst_len) != 0 )
+ flags &= ~MTE_TRIGGER_FLAG_SYSUPT;
+ break;
+
+ case 'e': /* event */
+ cp = copy_nword_const(cp, ename, MTE_STR1_LEN);
+ break;
+
+ case 'I': /* value instance */
+ flags &= ~MTE_TRIGGER_FLAG_VWILD;
+ break;
+
+ /*
+ * "instance" flag:
+ * either non-wildcarded mteTriggerValueID
+ * (backwards compatability - see '-I')
+ * or exact payload OID
+ * (c.f. notificationEvent config)
+ */
+ case 'i':
+ if ( *cp == '-' ) {
+ /* Backwards compatibility - now '-I' */
+ flags &= ~MTE_TRIGGER_FLAG_VWILD;
+ continue;
+ }
+ idx++;
+ cp = copy_nword_const(cp, buf, SPRINT_MAX_LEN);
+ object = mteObjects_addOID( "snmpd.conf", tname, idx, buf, 0 );
+ if (!object) {
+ snmp_log(LOG_ERR, "Unknown payload OID: %s\n", buf);
+ config_perror("Unknown payload OID");
+ mteObjects_removeEntries( "snmpd.conf", tname );
+ } else
+ idx = object->mteOIndex;
+ break;
+
+ case 'o': /* object */
+ idx++;
+ cp = copy_nword_const(cp, buf, SPRINT_MAX_LEN);
+ object = mteObjects_addOID( "snmpd.conf", tname, idx, buf, 1 );
+ if (!object) {
+ snmp_log(LOG_ERR, "Unknown payload OID: %s\n", buf);
+ config_perror("Unknown payload OID");
+ mteObjects_removeEntries( "snmpd.conf", tname );
+ } else
+ idx = object->mteOIndex;
+ break;
+
+ case 'r': /* repeat frequency */
+ cp = copy_nword_const(cp, buf, SPRINT_MAX_LEN);
+ repeat = strtoul(buf, NULL, 0);
+ break;
+
+ case 'S': /* disable startup tests */
+ startup = 0;
+ break;
+
+ case 's': /* enable startup tests (default?) */
+ startup = 1;
+ break;
+
+ case 't': /* threshold test - already handled */
+ break;
+
+ case 'u': /* user */
+ cp = copy_nword_const(cp, buf, SPRINT_MAX_LEN);
+ sess = netsnmp_iquery_user_session(buf);
+ if (NULL == sess) {
+ snmp_log(LOG_ERR, "user name %s not found\n", buf);
+ config_perror("Unknown user name\n");
+ mteObjects_removeEntries( "snmpd.conf", tname );
+ return;
+ }
+ break;
+ }
+ } else {
+ /*
+ * Skip the first non-option token - the trigger
+ * name (which has already been processed earlier).
+ */
+ if ( !seen_name ) {
+ seen_name = 1;
+ } else {
+ /*
+ * But the next non-option token encountered will
+ * mark the start of the expression to be monitored.
+ *
+ * There are three possible expression formats:
+ * [op] OID (existence tests)
+ * OID op value (boolean tests)
+ * OID val val [val val] (threshold tests)
+ *
+ * Extract the OID, operation and (first) value.
+ */
+ switch ( test ) {
+ case MTE_TRIGGER_EXISTENCE:
+ /*
+ * Identify the existence operator (if any)...
+ */
+ op = MTE_EXIST_PRESENT;
+ if (buf[0] == '!') {
+ if (buf[1] == '=') {
+ op = MTE_EXIST_CHANGED;
+ } else {
+ op = MTE_EXIST_ABSENT;
+ }
+ cp = copy_nword_const(cp, buf, SPRINT_MAX_LEN);
+ }
+ /*
+ * ... then extract the monitored OID.
+ * (ignoring anything that remains)
+ */
+ memcpy(oid_name_buf, buf, SPRINT_MAX_LEN);
+ cp = NULL; /* To terminate the processing loop */
+ DEBUGMSGTL(("disman:event:conf", "%s: Exist (%s, %d)\n",
+ tname, oid_name_buf, op));
+ break;
+
+ case MTE_TRIGGER_BOOLEAN:
+ /*
+ * Extract the monitored OID, and
+ * identify the boolean operator ...
+ */
+ memcpy(oid_name_buf, buf, SPRINT_MAX_LEN);
+ cp = copy_nword_const(cp, buf, SPRINT_MAX_LEN);
+ if (buf[0] == '!') {
+ op = MTE_BOOL_UNEQUAL;
+ } else if (buf[0] == '=') {
+ op = MTE_BOOL_EQUAL;
+ } else if (buf[0] == '<') {
+ if (buf[1] == '=') {
+ op = MTE_BOOL_LESSEQUAL;
+ } else {
+ op = MTE_BOOL_LESS;
+ }
+ } else if (buf[0] == '>') {
+ if (buf[1] == '=') {
+ op = MTE_BOOL_GREATEREQUAL;
+ } else {
+ op = MTE_BOOL_GREATER;
+ }
+ }
+ /*
+ * ... then extract the comparison value.
+ * (ignoring anything that remains)
+ */
+ cp = copy_nword_const(cp, buf, SPRINT_MAX_LEN);
+ value = strtol(buf, NULL, 0);
+ cp = NULL; /* To terminate the processing loop */
+ DEBUGMSGTL(("disman:event:conf", "%s: Bool (%s, %d, %ld)\n",
+ tname, oid_name_buf, op, value));
+ break;
+
+ case MTE_TRIGGER_THRESHOLD:
+ /*
+ * Extract the monitored OID, and
+ * the first comparison value...
+ */
+ memcpy(oid_name_buf, buf, SPRINT_MAX_LEN);
+ memset( buf, 0, SPRINT_MAX_LEN);
+ cp = copy_nword_const(cp, buf, SPRINT_MAX_LEN);
+ value = strtol(buf, NULL, 0);
+
+ /*
+ * ... then save the rest of the line for later.
+ */
+ memset( buf, 0, strlen(buf));
+ memcpy( buf, cp, strlen(cp));
+ cp = NULL; /* To terminate the processing loop */
+ DEBUGMSGTL(("disman:event:conf", "%s: Thresh (%s, %ld, %s)\n",
+ tname, oid_name_buf, value, buf));
+ break;
+ }
+ }
+ }
+ if (!cp)
+ break;
+ }
+
+ if (NULL == sess) {
+ sess = netsnmp_query_get_default_session();
+ if (NULL == sess) {
+ config_perror
+ ("You must specify a default user name using the agentSecName token\n");
+ mteObjects_removeEntries( "snmpd.conf", tname );
+ return;
+ }
+ }
+
+ /*
+ * ... and then create the new trigger entry...
+ */
+ entry = _find_typed_mteTrigger_entry( "snmpd.conf", tname+2, test );
+ if (!entry) {
+ /* mteObjects_removeEntries( "snmpd.conf", tname ); */
+ return;
+ }
+
+ /*
+ * ... populate the type-independent fields...
+ * (setting the delta discontinuity OID first)
+ */
+ if ( (flags & MTE_TRIGGER_FLAG_DELTA) &&
+ !(flags & MTE_TRIGGER_FLAG_SYSUPT)) {
+ memset( entry->mteDeltaDiscontID, 0, sizeof(entry->mteDeltaDiscontID));
+ memcpy( entry->mteDeltaDiscontID, name_buf, name_buf_len*sizeof(oid));
+ entry->mteDeltaDiscontID_len = 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, "trigger OID: %s\n", oid_name_buf);
+ config_perror("unknown monitor OID");
+ mteObjects_removeEntries( "snmpd.conf", tname );
+ return;
+ }
+ entry->session = sess;
+ entry->flags |= flags;
+ entry->mteTriggerTest |= test;
+ entry->mteTriggerFrequency = repeat;
+ entry->mteTriggerValueID_len = name_buf_len;
+ memcpy(entry->mteTriggerValueID, name_buf, name_buf_len*sizeof(oid));
+
+ /*
+ * ... and the relevant test-specific fields.
+ */
+ switch (test) {
+ case MTE_TRIGGER_EXISTENCE:
+ entry->mteTExTest = op;
+ if (op != MTE_EXIST_CHANGED && startup)
+ entry->mteTExStartup = op;
+ if ( idx > 0 ) {
+ /*
+ * Refer to the objects for this trigger (if any)...
+ */
+ memset(entry->mteTExObjOwner, 0, MTE_STR1_LEN+1);
+ memcpy(entry->mteTExObjOwner, "snmpd.conf", 10);
+ memcpy(entry->mteTExObjects, tname, MTE_STR1_LEN+1);
+ }
+ if ( ename[0] ) {
+ /*
+ * ... and the specified event...
+ */
+ memset(entry->mteTExEvOwner, 0, MTE_STR1_LEN+1);
+ if ( ename[0] == '_' )
+ memcpy(entry->mteTExEvOwner, "_snmpd", 6);
+ else
+ memcpy(entry->mteTExEvOwner, "snmpd.conf", 10);
+ memcpy(entry->mteTExEvent, ename, MTE_STR1_LEN+1);
+ } else {
+ /*
+ * ... or the hardcoded default event.
+ */
+ memset(entry->mteTExEvOwner, 0, MTE_STR1_LEN+1);
+ memset(entry->mteTExEvent, 0, MTE_STR1_LEN+1);
+ memcpy(entry->mteTExEvOwner, "_snmpd", 6);
+ memcpy(entry->mteTExEvent, "_mteTriggerFired", 16);
+ }
+ break;
+ case MTE_TRIGGER_BOOLEAN:
+ entry->mteTBoolComparison = op;
+ entry->mteTBoolValue = value;
+ if (!startup)
+ entry->flags &= ~MTE_TRIGGER_FLAG_BSTART;
+ if ( idx > 0 ) {
+ /*
+ * Refer to the objects for this trigger (if any)...
+ */
+ memset(entry->mteTBoolObjOwner, 0, MTE_STR1_LEN+1);
+ memcpy(entry->mteTBoolObjOwner, "snmpd.conf", 10);
+ memcpy(entry->mteTBoolObjects, tname, MTE_STR1_LEN+1);
+ }
+ if ( ename[0] ) {
+ /*
+ * ... and the specified event...
+ */
+ memset(entry->mteTBoolEvOwner, 0, MTE_STR1_LEN+1);
+ if ( ename[0] == '_' )
+ memcpy(entry->mteTBoolEvOwner, "_snmpd", 6);
+ else
+ memcpy(entry->mteTBoolEvOwner, "snmpd.conf", 10);
+ memcpy(entry->mteTBoolEvent, ename, MTE_STR1_LEN+1);
+ } else {
+ /*
+ * ... or the hardcoded default event.
+ */
+ memset(entry->mteTBoolEvOwner, 0, MTE_STR1_LEN+1);
+ memset(entry->mteTBoolEvent, 0, MTE_STR1_LEN+1);
+ memcpy(entry->mteTBoolEvOwner, "_snmpd", 6);
+ memcpy(entry->mteTBoolEvent, "_mteTriggerFired", 16);
+ }
+ break;
+ case MTE_TRIGGER_THRESHOLD:
+ entry->mteTThFallValue = value;
+ value = strtol(buf, NULL, 0);
+ entry->mteTThRiseValue = value;
+ if (!startup)
+ entry->mteTThStartup = 0;
+ if ( idx > 0 ) {
+ /*
+ * Refer to the objects for this trigger (if any)...
+ */
+ memset(entry->mteTThObjOwner, 0, MTE_STR1_LEN+1);
+ memcpy(entry->mteTThObjOwner, "snmpd.conf", 10);
+ memcpy(entry->mteTThObjects, tname, MTE_STR1_LEN+1);
+ }
+ if ( ename[0] ) {
+ /*
+ * ... and the specified event...
+ * (using the same event for all triggers)
+ */
+ memset(entry->mteTThRiseOwner, 0, MTE_STR1_LEN+1);
+ if ( ename[0] == '_' )
+ memcpy(entry->mteTThRiseOwner, "_snmpd", 6);
+ else
+ memcpy(entry->mteTThRiseOwner, "snmpd.conf", 10);
+ memcpy(entry->mteTThRiseEvent, ename, MTE_STR1_LEN+1);
+ memset(entry->mteTThFallOwner, 0, MTE_STR1_LEN+1);
+ if ( ename[0] == '_' )
+ memcpy(entry->mteTThFallOwner, "_snmpd", 6);
+ else
+ memcpy(entry->mteTThFallOwner, "snmpd.conf", 10);
+ memcpy(entry->mteTThFallEvent, ename, MTE_STR1_LEN+1);
+ } else {
+ /*
+ * ... or the hardcoded default events.
+ */
+ memset(entry->mteTThRiseOwner, 0, MTE_STR1_LEN+1);
+ memset(entry->mteTThFallOwner, 0, MTE_STR1_LEN+1);
+ memset(entry->mteTThRiseEvent, 0, MTE_STR1_LEN+1);
+ memset(entry->mteTThFallEvent, 0, MTE_STR1_LEN+1);
+ memcpy(entry->mteTThRiseOwner, "_snmpd", 6);
+ memcpy(entry->mteTThFallOwner, "_snmpd", 6);
+ memcpy(entry->mteTThRiseEvent, "_mteTriggerRising", 17);
+ memcpy(entry->mteTThFallEvent, "_mteTriggerFalling", 18);
+ }
+ cp = skip_token(buf); /* skip riseThreshold value */
+
+ /*
+ * Parse and set (optional) Delta thresholds & events
+ */
+ if ( cp && *cp != '\0' ) {
+ if (entry->flags & MTE_TRIGGER_FLAG_DELTA) {
+ config_perror("Delta-threshold on delta-samples not supported");
+ mteObjects_removeEntries( "snmpd.conf", tname );
+ return;
+ }
+ value = strtol(cp, NULL, 0);
+ entry->mteTThDFallValue = value;
+ cp = skip_token_const(cp);
+ value = strtol(cp, NULL, 0);
+ entry->mteTThDRiseValue = value;
+ /*
+ * Set the events in the same way as before
+ */
+ if ( ename[0] ) {
+ memset(entry->mteTThDRiseOwner, 0, MTE_STR1_LEN+1);
+ if ( ename[0] == '_' )
+ memcpy(entry->mteTThDRiseOwner, "_snmpd", 6);
+ else
+ memcpy(entry->mteTThDRiseOwner, "snmpd.conf", 10);
+ memcpy(entry->mteTThDRiseEvent, ename, MTE_STR1_LEN+1);
+ memset(entry->mteTThDFallOwner, 0, MTE_STR1_LEN+1);
+ if ( ename[0] == '_' )
+ memcpy(entry->mteTThDFallOwner, "_snmpd", 6);
+ else
+ memcpy(entry->mteTThDFallOwner, "snmpd.conf", 10);
+ memcpy(entry->mteTThDFallEvent, ename, MTE_STR1_LEN+1);
+ } else {
+ memset(entry->mteTThDRiseOwner, 0, MTE_STR1_LEN+1);
+ memset(entry->mteTThDFallOwner, 0, MTE_STR1_LEN+1);
+ memset(entry->mteTThDRiseEvent, 0, MTE_STR1_LEN+1);
+ memset(entry->mteTThDFallEvent, 0, MTE_STR1_LEN+1);
+ memcpy(entry->mteTThDRiseOwner, "_snmpd", 6);
+ memcpy(entry->mteTThDFallOwner, "_snmpd", 6);
+ memcpy(entry->mteTThDRiseEvent, "_mteTriggerRising", 17);
+ memcpy(entry->mteTThDFallEvent, "_mteTriggerFalling", 18);
+ }
+ }
+
+ break;
+ }
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY,
+ SNMP_CALLBACK_POST_READ_CONFIG,
+ _mteTrigger_callback_enable, entry );
+ return;
+}
+
+void
+parse_linkUpDown_traps(const char *token, const char *line)
+{
+ /*
+ * XXX - This isn't strictly correct according to the
+ * definitions in IF-MIB, but will do for now.
+ */
+ if (strncmp( line, "yes", 3) == 0) {
+ DEBUGMSGTL(("disman:event:conf", "Registering linkUpDown traps\n"));
+
+ /* ifOperStatus */
+ parse_mteMonitor("monitor",
+ "-r 60 -S -e _linkUp \"linkUp\" .1.3.6.1.2.1.2.2.1.8 != 2");
+ parse_mteMonitor("monitor",
+ "-r 60 -S -e _linkDown \"linkDown\" .1.3.6.1.2.1.2.2.1.8 == 2");
+ }
+}
+
+
+void
+parse_default_mteMonitors(const char *token, const char *line)
+{
+ if (strncmp( line, "yes", 3) == 0) {
+ DEBUGMSGTL(("disman:event:conf", "Registering default monitors\n"));
+
+ parse_mteMonitor("monitor",
+ "-o prNames -o prErrMessage \"process table\" prErrorFlag != 0");
+ parse_mteMonitor("monitor",
+ "-o memErrorName -o memSwapErrorMsg \"memory\" memSwapError != 0");
+ parse_mteMonitor("monitor",
+ "-o extNames -o extOutput \"extTable\" extResult != 0");
+ parse_mteMonitor("monitor",
+ "-o dskPath -o dskErrorMsg \"dskTable\" dskErrorFlag != 0");
+ parse_mteMonitor("monitor",
+ "-o laNames -o laErrMessage \"laTable\" laErrorFlag != 0");
+ parse_mteMonitor("monitor",
+ "-o fileName -o fileErrorMsg \"fileTable\" fileErrorFlag != 0");
+ parse_mteMonitor("monitor",
+ "-o snmperrErrMessage \"snmperrs\" snmperrErrorFlag != 0");
+ }
+ return;
+}
+
+/* ================================================
+ *
+ * Handlers for loading persistent trigger entries
+ *
+ * ================================================ */
+
+
+
+/*
+ * Entries for the main mteTriggerTable
+ */
+
+char *
+_parse_mteTCols( char *line, struct mteTrigger *entry, int bcomp )
+{
+ void *vp;
+ size_t tmp;
+ size_t len;
+
+ len = MTE_STR2_LEN; vp = entry->mteTriggerComment;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ if ( bcomp ) {
+ /*
+ * The newer style of config directive skips the
+ * mteTriggerTest and mteTriggerSampleType values,
+ * as these are set implicitly from the relevant
+ * config directives.
+ * Backwards compatability with the previous (combined)
+ * style reads these in explicitly.
+ */
+ len = 1;
+ vp = &entry->mteTriggerTest;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ if (tmp == 2)
+ entry->flags |= MTE_TRIGGER_FLAG_DELTA;
+ }
+ vp = entry->mteTriggerValueID;
+ entry->mteTriggerValueID_len = MAX_OID_LEN;
+ line = read_config_read_data(ASN_OBJECT_ID, line, &vp,
+ &entry->mteTriggerValueID_len);
+ if (bcomp) {
+ /*
+ * The newer style combines the various boolean values
+ * into a single field (which comes later).
+ * Backwards compatability means reading these individually.
+ */
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ if (tmp == TV_TRUE)
+ entry->flags |= MTE_TRIGGER_FLAG_VWILD;
+ }
+ len = MTE_STR2_LEN; vp = entry->mteTriggerTarget;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR2_LEN; vp = entry->mteTriggerContext;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ if (bcomp) {
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ if (tmp == TV_TRUE)
+ entry->flags |= MTE_TRIGGER_FLAG_CWILD;
+ }
+
+ line = read_config_read_data(ASN_UNSIGNED, line,
+ &entry->mteTriggerFrequency, NULL);
+
+ len = MTE_STR1_LEN; vp = entry->mteTriggerOOwner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteTriggerObjects;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+
+ /*
+ * Assorted boolean flag values, combined into a single field
+ */
+ if (bcomp) {
+ /*
+ * Backwards compatability stores the mteTriggerEnabled
+ * and mteTriggerEntryStatus values separately...
+ */
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ if (tmp == TV_TRUE)
+ entry->flags |= MTE_TRIGGER_FLAG_ENABLED;
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ if (tmp == RS_ACTIVE)
+ entry->flags |= MTE_TRIGGER_FLAG_ACTIVE;
+ } else {
+ /*
+ * ... while the newer style combines all the assorted
+ * boolean values into this single field.
+ */
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ entry->flags |= ( tmp &
+ (MTE_TRIGGER_FLAG_VWILD |MTE_TRIGGER_FLAG_CWILD|
+ MTE_TRIGGER_FLAG_ENABLED|MTE_TRIGGER_FLAG_ACTIVE));
+ }
+
+ return line;
+}
+
+void
+parse_mteTTable(const char *token, char *line)
+{
+ char owner[MTE_STR1_LEN+1];
+ char tname[MTE_STR1_LEN+1];
+ void *vp;
+ size_t len;
+ struct mteTrigger *entry;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing mteTriggerTable config...\n"));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( tname, 0, sizeof(tname));
+ len = MTE_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = tname;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ entry = _find_mteTrigger_entry( owner, tname );
+
+ DEBUGMSG(("disman:event:conf", "(%s, %s) ", owner, tname));
+
+ /*
+ * Read in the accessible (trigger-independent) column values.
+ */
+ line = _parse_mteTCols( line, entry, 0 );
+ /*
+ * XXX - Will need to read in the 'iquery' access information
+ */
+ entry->flags |= MTE_TRIGGER_FLAG_VALID;
+
+ DEBUGMSG(("disman:event:conf", "\n"));
+}
+
+
+/*
+ * Entries from the mteTriggerDeltaTable
+ */
+
+char *
+_parse_mteTDCols( char *line, struct mteTrigger *entry, int bcomp )
+{
+ void *vp;
+ size_t tmp;
+
+ entry->mteDeltaDiscontID_len = MAX_OID_LEN;
+ vp = entry->mteDeltaDiscontID;
+ line = read_config_read_data(ASN_OBJECT_ID, line, &vp,
+ &entry->mteDeltaDiscontID_len);
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ if (bcomp) {
+ if ( tmp == TV_TRUE )
+ entry->flags |= MTE_TRIGGER_FLAG_DWILD;
+ } else {
+ if ( tmp & MTE_TRIGGER_FLAG_DWILD )
+ entry->flags |= MTE_TRIGGER_FLAG_DWILD;
+ }
+ line = read_config_read_data(ASN_UNSIGNED, line,
+ &entry->mteDeltaDiscontIDType, NULL);
+
+ return line;
+}
+
+void
+parse_mteTDTable(const char *token, char *line)
+{
+ char owner[MTE_STR1_LEN+1];
+ char tname[MTE_STR1_LEN+1];
+ void *vp;
+ size_t len;
+ struct mteTrigger *entry;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing mteTriggerDeltaTable config... "));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( tname, 0, sizeof(tname));
+ len = MTE_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = tname;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ entry = _find_mteTrigger_entry( owner, tname );
+
+ DEBUGMSG(("disman:event:conf", "(%s, %s) ", owner, tname));
+
+ /*
+ * Read in the accessible column values.
+ */
+ line = _parse_mteTDCols( line, entry, 0 );
+
+ entry->flags |= (MTE_TRIGGER_FLAG_DELTA|
+ MTE_TRIGGER_FLAG_VALID);
+
+ DEBUGMSG(("disman:event:conf", "\n"));
+}
+
+
+/*
+ * Entries from the mteTriggerExistenceTable
+ */
+
+char *
+_parse_mteTExCols( char *line, struct mteTrigger *entry, int bcomp )
+{
+ void *vp;
+ size_t tmp;
+ size_t len;
+
+ if (bcomp) {
+ len = 1;
+ vp = &entry->mteTExTest;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = 1;
+ vp = &entry->mteTExStartup;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ } else {
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ entry->mteTExStartup = ( tmp & 0xff ); tmp >>= 8;
+ entry->mteTExTest = ( tmp & 0xff );
+ }
+
+ len = MTE_STR1_LEN; vp = entry->mteTExObjOwner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteTExObjects;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+
+ len = MTE_STR1_LEN; vp = entry->mteTExEvOwner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteTExEvent;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+
+ return line;
+}
+
+void
+parse_mteTExTable(const char *token, char *line)
+{
+ char owner[MTE_STR1_LEN+1];
+ char tname[MTE_STR1_LEN+1];
+ void *vp;
+ size_t len;
+ struct mteTrigger *entry;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing mteTriggerExistenceTable config... "));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( tname, 0, sizeof(tname));
+ len = MTE_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = tname;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ entry = _find_mteTrigger_entry( owner, tname );
+
+ DEBUGMSG(("disman:event:conf", "(%s, %s) ", owner, tname));
+
+ /*
+ * Read in the accessible column values.
+ * (Note that the first two are combined into a single field)
+ */
+ line = _parse_mteTExCols( line, entry, 0 );
+
+ entry->mteTriggerTest |= MTE_TRIGGER_EXISTENCE;
+ entry->flags |= MTE_TRIGGER_FLAG_VALID;
+
+ DEBUGMSG(("disman:event:conf", "\n"));
+}
+
+
+/*
+ * Entries from the mteTriggerBooleanTable
+ */
+
+char *
+_parse_mteTBlCols( char *line, struct mteTrigger *entry, int bcomp )
+{
+ void *vp;
+ size_t tmp;
+ size_t len;
+
+ if (bcomp) {
+ line = read_config_read_data(ASN_UNSIGNED, line,
+ &entry->mteTBoolComparison, NULL);
+ line = read_config_read_data(ASN_INTEGER, line,
+ &entry->mteTBoolValue, NULL);
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ if (tmp == TV_TRUE)
+ entry->flags |= MTE_TRIGGER_FLAG_BSTART;
+ } else {
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ entry->mteTBoolComparison = ( tmp & 0x0f );
+ entry->flags |= ( tmp & MTE_TRIGGER_FLAG_BSTART );
+ line = read_config_read_data(ASN_INTEGER, line,
+ &entry->mteTBoolValue, NULL);
+ }
+
+
+ len = MTE_STR1_LEN; vp = entry->mteTBoolObjOwner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteTBoolObjects;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+
+ len = MTE_STR1_LEN; vp = entry->mteTBoolEvOwner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteTBoolEvent;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+
+ return line;
+}
+
+void
+parse_mteTBlTable(const char *token, char *line)
+{
+ char owner[MTE_STR1_LEN+1];
+ char tname[MTE_STR1_LEN+1];
+ void *vp;
+ size_t len;
+ struct mteTrigger *entry;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing mteTriggerBooleanTable config... "));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( tname, 0, sizeof(tname));
+ len = MTE_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = tname;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ entry = _find_mteTrigger_entry( owner, tname );
+
+ DEBUGMSG(("disman:event:conf", "(%s, %s) ", owner, tname));
+
+ /*
+ * Read in the accessible column values.
+ * (Note that the first & third are combined into a single field)
+ */
+ line = _parse_mteTBlCols( line, entry, 0 );
+
+ entry->mteTriggerTest |= MTE_TRIGGER_BOOLEAN;
+ entry->flags |= MTE_TRIGGER_FLAG_VALID;
+
+ DEBUGMSG(("disman:event:conf", "\n"));
+}
+
+
+/*
+ * Entries from the mteTriggerThresholdTable
+ */
+
+char *
+_parse_mteTThCols( char *line, struct mteTrigger *entry, int bcomp )
+{
+ void *vp;
+ size_t len;
+
+ line = read_config_read_data(ASN_UNSIGNED, line,
+ &entry->mteTThStartup, NULL);
+ line = read_config_read_data(ASN_INTEGER, line,
+ &entry->mteTThRiseValue, NULL);
+ line = read_config_read_data(ASN_INTEGER, line,
+ &entry->mteTThFallValue, NULL);
+ line = read_config_read_data(ASN_INTEGER, line,
+ &entry->mteTThDRiseValue, NULL);
+ line = read_config_read_data(ASN_INTEGER, line,
+ &entry->mteTThDFallValue, NULL);
+
+ len = MTE_STR1_LEN; vp = entry->mteTThObjOwner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteTThObjects;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+
+ len = MTE_STR1_LEN; vp = entry->mteTThRiseOwner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteTThRiseEvent;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteTThFallOwner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteTThFallEvent;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+
+ len = MTE_STR1_LEN; vp = entry->mteTThDRiseOwner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteTThDRiseEvent;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteTThDFallOwner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = entry->mteTThDFallEvent;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+
+ return line;
+}
+
+void
+parse_mteTThTable(const char *token, char *line)
+{
+ char owner[MTE_STR1_LEN+1];
+ char tname[MTE_STR1_LEN+1];
+ void *vp;
+ size_t len;
+ struct mteTrigger *entry;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing mteTriggerThresholdTable config... "));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( tname, 0, sizeof(tname));
+ len = MTE_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = tname;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ entry = _find_mteTrigger_entry( owner, tname );
+
+ DEBUGMSG(("disman:event:conf", "(%s, %s) ", owner, tname));
+
+ /*
+ * Read in the accessible column values.
+ */
+ line = _parse_mteTThCols( line, entry, 0 );
+
+ entry->mteTriggerTest |= MTE_TRIGGER_THRESHOLD;
+ entry->flags |= MTE_TRIGGER_FLAG_VALID;
+
+ DEBUGMSG(("disman:event:conf", "\n"));
+}
+
+
+/*
+ * Backwards Compatability with the previous implementation
+ */
+
+void
+parse_mteTriggerTable(const char *token, char *line)
+{
+ char owner[MTE_STR1_LEN+1];
+ char tname[MTE_STR1_LEN+1];
+ void *vp;
+ size_t len;
+ struct mteTrigger *entry;
+
+ DEBUGMSGTL(("disman:event:conf", "Parsing previous mteTriggerTable config... "));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( tname, 0, sizeof(tname));
+ len = MTE_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MTE_STR1_LEN; vp = tname;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ entry = _find_mteTrigger_entry( owner, tname );
+
+ DEBUGMSG(("disman:event:conf", "(%s, %s) ", owner, tname));
+
+ /*
+ * Read in the accessible column values for each table in turn...
+ * (similar, though not identical to the newer style).
+ */
+ line = _parse_mteTCols( line, entry, 1 );
+ line = _parse_mteTDCols( line, entry, 1 );
+ line = _parse_mteTExCols( line, entry, 1 );
+ line = _parse_mteTBlCols( line, entry, 1 );
+ line = _parse_mteTThCols( line, entry, 1 );
+
+ /*
+ * ... and then read in the "local internal variables"
+ * XXX - TODO
+ */
+ entry->flags |= MTE_TRIGGER_FLAG_VALID;
+
+ /* XXX - mte_enable_trigger(); ??? */
+ DEBUGMSG(("disman:event:conf", "\n"));
+}
+
+/* ===============================================
+ *
+ * Handler for storing persistent trigger entries
+ *
+ * =============================================== */
+
+int
+store_mteTTable(int majorID, int minorID, void *serverarg, void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr, *cp;
+ void *vp;
+ size_t tint;
+ netsnmp_tdata_row *row;
+ struct mteTrigger *entry;
+
+
+ DEBUGMSGTL(("disman:event:conf", "Storing mteTriggerTable config:\n"));
+
+ for (row = netsnmp_tdata_row_first( trigger_table_data );
+ row;
+ row = netsnmp_tdata_row_next( trigger_table_data, row )) {
+
+ /*
+ * Skip entries that were set up via static config directives
+ */
+ entry = (struct mteTrigger *)netsnmp_tdata_row_entry( row );
+ if ( entry->flags & MTE_TRIGGER_FLAG_FIXED )
+ continue;
+
+ DEBUGMSGTL(("disman:event:conf", " Storing (%s %s)\n",
+ entry->mteOwner, entry->mteTName));
+
+ /*
+ * Save the basic mteTriggerTable entry...
+ */
+ memset(line, 0, sizeof(line));
+ strcat(line, "_mteTTable ");
+ cptr = line + strlen(line);
+
+ cp = entry->mteOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTName; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTriggerComment; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ /*
+ * ... (but skip the mteTriggerTest and
+ * assorted boolean flag fields)...
+ */
+ vp = entry->mteTriggerValueID;
+ tint = entry->mteTriggerValueID_len;
+ cptr = read_config_store_data( ASN_OBJECT_ID, cptr, &vp, &tint );
+ cp = entry->mteTriggerTarget; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTriggerContext; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ tint = entry->mteTriggerFrequency;
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+ cp = entry->mteTriggerOOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTriggerObjects; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ tint = entry->flags &
+ (MTE_TRIGGER_FLAG_VWILD |MTE_TRIGGER_FLAG_CWILD|
+ MTE_TRIGGER_FLAG_ENABLED|MTE_TRIGGER_FLAG_ACTIVE);
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+ /* XXX - Need to store the 'iquery' access information */
+ snmpd_store_config(line);
+
+ /*
+ * ... then save the other (relevant) table entries separately,
+ * starting with mteDeltaDiscontinuityTable...
+ */
+ if ( entry->flags & MTE_TRIGGER_FLAG_DELTA ) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "_mteTDTable ");
+ cptr = line + strlen(line);
+
+ cp = entry->mteOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTName; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+
+ vp = entry->mteDeltaDiscontID;
+ tint = entry->mteDeltaDiscontID_len;
+ cptr = read_config_store_data( ASN_OBJECT_ID, cptr, &vp, &tint );
+
+ tint = entry->flags & MTE_TRIGGER_FLAG_DWILD;
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+ tint = entry->mteDeltaDiscontIDType;
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+
+ snmpd_store_config(line);
+ }
+
+ /*
+ * ... and the three type-specific trigger tables.
+ */
+ if ( entry->mteTriggerTest & MTE_TRIGGER_EXISTENCE ) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "_mteTExTable ");
+ cptr = line + strlen(line);
+
+ cp = entry->mteOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTName; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+
+ tint = (entry->mteTExTest & 0xff) << 8;
+ tint|= (entry->mteTExStartup & 0xff);
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+
+ cp = entry->mteTExObjOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTExObjects; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+
+ cp = entry->mteTExEvOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTExEvent; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+
+ snmpd_store_config(line);
+ }
+ if ( entry->mteTriggerTest & MTE_TRIGGER_BOOLEAN ) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "_mteTBlTable ");
+ cptr = line + strlen(line);
+
+ cp = entry->mteOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTName; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+
+ tint = entry->mteTBoolComparison;
+ tint |= (entry->flags & MTE_TRIGGER_FLAG_BSTART);
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+ tint = entry->mteTBoolValue;
+ cptr = read_config_store_data( ASN_INTEGER, cptr, &tint, NULL );
+
+ cp = entry->mteTBoolObjOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTBoolObjects; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+
+ cp = entry->mteTBoolEvOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTBoolEvent; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+
+ snmpd_store_config(line);
+ }
+ if ( entry->mteTriggerTest & MTE_TRIGGER_THRESHOLD ) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "_mteTThTable ");
+ cptr = line + strlen(line);
+
+ cp = entry->mteOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTName; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+
+ cptr = read_config_store_data(ASN_UNSIGNED, cptr,
+ &entry->mteTThStartup, NULL );
+ cptr = read_config_store_data(ASN_INTEGER, cptr,
+ &entry->mteTThRiseValue, NULL );
+ cptr = read_config_store_data(ASN_INTEGER, cptr,
+ &entry->mteTThFallValue, NULL );
+ cptr = read_config_store_data(ASN_INTEGER, cptr,
+ &entry->mteTThDRiseValue, NULL );
+ cptr = read_config_store_data(ASN_INTEGER, cptr,
+ &entry->mteTThDFallValue, NULL );
+
+ cp = entry->mteTThObjOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTThObjects; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+
+ cp = entry->mteTThRiseOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTThRiseEvent; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTThFallOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTThFallEvent; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+
+ cp = entry->mteTThDRiseOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTThDRiseEvent; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTThDFallOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->mteTThDFallEvent; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+
+ snmpd_store_config(line);
+ }
+ }
+
+ DEBUGMSGTL(("disman:event:conf", " done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+int
+clear_mteTTable(int majorID, int minorID, void *serverarg, void *clientarg)
+{
+ netsnmp_tdata_row *row;
+
+ while (( row = netsnmp_tdata_row_first( trigger_table_data ))) {
+ struct mteTrigger *entry = (struct mteTrigger *)
+ netsnmp_tdata_remove_and_delete_row(trigger_table_data, row);
+ if (entry) {
+ /* Remove from the callbacks list and disable triggers */
+ snmp_unregister_callback( SNMP_CALLBACK_LIBRARY,
+ SNMP_CALLBACK_POST_READ_CONFIG,
+ _mteTrigger_callback_enable, entry, 0 );
+ mteTrigger_disable( entry );
+ SNMP_FREE(entry);
+ }
+ }
+ return SNMPERR_SUCCESS;
+}
diff --git a/agent/mibgroup/disman/event/mteTriggerConf.h b/agent/mibgroup/disman/event/mteTriggerConf.h
new file mode 100644
index 0000000..bfbcfcb
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTriggerConf.h
@@ -0,0 +1,23 @@
+#ifndef MTETRIGGERCONF_H
+#define MTETRIGGERCONF_H
+
+config_require(utilities/iquery)
+
+/*
+ * function declarations
+ */
+void init_mteTriggerConf(void);
+void parse_mteMonitor( const char *, const char *);
+void parse_default_mteMonitors( const char *, const char *);
+void parse_linkUpDown_traps(const char *, const char *);
+
+void parse_mteTTable( const char *, char *);
+void parse_mteTDTable( const char *, char *);
+void parse_mteTExTable(const char *, char *);
+void parse_mteTBlTable(const char *, char *);
+void parse_mteTThTable(const char *, char *);
+void parse_mteTriggerTable(const char *, char *);
+SNMPCallback store_mteTTable;
+SNMPCallback clear_mteTTable;
+
+#endif /* MTETRIGGERCONF_H */
diff --git a/agent/mibgroup/disman/event/mteTriggerDeltaTable.c b/agent/mibgroup/disman/event/mteTriggerDeltaTable.c
new file mode 100644
index 0000000..c2c2e8e
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTriggerDeltaTable.c
@@ -0,0 +1,273 @@
+/*
+ * DisMan Event MIB:
+ * Implementation of the mteTriggerDeltaTable MIB interface
+ * See 'mteTrigger.c' for active behaviour of this table.
+ *
+ * (based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "disman/event/mteTrigger.h"
+#include "disman/event/mteTriggerDeltaTable.h"
+
+netsnmp_feature_require(table_tdata)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(check_vb_oid)
+netsnmp_feature_require(check_vb_truthvalue)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+/** Initializes the mteTriggerDeltaTable module */
+void
+init_mteTriggerDeltaTable(void)
+{
+ static oid mteTDeltaTable_oid[] = { 1, 3, 6, 1, 2, 1, 88, 1, 2, 3 };
+ size_t mteTDeltaTable_oid_len = OID_LENGTH(mteTDeltaTable_oid);
+ netsnmp_handler_registration *reg;
+ netsnmp_table_registration_info *table_info;
+ int rc;
+
+ /*
+ * Ensure the (combined) table container is available...
+ */
+ init_trigger_table_data();
+
+ /*
+ * ... then set up the MIB interface to the mteTriggerDeltaTable slice
+ */
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ reg = netsnmp_create_handler_registration("mteTriggerDeltaTable",
+ mteTriggerDeltaTable_handler,
+ mteTDeltaTable_oid,
+ mteTDeltaTable_oid_len,
+ HANDLER_CAN_RWRITE);
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+ reg = netsnmp_create_handler_registration("mteTriggerDeltaTable",
+ mteTriggerDeltaTable_handler,
+ mteTDeltaTable_oid,
+ mteTDeltaTable_oid_len,
+ HANDLER_CAN_RONLY);
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_OCTET_STR, /* index: mteOwner */
+ /* index: mteTriggerName */
+ ASN_PRIV_IMPLIED_OCTET_STR,
+ 0);
+
+ table_info->min_column = COLUMN_MTETRIGGERDELTADISCONTINUITYID;
+ table_info->max_column = COLUMN_MTETRIGGERDELTADISCONTINUITYIDTYPE;
+
+ /* Register this using the (common) trigger_table_data container */
+ rc = netsnmp_tdata_register(reg, trigger_table_data, table_info);
+ if (rc != SNMPERR_SUCCESS)
+ return;
+ netsnmp_handler_owns_table_info(reg->handler->next);
+ DEBUGMSGTL(("disman:event:init", "Trigger Delta Table\n"));
+}
+
+
+/** handles requests for the mteTriggerDeltaTable table */
+int
+mteTriggerDeltaTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ struct mteTrigger *entry;
+ int ret;
+
+ DEBUGMSGTL(("disman:event:mib", "Delta Table handler (%d)\n",
+ reqinfo->mode));
+
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ /*
+ * The mteTriggerBooleanTable should only contains entries for
+ * rows where the mteTriggerSampleType is 'deltaValue(2)'
+ * So skip entries where this isn't the case.
+ */
+ if (!entry || !(entry->flags & MTE_TRIGGER_FLAG_DELTA )) {
+ netsnmp_request_set_error(request, SNMP_NOSUCHINSTANCE);
+ continue;
+ }
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERDELTADISCONTINUITYID:
+ snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
+ (u_char *) entry->mteDeltaDiscontID,
+ entry->mteDeltaDiscontID_len*sizeof(oid));
+ break;
+ case COLUMN_MTETRIGGERDELTADISCONTINUITYIDWILDCARD:
+ ret = (entry->flags & MTE_TRIGGER_FLAG_DWILD ) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_MTETRIGGERDELTADISCONTINUITYIDTYPE:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->mteDeltaDiscontIDType);
+ break;
+ }
+ }
+ break;
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ /*
+ * Write-support
+ */
+ case MODE_SET_RESERVE1:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ /*
+ * Since the mteTriggerDeltaTable only contains entries for
+ * rows where mteTriggerSampleType is 'deltaValue(2)',
+ * strictly speaking we should reject assignments where
+ * this isn't the case.
+ * But SET requests that include an assignment of
+ * 'deltaValue(2)' at the same time are valid, so would
+ * need to be accepted. Unfortunately, this assignment
+ * is only applied in the COMMIT pass, so it's difficult
+ * to detect whether this holds or not.
+ *
+ * Let's fudge things for now, by processing
+ * assignments even if this value isn't set.
+ */
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERDELTADISCONTINUITYID:
+ ret = netsnmp_check_vb_oid(request->requestvb);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGERDELTADISCONTINUITYIDWILDCARD:
+ ret = netsnmp_check_vb_truthvalue(request->requestvb);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGERDELTADISCONTINUITYIDTYPE:
+ ret = netsnmp_check_vb_int_range(request->requestvb,
+ MTE_DELTAD_TTICKS,
+ MTE_DELTAD_DATETIME);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ default:
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOTWRITABLE);
+ return SNMP_ERR_NOERROR;
+ }
+
+ /*
+ * The Event MIB is somewhat ambiguous as to whether the
+ * various trigger table entries can be modified once the
+ * main mteTriggerTable entry has been marked 'active'.
+ * But it's clear from discussion on the DisMan mailing
+ * list is that the intention is not.
+ *
+ * So check for whether this row is already active,
+ * and reject *all* SET requests if it is.
+ */
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ if (entry &&
+ entry->flags & MTE_TRIGGER_FLAG_ACTIVE ) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_RESERVE2:
+ case MODE_SET_FREE:
+ case MODE_SET_UNDO:
+ break;
+
+ case MODE_SET_ACTION:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ if (!entry) {
+ /*
+ * New rows must be created via the RowStatus column
+ * (in the main mteTriggerTable)
+ */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ /* or inconsistentName? */
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * All these assignments are "unfailable", so it's
+ * (reasonably) safe to apply them in the Commit phase
+ */
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERDELTADISCONTINUITYID:
+ if ( snmp_oid_compare(
+ request->requestvb->val.objid,
+ request->requestvb->val_len/sizeof(oid),
+ _sysUpTime_instance, _sysUpTime_inst_len) != 0 ) {
+ memset(entry->mteDeltaDiscontID, 0,
+ sizeof(entry->mteDeltaDiscontID));
+ memcpy(entry->mteDeltaDiscontID,
+ request->requestvb->val.string,
+ request->requestvb->val_len);
+ entry->mteDeltaDiscontID_len =
+ request->requestvb->val_len/sizeof(oid);
+ entry->flags &= ~MTE_TRIGGER_FLAG_SYSUPT;
+ }
+ break;
+ case COLUMN_MTETRIGGERDELTADISCONTINUITYIDWILDCARD:
+ if (*request->requestvb->val.integer == TV_TRUE)
+ entry->flags |= MTE_TRIGGER_FLAG_DWILD;
+ else
+ entry->flags &= ~MTE_TRIGGER_FLAG_DWILD;
+ break;
+ case COLUMN_MTETRIGGERDELTADISCONTINUITYIDTYPE:
+ entry->mteDeltaDiscontIDType = *request->requestvb->val.integer;
+ break;
+ }
+ }
+ break;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ }
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/event/mteTriggerDeltaTable.h b/agent/mibgroup/disman/event/mteTriggerDeltaTable.h
new file mode 100644
index 0000000..51f0bdb
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTriggerDeltaTable.h
@@ -0,0 +1,20 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.table_data.conf,v 1.8 2005/07/19 14:52:03 dts12 Exp $
+ */
+#ifndef MTETRIGGERDELTATABLE_H
+#define MTETRIGGERDELTATABLE_H
+
+/*
+ * function declarations
+ */
+void init_mteTriggerDeltaTable(void);
+Netsnmp_Node_Handler mteTriggerDeltaTable_handler;
+
+/*
+ * column number definitions for table mteTriggerDeltaTable
+ */
+#define COLUMN_MTETRIGGERDELTADISCONTINUITYID 1
+#define COLUMN_MTETRIGGERDELTADISCONTINUITYIDWILDCARD 2
+#define COLUMN_MTETRIGGERDELTADISCONTINUITYIDTYPE 3
+#endif /* MTETRIGGERDELTATABLE_H */
diff --git a/agent/mibgroup/disman/event/mteTriggerExistenceTable.c b/agent/mibgroup/disman/event/mteTriggerExistenceTable.c
new file mode 100644
index 0000000..22b683e
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTriggerExistenceTable.c
@@ -0,0 +1,290 @@
+/*
+ * DisMan Event MIB:
+ * Implementation of the mteTriggerExistenceTable MIB interface
+ * See 'mteTrigger.c' for active behaviour of this table.
+ *
+ * (based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "disman/event/mteTrigger.h"
+#include "disman/event/mteTriggerExistenceTable.h"
+
+netsnmp_feature_require(table_tdata)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(check_vb_type_and_max_size)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+static netsnmp_table_registration_info *table_info;
+
+/* Initializes the mteTriggerExistenceTable module */
+void
+init_mteTriggerExistenceTable(void)
+{
+ static oid mteTExistTable_oid[] = { 1, 3, 6, 1, 2, 1, 88, 1, 2, 4 };
+ size_t mteTExistTable_oid_len = OID_LENGTH(mteTExistTable_oid);
+ netsnmp_handler_registration *reg;
+ int rc;
+
+ /*
+ * Ensure the (combined) table container is available...
+ */
+ init_trigger_table_data();
+
+ /*
+ * ... then set up the MIB interface to the mteTriggerExistenceTable slice
+ */
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ reg = netsnmp_create_handler_registration("mteTriggerExistenceTable",
+ mteTriggerExistenceTable_handler,
+ mteTExistTable_oid,
+ mteTExistTable_oid_len,
+ HANDLER_CAN_RWRITE);
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+ reg = netsnmp_create_handler_registration("mteTriggerExistenceTable",
+ mteTriggerExistenceTable_handler,
+ mteTExistTable_oid,
+ mteTExistTable_oid_len,
+ HANDLER_CAN_RONLY);
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_OCTET_STR, /* index: mteOwner */
+ /* index: mteTriggerName */
+ ASN_PRIV_IMPLIED_OCTET_STR,
+ 0);
+
+ table_info->min_column = COLUMN_MTETRIGGEREXISTENCETEST;
+ table_info->max_column = COLUMN_MTETRIGGEREXISTENCEEVENT;
+
+ /* Register this using the (common) trigger_table_data container */
+ rc = netsnmp_tdata_register(reg, trigger_table_data, table_info);
+ if (rc != SNMPERR_SUCCESS)
+ return;
+
+ netsnmp_handler_owns_table_info(reg->handler->next);
+ DEBUGMSGTL(("disman:event:init", "Trigger Exist Table\n"));
+}
+
+
+/** handles requests for the mteTriggerExistenceTable table */
+int
+mteTriggerExistenceTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ struct mteTrigger *entry;
+ int ret;
+
+ DEBUGMSGTL(("disman:event:mib", "Exist Table handler (%d)\n",
+ reqinfo->mode));
+
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ /*
+ * The mteTriggerExistenceTable should only contains entries for
+ * rows where the mteTriggerTest 'existence(0)' bit is set.
+ * So skip entries where this isn't the case.
+ */
+ if (!entry || !(entry->mteTriggerTest & MTE_TRIGGER_EXISTENCE )) {
+ netsnmp_request_set_error(request, SNMP_NOSUCHINSTANCE);
+ continue;
+ }
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGEREXISTENCETEST:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *)&entry->mteTExTest, 1);
+ break;
+ case COLUMN_MTETRIGGEREXISTENCESTARTUP:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *)&entry->mteTExStartup, 1);
+ break;
+ case COLUMN_MTETRIGGEREXISTENCEOBJECTSOWNER:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTExObjOwner,
+ strlen(entry->mteTExObjOwner));
+ break;
+ case COLUMN_MTETRIGGEREXISTENCEOBJECTS:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTExObjects,
+ strlen(entry->mteTExObjects));
+ break;
+ case COLUMN_MTETRIGGEREXISTENCEEVENTOWNER:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTExEvOwner,
+ strlen(entry->mteTExEvOwner));
+ break;
+ case COLUMN_MTETRIGGEREXISTENCEEVENT:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTExEvent,
+ strlen(entry->mteTExEvent));
+ break;
+ }
+ }
+ break;
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ /*
+ * Write-support
+ */
+ case MODE_SET_RESERVE1:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ /*
+ * Since the mteTriggerExistenceTable only contains entries for
+ * rows where the mteTriggerTest 'existence(0)' bit is set,
+ * strictly speaking we should reject assignments where
+ * this isn't the case.
+ * But SET requests that include an assignment of the
+ * 'existence(0)' bit at the same time are valid, so would
+ * need to be accepted. Unfortunately, this assignment
+ * is only applied in the COMMIT pass, so it's difficult
+ * to detect whether this holds or not.
+ *
+ * Let's fudge things for now, by processing assignments
+ * even if the 'existence(0)' bit isn't set.
+ */
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGEREXISTENCETEST:
+ case COLUMN_MTETRIGGEREXISTENCESTARTUP:
+ ret = netsnmp_check_vb_type_and_size(
+ request->requestvb, ASN_OCTET_STR, 1);
+ if (ret != SNMP_ERR_NOERROR ) {
+ netsnmp_set_request_error(reqinfo, request, ret );
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+
+ case COLUMN_MTETRIGGEREXISTENCEOBJECTSOWNER:
+ case COLUMN_MTETRIGGEREXISTENCEOBJECTS:
+ case COLUMN_MTETRIGGEREXISTENCEEVENTOWNER:
+ case COLUMN_MTETRIGGEREXISTENCEEVENT:
+ ret = netsnmp_check_vb_type_and_max_size(
+ request->requestvb, ASN_OCTET_STR, MTE_STR1_LEN);
+ if (ret != SNMP_ERR_NOERROR ) {
+ netsnmp_set_request_error(reqinfo, request, ret );
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+
+ default:
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOTWRITABLE);
+ return SNMP_ERR_NOERROR;
+ }
+
+ /*
+ * The Event MIB is somewhat ambiguous as to whether the
+ * various trigger table entries can be modified once the
+ * main mteTriggerTable entry has been marked 'active'.
+ * But it's clear from discussion on the DisMan mailing
+ * list is that the intention is not.
+ *
+ * So check for whether this row is already active,
+ * and reject *all* SET requests if it is.
+ */
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ if (entry &&
+ entry->flags & MTE_TRIGGER_FLAG_ACTIVE ) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_RESERVE2:
+ case MODE_SET_FREE:
+ case MODE_SET_UNDO:
+ break;
+
+ case MODE_SET_ACTION:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ if (!entry) {
+ /*
+ * New rows must be created via the RowStatus column
+ * (in the main mteTriggerTable)
+ */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ /* or inconsistentName? */
+ return SNMP_ERR_NOERROR;
+
+ }
+ }
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * All these assignments are "unfailable", so it's
+ * (reasonably) safe to apply them in the Commit phase
+ */
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGEREXISTENCETEST:
+ entry->mteTExTest = request->requestvb->val.string[0];
+ break;
+ case COLUMN_MTETRIGGEREXISTENCESTARTUP:
+ entry->mteTExStartup = request->requestvb->val.string[0];
+ break;
+ case COLUMN_MTETRIGGEREXISTENCEOBJECTSOWNER:
+ memset(entry->mteTExObjOwner, 0, sizeof(entry->mteTExObjOwner));
+ memcpy(entry->mteTExObjOwner, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGEREXISTENCEOBJECTS:
+ memset(entry->mteTExObjects, 0, sizeof(entry->mteTExObjects));
+ memcpy(entry->mteTExObjects, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGEREXISTENCEEVENTOWNER:
+ memset(entry->mteTExEvOwner, 0, sizeof(entry->mteTExEvOwner));
+ memcpy(entry->mteTExEvOwner, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGEREXISTENCEEVENT:
+ memset(entry->mteTExEvent, 0, sizeof(entry->mteTExEvent));
+ memcpy(entry->mteTExEvent, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ }
+ }
+ break;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ }
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/event/mteTriggerExistenceTable.h b/agent/mibgroup/disman/event/mteTriggerExistenceTable.h
new file mode 100644
index 0000000..c845660
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTriggerExistenceTable.h
@@ -0,0 +1,23 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.table_data.conf,v 1.8 2005/07/19 14:52:03 dts12 Exp $
+ */
+#ifndef MTETRIGGEREXISTENCETABLE_H
+#define MTETRIGGEREXISTENCETABLE_H
+
+/*
+ * function declarations
+ */
+void init_mteTriggerExistenceTable(void);
+Netsnmp_Node_Handler mteTriggerExistenceTable_handler;
+
+/*
+ * column number definitions for table mteTriggerExistenceTable
+ */
+#define COLUMN_MTETRIGGEREXISTENCETEST 1
+#define COLUMN_MTETRIGGEREXISTENCESTARTUP 2
+#define COLUMN_MTETRIGGEREXISTENCEOBJECTSOWNER 3
+#define COLUMN_MTETRIGGEREXISTENCEOBJECTS 4
+#define COLUMN_MTETRIGGEREXISTENCEEVENTOWNER 5
+#define COLUMN_MTETRIGGEREXISTENCEEVENT 6
+#endif /* MTETRIGGEREXISTENCETABLE_H */
diff --git a/agent/mibgroup/disman/event/mteTriggerTable.c b/agent/mibgroup/disman/event/mteTriggerTable.c
new file mode 100644
index 0000000..88c2f8b
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTriggerTable.c
@@ -0,0 +1,508 @@
+/*
+ * DisMan Event MIB:
+ * Implementation of the mteTriggerTable MIB interface
+ * See 'mteTrigger.c' for active behaviour of this table.
+ *
+ * (based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "utilities/iquery.h"
+#include "disman/event/mteTrigger.h"
+#include "disman/event/mteTriggerTable.h"
+
+netsnmp_feature_require(iquery)
+netsnmp_feature_require(table_tdata)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(iquery_pdu_session)
+netsnmp_feature_require(check_vb_type_and_max_size)
+netsnmp_feature_require(check_vb_oid)
+netsnmp_feature_require(check_vb_uint)
+netsnmp_feature_require(mtetrigger_removeentry)
+netsnmp_feature_require(check_vb_truthvalue)
+netsnmp_feature_require(table_tdata_insert_row)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+static netsnmp_table_registration_info *table_info;
+
+/** Initializes the mteTriggerTable module */
+void
+init_mteTriggerTable(void)
+{
+ static oid mteTriggerTable_oid[] = { 1, 3, 6, 1, 2, 1, 88, 1, 2, 2 };
+ size_t mteTriggerTable_oid_len = OID_LENGTH(mteTriggerTable_oid);
+ netsnmp_handler_registration *reg;
+
+ /*
+ * Ensure the (combined) table container is available...
+ */
+ init_trigger_table_data();
+
+ /*
+ * ... then set up the MIB interface to the mteTriggerTable slice
+ */
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ reg = netsnmp_create_handler_registration("mteTriggerTable",
+ mteTriggerTable_handler,
+ mteTriggerTable_oid,
+ mteTriggerTable_oid_len,
+ HANDLER_CAN_RWRITE);
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+ reg = netsnmp_create_handler_registration("mteTriggerTable",
+ mteTriggerTable_handler,
+ mteTriggerTable_oid,
+ mteTriggerTable_oid_len,
+ HANDLER_CAN_RONLY);
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_OCTET_STR, /* index: mteOwner */
+ /* index: mteTriggerName */
+ ASN_PRIV_IMPLIED_OCTET_STR,
+ 0);
+
+ table_info->min_column = COLUMN_MTETRIGGERCOMMENT;
+ table_info->max_column = COLUMN_MTETRIGGERENTRYSTATUS;
+
+ /* Register this using the (common) trigger_table_data container */
+ netsnmp_tdata_register(reg, trigger_table_data, table_info);
+ DEBUGMSGTL(("disman:event:init", "Trigger Table\n"));
+}
+
+void
+shutdown_mteTriggerTable(void)
+{
+ if (table_info) {
+ netsnmp_table_registration_info_free(table_info);
+ table_info = NULL;
+ }
+}
+
+
+/** handles requests for the mteTriggerTable table */
+int
+mteTriggerTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ netsnmp_tdata_row *row;
+ struct mteTrigger *entry;
+ char mteOwner[MTE_STR1_LEN+1];
+ char mteTName[MTE_STR1_LEN+1];
+ long ret;
+
+ DEBUGMSGTL(("disman:event:mib", "Trigger Table handler (%d)\n",
+ reqinfo->mode));
+
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERCOMMENT:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ entry->mteTriggerComment,
+ strlen(entry->mteTriggerComment));
+ break;
+ case COLUMN_MTETRIGGERTEST:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ &entry->mteTriggerTest, 1);
+ break;
+ case COLUMN_MTETRIGGERSAMPLETYPE:
+ ret = (entry->flags & MTE_TRIGGER_FLAG_DELTA ) ?
+ MTE_SAMPLE_DELTA : MTE_SAMPLE_ABSOLUTE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_MTETRIGGERVALUEID:
+ snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
+ (u_char *) entry->mteTriggerValueID,
+ entry->mteTriggerValueID_len*sizeof(oid));
+ break;
+ case COLUMN_MTETRIGGERVALUEIDWILDCARD:
+ ret = (entry->flags & MTE_TRIGGER_FLAG_VWILD ) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_MTETRIGGERTARGETTAG:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ entry->mteTriggerTarget,
+ strlen(entry->mteTriggerTarget));
+ break;
+ case COLUMN_MTETRIGGERCONTEXTNAME:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ entry->mteTriggerContext,
+ strlen(entry->mteTriggerContext));
+ break;
+ case COLUMN_MTETRIGGERCONTEXTNAMEWILDCARD:
+ ret = (entry->flags & MTE_TRIGGER_FLAG_CWILD ) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_MTETRIGGERFREQUENCY:
+ snmp_set_var_typed_integer(request->requestvb, ASN_UNSIGNED,
+ entry->mteTriggerFrequency);
+ break;
+ case COLUMN_MTETRIGGEROBJECTSOWNER:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ entry->mteTriggerOOwner,
+ strlen(entry->mteTriggerOOwner));
+ break;
+ case COLUMN_MTETRIGGEROBJECTS:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ entry->mteTriggerObjects,
+ strlen(entry->mteTriggerObjects));
+ break;
+ case COLUMN_MTETRIGGERENABLED:
+ ret = (entry->flags & MTE_TRIGGER_FLAG_ENABLED ) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_MTETRIGGERENTRYSTATUS:
+ ret = (entry->flags & MTE_TRIGGER_FLAG_ACTIVE ) ?
+ RS_ACTIVE : RS_NOTINSERVICE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ }
+ }
+ break;
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ /*
+ * Write-support
+ */
+ case MODE_SET_RESERVE1:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERCOMMENT:
+ case COLUMN_MTETRIGGERTARGETTAG:
+ case COLUMN_MTETRIGGERCONTEXTNAME:
+ ret = netsnmp_check_vb_type_and_max_size(
+ request->requestvb, ASN_OCTET_STR, MTE_STR2_LEN);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGERTEST:
+ ret = netsnmp_check_vb_type_and_size(
+ request->requestvb, ASN_OCTET_STR, 1);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGERSAMPLETYPE:
+ ret = netsnmp_check_vb_int_range(request->requestvb,
+ MTE_SAMPLE_ABSOLUTE, MTE_SAMPLE_DELTA);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGERVALUEID:
+ ret = netsnmp_check_vb_oid(request->requestvb);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGERVALUEIDWILDCARD:
+ case COLUMN_MTETRIGGERCONTEXTNAMEWILDCARD:
+ case COLUMN_MTETRIGGERENABLED:
+ ret = netsnmp_check_vb_truthvalue(request->requestvb);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+
+ case COLUMN_MTETRIGGERFREQUENCY:
+ ret = netsnmp_check_vb_uint(request->requestvb);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGEROBJECTSOWNER:
+ case COLUMN_MTETRIGGEROBJECTS:
+ ret = netsnmp_check_vb_type_and_max_size(
+ request->requestvb, ASN_OCTET_STR, MTE_STR1_LEN);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGERENTRYSTATUS:
+ ret = netsnmp_check_vb_rowstatus(request->requestvb,
+ (entry ? RS_ACTIVE : RS_NONEXISTENT));
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ default:
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOTWRITABLE);
+ return SNMP_ERR_NOERROR;
+ }
+
+
+ /*
+ * Once a row has been made active, it cannot be
+ * modified except to delete it. There's no good
+ * reason for this, but that's what the MIB says.
+ *
+ * The published version of the Event MIB even forbids
+ * enabling (or disabling) an active row, which
+ * would make this object completely pointless!
+ * Fortunately this ludicrous decision has since been corrected.
+ */
+ if (entry &&
+ entry->flags & MTE_TRIGGER_FLAG_ACTIVE ) {
+ /* check for the acceptable assignments */
+ if ((tinfo->colnum == COLUMN_MTETRIGGERENABLED) ||
+ (tinfo->colnum == COLUMN_MTETRIGGERENTRYSTATUS &&
+ *request->requestvb->val.integer != RS_NOTINSERVICE))
+ continue;
+
+ /* Otherwise, reject this request */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_RESERVE2:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_CREATEANDGO:
+ case RS_CREATEANDWAIT:
+ /*
+ * Create an (empty) new row structure
+ */
+ memset(mteOwner, 0, sizeof(mteOwner));
+ memcpy(mteOwner, tinfo->indexes->val.string,
+ tinfo->indexes->val_len);
+ memset(mteTName, 0, sizeof(mteTName));
+ memcpy(mteTName,
+ tinfo->indexes->next_variable->val.string,
+ tinfo->indexes->next_variable->val_len);
+
+ row = mteTrigger_createEntry(mteOwner, mteTName, 0);
+ if (!row) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_RESOURCEUNAVAILABLE);
+ return SNMP_ERR_NOERROR;
+ }
+ netsnmp_insert_tdata_row( request, row );
+ }
+ }
+ }
+ break;
+
+ case MODE_SET_FREE:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_CREATEANDGO:
+ case RS_CREATEANDWAIT:
+ /*
+ * Tidy up after a failed row creation request
+ */
+ entry = (struct mteTrigger *)
+ netsnmp_tdata_extract_entry(request);
+ if (entry &&
+ !(entry->flags & MTE_TRIGGER_FLAG_VALID)) {
+ row = (netsnmp_tdata_row *)
+ netsnmp_tdata_extract_row(request);
+ mteTrigger_removeEntry( row );
+ }
+ }
+ }
+ }
+ break;
+
+ case MODE_SET_ACTION:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ if (!entry) {
+ /*
+ * New rows must be created via the RowStatus column
+ */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ /* or inconsistentName? */
+ return SNMP_ERR_NOERROR;
+
+ }
+ }
+ break;
+
+ case MODE_SET_UNDO:
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * All these assignments are "unfailable", so it's
+ * (reasonably) safe to apply them in the Commit phase
+ */
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERCOMMENT:
+ memset(entry->mteTriggerComment, 0,
+ sizeof(entry->mteTriggerComment));
+ memcpy(entry->mteTriggerComment,
+ request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERTEST:
+ entry->mteTriggerTest = request->requestvb->val.string[0];
+ break;
+ case COLUMN_MTETRIGGERSAMPLETYPE:
+ if (*request->requestvb->val.integer == MTE_SAMPLE_DELTA)
+ entry->flags |= MTE_TRIGGER_FLAG_DELTA;
+ else
+ entry->flags &= ~MTE_TRIGGER_FLAG_DELTA;
+ break;
+ case COLUMN_MTETRIGGERVALUEID:
+ memset(entry->mteTriggerValueID, 0,
+ sizeof(entry->mteTriggerValueID));
+ memcpy(entry->mteTriggerValueID,
+ request->requestvb->val.string,
+ request->requestvb->val_len);
+ entry->mteTriggerValueID_len = request->requestvb->val_len/sizeof(oid);
+ break;
+ case COLUMN_MTETRIGGERVALUEIDWILDCARD:
+ if (*request->requestvb->val.integer == TV_TRUE)
+ entry->flags |= MTE_TRIGGER_FLAG_VWILD;
+ else
+ entry->flags &= ~MTE_TRIGGER_FLAG_VWILD;
+ break;
+ case COLUMN_MTETRIGGERTARGETTAG:
+ memset(entry->mteTriggerTarget, 0,
+ sizeof(entry->mteTriggerTarget));
+ memcpy(entry->mteTriggerTarget,
+ request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERCONTEXTNAME:
+ memset(entry->mteTriggerContext, 0,
+ sizeof(entry->mteTriggerContext));
+ memcpy(entry->mteTriggerContext,
+ request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERCONTEXTNAMEWILDCARD:
+ if (*request->requestvb->val.integer == TV_TRUE)
+ entry->flags |= MTE_TRIGGER_FLAG_CWILD;
+ else
+ entry->flags &= ~MTE_TRIGGER_FLAG_CWILD;
+ break;
+ case COLUMN_MTETRIGGERFREQUENCY:
+ entry->mteTriggerFrequency = *request->requestvb->val.integer;
+ break;
+ case COLUMN_MTETRIGGEROBJECTSOWNER:
+ memset(entry->mteTriggerOOwner, 0,
+ sizeof(entry->mteTriggerOOwner));
+ memcpy(entry->mteTriggerOOwner,
+ request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGEROBJECTS:
+ memset(entry->mteTriggerObjects, 0,
+ sizeof(entry->mteTriggerObjects));
+ memcpy(entry->mteTriggerObjects,
+ request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERENABLED:
+ if (*request->requestvb->val.integer == TV_TRUE)
+ entry->flags |= MTE_TRIGGER_FLAG_ENABLED;
+ else
+ entry->flags &= ~MTE_TRIGGER_FLAG_ENABLED;
+ break;
+ case COLUMN_MTETRIGGERENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_ACTIVE:
+ entry->flags |= MTE_TRIGGER_FLAG_ACTIVE;
+ mteTrigger_enable( entry );
+ break;
+ case RS_CREATEANDGO:
+ entry->flags |= MTE_TRIGGER_FLAG_ACTIVE;
+ entry->flags |= MTE_TRIGGER_FLAG_VALID;
+ entry->session =
+ netsnmp_iquery_pdu_session(reqinfo->asp->pdu);
+ mteTrigger_enable( entry );
+ break;
+ case RS_CREATEANDWAIT:
+ entry->flags |= MTE_TRIGGER_FLAG_VALID;
+ entry->session =
+ netsnmp_iquery_pdu_session(reqinfo->asp->pdu);
+ break;
+
+ case RS_DESTROY:
+ row = (netsnmp_tdata_row *)
+ netsnmp_tdata_extract_row(request);
+ mteTrigger_removeEntry(row);
+ }
+ break;
+ }
+ }
+
+ /** set up to save persistent store */
+ snmp_store_needed(NULL);
+
+ break;
+
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ }
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/event/mteTriggerTable.h b/agent/mibgroup/disman/event/mteTriggerTable.h
new file mode 100644
index 0000000..c5c393a
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTriggerTable.h
@@ -0,0 +1,35 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.table_data.conf,v 1.8 2005/07/19 14:52:03 dts12 Exp $
+ */
+#ifndef MTETRIGGERTABLE_H
+#define MTETRIGGERTABLE_H
+
+config_require(utilities/iquery)
+
+/*
+ * function declarations
+ */
+void init_mteTriggerTable(void);
+void shutdown_mteTriggerTable(void);
+Netsnmp_Node_Handler mteTriggerTable_handler;
+
+/*
+ * column number definitions for table mteTriggerTable
+ */
+#define COLUMN_MTEOWNER 1
+#define COLUMN_MTETRIGGERNAME 2
+#define COLUMN_MTETRIGGERCOMMENT 3
+#define COLUMN_MTETRIGGERTEST 4
+#define COLUMN_MTETRIGGERSAMPLETYPE 5
+#define COLUMN_MTETRIGGERVALUEID 6
+#define COLUMN_MTETRIGGERVALUEIDWILDCARD 7
+#define COLUMN_MTETRIGGERTARGETTAG 8
+#define COLUMN_MTETRIGGERCONTEXTNAME 9
+#define COLUMN_MTETRIGGERCONTEXTNAMEWILDCARD 10
+#define COLUMN_MTETRIGGERFREQUENCY 11
+#define COLUMN_MTETRIGGEROBJECTSOWNER 12
+#define COLUMN_MTETRIGGEROBJECTS 13
+#define COLUMN_MTETRIGGERENABLED 14
+#define COLUMN_MTETRIGGERENTRYSTATUS 15
+#endif /* MTETRIGGERTABLE_H */
diff --git a/agent/mibgroup/disman/event/mteTriggerThresholdTable.c b/agent/mibgroup/disman/event/mteTriggerThresholdTable.c
new file mode 100644
index 0000000..5aed0c8
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTriggerThresholdTable.c
@@ -0,0 +1,389 @@
+/*
+ * DisMan Event MIB:
+ * Implementation of the mteTriggerThresholdTable MIB interface
+ * See 'mteTrigger.c' for active behaviour of this table.
+ *
+ * (based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "disman/event/mteTrigger.h"
+#include "disman/event/mteTriggerThresholdTable.h"
+
+netsnmp_feature_require(table_tdata)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(check_vb_type_and_max_size)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+static netsnmp_table_registration_info *table_info;
+
+/** Initializes the mteTriggerThresholdTable module */
+void
+init_mteTriggerThresholdTable(void)
+{
+ static oid mteTThreshTable_oid[] = { 1, 3, 6, 1, 2, 1, 88, 1, 2, 6 };
+ size_t mteTThreshTable_oid_len = OID_LENGTH(mteTThreshTable_oid);
+ netsnmp_handler_registration *reg;
+
+ /*
+ * Ensure the (combined) table container is available...
+ */
+ init_trigger_table_data();
+
+ /*
+ * ... then set up the MIB interface to the mteTriggerThresholdTable slice
+ */
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ reg = netsnmp_create_handler_registration("mteTriggerThresholdTable",
+ mteTriggerThresholdTable_handler,
+ mteTThreshTable_oid,
+ mteTThreshTable_oid_len,
+ HANDLER_CAN_RWRITE);
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+ reg = netsnmp_create_handler_registration("mteTriggerThresholdTable",
+ mteTriggerThresholdTable_handler,
+ mteTThreshTable_oid,
+ mteTThreshTable_oid_len,
+ HANDLER_CAN_RONLY);
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_OCTET_STR, /* index: mteOwner */
+ /* index: mteTriggerName */
+ ASN_PRIV_IMPLIED_OCTET_STR,
+ 0);
+
+ table_info->min_column = COLUMN_MTETRIGGERTHRESHOLDSTARTUP;
+ table_info->max_column = COLUMN_MTETRIGGERTHRESHOLDDELTAFALLINGEVENT;
+
+ /* Register this using the (common) trigger_table_data container */
+ netsnmp_tdata_register(reg, trigger_table_data, table_info);
+ DEBUGMSGTL(("disman:event:init", "Trigger Threshold Table\n"));
+}
+
+void
+shutdown_mteTriggerThresholdTable(void)
+{
+ if (table_info) {
+ netsnmp_table_registration_info_free(table_info);
+ table_info = NULL;
+ }
+}
+
+
+/** handles requests for the mteTriggerThresholdTable table */
+int
+mteTriggerThresholdTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ struct mteTrigger *entry;
+ int ret;
+
+ DEBUGMSGTL(("disman:event:mib", "Threshold Table handler (%d)\n",
+ reqinfo->mode));
+
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ /*
+ * The mteTriggerThresholdTable should only contains entries for
+ * rows where the mteTriggerTest 'threshold(2)' bit is set.
+ * So skip entries where this isn't the case.
+ */
+ if (!entry || !(entry->mteTriggerTest & MTE_TRIGGER_THRESHOLD )) {
+ netsnmp_request_set_error(request, SNMP_NOSUCHINSTANCE);
+ continue;
+ }
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERTHRESHOLDSTARTUP:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->mteTThStartup);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDRISING:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->mteTThRiseValue);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDFALLING:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->mteTThFallValue);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDDELTARISING:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->mteTThDRiseValue);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDDELTAFALLING:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->mteTThDFallValue);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDOBJECTSOWNER:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTThObjOwner,
+ strlen(entry->mteTThObjOwner));
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDOBJECTS:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTThObjects,
+ strlen(entry->mteTThObjects));
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDRISINGEVENTOWNER:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTThRiseOwner,
+ strlen(entry->mteTThRiseOwner));
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDRISINGEVENT:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTThRiseEvent,
+ strlen(entry->mteTThRiseEvent));
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDFALLINGEVENTOWNER:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTThFallOwner,
+ strlen(entry->mteTThFallOwner));
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDFALLINGEVENT:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTThFallEvent,
+ strlen(entry->mteTThFallEvent));
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDDELTARISINGEVENTOWNER:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTThDRiseOwner,
+ strlen(entry->mteTThDRiseOwner));
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDDELTARISINGEVENT:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTThDRiseEvent,
+ strlen(entry->mteTThDRiseEvent));
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDDELTAFALLINGEVENTOWNER:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTThDFallOwner,
+ strlen(entry->mteTThDFallOwner));
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDDELTAFALLINGEVENT:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char *) entry->mteTThDFallEvent,
+ strlen(entry->mteTThDFallEvent));
+ break;
+ }
+ }
+ break;
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ /*
+ * Write-support
+ */
+ case MODE_SET_RESERVE1:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ /*
+ * Since the mteTriggerThresholdTable only contains entries for
+ * rows where the mteTriggerTest 'threshold(2)' bit is set,
+ * strictly speaking we should reject assignments where
+ * this isn't the case.
+ * But SET requests that include an assignment of the
+ * 'threshold(2)' bit at the same time are valid, so would
+ * need to be accepted. Unfortunately, this assignment
+ * is only applied in the COMMIT pass, so it's difficult
+ * to detect whether this holds or not.
+ *
+ * Let's fudge things for now, by processing assignments
+ * even if the 'threshold(2)' bit isn't set.
+ */
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERTHRESHOLDSTARTUP:
+ ret = netsnmp_check_vb_int_range(request->requestvb,
+ MTE_THRESH_START_RISE,
+ MTE_THRESH_START_RISEFALL );
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDRISING:
+ case COLUMN_MTETRIGGERTHRESHOLDFALLING:
+ case COLUMN_MTETRIGGERTHRESHOLDDELTARISING:
+ case COLUMN_MTETRIGGERTHRESHOLDDELTAFALLING:
+ ret = netsnmp_check_vb_int(request->requestvb);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDOBJECTSOWNER:
+ case COLUMN_MTETRIGGERTHRESHOLDOBJECTS:
+ case COLUMN_MTETRIGGERTHRESHOLDRISINGEVENTOWNER:
+ case COLUMN_MTETRIGGERTHRESHOLDRISINGEVENT:
+ case COLUMN_MTETRIGGERTHRESHOLDFALLINGEVENTOWNER:
+ case COLUMN_MTETRIGGERTHRESHOLDFALLINGEVENT:
+ case COLUMN_MTETRIGGERTHRESHOLDDELTARISINGEVENTOWNER:
+ case COLUMN_MTETRIGGERTHRESHOLDDELTARISINGEVENT:
+ case COLUMN_MTETRIGGERTHRESHOLDDELTAFALLINGEVENTOWNER:
+ case COLUMN_MTETRIGGERTHRESHOLDDELTAFALLINGEVENT:
+ ret = netsnmp_check_vb_type_and_max_size(
+ request->requestvb, ASN_OCTET_STR, MTE_STR1_LEN);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ default:
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOTWRITABLE);
+ return SNMP_ERR_NOERROR;
+ }
+
+ /*
+ * The Event MIB is somewhat ambiguous as to whether the
+ * various trigger table entries can be modified once the
+ * main mteTriggerTable entry has been marked 'active'.
+ * But it's clear from discussion on the DisMan mailing
+ * list is that the intention is not.
+ *
+ * So check for whether this row is already active,
+ * and reject *all* SET requests if it is.
+ */
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ if (entry &&
+ entry->flags & MTE_TRIGGER_FLAG_ACTIVE ) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_INCONSISTENTVALUE);
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_RESERVE2:
+ case MODE_SET_FREE:
+ case MODE_SET_UNDO:
+ break;
+
+ case MODE_SET_ACTION:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ if (!entry) {
+ /*
+ * New rows must be created via the RowStatus column
+ * (in the main mteTriggerTable)
+ */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ /* or inconsistentName? */
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * All these assignments are "unfailable", so it's
+ * (reasonably) safe to apply them in the Commit phase
+ */
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct mteTrigger *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_MTETRIGGERTHRESHOLDSTARTUP:
+ entry->mteTThStartup = *request->requestvb->val.integer;
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDRISING:
+ entry->mteTThRiseValue = *request->requestvb->val.integer;
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDFALLING:
+ entry->mteTThFallValue = *request->requestvb->val.integer;
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDDELTARISING:
+ entry->mteTThDRiseValue = *request->requestvb->val.integer;
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDDELTAFALLING:
+ entry->mteTThDFallValue = *request->requestvb->val.integer;
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDOBJECTSOWNER:
+ memset(entry->mteTThObjOwner, 0, sizeof(entry->mteTThObjOwner));
+ memcpy(entry->mteTThObjOwner, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDOBJECTS:
+ memset(entry->mteTThObjects, 0, sizeof(entry->mteTThObjects));
+ memcpy(entry->mteTThObjects, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDRISINGEVENTOWNER:
+ memset(entry->mteTThRiseOwner, 0, sizeof(entry->mteTThRiseOwner));
+ memcpy(entry->mteTThRiseOwner, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDRISINGEVENT:
+ memset(entry->mteTThRiseEvent, 0, sizeof(entry->mteTThRiseEvent));
+ memcpy(entry->mteTThRiseEvent, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDFALLINGEVENTOWNER:
+ memset(entry->mteTThFallOwner, 0, sizeof(entry->mteTThFallOwner));
+ memcpy(entry->mteTThFallOwner, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDFALLINGEVENT:
+ memset(entry->mteTThFallEvent, 0, sizeof(entry->mteTThFallEvent));
+ memcpy(entry->mteTThFallEvent, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDDELTARISINGEVENTOWNER:
+ memset(entry->mteTThDRiseOwner, 0, sizeof(entry->mteTThDRiseOwner));
+ memcpy(entry->mteTThDRiseOwner, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDDELTARISINGEVENT:
+ memset(entry->mteTThDRiseEvent, 0, sizeof(entry->mteTThDRiseEvent));
+ memcpy(entry->mteTThDRiseEvent, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDDELTAFALLINGEVENTOWNER:
+ memset(entry->mteTThDFallOwner, 0, sizeof(entry->mteTThDFallOwner));
+ memcpy(entry->mteTThDFallOwner, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_MTETRIGGERTHRESHOLDDELTAFALLINGEVENT:
+ memset(entry->mteTThDFallEvent, 0, sizeof(entry->mteTThDFallEvent));
+ memcpy(entry->mteTThDFallEvent, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ }
+ }
+ break;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ }
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/event/mteTriggerThresholdTable.h b/agent/mibgroup/disman/event/mteTriggerThresholdTable.h
new file mode 100644
index 0000000..80f5f2a
--- /dev/null
+++ b/agent/mibgroup/disman/event/mteTriggerThresholdTable.h
@@ -0,0 +1,34 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.table_data.conf,v 1.8 2005/07/19 14:52:03 dts12 Exp $
+ */
+#ifndef MTETRIGGERTHRESHOLDTABLE_H
+#define MTETRIGGERTHRESHOLDTABLE_H
+
+/*
+ * function declarations
+ */
+void init_mteTriggerThresholdTable(void);
+void shutdown_mteTriggerThresholdTable(void);
+Netsnmp_Node_Handler mteTriggerThresholdTable_handler;
+
+/*
+ * column number definitions for table mteTriggerThresholdTable
+ */
+#define COLUMN_MTETRIGGERTHRESHOLDSTARTUP 1
+#define COLUMN_MTETRIGGERTHRESHOLDRISING 2
+#define COLUMN_MTETRIGGERTHRESHOLDFALLING 3
+#define COLUMN_MTETRIGGERTHRESHOLDDELTARISING 4
+#define COLUMN_MTETRIGGERTHRESHOLDDELTAFALLING 5
+#define COLUMN_MTETRIGGERTHRESHOLDOBJECTSOWNER 6
+#define COLUMN_MTETRIGGERTHRESHOLDOBJECTS 7
+#define COLUMN_MTETRIGGERTHRESHOLDRISINGEVENTOWNER 8
+#define COLUMN_MTETRIGGERTHRESHOLDRISINGEVENT 9
+#define COLUMN_MTETRIGGERTHRESHOLDFALLINGEVENTOWNER 10
+#define COLUMN_MTETRIGGERTHRESHOLDFALLINGEVENT 11
+#define COLUMN_MTETRIGGERTHRESHOLDDELTARISINGEVENTOWNER 12
+#define COLUMN_MTETRIGGERTHRESHOLDDELTARISINGEVENT 13
+#define COLUMN_MTETRIGGERTHRESHOLDDELTAFALLINGEVENTOWNER 14
+#define COLUMN_MTETRIGGERTHRESHOLDDELTAFALLINGEVENT 15
+
+#endif /* MTETRIGGERTHRESHOLDTABLE_H */
diff --git a/agent/mibgroup/disman/expr/expErrorTable.c b/agent/mibgroup/disman/expr/expErrorTable.c
new file mode 100644
index 0000000..a759e2d
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expErrorTable.c
@@ -0,0 +1,120 @@
+/*
+ * DisMan Expression MIB:
+ * Implementation of the expExpressionErrorTable MIB interface
+ * See 'expExpression.c' for active behaviour of this table.
+ *
+ * (Based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "disman/expr/expExpression.h"
+#include "disman/expr/expErrorTable.h"
+
+netsnmp_feature_require(table_tdata)
+
+/* Initializes the expExpressionErrorTable module */
+void
+init_expErrorTable(void)
+{
+ static oid expErrorTable_oid[] = { 1, 3, 6, 1, 2, 1, 90, 1, 2, 2 };
+ size_t expErrorTable_oid_len = OID_LENGTH(expErrorTable_oid);
+ netsnmp_handler_registration *reg;
+ netsnmp_table_registration_info *table_info;
+
+ /*
+ * Ensure the expression table container is available...
+ */
+ init_expr_table_data();
+
+ /*
+ * ... then set up the MIB interface to the expExpressionErrorTable slice
+ */
+ reg = netsnmp_create_handler_registration("expErrorTable",
+ expErrorTable_handler,
+ expErrorTable_oid,
+ expErrorTable_oid_len,
+ HANDLER_CAN_RWRITE);
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ /* index: expExpressionOwner */
+ ASN_OCTET_STR,
+ /* index: expExpressionName */
+ ASN_OCTET_STR,
+ 0);
+
+ table_info->min_column = COLUMN_EXPERRORTIME;
+ table_info->max_column = COLUMN_EXPERRORINSTANCE;
+
+ /* Register this using the (common) expr_table_data container */
+ netsnmp_tdata_register(reg, expr_table_data, table_info);
+ DEBUGMSGTL(("disman:expr:init", "Expression Error Table container (%p)\n",
+ expr_table_data));
+}
+
+
+/** handles requests for the expExpressionErrorTable table */
+int
+expErrorTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ struct expExpression *entry;
+
+ DEBUGMSGTL(("disman:expr:mib", "Expression Error Table handler (%d)\n",
+ reqinfo->mode));
+
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct expExpression *)
+ netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+ if (!entry || !(entry->flags & EXP_FLAG_VALID))
+ continue;
+
+ /*
+ * "Entries only appear in this table ... when there
+ * has been an error for that [matching] expression"
+ */
+ if (entry->expErrorCount == 0)
+ continue;
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPERRORTIME:
+ snmp_set_var_typed_integer(request->requestvb, ASN_TIMETICKS,
+ entry->expErrorTime);
+ break;
+ case COLUMN_EXPERRORINDEX:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->expErrorIndex);
+ break;
+ case COLUMN_EXPERRORCODE:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->expErrorCode);
+ break;
+ case COLUMN_EXPERRORINSTANCE:
+ snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
+ (u_char *) entry->expErrorInstance,
+ entry->expErrorInst_len*sizeof(oid));
+ break;
+ }
+ }
+ break;
+ }
+ DEBUGMSGTL(("disman:expr:mib", "Expression Error handler - done \n"));
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/expr/expErrorTable.h b/agent/mibgroup/disman/expr/expErrorTable.h
new file mode 100644
index 0000000..1d8339e
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expErrorTable.h
@@ -0,0 +1,21 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.table_data.conf,v 1.11 2005/09/16 11:48:12 dts12 Exp $
+ */
+#ifndef EXPEXPRESSIONERRORTABLE_H
+#define EXPEXPRESSIONERRORTABLE_H
+
+/*
+ * function declarations
+ */
+void init_expErrorTable(void);
+Netsnmp_Node_Handler expErrorTable_handler;
+
+/*
+ * column number definitions for table expExpressionErrorTable
+ */
+#define COLUMN_EXPERRORTIME 1
+#define COLUMN_EXPERRORINDEX 2
+#define COLUMN_EXPERRORCODE 3
+#define COLUMN_EXPERRORINSTANCE 4
+#endif /* EXPEXPRESSIONERRORTABLE_H */
diff --git a/agent/mibgroup/disman/expr/expExpression.c b/agent/mibgroup/disman/expr/expExpression.c
new file mode 100644
index 0000000..c924141
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expExpression.c
@@ -0,0 +1,365 @@
+/*
+ * DisMan Expression MIB:
+ * Core implementation of the expression 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/expr/expExpression.h"
+#include "disman/expr/expObject.h"
+
+netsnmp_tdata *expr_table_data;
+
+ /*
+ * Initializes the container for the expExpression table,
+ * regardless of which module initialisation routine is called first.
+ */
+void
+init_expr_table_data(void)
+{
+ DEBUGMSGTL(("disman:expr:init", "init expression container\n"));
+ if (!expr_table_data) {
+ expr_table_data = netsnmp_tdata_create_table("expExpressionTable", 0);
+ DEBUGMSGTL(("disman:expr:init", "create expression container (%p)\n",
+ expr_table_data));
+ }
+}
+
+/** Initialize the expExpression module */
+void
+init_expExpression(void)
+{
+ init_expr_table_data();
+}
+
+
+ /* ===================================================
+ *
+ * APIs for maintaining the contents of the
+ * expression table container.
+ *
+ * =================================================== */
+
+void
+_mteExpr_dump(void)
+{
+ struct mteExpression *entry;
+ netsnmp_tdata_row *row;
+ int i = 0;
+
+ for (row = netsnmp_tdata_row_first(expr_table_data);
+ row;
+ row = netsnmp_tdata_row_next(expr_table_data, row)) {
+ entry = (struct mteExpression *)row->data;
+ DEBUGMSGTL(("disman:expr:dump", "ExpressionTable entry %d: ", i));
+ DEBUGMSGOID(("disman:expr:dump", row->oid_index.oids, row->oid_index.len));
+ DEBUGMSG(("disman:expr:dump", "(%s, %s)",
+ row->indexes->val.string,
+ row->indexes->next_variable->val.string));
+ DEBUGMSG(("disman:expr:dump", ": %p, %p\n", row, entry));
+ i++;
+ }
+ DEBUGMSGTL(("disman:expr:dump", "ExpressionTable %d entries\n", i));
+}
+
+
+
+/*
+ * Create a new row in the expression table
+ */
+struct expExpression *
+expExpression_createEntry(const char *expOwner, const char *expName, int fixed)
+{
+ netsnmp_tdata_row *row;
+
+ row = expExpression_createRow(expOwner, expName, fixed);
+ return row ? (struct expExpression *)row->data : NULL;
+}
+
+
+netsnmp_tdata_row *
+expExpression_createRow(const char *expOwner, const char *expName, int fixed)
+{
+ struct expExpression *entry;
+ netsnmp_tdata_row *row;
+ size_t expOwner_len = (expOwner) ? strlen(expOwner) : 0;
+ size_t expName_len = (expName) ? strlen(expName) : 0;
+
+ /*
+ * Create the expExpression entry, and the
+ * (table-independent) row wrapper structure...
+ */
+ entry = SNMP_MALLOC_TYPEDEF(struct expExpression);
+ 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 (expOwner)
+ memcpy(entry->expOwner, expOwner, expOwner_len);
+ netsnmp_tdata_row_add_index(row, ASN_OCTET_STR,
+ entry->expOwner, expOwner_len);
+ if (expName)
+ memcpy(entry->expName, expName, expName_len);
+ netsnmp_tdata_row_add_index(row, ASN_OCTET_STR,
+ entry->expName, expName_len);
+
+ entry->expValueType = EXPVALTYPE_COUNTER;
+ entry->expErrorCount = 0;
+ if (fixed)
+ entry->flags |= EXP_FLAG_FIXED;
+
+ /*
+ * ... and insert the row into the table container.
+ */
+ netsnmp_tdata_add_row(expr_table_data, row);
+ DEBUGMSGTL(("disman:expr:table", "Expression entry created (%s, %s)\n",
+ expOwner, expName));
+ return row;
+}
+
+/*
+ * Remove a row from the expression table
+ */
+void
+expExpression_removeEntry(netsnmp_tdata_row *row)
+{
+ struct expExpression *entry;
+
+ if (!row)
+ return; /* Nothing to remove */
+ entry = (struct expExpression *)
+ netsnmp_tdata_remove_and_delete_row(expr_table_data, row);
+ if (entry) {
+ /* expExpression_disable( entry ) */
+ SNMP_FREE(entry);
+ }
+}
+
+
+struct expExpression *
+expExpression_getFirstEntry( void )
+{
+ return (struct expExpression *)
+ netsnmp_tdata_row_entry(netsnmp_tdata_row_first(expr_table_data));
+}
+
+struct expExpression *
+expExpression_getNextEntry(const char *owner, const char *name )
+{
+ netsnmp_variable_list owner_var, name_var;
+
+ memset(&owner_var, 0, sizeof(netsnmp_variable_list));
+ memset(&name_var, 0, sizeof(netsnmp_variable_list));
+ snmp_set_var_typed_value( &owner_var, ASN_OCTET_STR,
+ (const u_char*)owner, strlen(owner));
+ snmp_set_var_typed_value( &name_var, ASN_OCTET_STR,
+ (const u_char*)name, strlen(name));
+ owner_var.next_variable = &name_var;
+
+ return (struct expExpression *)
+ netsnmp_tdata_row_entry(
+ netsnmp_tdata_row_next_byidx(expr_table_data, &owner_var));
+}
+
+struct expExpression *
+expExpression_getEntry(const char *owner, const char *name )
+{
+ netsnmp_variable_list owner_var, name_var;
+
+ memset(&owner_var, 0, sizeof(netsnmp_variable_list));
+ memset(&name_var, 0, sizeof(netsnmp_variable_list));
+ snmp_set_var_typed_value( &owner_var, ASN_OCTET_STR,
+ (const u_char*)owner, strlen(owner));
+ snmp_set_var_typed_value( &name_var, ASN_OCTET_STR,
+ (const u_char*)name, strlen(name));
+ owner_var.next_variable = &name_var;
+
+ return (struct expExpression *)
+ netsnmp_tdata_row_entry(
+ netsnmp_tdata_row_get_byidx(expr_table_data, &owner_var));
+}
+
+
+ /* ===================================================
+ *
+ * APIs for evaluating an expression - data gathering
+ *
+ * =================================================== */
+
+
+
+/*
+ * Gather the data necessary for evaluating an expression.
+ *
+ * This will retrieve *all* the data relevant for all
+ * instances of this expression, rather than just the
+ * just the values needed for expanding a given instance.
+ */
+void
+expExpression_getData( unsigned int reg, void *clientarg )
+{
+ struct expExpression *entry = (struct expExpression *)clientarg;
+ netsnmp_tdata_row *row;
+ netsnmp_variable_list *var;
+ int ret;
+
+ if ( !entry && reg ) {
+ snmp_alarm_unregister( reg );
+ return;
+ }
+
+ if (( entry->expExpression[0] == '\0' ) ||
+ !(entry->flags & EXP_FLAG_ACTIVE) ||
+ !(entry->flags & EXP_FLAG_VALID))
+ return;
+
+ DEBUGMSGTL(("disman:expr:run", "Gathering expression data (%s, %s)\n",
+ entry->expOwner, entry->expName));
+
+ /*
+ * This routine can be called in two situations:
+ * - regularly by 'snmp_alarm' (reg != 0)
+ * (as part of ongoing delta-value sampling)
+ * - on-demand (reg == 0)
+ * (for evaluating a particular entry)
+ *
+ * If a regularly sampled expression (entry->alarm != 0)
+ * is invoked on-demand (reg == 0), then use the most
+ * recent sampled values, rather than retrieving them again.
+ */
+ if ( !reg && entry->alarm )
+ return;
+
+ /*
+ * XXX - may want to implement caching for on-demand evaluation
+ * of non-regularly sampled expressions.
+ */
+
+ /*
+ * For a wildcarded expression, expExpressionPrefix is used
+ * to determine which object instances to retrieve.
+ * (For a non-wildcarded expression, we already know
+ * explicitly which object instances will be needed).
+ *
+ * If we walk this object here, then the results can be
+ * used to build the necessary GET requests for each
+ * individual parameter object (within expObject_getData)
+ *
+ * This will probably be simpler (and definitely more efficient)
+ * than walking the object instances separately and merging
+ * merging the results).
+ *
+ * NB: Releasing any old results is handled by expObject_getData.
+ * Assigning to 'entry->pvars' without first releasing the
+ * previous contents does *not* introduce a memory leak.
+ */
+ if ( entry->expPrefix_len ) {
+ var = (netsnmp_variable_list *)
+ SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ snmp_set_var_objid( var, entry->expPrefix, entry->expPrefix_len);
+ ret = netsnmp_query_walk( var, entry->session );
+ DEBUGMSGTL(("disman:expr:run", "Walk returned %d\n", ret ));
+ entry->pvars = var;
+ }
+
+ /* XXX - retrieve sysUpTime.0 value, and check for discontinuity */
+ /*
+ entry->flags &= ~EXP_FLAG_SYSUT;
+ var = (netsnmp_variable_list *)
+ SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ snmp_set_var_objid( var, sysUT_oid, sysUT_oid_len );
+ netsnmp_query_get( var, entry->session );
+ if ( *var->val.integer != entry->sysUpTime ) {
+ entry->flags |= EXP_FLAG_SYSUT;
+ entry->sysUpTime = *var->val.integer;
+ }
+ snmp_free_varbind(var);
+ */
+
+ /*
+ * Loop through the list of relevant objects,
+ * and retrieve the corresponding values.
+ */
+ for ( row = expObject_getFirst( entry->expOwner, entry->expName );
+ row;
+ row = expObject_getNext( row )) {
+
+ /* XXX - may need to check whether owner/name still match */
+ expObject_getData( entry, (struct expObject *)row->data);
+ }
+}
+
+
+void
+expExpression_enable( struct expExpression *entry )
+{
+ DEBUGMSG(("disman:expr:run", "Enabling %s\n", entry->expName));
+ if (!entry)
+ return;
+
+ if (entry->alarm) {
+ /* or explicitly call expExpression_disable ?? */
+ snmp_alarm_unregister( entry->alarm );
+ entry->alarm = 0;
+ }
+
+ if (entry->expDeltaInterval) {
+ entry->alarm = snmp_alarm_register(
+ entry->expDeltaInterval, SA_REPEAT,
+ expExpression_getData, entry );
+ expExpression_getData( entry->alarm, (void*)entry );
+ }
+}
+
+void
+expExpression_disable( struct expExpression *entry )
+{
+ if (!entry)
+ return;
+
+ if (entry->alarm) {
+ snmp_alarm_unregister( entry->alarm );
+ entry->alarm = 0;
+ /* Perhaps release any previous results ?? */
+ }
+}
+
+
+long _expExpression_MaxCount = 0;
+long _expExpression_countEntries(void)
+{
+ struct expExpression *entry;
+ netsnmp_tdata_row *row;
+ long count = 0;
+
+ for (row = netsnmp_tdata_row_first(expr_table_data);
+ row;
+ row = netsnmp_tdata_row_next(expr_table_data, row)) {
+ entry = (struct expExpression *)row->data;
+ count += entry->count;
+ }
+
+ return count;
+}
+
+long expExpression_getNumEntries(int max)
+{
+ long count;
+ /* XXX - implement some form of caching ??? */
+ count = _expExpression_countEntries();
+ if ( count > _expExpression_MaxCount )
+ _expExpression_MaxCount = count;
+
+ return ( max ? _expExpression_MaxCount : count);
+}
diff --git a/agent/mibgroup/disman/expr/expExpression.h b/agent/mibgroup/disman/expr/expExpression.h
new file mode 100644
index 0000000..282e2bf
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expExpression.h
@@ -0,0 +1,91 @@
+#ifndef EXPEXPRESSION_H
+#define EXPEXPRESSION_H
+
+#include "disman/expr/exp_enum.h"
+
+ /*
+ * Flags relating to the expression table ....
+ */
+#define EXP_FLAG_ACTIVE 0x01 /* for expExpressionEntryStatus */
+#define EXP_FLAG_FIXED 0x02 /* for snmpd.conf persistence */
+#define EXP_FLAG_VALID 0x04 /* for row creation/undo */
+#define EXP_FLAG_SYSUT 0x08 /* sysUpTime.0 discontinuity */
+
+ /*
+ * Standard lengths for various Expression-MIB OCTET STRING objects:
+ * short tags ( 32 characters)
+ * SnmpAdminString-style values (255 characters)
+ * "long" DisplayString values (1024 characters)
+ */
+#define EXP_STR1_LEN 32
+#define EXP_STR2_LEN 255
+#define EXP_STR3_LEN 1024
+
+/*
+ * Data structure for an expression row.
+ * Covers both expExpressionTable and expErrorTable
+ */
+struct expExpression {
+ /*
+ * Index values
+ */
+ char expOwner[ EXP_STR1_LEN+1 ];
+ char expName[ EXP_STR1_LEN+1 ];
+
+ /*
+ * Column values for the main expExpressionTable
+ */
+ char expExpression[ EXP_STR3_LEN+1 ];
+ char expComment[ EXP_STR2_LEN+1 ];
+ oid expPrefix[ MAX_OID_LEN ];
+ size_t expPrefix_len;
+ long expValueType;
+ long expDeltaInterval;
+ u_long expErrorCount;
+
+ /*
+ * Column values for the expExpressionErrorTable
+ */
+ u_long expErrorTime;
+ long expErrorIndex;
+ long expErrorCode;
+ oid expErrorInstance[ MAX_OID_LEN ];
+ size_t expErrorInst_len;
+
+ unsigned int alarm;
+ netsnmp_session *session;
+ netsnmp_variable_list *pvars; /* expPrefix values */
+ long sysUpTime;
+ long count;
+ long flags;
+};
+
+
+ /*
+ * Container structure for the expExpressionTable,
+ * and initialisation routine to create this.
+ */
+extern netsnmp_tdata *expr_table_data;
+extern void init_expr_table_data(void);
+
+/*
+ * function declarations
+ */
+void init_expExpression(void);
+
+struct expExpression *expExpression_createEntry(const char *, const char *, int);
+netsnmp_tdata_row *expExpression_createRow(const char *, const char *, int);
+void expExpression_removeEntry( netsnmp_tdata_row *);
+
+struct expExpression *expExpression_getEntry(const char *, const char *);
+struct expExpression *expExpression_getFirstEntry( void );
+struct expExpression *expExpression_getNextEntry(const char *, const char *);
+
+void expExpression_enable( struct expExpression *);
+void expExpression_disable( struct expExpression *);
+
+void expExpression_getData( unsigned int, void *);
+void expExpression_evaluate(struct expExpression *);
+long expExpression_getNumEntries(int);
+
+#endif /* EXPEXPRESSIONTABLE_H */
diff --git a/agent/mibgroup/disman/expr/expExpressionConf.c b/agent/mibgroup/disman/expr/expExpressionConf.c
new file mode 100644
index 0000000..5c08c72
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expExpressionConf.c
@@ -0,0 +1,292 @@
+/*
+ * DisMan Expression MIB:
+ * Implementation of the expression table configuration handling.
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include <ctype.h>
+
+#include "utilities/iquery.h"
+#include "disman/expr/expExpression.h"
+#include "disman/expr/expObject.h"
+#include "disman/expr/expExpressionConf.h"
+
+netsnmp_feature_require(iquery)
+
+/* Initializes the expExpressionConf module */
+void
+init_expExpressionConf(void)
+{
+ init_expr_table_data();
+
+ /*
+ * Register config handler for user-level (fixed) expressions...
+ * XXX - TODO
+ */
+ snmpd_register_config_handler("expression", parse_expression, NULL, NULL);
+
+ /*
+ * ... and persistent storage of dynamically configured entries.
+ */
+ snmpd_register_config_handler("_expETable", parse_expETable, NULL, NULL);
+
+ /*
+ * Register to save (non-fixed) entries when the agent shuts down
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_expETable, NULL);
+}
+
+
+
+/* ================================================
+ *
+ * Handlers for loading/storing persistent expression entries
+ *
+ * ================================================ */
+
+char *
+_parse_expECols( char *line, struct expExpression *entry )
+{
+ void *vp;
+ size_t tmp;
+ size_t len;
+
+ len = EXP_STR3_LEN; vp = entry->expExpression;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ entry->expValueType = tmp;
+
+ len = EXP_STR2_LEN; vp = entry->expComment;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ entry->expDeltaInterval = tmp;
+
+ vp = entry->expPrefix;
+ entry->expPrefix_len = MAX_OID_LEN;
+ line = read_config_read_data(ASN_OBJECT_ID, line, &vp,
+ &entry->expPrefix_len);
+
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ entry->flags |= (tmp & EXP_FLAG_ACTIVE);
+
+ return line;
+}
+
+
+void
+parse_expression(const char *token, char *line)
+{
+ char buf[ SPRINT_MAX_LEN];
+ char ename[EXP_STR1_LEN+1];
+ oid name_buf[MAX_OID_LEN];
+ size_t name_len;
+ char *cp, *cp2;
+ struct expExpression *entry;
+ struct expObject *object;
+ netsnmp_session *sess = NULL;
+ int type=EXPVALTYPE_COUNTER;
+ int i=1;
+
+ DEBUGMSGTL(("disman:expr:conf", "Parsing expression config... "));
+
+ memset(buf, 0, sizeof(buf));
+ memset(ename, 0, sizeof(ename));
+
+ for (cp = copy_nword(line, buf, SPRINT_MAX_LEN);
+ ;
+ cp = copy_nword(cp, buf, SPRINT_MAX_LEN)) {
+
+ if (buf[0] == '-' ) {
+ switch (buf[1]) {
+ case 't': /* type */
+ switch (buf[2]) {
+ case 'c': type = EXPVALTYPE_COUNTER; break;
+ case 'u': type = EXPVALTYPE_UNSIGNED; break;
+ case 't': type = EXPVALTYPE_TIMETICKS; break;
+ case 'i': type = EXPVALTYPE_INTEGER; break;
+ case 'a': type = EXPVALTYPE_IPADDRESS; break;
+ case 's': type = EXPVALTYPE_STRING; break;
+ case 'o': type = EXPVALTYPE_OID; break;
+ case 'C': type = EXPVALTYPE_COUNTER64; break;
+ }
+ break;
+ case 'u': /* user */
+ cp = copy_nword(cp, buf, SPRINT_MAX_LEN);
+ sess = netsnmp_iquery_user_session(buf);
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ memcpy(ename, buf, sizeof(ename));
+ /* cp = copy_nword(line, ename, sizeof(ename)); */
+ entry = expExpression_createEntry( "snmpd.conf", ename, 1 );
+ if (!entry)
+ return;
+
+ cp2 = entry->expExpression;
+ while (cp && *cp) {
+ /*
+ * Copy everything that can't possibly be a MIB
+ * object name into the expression field...
+ */
+ /* XXX - TODO - Handle string literals */
+ if (!isalpha(*cp)) {
+ *cp2++ = *cp++;
+ continue;
+ }
+ /*
+ * ... and copy the defined functions across as well
+ * XXX - TODO
+ */
+
+ /*
+ * Anything else is presumably a MIB object (or instance).
+ * Create an entry in the expObjectTable, and insert a
+ * corresponding parameter in the expression itself.
+ */
+ name_len = MAX_OID_LEN;
+ cp = copy_nword(cp, buf, SPRINT_MAX_LEN);
+ snmp_parse_oid( buf, name_buf, &name_len );
+ object = expObject_createEntry( "snmpd.conf", ename, i, 1 );
+ memcpy( object->expObjectID, name_buf, name_len*sizeof(oid));
+ object->expObjectID_len = name_len;
+ object->flags |= EXP_OBJ_FLAG_VALID
+ | EXP_OBJ_FLAG_ACTIVE
+ | EXP_OBJ_FLAG_OWILD;
+ /*
+ * The first such object can also be used as the
+ * expExpressionPrefix
+ */
+ if ( i == 1 ) {
+ memcpy( entry->expPrefix, name_buf, name_len*sizeof(oid));
+ entry->expPrefix_len = name_len;
+ object->flags |= EXP_OBJ_FLAG_PREFIX;
+ }
+ sprintf(cp2, "$%d", i++);
+ while (*cp2)
+ cp2++; /* Skip over this parameter */
+ }
+
+ if (sess)
+ entry->session = sess;
+ else
+ entry->session = netsnmp_query_get_default_session();
+ entry->expDeltaInterval = 10;
+ entry->expValueType = type;
+ entry->flags |= EXP_FLAG_VALID
+ | EXP_FLAG_ACTIVE;
+ expExpression_enable( entry );
+ DEBUGMSG(("disman:expr:conf", "(%s, %s)\n", ename,
+ entry->expExpression));
+}
+
+void
+parse_expETable(const char *token, char *line)
+{
+ char owner[EXP_STR1_LEN+1];
+ char ename[EXP_STR1_LEN+1];
+ void *vp;
+ size_t len;
+ struct expExpression *entry;
+
+ DEBUGMSGTL(("disman:expr:conf", "Parsing mteExpressionTable config... "));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( ename, 0, sizeof(ename));
+ len = EXP_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = EXP_STR1_LEN; vp = ename;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ entry = expExpression_createEntry( owner, ename, 0 );
+
+ DEBUGMSG(("disman:expr:conf", "(%s, %s) ", owner, ename));
+
+ /*
+ * Read in the accessible column values.
+ */
+ line = _parse_expECols( line, entry );
+ /*
+ * XXX - Will need to read in the 'iquery' access information
+ */
+ entry->flags |= EXP_FLAG_VALID;
+
+ DEBUGMSG(("disman:expr:conf", "\n"));
+}
+
+
+int
+store_expETable(int majorID, int minorID, void *serverarg, void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr, *cp;
+ void *vp;
+ size_t tint;
+ netsnmp_tdata_row *row;
+ struct expExpression *entry;
+
+
+ DEBUGMSGTL(("disman:expr:conf", "Storing expExpressionTable config:\n"));
+
+ for (row = netsnmp_tdata_row_first( expr_table_data );
+ row;
+ row = netsnmp_tdata_row_next( expr_table_data, row )) {
+
+ /*
+ * Skip entries that were set up via static config directives
+ */
+ entry = (struct expExpression *)netsnmp_tdata_row_entry( row );
+ if ( entry->flags & EXP_FLAG_FIXED )
+ continue;
+
+ DEBUGMSGTL(("disman:expr:conf", " Storing (%s %s)\n",
+ entry->expOwner, entry->expName));
+
+ /*
+ * Save the basic expExpression entry
+ */
+ memset(line, 0, sizeof(line));
+ strcat(line, "_expETable ");
+ cptr = line + strlen(line);
+
+ cp = entry->expOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->expName; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+
+ cp = entry->expExpression; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ tint = entry->expValueType;
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+ cp = entry->expComment; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ tint = entry->expDeltaInterval;
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+
+ vp = entry->expPrefix;
+ tint = entry->expPrefix_len;
+ cptr = read_config_store_data( ASN_OBJECT_ID, cptr, &vp, &tint );
+
+ tint = entry->flags;
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+
+ /* XXX - Need to store the 'iquery' access information */
+ snmpd_store_config(line);
+ }
+
+ DEBUGMSGTL(("disman:expr:conf", " done.\n"));
+ return SNMPERR_SUCCESS;
+}
diff --git a/agent/mibgroup/disman/expr/expExpressionConf.h b/agent/mibgroup/disman/expr/expExpressionConf.h
new file mode 100644
index 0000000..2729109
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expExpressionConf.h
@@ -0,0 +1,10 @@
+#ifndef EXPEXPRESSIONCONF_H
+#define EXPEXPRESSIONCONF_H
+
+void init_expExpressionConf(void);
+
+void parse_expression(const char *, char *);
+void parse_expETable( const char *, char *);
+SNMPCallback store_expETable;
+
+#endif /* EXPEXPRESSIONCONF_H */
diff --git a/agent/mibgroup/disman/expr/expExpressionTable.c b/agent/mibgroup/disman/expr/expExpressionTable.c
new file mode 100644
index 0000000..79aa715
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expExpressionTable.c
@@ -0,0 +1,364 @@
+/*
+ * DisMan Expression MIB:
+ * Implementation of the expExpressionTable MIB interface
+ * See 'expExpression.c' for active behaviour of this table.
+ *
+ * (Based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "utilities/iquery.h"
+#include "disman/expr/expExpression.h"
+#include "disman/expr/expExpressionTable.h"
+
+netsnmp_feature_require(iquery)
+netsnmp_feature_require(table_tdata)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(check_vb_type_and_max_size)
+netsnmp_feature_require(table_tdata_insert_row)
+netsnmp_feature_require(iquery_pdu_session)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+/* Initializes the expExpressionTable module */
+void
+init_expExpressionTable(void)
+{
+ static oid expExpressionTable_oid[] = { 1, 3, 6, 1, 2, 1, 90, 1, 2, 1 };
+ size_t expExpressionTable_oid_len = OID_LENGTH(expExpressionTable_oid);
+ netsnmp_handler_registration *reg;
+ netsnmp_table_registration_info *table_info;
+
+ /*
+ * Ensure the expression table container is available...
+ */
+ init_expr_table_data();
+
+ /*
+ * ... then set up the MIB interface to the expExpressionTable slice
+ */
+ reg = netsnmp_create_handler_registration("expExpressionTable",
+ expExpressionTable_handler,
+ expExpressionTable_oid,
+ expExpressionTable_oid_len,
+ HANDLER_CAN_RWRITE);
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ /* index: expExpressionOwner */
+ ASN_OCTET_STR,
+ /* index: expExpressionName */
+ ASN_OCTET_STR,
+ 0);
+
+ table_info->min_column = COLUMN_EXPEXPRESSION;
+ table_info->max_column = COLUMN_EXPEXPRESSIONENTRYSTATUS;
+
+ /* Register this using the (common) expr_table_data container */
+ netsnmp_tdata_register(reg, expr_table_data, table_info);
+ DEBUGMSGTL(("disman:expr:init", "Expression Table container (%p)\n",
+ expr_table_data));
+}
+
+
+/** handles requests for the expExpressionTable table */
+int
+expExpressionTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ netsnmp_tdata_row *row;
+ struct expExpression *entry;
+ char expOwner[EXP_STR1_LEN+1];
+ char expName[ EXP_STR1_LEN+1];
+ long ret;
+
+ DEBUGMSGTL(("disman:expr:mib", "Expression Table handler (%d)\n",
+ reqinfo->mode));
+
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct expExpression *)
+ netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+ if (!entry || !(entry->flags & EXP_FLAG_VALID))
+ continue;
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPEXPRESSION:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char*)entry->expExpression,
+ strlen(entry->expExpression));
+ break;
+ case COLUMN_EXPEXPRESSIONVALUETYPE:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->expValueType);
+ break;
+ case COLUMN_EXPEXPRESSIONCOMMENT:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ (u_char*)entry->expComment,
+ strlen(entry->expComment));
+ break;
+ case COLUMN_EXPEXPRESSIONDELTAINTERVAL:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->expDeltaInterval);
+ break;
+ case COLUMN_EXPEXPRESSIONPREFIX:
+ /*
+ * XXX - Need to search expObjectTable for a suitable OID
+ */
+ /*
+ * Empty OIDs (len=0) are converted into .0.0
+ * by the SNMP library automatically :-(
+ */
+ if ( entry->expPrefix_len ) {
+ snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
+ (u_char *) entry->expPrefix,
+ entry->expPrefix_len*sizeof(oid));
+ } else {
+ /* XXX - possibly not needed */
+ request->requestvb->type = ASN_OBJECT_ID;
+ request->requestvb->val_len = 0;
+ }
+ break;
+ case COLUMN_EXPEXPRESSIONERRORS:
+ snmp_set_var_typed_integer(request->requestvb, ASN_COUNTER,
+ entry->expErrorCount);
+ break;
+ case COLUMN_EXPEXPRESSIONENTRYSTATUS:
+ /* What would indicate 'notReady' ? */
+ ret = (entry->flags & EXP_FLAG_ACTIVE) ?
+ RS_ACTIVE : RS_NOTINSERVICE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ }
+ }
+ break;
+
+ /*
+ * Write-support
+ */
+ case MODE_SET_RESERVE1:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct expExpression *)
+ netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPEXPRESSION:
+ ret = netsnmp_check_vb_type_and_max_size(
+ request->requestvb, ASN_OCTET_STR, EXP_STR3_LEN);
+ /* XXX - check new expression is syntactically valid */
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_EXPEXPRESSIONVALUETYPE:
+ ret = netsnmp_check_vb_int_range(request->requestvb, 1, 8);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_EXPEXPRESSIONCOMMENT:
+ ret = netsnmp_check_vb_type_and_max_size(
+ request->requestvb, ASN_OCTET_STR, EXP_STR2_LEN);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_EXPEXPRESSIONDELTAINTERVAL:
+ ret = netsnmp_check_vb_int_range(request->requestvb, 0, 86400);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_EXPEXPRESSIONENTRYSTATUS:
+ ret = netsnmp_check_vb_rowstatus(request->requestvb,
+ (entry ? RS_ACTIVE : RS_NONEXISTENT));
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ default:
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOTWRITABLE);
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_RESERVE2:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPEXPRESSIONENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_CREATEANDGO:
+ case RS_CREATEANDWAIT:
+ /*
+ * Create an (empty) new row structure
+ */
+ memset(expOwner, 0, sizeof(expOwner));
+ memcpy(expOwner, tinfo->indexes->val.string,
+ tinfo->indexes->val_len);
+ memset(expName, 0, sizeof(expName));
+ memcpy(expName,
+ tinfo->indexes->next_variable->val.string,
+ tinfo->indexes->next_variable->val_len);
+
+ row = expExpression_createRow(expOwner, expName, 0);
+ if (!row) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_RESOURCEUNAVAILABLE);
+ return SNMP_ERR_NOERROR;
+ }
+ netsnmp_insert_tdata_row( request, row );
+ }
+ }
+ }
+ break;
+
+ case MODE_SET_FREE:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPEXPRESSIONENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_CREATEANDGO:
+ case RS_CREATEANDWAIT:
+ /*
+ * Tidy up after a failed row creation request
+ */
+ entry = (struct expExpression *)
+ netsnmp_tdata_extract_entry(request);
+ if (entry &&
+ !(entry->flags & EXP_FLAG_VALID)) {
+ row = (netsnmp_tdata_row *)
+ netsnmp_tdata_extract_row(request);
+ expExpression_removeEntry( row );
+ }
+ }
+ }
+ }
+ break;
+
+ case MODE_SET_ACTION:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+ entry = (struct expExpression *)
+ netsnmp_tdata_extract_entry(request);
+ if (!entry) {
+ /*
+ * New rows must be created via the RowStatus column
+ */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ /* or inconsistentName? */
+ return SNMP_ERR_NOERROR;
+
+ }
+ }
+ break;
+
+ case MODE_SET_UNDO:
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * All these assignments are "unfailable", so it's
+ * (reasonably) safe to apply them in the Commit phase
+ */
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct expExpression *)
+ netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPEXPRESSION:
+ memset(entry->expExpression, 0, EXP_STR3_LEN+1);
+ memcpy(entry->expExpression,
+ request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_EXPEXPRESSIONVALUETYPE:
+ entry->expValueType = *request->requestvb->val.integer;
+ break;
+ case COLUMN_EXPEXPRESSIONCOMMENT:
+ memset(entry->expComment, 0, EXP_STR2_LEN+1);
+ memcpy(entry->expComment,
+ request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_EXPEXPRESSIONDELTAINTERVAL:
+ entry->expDeltaInterval = *request->requestvb->val.integer;
+ break;
+ case COLUMN_EXPEXPRESSIONENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_ACTIVE:
+ entry->flags |= EXP_FLAG_ACTIVE;
+ expExpression_enable( entry );
+ break;
+ case RS_NOTINSERVICE:
+ entry->flags &= ~EXP_FLAG_ACTIVE;
+ expExpression_disable( entry );
+ break;
+ case RS_CREATEANDGO:
+ entry->flags |= EXP_FLAG_ACTIVE;
+ entry->flags |= EXP_FLAG_VALID;
+ entry->session =
+ netsnmp_iquery_pdu_session(reqinfo->asp->pdu);
+ expExpression_enable( entry );
+ break;
+ case RS_CREATEANDWAIT:
+ entry->flags |= EXP_FLAG_VALID;
+ entry->session =
+ netsnmp_iquery_pdu_session(reqinfo->asp->pdu);
+ break;
+
+ case RS_DESTROY:
+ row = (netsnmp_tdata_row *)
+ netsnmp_tdata_extract_row(request);
+ expExpression_removeEntry(row);
+ }
+ }
+ }
+ break;
+ }
+ DEBUGMSGTL(("disman:expr:mib", "Expression Table handler - done \n"));
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/expr/expExpressionTable.h b/agent/mibgroup/disman/expr/expExpressionTable.h
new file mode 100644
index 0000000..a32d8f5
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expExpressionTable.h
@@ -0,0 +1,26 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.table_data.conf,v 1.11 2005/09/16 11:48:12 dts12 Exp $
+ */
+#ifndef EXPEXPRESSIONTABLE_H
+#define EXPEXPRESSIONTABLE_H
+
+/*
+ * function declarations
+ */
+void init_expExpressionTable(void);
+Netsnmp_Node_Handler expExpressionTable_handler;
+
+/*
+ * column number definitions for table expExpressionTable
+ */
+#define COLUMN_EXPEXPRESSIONOWNER 1
+#define COLUMN_EXPEXPRESSIONNAME 2
+#define COLUMN_EXPEXPRESSION 3
+#define COLUMN_EXPEXPRESSIONVALUETYPE 4
+#define COLUMN_EXPEXPRESSIONCOMMENT 5
+#define COLUMN_EXPEXPRESSIONDELTAINTERVAL 6
+#define COLUMN_EXPEXPRESSIONPREFIX 7
+#define COLUMN_EXPEXPRESSIONERRORS 8
+#define COLUMN_EXPEXPRESSIONENTRYSTATUS 9
+#endif /* EXPEXPRESSIONTABLE_H */
diff --git a/agent/mibgroup/disman/expr/expObject.c b/agent/mibgroup/disman/expr/expObject.c
new file mode 100644
index 0000000..c27437b
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expObject.c
@@ -0,0 +1,345 @@
+/*
+ * DisMan Expression MIB:
+ * Core implementation of expression object handling
+ */
+
+#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/expr/expObject.h"
+#include "disman/expr/expExpression.h"
+
+netsnmp_tdata *expObject_table_data;
+
+ /*
+ * Initializes the container for the expression object table,
+ * regardless of which module is initialised first.
+ */
+void
+init_expObject_table_data(void)
+{
+ DEBUGMSGTL(("disman:expr:init", "init expObject container\n"));
+ if (!expObject_table_data) {
+ expObject_table_data = netsnmp_tdata_create_table("expObjectTable", 0);
+ DEBUGMSGTL(("disman:expr:init", "create expObject container (%p)\n",
+ expObject_table_data));
+ }
+}
+
+/* Initialize the expObject module */
+void
+init_expObject(void)
+{
+ init_expObject_table_data();
+}
+
+
+/*
+ * Create a new row in the object table
+ */
+struct expObject *
+expObject_createEntry(const char *expOwner, const char *expName, long expIndex, int fixed)
+{
+ netsnmp_tdata_row *row;
+
+ row = expObject_createRow(expOwner, expName, expIndex, fixed);
+ return row ? (struct expObject *)row->data : NULL;
+}
+
+netsnmp_tdata_row *
+expObject_createRow( const char *expOwner, const char *expName, long expIndex, int fixed)
+{
+ struct expObject *entry;
+ netsnmp_tdata_row *row;
+ size_t expOwner_len = (expOwner) ? strlen(expOwner) : 0;
+ size_t expName_len = (expName) ? strlen(expName) : 0;
+
+ /*
+ * Create the expObject entry, and the
+ * (table-independent) row wrapper structure...
+ */
+ entry = SNMP_MALLOC_TYPEDEF(struct expObject);
+ 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 (expOwner)
+ memcpy(entry->expOwner, expOwner, expOwner_len);
+ netsnmp_tdata_row_add_index(row, ASN_OCTET_STR,
+ entry->expOwner, expOwner_len);
+ if (expName)
+ memcpy(entry->expName, expName, expName_len);
+ netsnmp_tdata_row_add_index(row, ASN_OCTET_STR,
+ entry->expName, expName_len);
+ entry->expObjectIndex = expIndex;
+ netsnmp_tdata_row_add_index(row, ASN_INTEGER,
+ &entry->expObjectIndex, sizeof(long));
+
+ entry->expObjectSampleType = 1; /* absoluteValue */
+ entry->expObjDiscontinuityType = 1; /* timeTicks */
+ if (fixed)
+ entry->flags |= EXP_OBJ_FLAG_FIXED;
+
+ /*
+ * ... and insert the row into the table container.
+ */
+ netsnmp_tdata_add_row(expObject_table_data, row);
+ return row;
+}
+
+/*
+ * Remove a row from the expression object table
+ */
+void
+expObject_removeEntry(netsnmp_tdata_row * row)
+{
+ struct expObject *entry;
+
+ if (!row)
+ return; /* Nothing to remove */
+ entry = (struct expObject *)
+ netsnmp_tdata_remove_and_delete_row(expObject_table_data, row);
+ if (entry) {
+ if (entry->vars ) snmp_free_varbind( entry->vars );
+ if (entry->old_vars ) snmp_free_varbind( entry->old_vars );
+ if (entry->dvars ) snmp_free_varbind( entry->dvars );
+ if (entry->old_dvars ) snmp_free_varbind( entry->old_dvars );
+ if (entry->cvars ) snmp_free_varbind( entry->cvars );
+ SNMP_FREE(entry);
+ }
+}
+
+
+netsnmp_tdata_row *
+expObject_getFirst( const char *expOwner, const char *expName )
+{
+ netsnmp_tdata_row *row;
+ struct expObject *entry;
+ netsnmp_variable_list owner_var;
+ netsnmp_variable_list name_var;
+
+ if (!expOwner || !expName)
+ return NULL;
+
+ /*
+ * Find the first object entry that could potentially
+ * refer to the specified expression...
+ */
+ memset(&owner_var, 0, sizeof(netsnmp_variable_list));
+ memset(&name_var, 0, sizeof(netsnmp_variable_list));
+ snmp_set_var_typed_value( &owner_var, ASN_OCTET_STR,
+ (const u_char*)expOwner, strlen(expOwner));
+ snmp_set_var_typed_value( &name_var, ASN_OCTET_STR,
+ (const u_char*)expName, strlen(expName));
+ owner_var.next_variable = &name_var;
+ row = netsnmp_tdata_row_next_byidx( expObject_table_data, &owner_var );
+
+ /*
+ * ... and check that it does!
+ */
+ if (!row || !row->data)
+ return NULL;
+ entry = (struct expObject *)row->data;
+
+ if ((strcmp( entry->expOwner, expOwner ) != 0) ||
+ (strcmp( entry->expName, expName ) != 0))
+ return NULL;
+
+ return row;
+}
+
+netsnmp_tdata_row *
+expObject_getNext( netsnmp_tdata_row *thisRow )
+{
+ struct expObject *thisEntry;
+ struct expObject *nextEntry;
+ netsnmp_tdata_row *nextRow;
+
+ if (!thisRow || !thisRow->data)
+ return NULL;
+ thisEntry = (struct expObject *)thisRow->data;
+
+ /*
+ * Retrieve the next row, and check whether this
+ * refers to the same expression too.
+ */
+ nextRow = netsnmp_tdata_row_next( expObject_table_data, thisRow );
+
+ if (!nextRow || !nextRow->data)
+ return NULL;
+ nextEntry = (struct expObject *)nextRow->data;
+
+ if ((strcmp( nextEntry->expOwner, thisEntry->expOwner ) != 0) ||
+ (strcmp( nextEntry->expName, thisEntry->expName ) != 0))
+ return NULL;
+
+ return nextRow;
+}
+
+
+netsnmp_variable_list *
+_expObject_buildList( oid *root, size_t root_len, size_t prefix_len,
+ netsnmp_variable_list *template_list )
+{
+ netsnmp_variable_list *query_list = NULL;
+ netsnmp_variable_list *vp1, *vp2 = NULL;
+ oid name[ MAX_OID_LEN ];
+ int i;
+
+ if ( prefix_len ) {
+ /*
+ * For wildcarded objects, build a list of all relevant
+ * instances, using the template_list to provide the
+ * necessary instance suffixes.
+ */
+ memset( name, 0, sizeof(name));
+ memcpy( name, root, root_len*sizeof(oid));
+ for ( vp1 = template_list; vp1; vp1=vp1->next_variable ) {
+ /*
+ * Append a new varbind to the list for this object ...
+ */
+ if ( !query_list ) {
+ query_list = (netsnmp_variable_list*)
+ SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ vp2 = query_list;
+ } else {
+ vp2->next_variable = (netsnmp_variable_list*)
+ SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ vp2 = vp2->next_variable;
+ }
+ /*
+ * ... and set the OID using the template suffix
+ */
+ for ( i=0; i <= vp1->name_length - prefix_len; i++)
+ name[ root_len+i ] = vp1->name[ prefix_len+i ];
+ snmp_set_var_objid( vp2, name, root_len+i );
+ }
+ } else {
+ /*
+ * Otherwise, just use the (single) OID provided.
+ */
+ query_list = (netsnmp_variable_list*)
+ SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ snmp_set_var_objid( query_list, root, root_len );
+ }
+ return query_list;
+}
+
+
+void
+expObject_getData( struct expExpression *expr, struct expObject *obj )
+{
+ netsnmp_variable_list *var;
+
+ /*
+ * Retrieve and store the basic object value(s)
+ * (keeping the previous values if necessary)
+ */
+ if (obj->flags & EXP_OBJ_FLAG_PREFIX ) {
+ /*
+ * If this is the expExpressionPrefix object, then
+ * we already have the necessary list of values.
+ * There's no need to retrieve it again.
+ * This also takes care of releasing the prefix list
+ * once the results are no longer needed.
+ */
+ var = expr->pvars;
+ } else {
+ if (!(obj->flags & EXP_OBJ_FLAG_OWILD ))
+ /*
+ * Set up the request 'list' for an
+ * exact (non-wildcarded) object.
+ */
+ var = _expObject_buildList( obj->expObjectID,
+ obj->expObjectID_len, 0, NULL );
+ else {
+ if ( !expr->expPrefix_len ) {
+ /*
+ * You can't really have wildcarded objects unless
+ * the expression as a whole is wildcarded too.
+ */
+ return;
+ }
+ /*
+ * Set up the request list for a wildcarded object
+ */
+ var = _expObject_buildList( obj->expObjectID,
+ obj->expObjectID_len,
+ expr->expPrefix_len,
+ expr->pvars );
+ }
+ netsnmp_query_get( var, expr->session );
+ }
+
+ if ( obj->expObjectSampleType != EXPSAMPLETYPE_ABSOLUTE ) {
+ /*
+ * For Delta (and Changed) samples, we need
+ * to store the previous value as well.
+ */
+ if ( obj->old_vars )
+ snmp_free_varbind( obj->old_vars );
+ obj->old_vars = obj->vars;
+ } else
+ snmp_free_varbind( obj->vars );
+
+ obj->vars = var;
+
+
+ /*
+ * For Delta samples, there may be a discontinuity marker
+ * (or set of wildcarded markers) to be sampled as well.
+ * This necessarily requires storing the previous marker(s).
+ */
+ if (( obj->expObjectSampleType != EXPSAMPLETYPE_ABSOLUTE ) &&
+ ( obj->flags & EXP_OBJ_FLAG_DDISC )) {
+
+ if ( obj->flags & EXP_OBJ_FLAG_DWILD )
+ var = _expObject_buildList( obj->expObjDeltaD,
+ obj->expObjDeltaD_len,
+ expr->expPrefix_len,
+ expr->pvars );
+ else
+ var = _expObject_buildList( obj->expObjDeltaD,
+ obj->expObjDeltaD_len, 0, NULL );
+ netsnmp_query_get( var, expr->session );
+ if ( obj->old_dvars )
+ snmp_free_varbind( obj->old_dvars );
+ obj->old_dvars = obj->dvars;
+ obj->dvars = var;
+ }
+
+ /*
+ * If there's an expObjectConditional value specified
+ * (or set of wildcarded values) then add these to the
+ * ever-growing collection of retrieved values.
+ */
+ if ( obj->expObjCond_len ) {
+ if ( obj->flags & EXP_OBJ_FLAG_CWILD )
+ var = _expObject_buildList( obj->expObjCond,
+ obj->expObjCond_len,
+ expr->expPrefix_len,
+ expr->pvars );
+ else
+ var = _expObject_buildList( obj->expObjCond,
+ obj->expObjCond_len, 0, NULL );
+ /*
+ * XXX - Check when to use GetNext
+ *
+ * (The MIB description seems bogus?)
+ */
+ netsnmp_query_get( var, expr->session );
+ if ( obj->cvars )
+ snmp_free_varbind( obj->cvars );
+ obj->cvars = var;
+ }
+}
diff --git a/agent/mibgroup/disman/expr/expObject.h b/agent/mibgroup/disman/expr/expObject.h
new file mode 100644
index 0000000..c62158a
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expObject.h
@@ -0,0 +1,77 @@
+#ifndef EXPOBJECT_H
+#define EXPOBJECT_H
+
+#include "disman/expr/expExpression.h"
+
+ /*
+ * Flags relating to the expression object table
+ */
+#define EXP_OBJ_FLAG_OWILD 0x01 /* for expObjectIDWildcard */
+#define EXP_OBJ_FLAG_DDISC 0x02 /* non-trivial expObjDiscontinuityID */
+#define EXP_OBJ_FLAG_DWILD 0x04 /* for expObjDiscontinuityIDWildcard */
+#define EXP_OBJ_FLAG_CWILD 0x08 /* for expObjConditionalWildcard */
+#define EXP_OBJ_FLAG_PREFIX 0x10 /* expExpressionPrefix object */
+#define EXP_OBJ_FLAG_ACTIVE 0x20 /* for expObjectEntryStatus */
+#define EXP_OBJ_FLAG_FIXED 0x40 /* for snmpd.conf persistence */
+#define EXP_OBJ_FLAG_VALID 0x80 /* for row creation/undo */
+
+ /*
+ * Standard lengths for various Expression-MIB OCTET STRING objects:
+ * short tags ( 32 characters)
+ * SnmpAdminString-style values (255 characters)
+ * "long" DisplayString values (1024 characters)
+ */
+#define EXP_STR1_LEN 32
+#define EXP_STR2_LEN 255
+#define EXP_STR3_LEN 1024
+
+/*
+ * Data structure for an expObject row.
+ */
+struct expObject {
+ /*
+ * Index values
+ */
+ char expOwner[ EXP_STR1_LEN+1 ];
+ char expName[ EXP_STR1_LEN+1 ];
+ u_long expObjectIndex;
+
+ /*
+ * Column values
+ */
+ oid expObjectID[ MAX_OID_LEN ];
+ oid expObjDeltaD[ MAX_OID_LEN ];
+ oid expObjCond[ MAX_OID_LEN ];
+ size_t expObjectID_len;
+ size_t expObjDeltaD_len;
+ size_t expObjCond_len;
+ long expObjectSampleType;
+ long expObjDiscontinuityType;
+
+ netsnmp_variable_list *vars, *old_vars;
+ netsnmp_variable_list *dvars, *old_dvars;
+ netsnmp_variable_list *cvars, *old_cvars;
+
+ long flags;
+};
+
+ /*
+ * Container structure for the expObjectTable,
+ * and initialisation routine to create this.
+ */
+extern netsnmp_tdata *expObject_table_data;
+void init_expObject_table_data(void);
+
+/*
+ * function declarations
+ */
+void init_expObject(void);
+struct expObject * expObject_createEntry( const char *, const char *, long, int );
+netsnmp_tdata_row * expObject_createRow( const char *, const char *, long, int );
+void expObject_removeEntry( netsnmp_tdata_row * );
+
+netsnmp_tdata_row * expObject_getFirst( const char *, const char * );
+netsnmp_tdata_row * expObject_getNext( netsnmp_tdata_row * );
+void expObject_getData( struct expExpression *,
+ struct expObject * );
+#endif /* EXPOBJECT_H */
diff --git a/agent/mibgroup/disman/expr/expObjectConf.c b/agent/mibgroup/disman/expr/expObjectConf.c
new file mode 100644
index 0000000..64069d9
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expObjectConf.c
@@ -0,0 +1,185 @@
+/*
+ * DisMan Expression MIB:
+ * Implementation of the object table configuration handling.
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "utilities/iquery.h"
+#include "disman/expr/expObject.h"
+#include "disman/expr/expObjectConf.h"
+
+netsnmp_feature_require(iquery)
+
+/* Initializes the expObjectConf module */
+void
+init_expObjectConf(void)
+{
+ init_expObject_table_data();
+
+ /*
+ * Register config handler for persistent storage
+ * of dynamically configured entries.
+ */
+ snmpd_register_config_handler("_expOTable", parse_expOTable, NULL, NULL);
+
+ /*
+ * Register to save (non-fixed) entries when the agent shuts down
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_expOTable, NULL);
+}
+
+
+
+/* ================================================
+ *
+ * Handlers for loading/storing persistent expression entries
+ *
+ * ================================================ */
+
+char *
+_parse_expOCols( char *line, struct expObject *entry )
+{
+ void *vp;
+ size_t tmp;
+
+ vp = entry->expObjectID;
+ entry->expObjectID_len = MAX_OID_LEN;
+ line = read_config_read_data(ASN_OBJECT_ID, line, &vp,
+ &entry->expObjectID_len);
+
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ entry->expObjectSampleType = tmp;
+
+ vp = entry->expObjDeltaD;
+ entry->expObjDeltaD_len = MAX_OID_LEN;
+ line = read_config_read_data(ASN_OBJECT_ID, line, &vp,
+ &entry->expObjDeltaD_len);
+
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ entry->expObjDiscontinuityType = tmp;
+
+ vp = entry->expObjCond;
+ entry->expObjCond_len = MAX_OID_LEN;
+ line = read_config_read_data(ASN_OBJECT_ID, line, &vp,
+ &entry->expObjCond_len);
+
+ line = read_config_read_data(ASN_UNSIGNED, line, &tmp, NULL);
+ entry->flags |= tmp;
+
+ return line;
+}
+
+
+void
+parse_expOTable(const char *token, char *line)
+{
+ char owner[EXP_STR1_LEN+1];
+ char oname[EXP_STR1_LEN+1];
+ long idx;
+ void *vp;
+ size_t len;
+ struct expObject *entry;
+
+ DEBUGMSGTL(("disman:expr:conf", "Parsing mteObjectTable config... "));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( oname, 0, sizeof(oname));
+ len = EXP_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = EXP_STR1_LEN; vp = oname;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ line = read_config_read_data(ASN_UNSIGNED, line, &idx, NULL);
+ entry = expObject_createEntry( owner, oname, idx, 0 );
+
+ DEBUGMSG(("disman:expr:conf", "(%s, %s, %ld) ", owner, oname, idx));
+
+ /*
+ * Read in the accessible column values.
+ */
+ line = _parse_expOCols( line, entry );
+ /*
+ * XXX - Will need to read in the 'iquery' access information
+ */
+ entry->flags |= EXP_OBJ_FLAG_VALID;
+
+ DEBUGMSG(("disman:expr:conf", "\n"));
+}
+
+
+int
+store_expOTable(int majorID, int minorID, void *serverarg, void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr, *cp;
+ void *vp;
+ size_t tint;
+ netsnmp_tdata_row *row;
+ struct expObject *entry;
+
+
+ DEBUGMSGTL(("disman:expr:conf", "Storing expObjectTable config:\n"));
+
+ for (row = netsnmp_tdata_row_first( expObject_table_data );
+ row;
+ row = netsnmp_tdata_row_next( expObject_table_data, row )) {
+
+ /*
+ * Skip entries that were set up via static config directives
+ */
+ entry = (struct expObject *)netsnmp_tdata_row_entry( row );
+ if ( entry->flags & EXP_OBJ_FLAG_FIXED )
+ continue;
+
+ DEBUGMSGTL(("disman:expr:conf", " Storing (%s %s %lu)\n",
+ entry->expOwner, entry->expName, entry->expObjectIndex));
+
+ /*
+ * Save the basic expObject entry, indexes...
+ */
+ memset(line, 0, sizeof(line));
+ strcat(line, "_expOTable ");
+ cptr = line + strlen(line);
+
+ cp = entry->expOwner; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->expName; tint = strlen( cp );
+ cptr = read_config_store_data( ASN_OCTET_STR, cptr, &cp, &tint );
+ tint = entry->expObjectIndex;
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+
+ /*
+ * ... and column values.
+ */
+ vp = entry->expObjectID;
+ tint = entry->expObjectID_len;
+ cptr = read_config_store_data( ASN_OBJECT_ID, cptr, &vp, &tint );
+ tint = entry->expObjectSampleType;
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+
+ vp = entry->expObjDeltaD;
+ tint = entry->expObjDeltaD_len;
+ cptr = read_config_store_data( ASN_OBJECT_ID, cptr, &vp, &tint );
+ tint = entry->expObjDiscontinuityType;
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+
+ vp = entry->expObjCond;
+ tint = entry->expObjCond_len;
+ cptr = read_config_store_data( ASN_OBJECT_ID, cptr, &vp, &tint );
+
+ tint = entry->flags;
+ cptr = read_config_store_data( ASN_UNSIGNED, cptr, &tint, NULL );
+
+ snmpd_store_config(line);
+ }
+
+ DEBUGMSGTL(("disman:expr:conf", " done.\n"));
+ return SNMPERR_SUCCESS;
+}
diff --git a/agent/mibgroup/disman/expr/expObjectConf.h b/agent/mibgroup/disman/expr/expObjectConf.h
new file mode 100644
index 0000000..8a67cca
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expObjectConf.h
@@ -0,0 +1,9 @@
+#ifndef EXPOBJECTCONF_H
+#define EXPOBJECTCONF_H
+
+void init_expObjectConf(void);
+
+void parse_expOTable(const char *, char *);
+SNMPCallback store_expOTable;
+
+#endif /* EXPOBJECTCONF_H */
diff --git a/agent/mibgroup/disman/expr/expObjectTable.c b/agent/mibgroup/disman/expr/expObjectTable.c
new file mode 100644
index 0000000..adda438
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expObjectTable.c
@@ -0,0 +1,461 @@
+/*
+ * DisMan Expression MIB:
+ * Implementation of the expExpressionObjectTable MIB interface
+ * See 'expObject.c' for active behaviour of this table.
+ *
+ * (Based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "disman/expr/expObject.h"
+#include "disman/expr/expObjectTable.h"
+
+netsnmp_feature_require(table_tdata)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(check_vb_oid)
+netsnmp_feature_require(check_vb_truthvalue)
+netsnmp_feature_require(table_tdata_insert_row)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+/* Initializes the expObjectTable module */
+void
+init_expObjectTable(void)
+{
+ static oid expObjectTable_oid[] = { 1, 3, 6, 1, 2, 1, 90, 1, 2, 3 };
+ size_t expObjectTable_oid_len = OID_LENGTH(expObjectTable_oid);
+ netsnmp_handler_registration *reg;
+ netsnmp_table_registration_info *table_info;
+
+ /*
+ * Ensure the expObject table container is available...
+ */
+ init_expObject_table_data();
+
+ /*
+ * ... then set up the MIB interface to the expObjectTable
+ */
+ reg = netsnmp_create_handler_registration("expObjectTable",
+ expObjectTable_handler,
+ expObjectTable_oid,
+ expObjectTable_oid_len,
+ HANDLER_CAN_RWRITE);
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ /* index: expExpressionOwner */
+ ASN_OCTET_STR,
+ /* index: expExpressionName */
+ ASN_OCTET_STR,
+ /* index: expObjectIndex */
+ ASN_UNSIGNED,
+ 0);
+
+ table_info->min_column = COLUMN_EXPOBJECTID;
+ table_info->max_column = COLUMN_EXPOBJECTENTRYSTATUS;
+
+ /* Register this using the common expObject_table_data container */
+ netsnmp_tdata_register(reg, expObject_table_data, table_info);
+ DEBUGMSGTL(("disman:expr:init", "Expression Object Table container (%p)\n",
+ expObject_table_data));
+}
+
+
+/** handles requests for the expObjectTable table */
+int
+expObjectTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ netsnmp_tdata_row *row;
+ struct expObject *entry;
+ struct expExpression *exp;
+ char expOwner[EXP_STR1_LEN+1];
+ char expName[ EXP_STR1_LEN+1];
+ long objIndex;
+ long ret;
+ netsnmp_variable_list *vp;
+
+ DEBUGMSGTL(("disman:expr:mib", "Expression Object Table handler (%d)\n",
+ reqinfo->mode));
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct expObject *)netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+ if (!entry || !(entry->flags & EXP_OBJ_FLAG_VALID))
+ continue;
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPOBJECTID:
+ snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
+ (u_char *) entry->expObjectID,
+ entry->expObjectID_len*sizeof(oid));
+ break;
+ case COLUMN_EXPOBJECTIDWILDCARD:
+ ret = (entry->flags & EXP_OBJ_FLAG_OWILD) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_EXPOBJECTSAMPLETYPE:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->expObjectSampleType);
+ break;
+ case COLUMN_EXPOBJECTDELTADISCONTINUITYID:
+ /*
+ * "This object [and the next two] are instantiated only if
+ * expObjectSampleType is 'deltaValue' or 'changedValue'"
+ */
+ if ( entry->expObjectSampleType == 1 )
+ continue;
+ snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
+ (u_char *) entry->expObjDeltaD,
+ entry->expObjDeltaD_len*sizeof(oid));
+ break;
+ case COLUMN_EXPOBJECTDISCONTINUITYIDWILDCARD:
+ if ( entry->expObjectSampleType == 1 )
+ continue;
+ ret = (entry->flags & EXP_OBJ_FLAG_DWILD) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_EXPOBJECTDISCONTINUITYIDTYPE:
+ if ( entry->expObjectSampleType == 1 )
+ continue;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->expObjDiscontinuityType);
+ break;
+ case COLUMN_EXPOBJECTCONDITIONAL:
+ snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
+ (u_char *) entry->expObjCond,
+ entry->expObjCond_len*sizeof(oid));
+ break;
+ case COLUMN_EXPOBJECTCONDITIONALWILDCARD:
+ ret = (entry->flags & EXP_OBJ_FLAG_CWILD) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_EXPOBJECTENTRYSTATUS:
+ /* What would indicate 'notReady' ? */
+ ret = (entry->flags & EXP_OBJ_FLAG_ACTIVE) ?
+ RS_ACTIVE : RS_NOTINSERVICE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ }
+ }
+ break;
+
+ /*
+ * Write-support
+ */
+ case MODE_SET_RESERVE1:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct expObject *)
+ netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPOBJECTID:
+ case COLUMN_EXPOBJECTDELTADISCONTINUITYID:
+ case COLUMN_EXPOBJECTCONDITIONAL:
+ ret = netsnmp_check_vb_oid(request->requestvb);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+
+ case COLUMN_EXPOBJECTIDWILDCARD:
+ case COLUMN_EXPOBJECTDISCONTINUITYIDWILDCARD:
+ case COLUMN_EXPOBJECTCONDITIONALWILDCARD:
+ ret = netsnmp_check_vb_truthvalue(request->requestvb);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+
+ case COLUMN_EXPOBJECTSAMPLETYPE:
+ case COLUMN_EXPOBJECTDISCONTINUITYIDTYPE:
+ ret = netsnmp_check_vb_int_range(request->requestvb, 1, 3);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+
+ case COLUMN_EXPOBJECTENTRYSTATUS:
+ ret = netsnmp_check_vb_rowstatus(request->requestvb,
+ (entry ? RS_ACTIVE : RS_NONEXISTENT));
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ default:
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOTWRITABLE);
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_RESERVE2:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPOBJECTENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_CREATEANDGO:
+ case RS_CREATEANDWAIT:
+ /*
+ * Create an (empty) new row structure
+ */
+ memset(expOwner, 0, sizeof(expOwner));
+ memcpy(expOwner, tinfo->indexes->val.string,
+ tinfo->indexes->val_len);
+ memset(expName, 0, sizeof(expName));
+ memcpy(expName,
+ tinfo->indexes->next_variable->val.string,
+ tinfo->indexes->next_variable->val_len);
+ vp = tinfo->indexes->next_variable->next_variable;
+ objIndex = *vp->val.integer;
+
+ row = expObject_createRow(expOwner, expName, objIndex, 0);
+ if (!row) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_RESOURCEUNAVAILABLE);
+ return SNMP_ERR_NOERROR;
+ }
+ netsnmp_insert_tdata_row( request, row );
+ }
+ }
+ }
+ break;
+
+ case MODE_SET_FREE:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPOBJECTENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_CREATEANDGO:
+ case RS_CREATEANDWAIT:
+ /*
+ * Tidy up after a failed row creation request
+ */
+ entry = (struct expObject *)
+ netsnmp_tdata_extract_entry(request);
+ if (entry &&
+ !(entry->flags & EXP_OBJ_FLAG_VALID)) {
+ row = (netsnmp_tdata_row *)
+ netsnmp_tdata_extract_row(request);
+ expObject_removeEntry( row );
+ }
+ }
+ }
+ }
+ break;
+
+ case MODE_SET_ACTION:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+ entry = (struct expObject *)
+ netsnmp_tdata_extract_entry(request);
+ if (!entry) {
+ /*
+ * New rows must be created via the RowStatus column
+ */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ /* or inconsistentName? */
+ return SNMP_ERR_NOERROR;
+
+ }
+ }
+ break;
+
+ case MODE_SET_UNDO:
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * All these assignments are "unfailable", so it's
+ * (reasonably) safe to apply them in the Commit phase
+ */
+ ret = 0; /* Flag to re-check expExpressionPrefix settings */
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct expObject *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPOBJECTID:
+ memset(entry->expObjectID, 0, sizeof(entry->expObjectID));
+ memcpy(entry->expObjectID, request->requestvb->val.string,
+ request->requestvb->val_len);
+ entry->expObjectID_len = request->requestvb->val_len;
+ break;
+ case COLUMN_EXPOBJECTIDWILDCARD:
+ if (*request->requestvb->val.integer == TV_TRUE)
+ entry->flags |= EXP_OBJ_FLAG_OWILD;
+ else
+ entry->flags &= ~EXP_OBJ_FLAG_OWILD;
+ break;
+ case COLUMN_EXPOBJECTSAMPLETYPE:
+ entry->expObjectSampleType = *request->requestvb->val.integer;
+ break;
+ case COLUMN_EXPOBJECTDELTADISCONTINUITYID:
+ memset(entry->expObjDeltaD, 0, sizeof(entry->expObjDeltaD));
+ memcpy(entry->expObjDeltaD, request->requestvb->val.string,
+ request->requestvb->val_len);
+ entry->expObjDeltaD_len = request->requestvb->val_len/sizeof(oid);
+ /* XXX
+ if ( snmp_oid_compare( entry->expObjDeltaD,
+ entry->expObjDeltaD_len,
+ sysUpTime_inst,
+ sysUpTime_inst_len ) != 0 )
+ entry->flags |= EXP_OBJ_FLAG_DDISC;
+ */
+
+ /*
+ * If the OID used for the expExpressionPrefix object
+ * has changed, then update the expression structure.
+ */
+ if ( entry->flags & EXP_OBJ_FLAG_PREFIX ) {
+ exp = expExpression_getEntry( entry->expOwner,
+ entry->expName );
+ memcpy( exp->expPrefix, entry->expObjDeltaD,
+ MAX_OID_LEN*sizeof(oid));
+ exp->expPrefix_len = entry->expObjDeltaD_len;
+ }
+ break;
+ case COLUMN_EXPOBJECTDISCONTINUITYIDWILDCARD:
+ if (*request->requestvb->val.integer == TV_TRUE) {
+ /*
+ * Possible new prefix OID candidate
+ * Can't set the value here, since the OID
+ * assignment might not have been processed yet.
+ */
+ exp = expExpression_getEntry( entry->expOwner,
+ entry->expName );
+ if (exp && exp->expPrefix_len == 0 )
+ ret = 1; /* Set the prefix later */
+ entry->flags |= EXP_OBJ_FLAG_DWILD;
+ } else {
+ if ( entry->flags | EXP_OBJ_FLAG_PREFIX ) {
+ exp = expExpression_getEntry( entry->expOwner,
+ entry->expName );
+ memset( exp->expPrefix, 0, MAX_OID_LEN*sizeof(oid));
+ exp->expPrefix_len = 0;
+ ret = 1; /* Need a new prefix OID */
+ }
+ entry->flags &= ~EXP_OBJ_FLAG_DWILD;
+ }
+ break;
+ case COLUMN_EXPOBJECTDISCONTINUITYIDTYPE:
+ entry->expObjDiscontinuityType =
+ *request->requestvb->val.integer;
+ break;
+ case COLUMN_EXPOBJECTCONDITIONAL:
+ memset(entry->expObjCond, 0, sizeof(entry->expObjCond));
+ memcpy(entry->expObjCond, request->requestvb->val.string,
+ request->requestvb->val_len);
+ entry->expObjCond_len = request->requestvb->val_len/sizeof(oid);
+ break;
+ case COLUMN_EXPOBJECTCONDITIONALWILDCARD:
+ if (*request->requestvb->val.integer == TV_TRUE)
+ entry->flags |= EXP_OBJ_FLAG_CWILD;
+ else
+ entry->flags &= ~EXP_OBJ_FLAG_CWILD;
+ break;
+ case COLUMN_EXPOBJECTENTRYSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_ACTIVE:
+ entry->flags |= EXP_OBJ_FLAG_ACTIVE;
+ break;
+ case RS_NOTINSERVICE:
+ entry->flags &= ~EXP_OBJ_FLAG_ACTIVE;
+ break;
+ case RS_CREATEANDGO:
+ entry->flags |= EXP_OBJ_FLAG_ACTIVE;
+ entry->flags |= EXP_OBJ_FLAG_VALID;
+ break;
+ case RS_CREATEANDWAIT:
+ entry->flags |= EXP_OBJ_FLAG_VALID;
+ break;
+
+ case RS_DESTROY:
+ row = (netsnmp_tdata_row *)
+ netsnmp_tdata_extract_row(request);
+ expObject_removeEntry(row);
+ }
+ }
+ }
+
+ /*
+ * Need to check for changes in expExpressionPrefix handling
+ */
+ for (request = requests; request; request = request->next) {
+ entry = (struct expObject *) netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPOBJECTDISCONTINUITYIDWILDCARD:
+ /*
+ * If a column has just been marked as wild,
+ * then consider using it as the prefix OID
+ */
+ if (*request->requestvb->val.integer == TV_TRUE) {
+ exp = expExpression_getEntry( entry->expOwner,
+ entry->expName );
+ if ( exp->expPrefix_len == 0 ) {
+ memcpy( exp->expPrefix, entry->expObjDeltaD,
+ MAX_OID_LEN*sizeof(oid));
+ exp->expPrefix_len = entry->expObjDeltaD_len;
+ entry->flags |= EXP_OBJ_FLAG_PREFIX;
+ }
+ }
+ /*
+ * If it's just been marked as non-wildcarded
+ * then we need to look for a new candidate.
+ */
+ else {
+
+ }
+ break;
+ }
+ }
+ break;
+ }
+ DEBUGMSGTL(("disman:expr:mib", "Expression Object handler - done \n"));
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/expr/expObjectTable.h b/agent/mibgroup/disman/expr/expObjectTable.h
new file mode 100644
index 0000000..568f67a
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expObjectTable.h
@@ -0,0 +1,27 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.table_data.conf,v 1.11 2005/09/16 11:48:12 dts12 Exp $
+ */
+#ifndef EXPOBJECTTABLE_H
+#define EXPOBJECTTABLE_H
+
+/*
+ * function declarations
+ */
+void init_expObjectTable(void);
+Netsnmp_Node_Handler expObjectTable_handler;
+
+/*
+ * column number definitions for table expObjectTable
+ */
+#define COLUMN_EXPOBJECTINDEX 1
+#define COLUMN_EXPOBJECTID 2
+#define COLUMN_EXPOBJECTIDWILDCARD 3
+#define COLUMN_EXPOBJECTSAMPLETYPE 4
+#define COLUMN_EXPOBJECTDELTADISCONTINUITYID 5
+#define COLUMN_EXPOBJECTDISCONTINUITYIDWILDCARD 6
+#define COLUMN_EXPOBJECTDISCONTINUITYIDTYPE 7
+#define COLUMN_EXPOBJECTCONDITIONAL 8
+#define COLUMN_EXPOBJECTCONDITIONALWILDCARD 9
+#define COLUMN_EXPOBJECTENTRYSTATUS 10
+#endif /* EXPOBJECTTABLE_H */
diff --git a/agent/mibgroup/disman/expr/expScalars.c b/agent/mibgroup/disman/expr/expScalars.c
new file mode 100644
index 0000000..4a3ebc7
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expScalars.c
@@ -0,0 +1,97 @@
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "expScalars.h"
+#include "expExpression.h"
+
+/** Initializes the expScalars module */
+void
+init_expScalars(void)
+{
+ static oid expResource_oid[] = { 1, 3, 6, 1, 2, 1, 90, 1, 1 };
+
+ DEBUGMSGTL(("expScalars", "Initializing\n"));
+
+ netsnmp_register_scalar_group(
+ netsnmp_create_handler_registration("expResource",
+ handle_expResourceGroup,
+ expResource_oid, OID_LENGTH(expResource_oid),
+ HANDLER_CAN_RONLY),
+ EXP_RESOURCE_MIN_DELTA, EXP_RESOURCE_SAMPLE_LACKS);
+
+}
+
+int
+handle_expResourceGroup(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+ oid obj;
+ long value = 0;
+
+ switch (reqinfo->mode) {
+ case MODE_GET:
+ obj = requests->requestvb->name[ requests->requestvb->name_length-2 ];
+ switch (obj) {
+ case EXP_RESOURCE_MIN_DELTA:
+ value = 1; /* Fixed minimum sample frequency */
+ snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
+ (u_char *)&value, sizeof(value));
+ break;
+
+ case EXP_RESOURCE_SAMPLE_MAX:
+ value = 0; /* No fixed maximum */
+ snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
+ (u_char *)&value, sizeof(value));
+ break;
+
+ case EXP_RESOURCE_SAMPLE_INSTANCES:
+#ifdef USING_DISMAN_EXPR_EXPEXPRESSION_MODULE
+ value = expExpression_getNumEntries(0);
+#else
+ value = 0;
+#endif
+ snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE,
+ (u_char *)&value, sizeof(value));
+ break;
+
+ case EXP_RESOURCE_SAMPLE_HIGH:
+#ifdef USING_DISMAN_EXPR_EXPEXPRESSION_MODULE
+ value = expExpression_getNumEntries(1);
+#else
+ value = 0;
+#endif
+ snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE,
+ (u_char *)&value, sizeof(value));
+ break;
+
+ case EXP_RESOURCE_SAMPLE_LACKS:
+ value = 0; /* expResSampleInstMax not used */
+ snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER,
+ (u_char *)&value, sizeof(value));
+ break;
+
+ default:
+ snmp_log(LOG_ERR,
+ "unknown object (%d) in handle_expResourceGroup\n", (int)obj);
+ return SNMP_ERR_GENERR;
+ }
+ break;
+
+ default:
+ /*
+ * Although expResourceDeltaMinimum and expResDeltaWildcardInstMaximum
+ * are defined with MAX-ACCESS read-write, this version hardcodes
+ * these values, so doesn't need to implement write access.
+ */
+ snmp_log(LOG_ERR,
+ "unknown mode (%d) in handle_expResourceGroup\n",
+ reqinfo->mode);
+ return SNMP_ERR_GENERR;
+ }
+
+ return SNMP_ERR_NOERROR;
+}
+
diff --git a/agent/mibgroup/disman/expr/expScalars.h b/agent/mibgroup/disman/expr/expScalars.h
new file mode 100644
index 0000000..022e01b
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expScalars.h
@@ -0,0 +1,13 @@
+#ifndef EXPSCALARS_H
+#define EXPSCALARS_H
+
+void init_expScalars(void);
+Netsnmp_Node_Handler handle_expResourceGroup;
+
+#define EXP_RESOURCE_MIN_DELTA 1
+#define EXP_RESOURCE_SAMPLE_MAX 2
+#define EXP_RESOURCE_SAMPLE_INSTANCES 3
+#define EXP_RESOURCE_SAMPLE_HIGH 4
+#define EXP_RESOURCE_SAMPLE_LACKS 5
+
+#endif /* EXPSCALARS_H */
diff --git a/agent/mibgroup/disman/expr/expValue.c b/agent/mibgroup/disman/expr/expValue.c
new file mode 100644
index 0000000..46638f2
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expValue.c
@@ -0,0 +1,808 @@
+/*
+ * DisMan Expression MIB:
+ * Core implementation of expression evaluation
+ */
+
+#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/expr/expExpression.h"
+#include "disman/expr/expObject.h"
+#include "disman/expr/expValue.h"
+
+#include <ctype.h>
+
+void _expValue_setError( struct expExpression *exp, int reason,
+ oid *suffix, size_t suffix_len,
+ netsnmp_variable_list *var);
+
+
+#define ASN_PRIV_OPERATOR (ASN_PRIVATE | 0x0f)
+#define ASN_PRIV_FUNCTION (ASN_PRIVATE | 0x0e)
+
+int ops[128]; /* mapping from operator characters to numeric
+ tokens (ordered by priority). */
+
+void
+init_expValue(void)
+{
+DEBUGMSGTL(("disman:expr:eval", "Init expValue"));
+ /* Single-character operators */
+ ops['+'] = EXP_OPERATOR_ADD;
+ ops['-'] = EXP_OPERATOR_SUBTRACT;
+ ops['*'] = EXP_OPERATOR_MULTIPLY;
+ ops['/'] = EXP_OPERATOR_DIVIDE;
+ ops['%'] = EXP_OPERATOR_REMAINDER;
+ ops['^'] = EXP_OPERATOR_BITXOR;
+ ops['~'] = EXP_OPERATOR_BITNEGATE;
+ ops['|'] = EXP_OPERATOR_BITOR;
+ ops['&'] = EXP_OPERATOR_BITAND;
+ ops['!'] = EXP_OPERATOR_NOT;
+ ops['<'] = EXP_OPERATOR_LESS;
+ ops['>'] = EXP_OPERATOR_GREAT;
+
+ /*
+ * Arbitrary offsets, chosen so
+ * the three blocks don't overlap.
+ */
+ /* "X=" operators */
+ ops['='+20] = EXP_OPERATOR_EQUAL;
+ ops['!'+20] = EXP_OPERATOR_NOTEQ;
+ ops['<'+20] = EXP_OPERATOR_LESSEQ;
+ ops['>'+20] = EXP_OPERATOR_GREATEQ;
+
+ /* "XX" operators */
+ ops['|'-30] = EXP_OPERATOR_OR;
+ ops['&'-30] = EXP_OPERATOR_AND;
+ ops['<'-30] = EXP_OPERATOR_LSHIFT;
+ ops['>'-30] = EXP_OPERATOR_RSHIFT;
+}
+
+ /*
+ * Insert the value of the specified object parameter,
+ * using the instance 'suffix' for wildcarded objects.
+ */
+netsnmp_variable_list *
+_expValue_evalParam( netsnmp_variable_list *expIdx, int param,
+ oid *suffix, size_t suffix_len )
+{
+ netsnmp_variable_list *var = SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
+ struct expObject *obj;
+ netsnmp_variable_list *val_var = NULL, *oval_var = NULL; /* values */
+ netsnmp_variable_list *dd_var = NULL, *odd_var = NULL; /* deltaDs */
+ netsnmp_variable_list *cond_var = NULL; /* conditionals */
+ int n;
+
+ /*
+ * Retrieve the expObject entry for the requested parameter.
+ */
+ if ( !var || !expIdx || !expIdx->next_variable ||
+ !expIdx->next_variable->next_variable )
+ return NULL;
+
+ *expIdx->next_variable->next_variable->val.integer = param;
+ obj = (struct expObject *)
+ netsnmp_tdata_row_entry(
+ netsnmp_tdata_row_get_byidx( expObject_table_data, expIdx ));
+ if (!obj) {
+ /*
+ * No such parameter configured for this expression
+ */
+ snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_INDEX );
+ var->type = ASN_NULL;
+ return var;
+ }
+ if ( obj->expObjectSampleType != EXPSAMPLETYPE_ABSOLUTE &&
+ obj->old_vars == NULL ) {
+ /*
+ * Can't calculate delta values until the second pass
+ */
+ snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_RESOURCE );
+ var->type = ASN_NULL;
+ return var;
+ }
+
+
+ /*
+ * For a wildcarded object, search for the matching suffix.
+ */
+ val_var = obj->vars;
+ if ( obj->flags & EXP_OBJ_FLAG_OWILD ) {
+ if ( !suffix ) {
+ /*
+ * If there's no suffix to match against, throw an error.
+ * An exact expression with a wildcarded object is invalid.
+ * XXX - Or just use first entry?
+ */
+ snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_INDEX );
+ var->type = ASN_NULL;
+ return var;
+ }
+ /*
+ * Otherwise, we'll walk *all* wildcarded values in parallel.
+ * This relies on the various varbind lists being set up with
+ * exactly the same entries. A little extra preparation
+ * during the data gathering simplifies things significantly!
+ */
+ if ( obj->expObjectSampleType != EXPSAMPLETYPE_ABSOLUTE )
+ oval_var = obj->old_vars;
+ if ( obj->flags & EXP_OBJ_FLAG_DWILD ) {
+ dd_var = obj->dvars;
+ odd_var = obj->old_dvars;
+ }
+ if ( obj->flags & EXP_OBJ_FLAG_CWILD )
+ cond_var = obj->cvars;
+
+ n = obj->expObjectID_len;
+ while ( val_var ) {
+ if ( snmp_oid_compare( val_var->name+n, val_var->name_length-n,
+ suffix, suffix_len ))
+ break;
+ val_var = val_var->next_variable;
+ if (oval_var)
+ oval_var = oval_var->next_variable;
+ if (dd_var) {
+ dd_var = dd_var->next_variable;
+ odd_var = odd_var->next_variable;
+ }
+ if (cond_var)
+ cond_var = cond_var->next_variable;
+ }
+
+ }
+ if (!val_var) {
+ /*
+ * No matching entry
+ */
+ snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_INDEX );
+ var->type = ASN_NULL;
+ return var;
+ }
+ /*
+ * Set up any non-wildcarded values - some
+ * of which may be null. That's fine.
+ */
+ if (!oval_var)
+ oval_var = obj->old_vars;
+ if (!dd_var) {
+ dd_var = obj->dvars;
+ odd_var = obj->old_dvars;
+ }
+ if (!cond_var)
+ cond_var = obj->cvars;
+
+
+ /*
+ * ... and return the appropriate value.
+ */
+ if (obj->expObjCond_len &&
+ (!cond_var || *cond_var->val.integer == 0)) {
+ /*
+ * expObjectConditional says no
+ */
+ snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_INDEX );
+ var->type = ASN_NULL;
+ return var;
+ }
+ if (dd_var && odd_var &&
+ *dd_var->val.integer != *odd_var->val.integer) {
+ /*
+ * expObjectDeltaD says no
+ */
+ snmp_set_var_typed_integer( var, ASN_INTEGER, EXPERRCODE_INDEX );
+ var->type = ASN_NULL;
+ return var;
+ }
+
+ /*
+ * XXX - May need to check sysUpTime discontinuities
+ * (unless this is handled earlier....)
+ */
+ switch ( obj->expObjectSampleType ) {
+ case EXPSAMPLETYPE_ABSOLUTE:
+ snmp_clone_var( val_var, var );
+ break;
+ case EXPSAMPLETYPE_DELTA:
+ snmp_set_var_typed_integer( var, ASN_INTEGER /* or UNSIGNED? */,
+ *val_var->val.integer - *oval_var->val.integer );
+ break;
+ case EXPSAMPLETYPE_CHANGED:
+ if ( val_var->val_len != oval_var->val_len )
+ n = 1;
+ else if (memcmp( val_var->val.string, oval_var->val.string,
+ val_var->val_len ) != 0 )
+ n = 1;
+ else
+ n = 0;
+ snmp_set_var_typed_integer( var, ASN_UNSIGNED, n );
+ }
+ return var;
+}
+
+
+ /*
+ * Utility routine to parse (and skip over) an integer constant
+ */
+int
+_expParse_integer( char *start, char **end ) {
+ int n;
+ char *cp;
+
+ n = atoi(start);
+ for (cp=start; *cp; cp++)
+ if (!isdigit(*cp))
+ break;
+ *end = cp;
+ return n;
+}
+
+netsnmp_variable_list *
+_expValue_evalOperator(netsnmp_variable_list *left,
+ netsnmp_variable_list *op,
+ netsnmp_variable_list *right) {
+ int n;
+
+ switch( *op->val.integer ) {
+ case EXP_OPERATOR_ADD:
+ n = *left->val.integer + *right->val.integer; break;
+ case EXP_OPERATOR_SUBTRACT:
+ n = *left->val.integer - *right->val.integer; break;
+ case EXP_OPERATOR_MULTIPLY:
+ n = *left->val.integer * *right->val.integer; break;
+ case EXP_OPERATOR_DIVIDE:
+ n = *left->val.integer / *right->val.integer; break;
+ case EXP_OPERATOR_REMAINDER:
+ n = *left->val.integer % *right->val.integer; break;
+ case EXP_OPERATOR_BITXOR:
+ n = *left->val.integer ^ *right->val.integer; break;
+ case EXP_OPERATOR_BITNEGATE:
+ n = 99; /* *left->val.integer ~ *right->val.integer; */ break;
+ case EXP_OPERATOR_BITOR:
+ n = *left->val.integer | *right->val.integer; break;
+ case EXP_OPERATOR_BITAND:
+ n = *left->val.integer & *right->val.integer; break;
+ case EXP_OPERATOR_NOT:
+ n = 99; /* *left->val.integer ! *right->val.integer; */ break;
+ case EXP_OPERATOR_LESS:
+ n = *left->val.integer < *right->val.integer; break;
+ case EXP_OPERATOR_GREAT:
+ n = *left->val.integer > *right->val.integer; break;
+ case EXP_OPERATOR_EQUAL:
+ n = *left->val.integer == *right->val.integer; break;
+ case EXP_OPERATOR_NOTEQ:
+ n = *left->val.integer != *right->val.integer; break;
+ case EXP_OPERATOR_LESSEQ:
+ n = *left->val.integer <= *right->val.integer; break;
+ case EXP_OPERATOR_GREATEQ:
+ n = *left->val.integer >= *right->val.integer; break;
+ case EXP_OPERATOR_OR:
+ n = *left->val.integer || *right->val.integer; break;
+ case EXP_OPERATOR_AND:
+ n = *left->val.integer && *right->val.integer; break;
+ case EXP_OPERATOR_LSHIFT:
+ n = *left->val.integer << *right->val.integer; break;
+ case EXP_OPERATOR_RSHIFT:
+ n = *left->val.integer >> *right->val.integer; break;
+ break;
+ default:
+ left->next_variable = NULL;
+ snmp_free_var(left);
+ right->next_variable = NULL;
+ snmp_free_var(right);
+
+ snmp_set_var_typed_integer( op, ASN_INTEGER, EXPERRCODE_OPERATOR );
+ op->type = ASN_NULL;
+ return op;
+ }
+
+ /* XXX */
+ left->next_variable = NULL;
+ snmp_free_var(left);
+ op->next_variable = NULL;
+ snmp_free_var(op);
+ snmp_set_var_typed_integer( right, ASN_INTEGER, n );
+ return right;
+}
+
+netsnmp_variable_list *
+_expValue_evalFunction(netsnmp_variable_list *func) {
+ netsnmp_variable_list *params = func->next_variable;
+ /* XXX */
+ params->next_variable = NULL;
+ snmp_free_var(params);
+ snmp_set_var_typed_integer( func, ASN_INTEGER, 99 );
+ return func;
+}
+
+netsnmp_variable_list *_expValue_evalExpr2(netsnmp_variable_list *exprAlDente);
+netsnmp_variable_list *
+_expValue_evalExpr( netsnmp_variable_list *expIdx,
+ char *exprRaw, char **exprEnd,
+ oid *suffix, size_t suffix_len )
+{
+ netsnmp_variable_list *exprAlDente = NULL;
+ netsnmp_variable_list *vtail = NULL;
+ char *cp1, *cp2;
+ netsnmp_variable_list *var = NULL;
+ int i, n;
+ int neg = 0;
+ oid oid_buf[MAX_OID_LEN];
+
+ DEBUGMSGTL(("disman:expr:eval1", "Evaluating '%s'\n", exprRaw));
+ if (!expIdx || !exprRaw)
+ return NULL;
+
+ /*
+ * The expression is evaluated in two stages.
+ * First, we simplify ("parboil") the raw expression,
+ * tokenizing it into a sequence of varbind values, inserting
+ * object parameters, and (recursively) evaluating any
+ * parenthesised sub-expressions or function arguments.
+ */
+
+ for (cp1=exprRaw; cp1 && *cp1; ) {
+ switch (*cp1) {
+ case '$':
+ /*
+ * Locate the appropriate instance of the specified
+ * parameter, and insert the corresponding value.
+ */
+ n = _expParse_integer( cp1+1, &cp1 );
+ var = _expValue_evalParam( expIdx, n, suffix, suffix_len );
+ if ( var && var->type == ASN_NULL ) {
+ DEBUGMSGTL(("disman:expr:eval", "Invalid parameter '%d'\n", n));
+ /* Note position of failure in expression */
+ var->data = (void *)(cp1 - exprRaw);
+ snmp_free_var(exprAlDente);
+ return var;
+ } else {
+ if (vtail)
+ vtail->next_variable = var;
+ else
+ exprAlDente = var;
+ vtail = var;
+ var = NULL;
+ }
+ break;
+ case '(':
+ /*
+ * Recursively evaluate the sub-expression
+ */
+ var = _expValue_evalExpr( expIdx, cp1+1, &cp2,
+ suffix, suffix_len );
+ if ( var && var->type == ASN_NULL ) {
+ /* Adjust position of failure */
+ var->data = (void *)(cp1 - exprRaw + (int)var->data);
+ return var;
+ } else if (*cp2 != ')') {
+ snmp_free_var(exprAlDente);
+ DEBUGMSGTL(("disman:expr:eval", "Unbalanced parenthesis\n"));
+ snmp_set_var_typed_integer( var, ASN_INTEGER,
+ EXPERRCODE_PARENTHESIS );
+ var->type = ASN_NULL;
+ var->data = (void *)(cp2 - exprRaw);
+ return var;
+ } else {
+ if (vtail)
+ vtail->next_variable = var;
+ else
+ exprAlDente = var;
+ vtail = var;
+ var = NULL;
+ cp1 = cp2+1; /* Skip to end of sub-expression */
+ }
+ break;
+ case ')':
+ case ',':
+ /*
+ * End of current (sub-)expression
+ * Note the end-position, and evaluate
+ * the parboiled list of tokens.
+ */
+ *exprEnd = cp1;
+ var = _expValue_evalExpr2( exprAlDente );
+ snmp_free_var(exprAlDente);
+ return var;
+
+ /* === Constants === */
+ case '.': /* OID */
+ i = 0;
+ memset( oid_buf, 0, sizeof(oid_buf));
+ while ( cp1 && *cp1 == '.' ) {
+ n = _expParse_integer( cp1+1, &cp2 );
+OID:
+ oid_buf[i++] = n;
+ cp1 = cp2;
+ }
+ var = snmp_varlist_add_variable( &exprAlDente, NULL, 0,
+ ASN_OBJECT_ID,
+ (u_char*)oid_buf, i*sizeof(oid));
+ break;
+DIGIT:
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = _expParse_integer( cp1, &cp2 );
+ if ( cp2 && *cp2 == '.' ) {
+ i = 0;
+ memset( oid_buf, 0, sizeof(oid_buf));
+ goto OID;
+ }
+ if ( neg )
+ n = -n;
+ var = snmp_varlist_add_variable( &exprAlDente, NULL, 0,
+ ASN_INTEGER,
+ (u_char*)&n, sizeof(n));
+ vtail = var;
+ var = NULL;
+ neg = 0;
+ cp1 = cp2;
+ break;
+
+ case '"': /* String Constant */
+ for ( cp2 = cp1+1; *cp2; cp2++ ) {
+ if ( *cp2 == '"' )
+ break;
+ if ( *cp2 == '\\' && *(cp2+1) == '"' )
+ cp2++;
+ }
+ if ( *cp2 != '"' ) {
+ /*
+ * Unterminated string
+ */
+ DEBUGMSGTL(("disman:expr:eval", "Unterminated string\n"));
+ snmp_set_var_typed_integer( var, ASN_INTEGER,
+ EXPERRCODE_SYNTAX );
+ var->type = ASN_NULL;
+ var->data = (void *)(cp2 - exprRaw);
+ return var;
+ }
+ n = cp2 - cp1;
+ var = snmp_varlist_add_variable( &exprAlDente, NULL, 0,
+ ASN_OCTET_STR,
+ (u_char*)cp1+1, n);
+ vtail = var;
+ var = NULL;
+ break;
+
+
+ /* === Operators === */
+ case '-':
+ /*
+ * Could be a unary minus....
+ */
+ if (!vtail || vtail->type == ASN_PRIV_OPERATOR) {
+ neg = 1;
+ goto DIGIT;
+ }
+ /*
+ * ... or a (single-character) binary operator.
+ */
+ /* Fallthrough */
+ case '+':
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ case '~':
+ if ( !vtail ) {
+ /*
+ * Can't start an expression with a binary operator
+ */
+ DEBUGMSGTL(("disman:expr:eval", "Initial binary operator\n"));
+ snmp_set_var_typed_integer( var, ASN_INTEGER,
+ EXPERRCODE_SYNTAX );
+ var->type = ASN_NULL;
+ var->data = (void *)(cp1 - exprRaw);
+ return var;
+ }
+ n = ops[ *cp1 & 0xFF ];
+ DEBUGMSGTL(("disman:expr:eval", "Binary operator %c (%d)\n", *cp1, n));
+ var = snmp_varlist_add_variable( &exprAlDente, NULL, 0,
+ ASN_INTEGER,
+ (u_char*)&n, sizeof(n));
+ var->type = ASN_PRIV_OPERATOR;
+ vtail = var;
+ cp1++;
+ break;
+
+ /*
+ * Multi-character binary operators
+ */
+ case '&':
+ case '|':
+ case '!':
+ case '>':
+ case '<':
+ case '=':
+ if ( !vtail ) {
+ /*
+ * Can't start an expression with a binary operator
+ */
+ DEBUGMSGTL(("disman:expr:eval", "Initial binary operator\n"));
+ snmp_set_var_typed_integer( var, ASN_INTEGER,
+ EXPERRCODE_SYNTAX );
+ var->type = ASN_NULL;
+ var->data = (void *)(cp1 - exprRaw);
+ return var;
+ }
+ if ( *(cp1+1) == '=' )
+ n = ops[ *cp1++ + 20];
+ else if ( *(cp1+1) == *cp1 )
+ n = ops[ *cp1++ - 30];
+ else
+ n = ops[ *cp1 & 0xFF ];
+ var = snmp_varlist_add_variable( &exprAlDente, NULL, 0,
+ ASN_INTEGER,
+ (u_char*)&n, sizeof(n));
+ var->type = ASN_PRIV_OPERATOR;
+ vtail = var;
+ cp1++;
+ break;
+
+ /* === Functions === */
+ case 'a': /* average/arraySection */
+ case 'c': /* counter32/counter64 */
+ case 'e': /* exists */
+ case 'm': /* maximum/minimum */
+ case 'o': /* oidBegins/Ends/Contains */
+ case 's': /* sum / string{B,E,C} */
+ var = snmp_varlist_add_variable( &exprAlDente, NULL, 0,
+ ASN_OCTET_STR,
+ (u_char*)cp1, 3 );
+ /* XXX */
+ var->type = ASN_PRIV_FUNCTION;
+ vtail = var;
+ while (*cp1 >= 'a' && *cp1 <= 'z')
+ cp1++;
+ break;
+
+ default:
+ if (isalpha( *cp1 )) {
+ /*
+ * Unrecognised function call ?
+ */
+ DEBUGMSGTL(("disman:expr:eval", "Unrecognised function '%s'\n", cp1));
+ snmp_set_var_typed_integer( var, ASN_INTEGER,
+ EXPERRCODE_FUNCTION );
+ var->type = ASN_NULL;
+ var->data = (void *)(cp1 - exprRaw);
+ return var;
+ }
+ else if (!isspace( *cp1 )) {
+ /*
+ * Unrecognised operator ?
+ */
+ DEBUGMSGTL(("disman:expr:eval", "Unrecognised operator '%c'\n", *cp1));
+ snmp_set_var_typed_integer( var, ASN_INTEGER,
+ EXPERRCODE_OPERATOR );
+ var->type = ASN_NULL;
+ var->data = (void *)(cp1 - exprRaw);
+ return var;
+ }
+ cp1++;
+ break;
+ }
+ }
+
+ /*
+ * ... then we evaluate the resulting simplified ("al dente")
+ * expression, in the usual manner.
+ */
+ *exprEnd = cp1;
+ var = _expValue_evalExpr2( exprAlDente );
+ DEBUGMSGTL(( "disman:expr:eval1", "Evaluated to "));
+ DEBUGMSGVAR(("disman:expr:eval1", var));
+ DEBUGMSG(( "disman:expr:eval1", "\n"));
+/* snmp_free_var(exprAlDente); XXX - Crashes */
+ return var;
+}
+
+netsnmp_variable_list *
+_expValue_evalExpr2( netsnmp_variable_list *exprAlD )
+{
+ netsnmp_variable_list *stack = NULL;
+ netsnmp_variable_list *lval, *rval, *op;
+ netsnmp_variable_list *vp, *vp1 = NULL;
+
+ DEBUGIF(( "disman:expr:eval2")) {
+ for (vp = exprAlD; vp; vp=vp->next_variable) {
+ if ( vp->type == ASN_PRIV_OPERATOR )
+ DEBUGMSGTL(( "disman:expr:eval2", "Operator %ld\n",
+ *vp->val.integer));
+ else if ( vp->type == ASN_PRIV_FUNCTION )
+ DEBUGMSGTL(( "disman:expr:eval2", "Function %s\n",
+ vp->val.string));
+ else {
+ DEBUGMSGTL(( "disman:expr:eval2", "Operand "));
+ DEBUGMSGVAR(("disman:expr:eval2", vp));
+ DEBUGMSG(( "disman:expr:eval2", "\n"));
+ }
+ }
+ }
+
+ for (vp = exprAlD; vp; vp=vp1) {
+ vp1 = vp->next_variable;
+ if ( vp->type == ASN_PRIV_OPERATOR ) {
+ /* Must *always* follow a value */
+ if ( !stack || stack->type == ASN_PRIV_OPERATOR ) {
+ snmp_set_var_typed_integer( vp, ASN_INTEGER,
+ EXPERRCODE_SYNTAX );
+ vp->type = ASN_NULL;
+ snmp_free_var( stack );
+ return vp;
+ }
+ /*
+ * Evaluate any higher priority operators
+ * already on the stack....
+ */
+ while ( stack->next_variable &&
+ stack->next_variable->type == ASN_PRIV_OPERATOR &&
+ (*stack->next_variable->val.integer > *vp->val.integer)) {
+ rval = stack;
+ op = stack->next_variable;
+ lval = op->next_variable;
+ stack = lval->next_variable;
+
+ rval = _expValue_evalOperator( lval, op, rval );
+ rval->next_variable = stack;
+ stack = rval;
+ }
+ /*
+ * ... and then push this operator onto the stack.
+ */
+ vp->next_variable = stack;
+ stack = vp;
+ } else if ( vp->type == ASN_PRIV_FUNCTION ) {
+ /* Must be first, or follow an operator */
+ if ( stack && stack->type != ASN_PRIV_OPERATOR ) {
+ snmp_set_var_typed_integer( vp, ASN_INTEGER,
+ EXPERRCODE_SYNTAX );
+ vp->type = ASN_NULL;
+ snmp_free_var( stack );
+ return vp;
+ }
+ /*
+ * Evaluate this function (consuming the
+ * appropriate parameters from the token
+ * list), and push the result onto the stack.
+ */
+ vp = _expValue_evalFunction( vp );
+ vp1 = vp->next_variable;
+ vp->next_variable = stack;
+ stack = vp;
+ } else {
+ /* Must be first, or follow an operator */
+ if ( stack && stack->type != ASN_PRIV_OPERATOR ) {
+ snmp_set_var_typed_integer( vp, ASN_INTEGER,
+ EXPERRCODE_SYNTAX );
+ vp->type = ASN_NULL;
+ snmp_free_var( stack );
+ return vp;
+ }
+ /*
+ * Push this value onto the stack
+ */
+ vp->next_variable = stack;
+ stack = vp;
+ }
+ }
+
+ /*
+ * Now evaluate whatever's left on the stack
+ * and return the final result.
+ */
+ while ( stack && stack->next_variable ) {
+ rval = stack;
+ op = stack->next_variable;
+ lval = op->next_variable;
+ stack = lval->next_variable;
+
+ rval = _expValue_evalOperator( lval, op, rval );
+ rval->next_variable = stack;
+ stack = rval;
+ }
+ return stack;
+}
+
+/* =============
+ * Main API
+ * ============= */
+netsnmp_variable_list *
+expValue_evaluateExpression( struct expExpression *exp,
+ oid *suffix, size_t suffix_len )
+{
+ char exprRaw[ EXP_STR3_LEN+1 ];
+ netsnmp_variable_list *var;
+ netsnmp_variable_list owner_var, name_var, param_var;
+ long n;
+ char *cp;
+
+ if (!exp)
+ return NULL;
+
+ /*
+ * Set up a varbind list containing the various index values
+ * (including a placeholder for expObjectIndex).
+ *
+ * This saves having to construct the same index list repeatedly
+ */
+ memset(&owner_var, 0, sizeof(netsnmp_variable_list));
+ memset(&name_var, 0, sizeof(netsnmp_variable_list));
+ memset(&param_var, 0, sizeof(netsnmp_variable_list));
+ snmp_set_var_typed_value( &owner_var, ASN_OCTET_STR,
+ (u_char*)exp->expOwner, strlen(exp->expOwner));
+ snmp_set_var_typed_value( &name_var, ASN_OCTET_STR,
+ (u_char*)exp->expName, strlen(exp->expName));
+ n = 99; /* dummy value */
+ snmp_set_var_typed_value( &param_var, ASN_INTEGER,
+ (u_char*)&n, sizeof(long));
+ owner_var.next_variable = &name_var;
+ name_var.next_variable = &param_var;
+
+ /*
+ * Make a working copy of the expression, and evaluate it.
+ */
+ memset(exprRaw, 0, sizeof(exprRaw));
+ memcpy(exprRaw, exp->expExpression, sizeof(exprRaw));
+
+ var = _expValue_evalExpr( &owner_var, exprRaw, &cp, suffix, suffix_len );
+ /*
+ * Check for any problems, and record the appropriate error
+ */
+ if (!cp || *cp != '\0') {
+ /*
+ * When we had finished, there was a lot
+ * of bricks^Wcharacters left over....
+ */
+ _expValue_setError( exp, EXPERRCODE_SYNTAX, suffix, suffix_len, NULL );
+ return NULL;
+ }
+ if (!var) {
+ /* Shouldn't happen */
+ _expValue_setError( exp, EXPERRCODE_RESOURCE, suffix, suffix_len, NULL );
+ return NULL;
+ }
+ if (var->type == ASN_NULL) {
+ /*
+ * Error explicitly reported from the evaluation routines.
+ */
+ _expValue_setError( exp, *(var->val.integer), suffix, suffix_len, var );
+ return NULL;
+ }
+ if (0 /* COMPARE var->type WITH exp->expValueType */ ) {
+ /*
+ * XXX - Check to see whether the returned type (ASN_XXX)
+ * is compatible with the requested type (an enum)
+ */
+
+ /* If not, throw an error */
+ _expValue_setError( exp, EXPERRCODE_TYPE, suffix, suffix_len, var );
+ return NULL;
+ }
+ return var;
+}
+
+void
+_expValue_setError( struct expExpression *exp, int reason,
+ oid *suffix, size_t suffix_len,
+ netsnmp_variable_list *var)
+{
+ if (!exp)
+ return;
+ exp->expErrorCount++;
+ /* exp->expErrorTime = NOW; */
+ exp->expErrorIndex = ( var && var->data ? (int)var->data : 0 );
+ exp->expErrorCode = reason;
+ memset( exp->expErrorInstance, 0, sizeof(exp->expErrorInstance));
+ memcpy( exp->expErrorInstance, suffix, suffix_len * sizeof(oid));
+ exp->expErrorInst_len = suffix_len;
+ snmp_free_var( var );
+}
diff --git a/agent/mibgroup/disman/expr/expValue.h b/agent/mibgroup/disman/expr/expValue.h
new file mode 100644
index 0000000..5b9bffb
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expValue.h
@@ -0,0 +1,12 @@
+
+#ifndef EXPVALUE_H
+#define EXPVALUE_H
+
+#include "disman/expr/expExpression.h"
+
+void init_expValue(void);
+netsnmp_variable_list *
+expValue_evaluateExpression( struct expExpression *exp,
+ oid *suffix, size_t suffix_len );
+
+#endif /* EXPVALUE_H */
diff --git a/agent/mibgroup/disman/expr/expValueTable.c b/agent/mibgroup/disman/expr/expValueTable.c
new file mode 100644
index 0000000..d74dbd1
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expValueTable.c
@@ -0,0 +1,329 @@
+/*
+ * DisMan Expression MIB:
+ * Implementation of the expValueTable MIB interface
+ * See 'expValue.c' for active evaluation of expressions.
+ *
+ * (Based roughly on mib2c.raw-table.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "expValue.h"
+#include "expValueTable.h"
+
+/** Initializes the expValueTable module */
+void
+init_expValueTable(void)
+{
+ static oid expValueTable_oid[] = { 1, 3, 6, 1, 2, 1, 90, 1, 3, 1 };
+ size_t expValueTable_oid_len = OID_LENGTH(expValueTable_oid);
+ netsnmp_handler_registration *reg;
+ netsnmp_table_registration_info *table_info;
+
+ reg =
+ netsnmp_create_handler_registration("expValueTable",
+ expValueTable_handler,
+ expValueTable_oid,
+ expValueTable_oid_len,
+ HANDLER_CAN_RONLY);
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_OCTET_STR, /* expExpressionOwner */
+ ASN_OCTET_STR, /* expExpressionName */
+ /* expValueInstance */
+ ASN_PRIV_IMPLIED_OBJECT_ID,
+ 0);
+
+ table_info->min_column = COLUMN_EXPVALUECOUNTER32VAL;
+ table_info->max_column = COLUMN_EXPVALUECOUNTER64VAL;
+
+ netsnmp_register_table(reg, table_info);
+ DEBUGMSGTL(("disman:expr:init", "Expression Value Table\n"));
+}
+
+
+netsnmp_variable_list *
+expValueTable_getEntry(netsnmp_variable_list * indexes,
+ int mode, unsigned int colnum)
+{
+ struct expExpression *exp;
+ netsnmp_variable_list *res, *vp, *vp2;
+ oid nullInstance[] = {0, 0, 0};
+ int plen;
+ size_t len;
+ unsigned int type = colnum-1; /* column object subIDs and type
+ enumerations are off by one. */
+
+ if (!indexes || !indexes->next_variable ||
+ !indexes->next_variable->next_variable ) {
+ /* XXX - Shouldn't happen! */
+ return NULL;
+ }
+
+ DEBUGMSGTL(( "disman:expr:val", "get (%d) entry (%s, %s, ", mode,
+ indexes->val.string, indexes->next_variable->val.string));
+ DEBUGMSGOID(("disman:expr:val",
+ indexes->next_variable->next_variable->val.objid,
+ indexes->next_variable->next_variable->val_len/sizeof(oid)));
+ DEBUGMSG(( "disman:expr:val", ")\n"));
+
+ /*
+ * Locate the expression that we've been asked to evaluate
+ */
+ if (!indexes->val_len || !indexes->next_variable->val_len ) {
+ /*
+ * Incomplete expression specification
+ */
+ if (mode == MODE_GETNEXT || mode == MODE_GETBULK) {
+ exp = expExpression_getFirstEntry();
+ DEBUGMSGTL(( "disman:expr:val", "first entry (%p)\n", exp ));
+ } else {
+ DEBUGMSGTL(( "disman:expr:val", "incomplete request\n" ));
+ return NULL; /* No match */
+ }
+ } else {
+ exp = expExpression_getEntry( (char*)indexes->val.string,
+ (char*)indexes->next_variable->val.string);
+ DEBUGMSGTL(( "disman:expr:val", "using entry (%p)\n", exp ));
+ }
+
+ /*
+ * We know what type of value was requested,
+ * so ignore any non-matching expressions.
+ */
+ while (exp && exp->expValueType != type) {
+ if (mode != MODE_GETNEXT && mode != MODE_GETBULK) {
+ DEBUGMSGTL(( "disman:expr:val", "wrong type (%d != %ld)\n",
+ type, (exp ? exp->expValueType : 0 )));
+ return NULL; /* Wrong type */
+ }
+NEXT_EXP:
+ exp = expExpression_getNextEntry( exp->expOwner, exp->expName );
+ DEBUGMSGTL(( "disman:expr:val", "using next entry (%p)\n", exp ));
+ }
+ if (!exp) {
+ DEBUGMSGTL(( "disman:expr:val", "no more entries\n"));
+ return NULL; /* No match (of the required type) */
+ }
+
+
+ /*
+ * Now consider which instance of the chosen expression is needed
+ */
+ vp = indexes->next_variable->next_variable;
+ if ( mode == MODE_GET ) {
+ /*
+ * For a GET request, check that the specified value instance
+ * is valid, and evaluate the expression using this.
+ */
+ if ( !vp || !vp->val_len ) {
+ DEBUGMSGTL(( "disman:expr:val", "no instance index\n"));
+ return NULL; /* No instance provided */
+ }
+ if ( vp->val.objid[0] != 0 ) {
+ DEBUGMSGTL(( "disman:expr:val",
+ "non-zero instance (%" NETSNMP_PRIo "d)\n", vp->val.objid[0]));
+ return NULL; /* Invalid instance */
+ }
+
+ if (exp->expPrefix_len == 0 ) {
+ /*
+ * The only valid instance for a non-wildcarded
+ * expression is .0.0.0
+ */
+ if ( vp->val_len != 3*sizeof(oid) ||
+ vp->val.objid[1] != 0 ||
+ vp->val.objid[2] != 0 ) {
+ DEBUGMSGTL(( "disman:expr:val", "invalid scalar instance\n"));
+ return NULL;
+ }
+ res = expValue_evaluateExpression( exp, NULL, 0 );
+ DEBUGMSGTL(( "disman:expr:val", "scalar get returned (%p)\n", res));
+ } else {
+ /*
+ * Otherwise, skip the leading '.0' and use
+ * the remaining instance subidentifiers.
+ */
+ res = expValue_evaluateExpression( exp, vp->val.objid+1,
+ vp->val_len/sizeof(oid)-1);
+ DEBUGMSGTL(( "disman:expr:val", "w/card get returned (%p)\n", res));
+ }
+ } else {
+ /*
+ * For a GETNEXT request, identify the appropriate next
+ * value instance, and evaluate the expression using
+ * that, updating the index list appropriately.
+ */
+ if ( vp->val_len > 0 && vp->val.objid[0] != 0 ) {
+ DEBUGMSGTL(( "disman:expr:val",
+ "non-zero next instance (%" NETSNMP_PRIo "d)\n", vp->val.objid[0]));
+ return NULL; /* All valid instances start with .0 */
+ }
+ plen = exp->expPrefix_len;
+ if (plen == 0 ) {
+ /*
+ * The only valid instances for GETNEXT on a
+ * non-wildcarded expression are .0 and .0.0
+ * Anything else is too late.
+ */
+ if ((vp->val_len > 2*sizeof(oid)) ||
+ (vp->val_len == 2*sizeof(oid) &&
+ vp->val.objid[1] != 0)) {
+ DEBUGMSGTL(( "disman:expr:val", "invalid scalar next instance\n"));
+ return NULL; /* Invalid instance */
+ }
+
+ /*
+ * Make sure the index varbind list refers to the
+ * (only) valid instance of this expression,
+ * and evaluate it.
+ */
+ snmp_set_var_typed_value( indexes, ASN_OCTET_STR,
+ (u_char*)exp->expOwner, strlen(exp->expOwner));
+ snmp_set_var_typed_value( indexes->next_variable, ASN_OCTET_STR,
+ (u_char*)exp->expName, strlen(exp->expName));
+ snmp_set_var_typed_value( vp, ASN_PRIV_IMPLIED_OBJECT_ID,
+ (u_char*)nullInstance, 3*sizeof(oid));
+ res = expValue_evaluateExpression( exp, NULL, 0 );
+ DEBUGMSGTL(( "disman:expr:val", "scalar next returned (%p)\n", res));
+ } else {
+ /*
+ * Now comes the interesting case - finding the
+ * appropriate instance of a wildcarded expression.
+ */
+ if ( vp->val_len == 0 ) {
+ if ( !exp->pvars ) {
+ DEBUGMSGTL(( "disman:expr:val", "no instances\n"));
+ goto NEXT_EXP;
+ }
+ DEBUGMSGTL(( "disman:expr:val", "using first instance\n"));
+ vp2 = exp->pvars;
+ } else {
+ /*
+ * Search the list of instances for the (first) greater one
+ * XXX - This comparison relies on the OID of the prefix
+ * object being the same length as the wildcarded
+ * parameter objects. It ain't necessarily so.
+ */
+ for ( vp2 = exp->pvars; vp2; vp2 = vp2->next_variable ) {
+ if ( snmp_oid_compare( vp2->name + plen,
+ vp2->name_length - plen,
+ vp->name,
+ vp->name_length) < 0 ) {
+ DEBUGMSGTL(( "disman:expr:val", "next instance "));
+ DEBUGMSGOID(("disman:expr:val", vp2->name, vp2->name_length ));
+ DEBUGMSG(( "disman:expr:val", "\n"));
+ break;
+ }
+ }
+ if (!vp2) {
+ DEBUGMSGTL(( "disman:expr:val", "no next instance\n"));
+ goto NEXT_EXP;
+ }
+ }
+ snmp_set_var_typed_value( indexes, ASN_OCTET_STR,
+ (u_char*)exp->expOwner, strlen(exp->expOwner));
+ snmp_set_var_typed_value( indexes->next_variable, ASN_OCTET_STR,
+ (u_char*)exp->expName, strlen(exp->expName));
+ if (vp2) {
+ len = vp2->name_length - exp->expPrefix_len;
+ snmp_set_var_typed_value( vp, ASN_PRIV_IMPLIED_OBJECT_ID,
+ (u_char*)(vp2->name+exp->expPrefix_len), len);
+ } else {
+ len = 1;
+ }
+ res = expValue_evaluateExpression( exp, vp->val.objid+1, len-1);
+ DEBUGMSGTL(( "disman:expr:val", "w/card next returned (%p)\n", res));
+ }
+ }
+ return res;
+}
+
+/** handles requests for the expValueTable table */
+int
+expValueTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ netsnmp_variable_list *value;
+ oid expValueOID[] = { 1, 3, 6, 1, 2, 1, 90, 1, 3, 1, 1, 99 };
+ size_t expValueOID_len = OID_LENGTH(expValueOID);
+ oid name_buf[ MAX_OID_LEN ];
+ size_t name_buf_len = MAX_OID_LEN;
+
+ DEBUGMSGTL(("disman:expr:mib", "Expression Value Table handler (%d)\n",
+ reqinfo->mode));
+ switch (reqinfo->mode) {
+ case MODE_GET:
+ case MODE_GETNEXT:
+ for (request = requests; request; request = request->next) {
+ tinfo = netsnmp_extract_table_info(request);
+ value = expValueTable_getEntry(tinfo->indexes,
+ reqinfo->mode,
+ tinfo->colnum);
+ if (!value || !value->val.integer) {
+ netsnmp_set_request_error(reqinfo, request,
+ (reqinfo->mode == MODE_GET) ?
+ SNMP_NOSUCHINSTANCE :
+ SNMP_ENDOFMIBVIEW);
+ continue;
+ }
+ if ( reqinfo->mode == MODE_GETNEXT ) {
+ /*
+ * Need to update the request varbind OID
+ * to match the instance just evaluated.
+ * (XXX - Is this the appropriate mechanism?)
+ */
+ build_oid_noalloc( name_buf, MAX_OID_LEN, &name_buf_len,
+ expValueOID, expValueOID_len, tinfo->indexes );
+ name_buf[ expValueOID_len -1 ] = tinfo->colnum;
+ snmp_set_var_objid(request->requestvb, name_buf, name_buf_len);
+ }
+
+ switch (tinfo->colnum) {
+ case COLUMN_EXPVALUECOUNTER32VAL:
+ snmp_set_var_typed_integer(request->requestvb, ASN_COUNTER,
+ *value->val.integer);
+ break;
+ case COLUMN_EXPVALUEUNSIGNED32VAL:
+ snmp_set_var_typed_integer(request->requestvb, ASN_UNSIGNED,
+ *value->val.integer);
+ break;
+ case COLUMN_EXPVALUETIMETICKSVAL:
+ snmp_set_var_typed_integer(request->requestvb, ASN_TIMETICKS,
+ *value->val.integer);
+ break;
+ case COLUMN_EXPVALUEINTEGER32VAL:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ *value->val.integer);
+ break;
+ case COLUMN_EXPVALUEIPADDRESSVAL:
+ snmp_set_var_typed_integer(request->requestvb, ASN_IPADDRESS,
+ *value->val.integer);
+ break;
+ case COLUMN_EXPVALUEOCTETSTRINGVAL:
+ snmp_set_var_typed_value( request->requestvb, ASN_OCTET_STR,
+ value->val.string, value->val_len);
+ break;
+ case COLUMN_EXPVALUEOIDVAL:
+ snmp_set_var_typed_value( request->requestvb, ASN_OBJECT_ID,
+ (u_char *)value->val.objid, value->val_len);
+ break;
+ case COLUMN_EXPVALUECOUNTER64VAL:
+ snmp_set_var_typed_value( request->requestvb, ASN_COUNTER64,
+ (u_char *)value->val.counter64, value->val_len);
+ break;
+ }
+ }
+ break;
+
+ }
+ DEBUGMSGTL(("disman:expr:mib", "Expression Value handler - done \n"));
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/expr/expValueTable.h b/agent/mibgroup/disman/expr/expValueTable.h
new file mode 100644
index 0000000..15f3202
--- /dev/null
+++ b/agent/mibgroup/disman/expr/expValueTable.h
@@ -0,0 +1,23 @@
+#ifndef EXPVALUETABLE_H
+#define EXPVALUETABLE_H
+
+/*
+ * function declarations
+ */
+void init_expValueTable(void);
+Netsnmp_Node_Handler expValueTable_handler;
+netsnmp_variable_list *expValue_getVal(netsnmp_variable_list *, int);
+
+/*
+ * column number definitions for table expValueTable
+ */
+#define COLUMN_EXPVALUEINSTANCE 1
+#define COLUMN_EXPVALUECOUNTER32VAL 2
+#define COLUMN_EXPVALUEUNSIGNED32VAL 3
+#define COLUMN_EXPVALUETIMETICKSVAL 4
+#define COLUMN_EXPVALUEINTEGER32VAL 5
+#define COLUMN_EXPVALUEIPADDRESSVAL 6
+#define COLUMN_EXPVALUEOCTETSTRINGVAL 7
+#define COLUMN_EXPVALUEOIDVAL 8
+#define COLUMN_EXPVALUECOUNTER64VAL 9
+#endif /* EXPVALUETABLE_H */
diff --git a/agent/mibgroup/disman/expr/exp_enum.h b/agent/mibgroup/disman/expr/exp_enum.h
new file mode 100644
index 0000000..47085b2
--- /dev/null
+++ b/agent/mibgroup/disman/expr/exp_enum.h
@@ -0,0 +1,60 @@
+#ifndef EXP_ENUM_H
+#define EXP_ENUM_H
+
+ /* expExpressionValueType */
+#define EXPVALTYPE_COUNTER 1
+#define EXPVALTYPE_UNSIGNED 2
+#define EXPVALTYPE_TIMETICKS 3
+#define EXPVALTYPE_INTEGER 4
+#define EXPVALTYPE_IPADDRESS 5
+#define EXPVALTYPE_STRING 6
+#define EXPVALTYPE_OID 7
+#define EXPVALTYPE_COUNTER64 8
+
+ /* expErrorCode */
+#define EXPERRCODE_SYNTAX 1
+#define EXPERRCODE_INDEX 2
+#define EXPERRCODE_OPERATOR 3
+#define EXPERRCODE_FUNCTION 4
+#define EXPERRCODE_TYPE 5
+#define EXPERRCODE_PARENTHESIS 6
+#define EXPERRCODE_WILDCARD 7
+#define EXPERRCODE_RECURSION 8
+#define EXPERRCODE_DELTA 9
+#define EXPERRCODE_RESOURCE 10
+#define EXPERRCODE_DIVZERO 11
+
+ /* expObjectSampleType */
+#define EXPSAMPLETYPE_ABSOLUTE 1
+#define EXPSAMPLETYPE_DELTA 2
+#define EXPSAMPLETYPE_CHANGED 3
+
+ /* expObjectDiscontinuityIDType */
+#define EXPDISCID_TIMETICKS 1
+#define EXPDISCID_TIMESTAMP 2
+#define EXPDISCID_DATETIME 3
+
+ /* expression operators (in increasing order of priority) */
+ /* XXX - Check priority ordering */
+#define EXP_OPERATOR_ADD 1
+#define EXP_OPERATOR_SUBTRACT 2
+#define EXP_OPERATOR_MULTIPLY 3
+#define EXP_OPERATOR_DIVIDE 4
+#define EXP_OPERATOR_REMAINDER 5
+#define EXP_OPERATOR_BITXOR 6
+#define EXP_OPERATOR_BITNEGATE 7
+#define EXP_OPERATOR_BITOR 8
+#define EXP_OPERATOR_BITAND 9
+#define EXP_OPERATOR_NOT 10
+#define EXP_OPERATOR_OR 11
+#define EXP_OPERATOR_AND 12
+#define EXP_OPERATOR_EQUAL 13
+#define EXP_OPERATOR_NOTEQ 14
+#define EXP_OPERATOR_LESS 15
+#define EXP_OPERATOR_LESSEQ 16
+#define EXP_OPERATOR_GREAT 17
+#define EXP_OPERATOR_GREATEQ 18
+#define EXP_OPERATOR_LSHIFT 19
+#define EXP_OPERATOR_RSHIFT 20
+#endif /* EXP_ENUM_H */
+
diff --git a/agent/mibgroup/disman/expression-mib.h b/agent/mibgroup/disman/expression-mib.h
new file mode 100644
index 0000000..18db2af
--- /dev/null
+++ b/agent/mibgroup/disman/expression-mib.h
@@ -0,0 +1,21 @@
+/*
+*Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+*
+*All right reserved
+*
+*File Name:expression-mib.h
+*File Description: add DISMAN-EXPRESSION-MIB.
+*
+*Current Version:1.0
+*Author:JianShun Tong
+*Date:2004.8.20
+*/
+
+/*
+ * wrapper for the disman expression mib code files
+ */
+config_require(disman/expression/expExpressionTable)
+config_require(disman/expression/expErrorTable)
+config_require(disman/expression/expObjectTable)
+config_require(disman/expression/expValueTable)
+config_add_mib(DISMAN-EXPRESSION-MIB)
diff --git a/agent/mibgroup/disman/expression.h b/agent/mibgroup/disman/expression.h
new file mode 100644
index 0000000..82f7cc0
--- /dev/null
+++ b/agent/mibgroup/disman/expression.h
@@ -0,0 +1,13 @@
+/*
+ * wrapper for the disman expression mib code files
+ */
+config_require(disman/expr/expScalars)
+config_require(disman/expr/expExpression)
+config_require(disman/expr/expExpressionTable)
+config_require(disman/expr/expErrorTable)
+config_require(disman/expr/expExpressionConf)
+config_require(disman/expr/expObject)
+config_require(disman/expr/expObjectTable)
+config_require(disman/expr/expObjectConf)
+config_require(disman/expr/expValue)
+config_require(disman/expr/expValueTable)
diff --git a/agent/mibgroup/disman/expression/expErrorTable.c b/agent/mibgroup/disman/expression/expErrorTable.c
new file mode 100644
index 0000000..1feb3ee
--- /dev/null
+++ b/agent/mibgroup/disman/expression/expErrorTable.c
@@ -0,0 +1,144 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name: expErrorTable.c
+ *File Description: expErrorTable MIB operation.
+ *
+ *Current Version:1.0
+ *Author:JianShun Tong
+ *Date:2004.8.20
+ */
+
+
+/*
+ * This file was generated by mib2c and is intended for use as
+ * a mib module for the ucd-snmp snmpd agent.
+ */
+
+
+/*
+ * This should always be included first before anything else
+ */
+#include <net-snmp/net-snmp-config.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+
+/*
+ * minimal include directives
+ */
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "header_complex.h"
+#include "expErrorTable.h"
+#include "expExpressionTable.h"
+
+
+
+/*
+ * expErrorTable_variables_oid:
+ * this is the top level oid that we want to register under. This
+ * is essentially a prefix, with the suffix appearing in the
+ * variable below.
+ */
+
+oid expErrorTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 90, 1, 2, 2 };
+
+/*
+ * variable2 expErrorTable_variables:
+ */
+
+struct variable2 expErrorTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define EXPERRORTIME 1
+ {EXPERRORTIME, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_expErrorTable, 2, {1, 1}},
+#define EXPERRORINDEX 2
+ {EXPERRORINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_expErrorTable, 2, {1, 2}},
+#define EXPERRORCODE 3
+ {EXPERRORCODE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_expErrorTable, 2, {1, 3}},
+#define EXPERRORINSTANCE 4
+ {EXPERRORINSTANCE, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY,
+ var_expErrorTable, 2, {1, 4}}
+};
+
+extern struct header_complex_index *expExpressionTableStorage;
+
+
+void
+init_expErrorTable(void)
+{
+ DEBUGMSGTL(("expErrorTable", "initializing... "));
+
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("expErrorTable",
+ expErrorTable_variables, variable2,
+ expErrorTable_variables_oid);
+
+ DEBUGMSGTL(("expErrorTable", "done.\n"));
+}
+
+
+
+unsigned char *
+var_expErrorTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact, size_t *var_len, WriteMethod ** write_method)
+{
+ struct expExpressionTable_data *StorageTmp = NULL;
+
+ DEBUGMSGTL(("expErrorTable", "var_expErrorTable: Entering... \n"));
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(expExpressionTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL)
+ return NULL;
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+
+ case EXPERRORTIME:
+ *var_len = sizeof(StorageTmp->expErrorTime);
+ return (u_char *) & StorageTmp->expErrorTime;
+
+ case EXPERRORINDEX:
+ *var_len = sizeof(StorageTmp->expErrorIndex);
+ return (u_char *) & StorageTmp->expErrorIndex;
+
+ case EXPERRORCODE:
+ *var_len = sizeof(StorageTmp->expErrorCode);
+ return (u_char *) & StorageTmp->expErrorCode;
+
+ case EXPERRORINSTANCE:
+ *var_len = StorageTmp->expErrorInstanceLen * sizeof(oid);
+ return (u_char *) StorageTmp->expErrorInstance;
+ }
+
+ return NULL;
+}
diff --git a/agent/mibgroup/disman/expression/expErrorTable.h b/agent/mibgroup/disman/expression/expErrorTable.h
new file mode 100644
index 0000000..5399159
--- /dev/null
+++ b/agent/mibgroup/disman/expression/expErrorTable.h
@@ -0,0 +1,49 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:expErrorTable.h
+ *File Description: head file.
+ *
+ *Current Version:1.0
+ *Author:JianShun Tong
+ *Date:2004.8.20
+ */
+
+
+/*
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+
+#ifndef _MIBGROUP_EXPERRORTALBE_H
+#define _MIBGROUP_EXPERRORTALBE_H
+
+
+
+/*
+ * we may use header_complex from the header_complex module
+ */
+config_require(header_complex)
+
+
+ struct expErrorTable_data {
+
+ unsigned long expErrorTime;
+ long expErrorIndex;
+ long expErrorCode;
+ oid *expErrorInstance;
+ size_t expErrorInstanceLen;
+ };
+
+ /*
+ * function prototypes
+ */
+ void init_expErrorTable(void);
+ FindVarMethod var_expErrorTable;
+
+
+
+#endif /* _MIBGROUP_EXPERRORTALBE_H */
diff --git a/agent/mibgroup/disman/expression/expExpressionTable.c b/agent/mibgroup/disman/expression/expExpressionTable.c
new file mode 100644
index 0000000..ce3b0db
--- /dev/null
+++ b/agent/mibgroup/disman/expression/expExpressionTable.c
@@ -0,0 +1,1177 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name: expExpressionTable.c
+ *File Description: expExpressionTable MIB operation.
+ *
+ *Current Version:1.0
+ *Author:JianShun Tong
+ *Date:2004.8.20
+ */
+
+/*
+ * This file was generated by mib2c and is intended for use as
+ * a mib module for the ucd-snmp snmpd agent.
+ */
+
+
+/*
+ * This should always be included first before anything else
+ */
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+
+/*
+ * minimal include directives
+ */
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "header_complex.h"
+#include "expErrorTable.h"
+#include "expExpressionTable.h"
+#include "expObjectTable.h"
+#include "expValueTable.h"
+
+netsnmp_feature_require(tdomain_support)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(header_complex_find_entry)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+/*
+ * expExpressionTable_variables_oid:
+ * this is the top level oid that we want to register under. This
+ * is essentially a prefix, with the suffix appearing in the
+ * variable below.
+ */
+
+oid expExpressionTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 90, 1, 2, 1 };
+
+/*
+ * variable2 expExpressionTable_variables:
+ */
+
+struct variable2 expExpressionTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define EXPEXPRESSION 3
+ {EXPEXPRESSION, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_expExpressionTable, 2, {1, 3}},
+#define EXPEXPRESSIONVALUETYPE 4
+ {EXPEXPRESSIONVALUETYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_expExpressionTable, 2, {1, 4}},
+#define EXPEXPRESSIONCOMMENT 5
+ {EXPEXPRESSIONCOMMENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_expExpressionTable, 2, {1, 5}},
+#define EXPEXPRESSIONDELTALNTERVAL 6
+ {EXPEXPRESSIONDELTALNTERVAL, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_expExpressionTable, 2, {1, 6}},
+#define EXPEXPRESSIONPREFIX 7
+ {EXPEXPRESSIONPREFIX, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY,
+ var_expExpressionTable, 2, {1, 7}},
+#define EXPEXPRESSIONERRORS 8
+ {EXPEXPRESSIONERRORS, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_expExpressionTable, 2, {1, 8}},
+#define EXPEXPRESSIONENTRYSTATUS 9
+ {EXPEXPRESSIONENTRYSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_expExpressionTable, 2, {1, 9}}
+};
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+
+struct header_complex_index *expExpressionTableStorage = NULL;
+extern struct header_complex_index *expObjectTableStorage;
+extern struct header_complex_index *expValueTableStorage;
+
+oid mmTimeInstance[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 };
+
+/*
+ * init_expExpressionTable():
+ * Initialization routine. This is called when the agent starts up.
+ * At a minimum, registration of your variables should take place here.
+ */
+void
+init_expExpressionTable(void)
+{
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("expExpressionTable", expExpressionTable_variables,
+ variable2, expExpressionTable_variables_oid);
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("expExpressionTable",
+ parse_expExpressionTable, NULL, NULL);
+
+
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_expExpressionTable, NULL);
+
+
+ DEBUGMSGTL(("expExpressionTable", "done.\n"));
+}
+
+struct expExpressionTable_data *
+create_expExpressionTable_data(void)
+{
+ struct expExpressionTable_data *StorageNew;
+ StorageNew = SNMP_MALLOC_STRUCT(expExpressionTable_data);
+ /*
+ * fill in default row values here into StorageNew
+ */
+ /*
+ * fill in values for all tables (even if not
+ * appropriate), since its easier to do here than anywhere
+ * else
+ */
+
+ StorageNew->expExpression = strdup("");
+ StorageNew->expExpressionValueType = EXPEXPRESSION_COUNTER32;
+ StorageNew->expExpressionComment = strdup("");
+ StorageNew->expExpressionDeltaInterval = 0;
+ StorageNew->expExpressionPrefix = calloc(1, sizeof(oid) * 2); /* 0.0 */
+ StorageNew->expExpressionPrefixLen = 2;
+ StorageNew->hc_ObjectTableStorage = NULL;
+ StorageNew->hc_ValueTableStorage = NULL;
+ StorageNew->storageType = ST_NONVOLATILE;
+ return StorageNew;
+}
+
+int
+expExpressionTable_add(struct expExpressionTable_data *thedata)
+{
+ netsnmp_variable_list *vars = NULL;
+
+
+ DEBUGMSGTL(("expExpressionTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->expExpressionOwner, thedata->expExpressionOwnerLen); /* expExpressionOwner */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->expExpressionName, thedata->expExpressionNameLen); /* expExpressionName */
+
+ header_complex_add_data(&expExpressionTableStorage, vars, thedata);
+ DEBUGMSGTL(("expExpressionTable", "registered an entry\n"));
+
+
+ DEBUGMSGTL(("expExpressionTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+
+/*
+ * parse_mteTriggerTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+void
+parse_expExpressionTable(const char *token, char *line)
+{
+ size_t tmpint;
+ oid *tmpoid = NULL;
+ struct expExpressionTable_data *StorageTmp =
+ SNMP_MALLOC_STRUCT(expExpressionTable_data);
+
+ DEBUGMSGTL(("expExpressionTable", "parsing config... "));
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->expExpressionOwner,
+ &StorageTmp->expExpressionOwnerLen);
+ if (StorageTmp->expExpressionOwner == NULL) {
+ config_perror("invalid specification for expExpressionOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->expExpressionName,
+ &StorageTmp->expExpressionNameLen);
+ if (StorageTmp->expExpressionName == NULL) {
+ config_perror("invalid specification for expExpressionName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->expExpression,
+ &StorageTmp->expExpressionLen);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->expExpressionValueType,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->expExpressionComment,
+ &StorageTmp->expExpressionCommentLen);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->expExpressionDeltaInterval,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OBJECT_ID, line,
+ &StorageTmp->expExpressionPrefix,
+ &StorageTmp->expExpressionPrefixLen);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->expExpressionErrors, &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->expExpressionEntryStatus,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->have_copied_auth_info, &tmpint);
+ if (StorageTmp->have_copied_auth_info) {
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pdu_version, &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pdu_securityModel, &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pdu_securityLevel, &tmpint);
+ line =
+ read_config_read_data(ASN_OBJECT_ID, line, &tmpoid, &tmpint);
+ if (!netsnmp_tdomain_support
+ (tmpoid, tmpint, &StorageTmp->pdu_tDomain,
+ &StorageTmp->pdu_tDomainLen)) {
+ config_perror
+ ("unsupported transport domain for mteTriggerEntry");
+ return;
+ }
+ if (tmpoid != NULL) {
+ free(tmpoid);
+ }
+
+ /*
+ * can be NULL? Yes.
+ */
+ line = read_config_read_data(ASN_OCTET_STR, line,
+ &(StorageTmp->pdu_transport),
+ &StorageTmp->pdu_transportLen);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pdu_community,
+ &StorageTmp->pdu_community_len);
+ if (StorageTmp->pdu_community == NULL) {
+ config_perror("invalid specification for pdu_community");
+ return;
+ }
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pdu_securityName,
+ &StorageTmp->pdu_securityNameLen);
+ if (StorageTmp->pdu_securityName == NULL) {
+ config_perror("invalid specification for pdu_securityName");
+ return;
+ }
+ }
+ StorageTmp->storageType = ST_NONVOLATILE;
+ expExpressionTable_add(StorageTmp);
+
+
+ DEBUGMSGTL(("expExpressionTable", "done.\n"));
+}
+
+
+/*
+ * store_expExpressionTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+int
+store_expExpressionTable(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr;
+ size_t tmpint;
+ struct expExpressionTable_data *StorageTmp;
+ struct header_complex_index *hcindex;
+
+ DEBUGMSGTL(("expExpressionTable", "storing data... "));
+
+ for (hcindex = expExpressionTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct expExpressionTable_data *) hcindex->data;
+
+
+ if (StorageTmp->storageType == ST_NONVOLATILE) {
+
+ memset(line, 0, sizeof(line));
+ strcat(line, "expExpressionTable ");
+ cptr = line + strlen(line);
+ /*
+ * expExpressionTable
+ */
+
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->expExpressionOwner,
+ &StorageTmp->expExpressionOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->expExpressionName,
+ &StorageTmp->expExpressionNameLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->expExpression,
+ &StorageTmp->expExpressionLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->expExpressionValueType,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->expExpressionComment,
+ &StorageTmp->
+ expExpressionCommentLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ expExpressionDeltaInterval,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OBJECT_ID, cptr,
+ &StorageTmp->expExpressionPrefix,
+ &StorageTmp->
+ expExpressionPrefixLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->expExpressionErrors,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ expExpressionEntryStatus, &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->have_copied_auth_info,
+ &tmpint);
+ if (StorageTmp->have_copied_auth_info) {
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pdu_version,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pdu_securityModel,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pdu_securityLevel,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OBJECT_ID, cptr,
+ (void *) (&StorageTmp->
+ pdu_tDomain),
+ &StorageTmp->pdu_tDomainLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pdu_transport,
+ &StorageTmp->pdu_transportLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pdu_community,
+ &StorageTmp->pdu_community_len);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pdu_securityName,
+ &StorageTmp->
+ pdu_securityNameLen);
+ }
+
+
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("expExpressionTable", "storage done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+
+
+/*
+ * var_expExpressionTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_expExpressionTable above.
+ */
+unsigned char *
+var_expExpressionTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact,
+ size_t *var_len, WriteMethod ** write_method)
+{
+ struct expExpressionTable_data *StorageTmp = NULL;
+
+ DEBUGMSGTL(("expExpressionTable",
+ "var_expExpressionTable: Entering... \n"));
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(expExpressionTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL) {
+ if (vp->magic == EXPEXPRESSIONENTRYSTATUS)
+ *write_method = write_expExpressionEntryStatus;
+ return NULL;
+ }
+
+
+ switch (vp->magic) {
+
+
+ case EXPEXPRESSION:
+ *write_method = write_expExpression;
+ *var_len = StorageTmp->expExpressionLen;
+ return (u_char *) StorageTmp->expExpression;
+
+ case EXPEXPRESSIONVALUETYPE:
+ *write_method = write_expExpressionValueType;
+ *var_len = sizeof(StorageTmp->expExpressionValueType);
+ return (u_char *) & StorageTmp->expExpressionValueType;
+
+ case EXPEXPRESSIONCOMMENT:
+ *write_method = write_expExpressionComment;
+ *var_len = StorageTmp->expExpressionCommentLen;
+ return (u_char *) StorageTmp->expExpressionComment;
+
+ case EXPEXPRESSIONDELTALNTERVAL:
+ *write_method = write_expExpressionDeltaInterval;
+ *var_len = sizeof(StorageTmp->expExpressionDeltaInterval);
+ return (u_char *) & StorageTmp->expExpressionDeltaInterval;
+
+ case EXPEXPRESSIONPREFIX:
+ *var_len = StorageTmp->expExpressionPrefixLen * sizeof(oid);
+ return (u_char *) StorageTmp->expExpressionPrefix;
+
+ case EXPEXPRESSIONERRORS:
+ *var_len = sizeof(StorageTmp->expExpressionErrors);
+ return (u_char *) & StorageTmp->expExpressionErrors;
+
+ case EXPEXPRESSIONENTRYSTATUS:
+ *write_method = write_expExpressionEntryStatus;
+ *var_len = sizeof(StorageTmp->expExpressionEntryStatus);
+ return (u_char *) & StorageTmp->expExpressionEntryStatus;
+
+ default:
+ ERROR_MSG("");
+
+ }
+ return NULL;
+}
+
+
+
+int
+write_expExpression(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct expExpressionTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(expExpressionTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+
+ DEBUGMSGTL(("expExpressionTable",
+ "write_expExpression entering action=%d... \n", action));
+ if ((StorageTmp =
+ header_complex(expExpressionTableStorage, NULL,
+ &name[sizeof(expExpressionTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to expExpression not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->expExpression;
+ tmplen = StorageTmp->expExpressionLen;
+ memdup((u_char **) & StorageTmp->expExpression, var_val,
+ var_val_len);
+ StorageTmp->expExpressionLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->expExpression);
+ StorageTmp->expExpression = tmpvar;
+ StorageTmp->expExpressionLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+
+}
+
+
+
+int
+write_expExpressionValueType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct expExpressionTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(expExpressionTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+
+ DEBUGMSGTL(("expExpressionTable",
+ "write_expExpressionValueType entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(expExpressionTableStorage, NULL,
+ &name[sizeof(expExpressionTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to expExpressionValueType not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->expExpressionValueType;
+ StorageTmp->expExpressionValueType = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->expExpressionValueType = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+
+}
+
+
+int
+write_expExpressionComment(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct expExpressionTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(expExpressionTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+
+ DEBUGMSGTL(("expExpressionTable",
+ "write_expExpression entering action=%d... \n", action));
+ if ((StorageTmp =
+ header_complex(expExpressionTableStorage, NULL,
+ &name[sizeof(expExpressionTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to expExpressionComment not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->expExpressionComment;
+ tmplen = StorageTmp->expExpressionCommentLen;
+ memdup((u_char **) & StorageTmp->expExpressionComment, var_val,
+ var_val_len);
+ StorageTmp->expExpressionCommentLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->expExpressionComment);
+ StorageTmp->expExpressionComment = tmpvar;
+ StorageTmp->expExpressionCommentLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+
+}
+
+
+int
+write_expExpressionDeltaInterval(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static int tmpvar;
+ struct expExpressionTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(expExpressionTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+
+ DEBUGMSGTL(("expExpressionTable",
+ "write_expExpressionValueType entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(expExpressionTableStorage, NULL,
+ &name[sizeof(expExpressionTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to expExpressionDeltalnterval not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->expExpressionDeltaInterval;
+ StorageTmp->expExpressionDeltaInterval = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->expExpressionDeltaInterval = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+
+}
+
+
+int
+write_expExpressionEntryStatus(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ struct expExpressionTable_data *StorageTmp = NULL;
+ static struct expExpressionTable_data *StorageNew, *StorageDel;
+ size_t newlen =
+ name_len -
+ (sizeof(expExpressionTable_variables_oid) / sizeof(oid) + 3 - 1);
+ static int old_value;
+ int set_value;
+ static netsnmp_variable_list *vars, *vp;
+ struct header_complex_index *hciptr;
+
+ StorageTmp =
+ header_complex(expExpressionTableStorage, NULL,
+ &name[sizeof(expExpressionTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL, NULL);
+
+
+
+
+ if (var_val_type != ASN_INTEGER || var_val == NULL) {
+ snmp_log(LOG_ERR,
+ "write to expExpressionEntryStatus not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ set_value = *((long *) var_val);
+
+
+ /*
+ * check legal range, and notReady is reserved for us, not a user
+ */
+ if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY)
+ return SNMP_ERR_INCONSISTENTVALUE;
+
+
+ switch (action) {
+ case RESERVE1:
+ /*
+ * stage one: test validity
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * create the row now?
+ */
+
+
+ /*
+ * ditch illegal values now
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE)
+ return SNMP_ERR_INCONSISTENTVALUE;
+
+
+ /*
+ * destroying a non-existent row is actually legal
+ */
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+
+
+ /*
+ * illegal creation values
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ } else {
+ /*
+ * row exists. Check for a valid state change
+ */
+ if (set_value == RS_CREATEANDGO
+ || set_value == RS_CREATEANDWAIT) {
+ /*
+ * can't create a row that exists
+ */
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+
+ if (StorageTmp->expExpressionEntryStatus == RS_ACTIVE &&
+ set_value != RS_DESTROY) {
+ /*
+ * "Once made active an entry may not be modified except to
+ * delete it." XXX: doesn't this in fact apply to ALL
+ * columns of the table and not just this one?
+ */
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ break;
+
+
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * creation
+ */
+ vars = NULL;
+
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* expExpressionOwner */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* expExpressionName */
+
+
+
+ if (header_complex_parse_oid
+ (&
+ (name
+ [sizeof(expExpressionTable_variables_oid) / sizeof(oid) +
+ 2]), newlen, vars) != SNMPERR_SUCCESS) {
+ /*
+ * XXX: free, zero vars
+ */
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+ vp = vars;
+
+
+ StorageNew = create_expExpressionTable_data();
+
+ StorageNew->expExpressionOwner = malloc(vp->val_len + 1);
+ memcpy(StorageNew->expExpressionOwner, vp->val.string,
+ vp->val_len);
+ StorageNew->expExpressionOwner[vp->val_len] = '\0';
+ StorageNew->expExpressionOwnerLen = vp->val_len;
+
+ vp = vp->next_variable;
+ StorageNew->expExpressionName = malloc(vp->val_len + 1);
+ memcpy(StorageNew->expExpressionName, vp->val.string,
+ vp->val_len);
+ StorageNew->expExpressionName[vp->val_len] = '\0';
+ StorageNew->expExpressionNameLen = vp->val_len;
+
+ vp = vp->next_variable;
+
+ StorageNew->expExpressionEntryStatus = set_value;
+
+ }
+
+
+ break;
+
+
+
+
+ case FREE:
+ /*
+ * XXX: free, zero vars
+ */
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in set_value for you to
+ * use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in
+ * the UNDO case
+ */
+
+
+ if (StorageTmp == NULL) {
+ /*
+ * row creation, so add it
+ */
+ if (StorageNew != NULL)
+ expExpressionTable_add(StorageNew);
+ /*
+ * XXX: ack, and if it is NULL?
+ */
+ } else if (set_value != RS_DESTROY) {
+ /*
+ * set the flag?
+ */
+ old_value = StorageTmp->expExpressionEntryStatus;
+ StorageTmp->expExpressionEntryStatus = *((long *) var_val);
+ } else {
+ /*
+ * destroy... extract it for now
+ */
+ hciptr =
+ header_complex_find_entry(expExpressionTableStorage,
+ StorageTmp);
+ StorageDel =
+ header_complex_extract_entry(&expExpressionTableStorage,
+ hciptr);
+ }
+ break;
+
+
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * row creation, so remove it again
+ */
+ hciptr =
+ header_complex_find_entry(expExpressionTableStorage,
+ StorageTmp);
+ StorageDel =
+ header_complex_extract_entry(&expExpressionTableStorage,
+ hciptr);
+ /*
+ * XXX: free it
+ */
+ } else if (StorageDel != NULL) {
+ /*
+ * row deletion, so add it again
+ */
+ expExpressionTable_add(StorageDel);
+ } else {
+ StorageTmp->expExpressionEntryStatus = old_value;
+ }
+ break;
+
+
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ if (StorageDel != NULL) {
+ StorageDel = 0;
+ /*
+ * XXX: free it, its dead
+ */
+ } else {
+ if (StorageTmp
+ && StorageTmp->expExpressionEntryStatus ==
+ RS_CREATEANDGO) {
+ StorageTmp->expExpressionEntryStatus = RS_ACTIVE;
+ } else if (StorageTmp &&
+ StorageTmp->expExpressionEntryStatus ==
+ RS_CREATEANDWAIT) {
+ StorageTmp->expExpressionEntryStatus = RS_NOTINSERVICE;
+ }
+ }
+ if (StorageTmp &&
+ StorageTmp->expExpressionEntryStatus == RS_ACTIVE &&
+ !StorageTmp->have_copied_auth_info) {
+
+ netsnmp_agent_session *asp =
+ netsnmp_get_current_agent_session();
+ netsnmp_pdu *pdu = NULL;
+
+ if (!asp) {
+ snmp_log(LOG_ERR,
+ "snmpTriggerTable: can't get master session for authentication params\n");
+ } else {
+ pdu = asp->orig_pdu;
+ if (!pdu) {
+ snmp_log(LOG_ERR,
+ "snmpTriggerTable: can't get master pdu for authentication params\n");
+ }
+ }
+
+ if (pdu) {
+ DEBUGMSGTL(("expExpressionTest",
+ "copying PDU auth info\n"));
+ StorageTmp->pdu_version = pdu->version;
+ StorageTmp->pdu_securityModel = pdu->securityModel;
+ StorageTmp->pdu_securityLevel = pdu->securityLevel;
+ StorageTmp->pdu_tDomain = pdu->tDomain;
+ StorageTmp->pdu_tDomainLen = pdu->tDomainLen;
+ if (pdu->transport_data != NULL) {
+ StorageTmp->pdu_transport =
+ malloc(pdu->transport_data_length);
+ memcpy(StorageTmp->pdu_transport, pdu->transport_data,
+ pdu->transport_data_length);
+ }
+ StorageTmp->pdu_transportLen = pdu->transport_data_length;
+ if (pdu->community) {
+ StorageTmp->pdu_community =
+ calloc(1, pdu->community_len + 1);
+ memcpy(StorageTmp->pdu_community, pdu->community,
+ pdu->community_len);
+ StorageTmp->pdu_community_len = pdu->community_len;
+ } else {
+ StorageTmp->pdu_community = NULL;
+ StorageTmp->pdu_community_len = 0;
+ }
+ if (pdu->securityName) {
+ StorageTmp->pdu_securityName =
+ calloc(1, pdu->securityNameLen + 1);
+ memcpy(StorageTmp->pdu_securityName, pdu->securityName,
+ pdu->securityNameLen);
+ StorageTmp->pdu_securityNameLen = pdu->securityNameLen;
+ } else {
+ StorageTmp->pdu_securityName = NULL;
+ StorageTmp->pdu_securityNameLen = 0;
+ }
+ StorageTmp->have_copied_auth_info = 1;
+ }
+ }
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/expression/expExpressionTable.h b/agent/mibgroup/disman/expression/expExpressionTable.h
new file mode 100644
index 0000000..6c139f8
--- /dev/null
+++ b/agent/mibgroup/disman/expression/expExpressionTable.h
@@ -0,0 +1,139 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name: expExpressionTable.h
+ *File Description: head file.
+ *
+ *Current Version:1.0
+ *Author:JianShun Tong
+ *Date:2004.8.20
+ */
+
+/*
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+
+#ifndef _MIBGROUP_EXPEXPRESSIONTABLE_H
+#define _MIBGROUP_EXPEXPRESSIONTABLE_H
+
+/*
+ * we may use header_complex from the header_complex module
+ */
+
+
+config_require(header_complex)
+
+ /*
+ * our storage structure(s)
+ */
+ struct expExpressionTable_data {
+
+ /*
+ * expExpressionTable
+ */
+ char *expExpressionOwner;
+ size_t expExpressionOwnerLen;
+ char *expExpressionName;
+ size_t expExpressionNameLen;
+ char *expExpression;
+ size_t expExpressionLen;
+ long expExpressionValueType;
+ char *expExpressionComment;
+ size_t expExpressionCommentLen;
+ long expExpressionDeltaInterval;
+ oid *expExpressionPrefix;
+ size_t expExpressionPrefixLen;
+ unsigned long expExpressionErrors;
+ long expExpressionEntryStatus;
+
+ /*
+ * expError Table
+ */
+ unsigned long expErrorTime;
+ long expErrorIndex;
+ long expErrorCode;
+ oid *expErrorInstance;
+ size_t expErrorInstanceLen;
+
+ /*
+ * internal variables
+ */
+ int storageType;
+
+ /*
+ * other tables storage
+ */
+ struct header_complex_index *hc_ObjectTableStorage;
+ struct header_complex_index *hc_ValueTableStorage;
+
+
+
+ /*
+ * pdu auth contents
+ */
+ long have_copied_auth_info;
+ long pdu_version;
+ long pdu_securityModel;
+ long pdu_securityLevel;
+ void *pdu_transport;
+ size_t pdu_transportLen;
+ const oid *pdu_tDomain;
+ size_t pdu_tDomainLen;
+ u_char *pdu_community;
+ size_t pdu_community_len;
+ char *pdu_contextName;
+ size_t pdu_contextNameLen;
+ char *pdu_securityName;
+ size_t pdu_securityNameLen;
+ };
+
+
+
+#define EXPEXPRESSION_COUNTER32 1
+#define EXPEXPRESSION_UNSIGNED32 2
+#define EXPEXPRESSION_TIMETICKS 3
+#define EXPEXPRESSION_INTEGER32 4
+#define EXPEXPRESSION_IPADDRESS 5
+#define EXPEXPRESSION_OCTETSTRING 6
+#define EXPEXPRESSION_OBJECTID 7
+#define EXPEXPRESSION_COUNTER64 8
+
+
+#define EXP_FAILURE_INVALIDSYNTAX 1
+#define EXP_FAILURE_UNDEFINEOBJECTINDEX 2
+#define EXP_FAILURE_UNRECOGNIZEOPERATOR 3
+#define EXP_FAILURE_UNRECOGNIZEDFUNCTION 4
+#define EXP_FAILURE_INVALIDOPERANDTYPE 5
+#define EXP_FAILURE_UNMATCHEDPARENTHESIS 6
+#define EXP_FAILURE_TOOMANYWILDCARDVALUES 7
+#define EXP_FAILURE_RECURSION 8
+#define EXP_FAILURE_DELTATOOSHORT 9
+#define EXP_FAILURE_RESOURCEUNAVAILABLE 10
+#define EXP_FAILURE_DIVIDEBYZERO 11
+
+
+/*
+ * function prototypes
+ */
+
+
+ void init_expExpressionTable(void);
+ FindVarMethod var_expExpressionTable;
+ SNMPCallback store_expExpressionTable;
+ void parse_expExpressionTable(const char *, char *);
+
+ WriteMethod write_expExpression;
+ WriteMethod write_expExpressionValueType;
+ WriteMethod write_expExpressionComment;
+ WriteMethod write_expExpressionDeltaInterval;
+ WriteMethod write_expExpressionEntryStatus;
+
+
+
+
+
+#endif /*_MIBGROUP_EXPEXPRESSIONTABLE_H */
diff --git a/agent/mibgroup/disman/expression/expObjectTable.c b/agent/mibgroup/disman/expression/expObjectTable.c
new file mode 100644
index 0000000..e56f25a
--- /dev/null
+++ b/agent/mibgroup/disman/expression/expObjectTable.c
@@ -0,0 +1,1465 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name: expObjectTable.c
+ *File Description: expObjectTable MIB operation.
+ *
+ *Current Version:1.0
+ *Author:JianShun Tong
+ *Date:2004.8.20
+ */
+
+
+/*
+ * This file was generated by mib2c and is intended for use as
+ * a mib module for the ucd-snmp snmpd agent.
+ */
+
+
+/*
+ * This should always be included first before anything else
+ */
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(header_complex_find_entry)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+/*
+ * minimal include directives
+ */
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "header_complex.h"
+#include "expExpressionTable.h"
+#include "expObjectTable.h"
+
+
+/*
+ * expObjectTable_variables_oid:
+ * this is the top level oid that we want to register under. This
+ * is essentially a prefix, with the suffix appearing in the
+ * variable below.
+ */
+oid TimeInstance[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 };
+
+oid expObjectTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 90, 1, 2, 3 };
+
+/*
+ * variable2 expObjectTable_variables:
+ */
+
+struct variable2 expObjectTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define EXPOBJECTID 2
+ {EXPOBJECTID, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
+ var_expObjectTable, 2, {1, 2}},
+#define EXPOBJECTIDWILDCARD 3
+ {EXPOBJECTIDWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_expObjectTable, 2, {1, 3}},
+#define EXPOBJECTSAMPLETYPE 4
+ {EXPOBJECTSAMPLETYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_expObjectTable, 2, {1, 4}},
+#define EXPOBJECTDELTADISCONTINUITYID 5
+ {EXPOBJECTDELTADISCONTINUITYID, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
+ var_expObjectTable, 2, {1, 5}},
+#define EXPOBJECTDISCONTINUITYIDWILDCARD 6
+ {EXPOBJECTDISCONTINUITYIDWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_expObjectTable, 2, {1, 6}},
+#define EXPOBJECTDISCONTINUITYIDTYPE 7
+ {EXPOBJECTDISCONTINUITYIDTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_expObjectTable, 2, {1, 7}},
+#define EXPOBJECTCONDITIONAL 8
+ {EXPOBJECTCONDITIONAL, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
+ var_expObjectTable, 2, {1, 8}},
+#define EXPOBJECTCONDITIONALWILDCARD 9
+ {EXPOBJECTCONDITIONALWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_expObjectTable, 2, {1, 9}},
+#define EXPOBJECTENTRYSTATUS 10
+ {EXPOBJECTENTRYSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_expObjectTable, 2, {1, 10}}
+};
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+extern struct header_complex_index *expExpressionTableStorage;
+extern struct header_complex_index *expValueTableStorage;
+
+struct header_complex_index *expObjectTableStorage = NULL;
+
+/*
+ * init_expObjectTable():
+ * Initialization routine. This is called when the agent starts up.
+ * At a minimum, registration of your variables should take place here.
+ */
+void
+init_expObjectTable(void)
+{
+ DEBUGMSGTL(("expObjectTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("expObjectTable",
+ expObjectTable_variables, variable2,
+ expObjectTable_variables_oid);
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("expObjectTable", parse_expObjectTable,
+ NULL, NULL);
+
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_expObjectTable, NULL);
+
+ DEBUGMSGTL(("expObjectTable", "done.\n"));
+}
+
+
+struct expObjectTable_data *
+create_expObjectTable_data(void)
+{
+ struct expObjectTable_data *StorageNew;
+
+ StorageNew = SNMP_MALLOC_STRUCT(expObjectTable_data);
+
+ /*
+ * fill in default row values here into StorageNew
+ */
+ /*
+ * fill in values for all tables (even if not
+ * appropriate), since its easier to do here than anywhere
+ * else
+ */
+
+ StorageNew->expObjectIDWildcard = EXPOBJCETIDWILDCARD_FALSE;
+ StorageNew->expObjectSampleType = EXPOBJCETSAMPLETYPE_ABSOLUTEVALUE;
+ memdup((unsigned char **)
+ &(StorageNew->expObjectDeltaDiscontinuityID),
+ (unsigned char *) TimeInstance, sizeof(TimeInstance));
+ StorageNew->expObjectDeltaDiscontinuityIDLen =
+ sizeof(TimeInstance) / sizeof(oid);
+
+
+
+
+ StorageNew->expObjectDiscontinuityIDWildcard =
+ EXPOBJCETDISCONTINUITYIDWILDCARD_FALSE;
+ StorageNew->expObjectDiscontinuityIDType =
+ EXPOBJECTDISCONTINUITYIDTYPE_TIMETICKS;
+
+ StorageNew->expObjectConditional = calloc(1, sizeof(oid) * 2); /* 0.0 */
+ StorageNew->expObjectConditionalLen = 2;
+
+ StorageNew->expObjectID = calloc(1, sizeof(oid) * 2); /* 0.0 */
+ StorageNew->expObjectIDLen = 2;
+
+ StorageNew->expObjectConditionalWildcard =
+ EXPOBJECTCONDITIONALWILDCARD_FALSE;
+ StorageNew->storageType = ST_NONVOLATILE;
+
+ return StorageNew;
+}
+
+int
+expObjectTable_add(struct expObjectTable_data *thedata)
+{
+ netsnmp_variable_list *vars = NULL;
+
+
+ DEBUGMSGTL(("expObjectTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->expExpressionOwner, thedata->expExpressionOwnerLen); /* expExpressionOwner */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->expExpressionName, thedata->expExpressionNameLen); /* expExpressionName */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_UNSIGNED, (char *) &thedata->expObjectIndex, sizeof(thedata->expObjectIndex)); /* expExpressionName */
+
+
+
+
+ header_complex_add_data(&expObjectTableStorage, vars, thedata);
+ DEBUGMSGTL(("expObjectTable", "registered an entry\n"));
+
+
+ DEBUGMSGTL(("expObjectTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+
+/*
+ * parse_mteTriggerTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+void
+parse_expObjectTable(const char *token, char *line)
+{
+ size_t tmpint;
+ struct expObjectTable_data *StorageTmp =
+ SNMP_MALLOC_STRUCT(expObjectTable_data);
+
+ DEBUGMSGTL(("expObjectTable", "parsing config... "));
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->expExpressionOwner,
+ &StorageTmp->expExpressionOwnerLen);
+ if (StorageTmp->expExpressionOwner == NULL) {
+ config_perror("invalid specification for expExpressionOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->expExpressionName,
+ &StorageTmp->expExpressionNameLen);
+ if (StorageTmp->expExpressionName == NULL) {
+ config_perror("invalid specification for expExpressionName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->expObjectIndex, &tmpint);
+
+ line =
+ read_config_read_data(ASN_OBJECT_ID, line,
+ &StorageTmp->expObjectID,
+ &StorageTmp->expObjectIDLen);
+ if (StorageTmp->expObjectID == NULL) {
+ config_perror("invalid specification for expObjectID");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->expObjectIDWildcard, &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->expObjectSampleType, &tmpint);
+
+ line =
+ read_config_read_data(ASN_OBJECT_ID, line,
+ &StorageTmp->expObjectDeltaDiscontinuityID,
+ &StorageTmp->
+ expObjectDeltaDiscontinuityIDLen);
+ if (StorageTmp->expObjectDeltaDiscontinuityID == NULL) {
+ config_perror
+ ("invalid specification for expObjectDeltaDiscontinuityID");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->
+ expObjectDiscontinuityIDWildcard, &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->expObjectDiscontinuityIDType,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OBJECT_ID, line,
+ &StorageTmp->expObjectConditional,
+ &StorageTmp->expObjectConditionalLen);
+ if (StorageTmp->expObjectConditional == NULL) {
+ config_perror("invalid specification for expObjectConditional");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->expObjectConditionalWildcard,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->expObjectEntryStatus, &tmpint);
+
+ StorageTmp->storageType = ST_NONVOLATILE;
+ expObjectTable_add(StorageTmp);
+
+ DEBUGMSGTL(("expObjectTable", "done.\n"));
+
+}
+
+
+
+/*
+ * store_expExpressionTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+int
+store_expObjectTable(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr;
+ size_t tmpint;
+ struct expObjectTable_data *StorageTmp;
+ struct header_complex_index *hcindex;
+
+ DEBUGMSGTL(("expObjectTable", "storing data... "));
+
+ for (hcindex = expObjectTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct expObjectTable_data *) hcindex->data;
+
+
+
+ if (StorageTmp->storageType == ST_NONVOLATILE) {
+
+ memset(line, 0, sizeof(line));
+ strcat(line, "expObjectTable ");
+ cptr = line + strlen(line);
+ /*
+ * expObjectTable
+ */
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->expExpressionOwner,
+ &StorageTmp->expExpressionOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->expExpressionName,
+ &StorageTmp->expExpressionNameLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->expObjectIndex,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OBJECT_ID, cptr,
+ &StorageTmp->expObjectID,
+ &StorageTmp->expObjectIDLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->expObjectIDWildcard,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->expObjectSampleType,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OBJECT_ID, cptr,
+ &StorageTmp->
+ expObjectDeltaDiscontinuityID,
+ &StorageTmp->
+ expObjectDeltaDiscontinuityIDLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ expObjectDiscontinuityIDWildcard,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ expObjectDiscontinuityIDType,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OBJECT_ID, cptr,
+ &StorageTmp->expObjectConditional,
+ &StorageTmp->
+ expObjectConditionalLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ expObjectConditionalWildcard,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->expObjectEntryStatus,
+ &tmpint);
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("expObjectTable", "storage done\n"));
+ return 0;
+}
+
+
+/*
+ * var_expObjectTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_expObjectTable above.
+ */
+unsigned char *
+var_expObjectTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact, size_t *var_len, WriteMethod ** write_method)
+{
+ struct expObjectTable_data *StorageTmp = NULL;
+
+
+ DEBUGMSGTL(("expObjectTable", "var_expObjectTable: Entering... \n"));
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(expObjectTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL) {
+ if (vp->magic == EXPOBJECTENTRYSTATUS)
+ *write_method = write_expObjectEntryStatus;
+ return NULL;
+ }
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+
+ case EXPOBJECTID:
+ *write_method = write_expObjectID;
+ *var_len = StorageTmp->expObjectIDLen * sizeof(oid);
+ return (u_char *) StorageTmp->expObjectID;
+
+ case EXPOBJECTIDWILDCARD:
+ *write_method = write_expObjectIDWildcard;
+ *var_len = sizeof(StorageTmp->expObjectIDWildcard);
+ return (u_char *) & StorageTmp->expObjectIDWildcard;
+
+ case EXPOBJECTSAMPLETYPE:
+ *write_method = write_expObjectSampleType;
+ *var_len = sizeof(StorageTmp->expObjectSampleType);
+ return (u_char *) & StorageTmp->expObjectSampleType;
+
+ case EXPOBJECTDELTADISCONTINUITYID:
+ *write_method = write_expObjectDeltaDiscontinuityID;
+ *var_len =
+ StorageTmp->expObjectDeltaDiscontinuityIDLen * sizeof(oid);
+ return (u_char *) StorageTmp->expObjectDeltaDiscontinuityID;
+
+ case EXPOBJECTDISCONTINUITYIDWILDCARD:
+ *write_method = write_expObjectDiscontinuityIDWildcard;
+ *var_len = sizeof(StorageTmp->expObjectDiscontinuityIDWildcard);
+ return (u_char *) & StorageTmp->expObjectDiscontinuityIDWildcard;
+
+ case EXPOBJECTDISCONTINUITYIDTYPE:
+ *write_method = write_expObjectDiscontinuityIDWildcard;
+ *var_len = sizeof(StorageTmp->expObjectDiscontinuityIDType);
+ return (u_char *) & StorageTmp->expObjectDiscontinuityIDType;
+
+ case EXPOBJECTCONDITIONAL:
+ *write_method = write_expObjectConditional;
+ *var_len = StorageTmp->expObjectConditionalLen * sizeof(oid);
+ return (u_char *) StorageTmp->expObjectConditional;
+
+ case EXPOBJECTCONDITIONALWILDCARD:
+ *write_method = write_expObjectConditionalWildcard;
+ *var_len = sizeof(StorageTmp->expObjectConditionalWildcard);
+ return (u_char *) & StorageTmp->expObjectConditionalWildcard;
+
+ case EXPOBJECTENTRYSTATUS:
+ *write_method = write_expObjectEntryStatus;
+ *var_len = sizeof(StorageTmp->expObjectEntryStatus);
+ return (u_char *) & StorageTmp->expObjectEntryStatus;
+
+
+ default:
+ ERROR_MSG("");
+ }
+ return NULL;
+}
+
+int
+write_expObjectID(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static oid *tmpvar;
+ struct expObjectTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len - (sizeof(expObjectTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("expObjectTable",
+ "write_expObjectID entering action=%d... \n", action));
+ if ((StorageTmp =
+ header_complex(expObjectTableStorage, NULL,
+ &name[sizeof(expObjectTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OBJECT_ID) {
+ snmp_log(LOG_ERR, "write to expObjectID not ASN_OBJECT_ID\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->expObjectID;
+ tmplen = StorageTmp->expObjectIDLen;
+ memdup((u_char **) & StorageTmp->expObjectID, var_val,
+ var_val_len);
+ StorageTmp->expObjectIDLen = var_val_len / sizeof(oid);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->expObjectID);
+ StorageTmp->expObjectID = tmpvar;
+ StorageTmp->expObjectIDLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ /*
+ * XXX: if the valueID has actually changed, shouldn't we dump any
+ * previous values, as these are from a different object?
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+int
+write_expObjectIDWildcard(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct expObjectTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(expObjectTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("expObjectTable",
+ "write_expObjectIDWildcard entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(expObjectTableStorage, NULL,
+ &name[sizeof(expObjectTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to expObjectIDWildcard not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->expObjectIDWildcard;
+ StorageTmp->expObjectIDWildcard = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->expObjectIDWildcard = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+int
+write_expObjectSampleType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct expObjectTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(expObjectTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("expObjectTable",
+ "write_expObjectSampleType entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(expObjectTableStorage, NULL,
+ &name[sizeof(expObjectTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to expObjectSampleTypenot ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->expObjectSampleType;
+ StorageTmp->expObjectSampleType = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->expObjectSampleType = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_expObjectDeltaDiscontinuityID(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static oid *tmpvar;
+ struct expObjectTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len - (sizeof(expObjectTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("expObjectTable",
+ "write_expObjectDeltaDiscontinuityID entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(expObjectTableStorage, NULL,
+ &name[sizeof(expObjectTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OBJECT_ID) {
+ snmp_log(LOG_ERR,
+ "write to expObjectDeltaDiscontinuityID not ASN_OBJECT_ID\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->expObjectDeltaDiscontinuityID;
+ tmplen = StorageTmp->expObjectDeltaDiscontinuityIDLen;
+ memdup((u_char **) & StorageTmp->expObjectDeltaDiscontinuityID,
+ var_val, var_val_len);
+ StorageTmp->expObjectDeltaDiscontinuityIDLen =
+ var_val_len / sizeof(oid);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->expObjectDeltaDiscontinuityID);
+ StorageTmp->expObjectDeltaDiscontinuityID = tmpvar;
+ StorageTmp->expObjectDeltaDiscontinuityIDLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ /*
+ * XXX: if the valueID has actually changed, shouldn't we dump any
+ * previous values, as these are from a different object?
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_expObjectDiscontinuityIDWildcard(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct expObjectTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(expObjectTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("expObjectTable",
+ "write_expObjectDiscontinuityIDWildcard entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(expObjectTableStorage, NULL,
+ &name[sizeof(expObjectTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to expObjectDiscontinuityIDWildcard not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->expObjectDiscontinuityIDWildcard;
+ StorageTmp->expObjectDiscontinuityIDWildcard = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->expObjectDiscontinuityIDWildcard = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_expObjectDiscontinuityIDType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct expObjectTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(expObjectTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("expObjectTable",
+ "write_expObjectDiscontinuityIDWildcard entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(expObjectTableStorage, NULL,
+ &name[sizeof(expObjectTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to expObjectDiscontinuityIDType not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->expObjectDiscontinuityIDType;
+ StorageTmp->expObjectDiscontinuityIDType = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->expObjectDiscontinuityIDType = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_expObjectConditional(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static oid *tmpvar;
+ struct expObjectTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len - (sizeof(expObjectTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("expObjectTable",
+ "write_expObjectConditional entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(expObjectTableStorage, NULL,
+ &name[sizeof(expObjectTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OBJECT_ID) {
+ snmp_log(LOG_ERR,
+ "write to expObjectConditional not ASN_OBJECT_ID\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->expObjectConditional;
+ tmplen = StorageTmp->expObjectConditionalLen;
+ memdup((u_char **) & StorageTmp->expObjectConditional, var_val,
+ var_val_len);
+ StorageTmp->expObjectConditionalLen = var_val_len / sizeof(oid);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->expObjectConditional);
+ StorageTmp->expObjectConditional = tmpvar;
+ StorageTmp->expObjectConditionalLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ /*
+ * XXX: if the valueID has actually changed, shouldn't we dump any
+ * previous values, as these are from a different object?
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_expObjectConditionalWildcard(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct expObjectTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(expObjectTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("expObjectTable",
+ "write_expObjectConditionalWildcard entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(expObjectTableStorage, NULL,
+ &name[sizeof(expObjectTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to expObjectConditionalWildcard not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->expObjectConditionalWildcard;
+ StorageTmp->expObjectConditionalWildcard = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->expObjectConditionalWildcard = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_expObjectEntryStatus(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ struct expObjectTable_data *StorageTmp = NULL;
+ static struct expObjectTable_data *StorageNew, *StorageDel;
+ size_t newlen =
+ name_len - (sizeof(expObjectTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+ static int old_value;
+ int set_value;
+ static netsnmp_variable_list *vars, *vp;
+ struct header_complex_index *hciptr;
+
+ StorageTmp =
+ header_complex(expObjectTableStorage, NULL,
+ &name[sizeof(expObjectTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL, NULL);
+
+
+
+
+ if (var_val_type != ASN_INTEGER || var_val == NULL) {
+ snmp_log(LOG_ERR,
+ "write to expObjectEntryStatus not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ set_value = *((long *) var_val);
+
+
+ /*
+ * check legal range, and notReady is reserved for us, not a user
+ */
+ if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY)
+ return SNMP_ERR_INCONSISTENTVALUE;
+
+
+ switch (action) {
+ case RESERVE1:
+ /*
+ * stage one: test validity
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * create the row now?
+ */
+
+
+ /*
+ * ditch illegal values now
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE)
+ return SNMP_ERR_INCONSISTENTVALUE;
+
+
+ /*
+ * destroying a non-existent row is actually legal
+ */
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+
+
+ /*
+ * illegal creation values
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ } else {
+ /*
+ * row exists. Check for a valid state change
+ */
+ if (set_value == RS_CREATEANDGO
+ || set_value == RS_CREATEANDWAIT) {
+ /*
+ * can't create a row that exists
+ */
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+
+ if (StorageTmp->expObjectEntryStatus == RS_ACTIVE &&
+ set_value != RS_DESTROY) {
+ /*
+ * "Once made active an entry may not be modified except to
+ * delete it." XXX: doesn't this in fact apply to ALL
+ * columns of the table and not just this one?
+ */
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ break;
+
+
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * creation
+ */
+ vars = NULL;
+
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* expExpressionOwner */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* expExpressionName */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_UNSIGNED, NULL, 0); /* expObjectIndex */
+
+
+
+ if (header_complex_parse_oid
+ (&
+ (name
+ [sizeof(expObjectTable_variables_oid) / sizeof(oid) +
+ 2]), newlen, vars) != SNMPERR_SUCCESS) {
+ /*
+ * XXX: free, zero vars
+ */
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+ vp = vars;
+
+
+ StorageNew = create_expObjectTable_data();
+
+ StorageNew->expExpressionOwner = malloc(vp->val_len + 1);
+ memcpy(StorageNew->expExpressionOwner, vp->val.string,
+ vp->val_len);
+ StorageNew->expExpressionOwner[vp->val_len] = '\0';
+ StorageNew->expExpressionOwnerLen = vp->val_len;
+
+ vp = vp->next_variable;
+ StorageNew->expExpressionName = malloc(vp->val_len + 1);
+ memcpy(StorageNew->expExpressionName, vp->val.string,
+ vp->val_len);
+
+ StorageNew->expExpressionName[vp->val_len] = '\0';
+ StorageNew->expExpressionNameLen = vp->val_len;
+
+ vp = vp->next_variable;
+ StorageNew->expObjectIndex = *vp->val.integer;
+
+ StorageNew->expObjectEntryStatus = set_value;
+
+ }
+
+
+ break;
+
+
+
+
+ case FREE:
+ /*
+ * XXX: free, zero vars
+ */
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in set_value for you to
+ * use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in
+ * the UNDO case
+ */
+
+
+ if (StorageTmp == NULL) {
+ /*
+ * row creation, so add it
+ */
+ if (StorageNew != NULL)
+ expObjectTable_add(StorageNew);
+ /*
+ * XXX: ack, and if it is NULL?
+ */
+ } else if (set_value != RS_DESTROY) {
+ /*
+ * set the flag?
+ */
+ old_value = StorageTmp->expObjectEntryStatus;
+ StorageTmp->expObjectEntryStatus = *((long *) var_val);
+ } else {
+ /*
+ * destroy... extract it for now
+ */
+ hciptr =
+ header_complex_find_entry(expObjectTableStorage,
+ StorageTmp);
+ StorageDel =
+ header_complex_extract_entry(&expObjectTableStorage,
+ hciptr);
+ }
+ break;
+
+
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * row creation, so remove it again
+ */
+ hciptr =
+ header_complex_find_entry(expObjectTableStorage,
+ StorageTmp);
+ StorageDel =
+ header_complex_extract_entry(&expObjectTableStorage,
+ hciptr);
+ /*
+ * XXX: free it
+ */
+ } else if (StorageDel != NULL) {
+ /*
+ * row deletion, so add it again
+ */
+ expObjectTable_add(StorageDel);
+ } else {
+ StorageTmp->expObjectEntryStatus = old_value;
+ }
+ break;
+
+
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ if (StorageDel != NULL) {
+ StorageDel = 0;
+ /*
+ * XXX: free it, its dead
+ */
+ } else {
+ if (StorageTmp
+ && StorageTmp->expObjectEntryStatus == RS_CREATEANDGO) {
+ StorageTmp->expObjectEntryStatus = RS_ACTIVE;
+ } else if (StorageTmp &&
+ StorageTmp->expObjectEntryStatus ==
+ RS_CREATEANDWAIT) {
+ StorageTmp->expObjectEntryStatus = RS_NOTINSERVICE;
+ }
+ }
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/expression/expObjectTable.h b/agent/mibgroup/disman/expression/expObjectTable.h
new file mode 100644
index 0000000..86fea31
--- /dev/null
+++ b/agent/mibgroup/disman/expression/expObjectTable.h
@@ -0,0 +1,92 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name: expObjectTable.h
+ *File Description: head file.
+ *
+ *Current Version:1.0
+ *Author:JianShun Tong
+ *Date:2004.8.20
+ */
+
+/*
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+
+#ifndef _MIBGROUP_EXPOBJECTABLE_H
+#define _MIBGROUP_EXPOBJECTABLE_H
+
+
+/*
+ * we may use header_complex from the header_complex module
+ */
+config_require(header_complex)
+
+ struct expObjectTable_data {
+ char *expExpressionOwner;
+ size_t expExpressionOwnerLen;
+ char *expExpressionName;
+ size_t expExpressionNameLen;
+ unsigned long expObjectIndex;
+ oid *expObjectID;
+ size_t expObjectIDLen;
+ long expObjectIDWildcard;
+ long expObjectSampleType;
+ oid *expObjectDeltaDiscontinuityID;
+ size_t expObjectDeltaDiscontinuityIDLen;
+ long expObjectDiscontinuityIDWildcard;
+ long expObjectDiscontinuityIDType;
+ oid *expObjectConditional;
+ size_t expObjectConditionalLen;
+ long expObjectConditionalWildcard;
+ long expObjectEntryStatus;
+
+
+ /*
+ * internal variables
+ */
+ int storageType;
+
+
+ };
+ /*
+ * enum definitions from the covered mib sections
+ */
+#define EXPOBJCETIDWILDCARD_TRUE 1
+#define EXPOBJCETIDWILDCARD_FALSE 2
+#define EXPOBJCETDISCONTINUITYIDWILDCARD_TRUE 1
+#define EXPOBJCETDISCONTINUITYIDWILDCARD_FALSE 2
+#define EXPOBJECTCONDITIONALWILDCARD_TRUE 1
+#define EXPOBJECTCONDITIONALWILDCARD_FALSE 2
+#define EXPOBJECTDISCONTINUITYIDTYPE_TIMETICKS 1
+#define EXPOBJECTDISCONTINUITYIDTYPE_TIMESTAMP 2
+#define EXPOBJECTDISCONTINUITYIDTYPE_DATEANDTIME 3
+#define EXPOBJCETSAMPLETYPE_ABSOLUTEVALUE 1
+#define EXPOBJCETSAMPLETYPE_DELTAVALUE 2
+#define EXPOBJCETSAMPLETYPE_CHANGEVALUE 3
+ /*
+ * function prototypes
+ */
+ void init_expObjectTable(void);
+ FindVarMethod var_expObjectTable;
+ SNMPCallback store_expObjectTable;
+ void parse_expObjectTable(const char *, char *);
+
+ WriteMethod write_expObjectID;
+ WriteMethod write_expObjectIDWildcard;
+ WriteMethod write_expObjectSampleType;
+ WriteMethod write_expObjectDeltaDiscontinuityID;
+ WriteMethod write_expObjectDiscontinuityIDWildcard;
+ WriteMethod write_expObjectDiscontinuityIDType;
+ WriteMethod write_expObjectConditional;
+ WriteMethod write_expObjectConditionalWildcard;
+ WriteMethod write_expObjectEntryStatus;
+
+
+
+
+#endif /* _MIBGROUP_EXPOBJECTABLE_H */
diff --git a/agent/mibgroup/disman/expression/expValueTable.c b/agent/mibgroup/disman/expression/expValueTable.c
new file mode 100644
index 0000000..6b315c6
--- /dev/null
+++ b/agent/mibgroup/disman/expression/expValueTable.c
@@ -0,0 +1,873 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name: expValueTable.c
+ *File Description: expValueTable MIB operation.
+ *
+ *Current Version:1.0
+ *Author:JianShun Tong
+ *Date:2004.8.20
+ */
+
+
+/*
+ * This file was generated by mib2c and is intended for use as
+ * a mib module for the ucd-snmp snmpd agent.
+ */
+
+
+/*
+ * This should always be included first before anything else
+ */
+#include <net-snmp/net-snmp-config.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdio.h>
+
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+
+/*
+ * minimal include directives
+ */
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "header_complex.h"
+#include "expExpressionTable.h"
+#include "expValueTable.h"
+#include "expObjectTable.h"
+
+
+/*
+ * expValueTable_variables_oid:
+ * this is the top level oid that we want to register under. This
+ * is essentially a prefix, with the suffix appearing in the
+ * variable below.
+ */
+
+oid expValueTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 90, 1, 3, 1 };
+
+struct s_node {
+ unsigned data;
+ struct s_node *next;
+};
+typedef struct s_node nodelink;
+nodelink *operater = NULL;
+nodelink *operand = NULL;
+
+/*
+ * variable2 expObjectTable_variables:
+ */
+
+struct variable2 expValueTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define EXPVALUECOUNTER32VAL 2
+ {EXPVALUECOUNTER32VAL, ASN_COUNTER, NETSNMP_OLDAPI_RONLY,
+ var_expValueTable, 2, {1, 2}},
+#define EXPVALUEUNSIGNED32VAL 3
+ {EXPVALUEUNSIGNED32VAL, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_expValueTable, 2, {1, 3}},
+#define EXPVALUETIMETICKSVAL 4
+ {EXPVALUETIMETICKSVAL, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_expValueTable, 2, {1, 4}},
+#define EXPVALUEINTEGER32VAL 5
+ {EXPVALUEINTEGER32VAL, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_expValueTable, 2, {1, 5}},
+#define EXPVALUEIPADDRESSVAL 6
+ {EXPVALUEIPADDRESSVAL, ASN_IPADDRESS, NETSNMP_OLDAPI_RONLY,
+ var_expValueTable, 2, {1, 6}},
+#define EXPVALUEOCTETSTRINGVAL 7
+ {EXPVALUEOCTETSTRINGVAL, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_expValueTable, 2, {1, 7}},
+#define EXPVALUEOIDVAL 8
+ {EXPVALUEOIDVAL, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY,
+ var_expValueTable, 2, {1, 8}},
+#define EXPVALUECOUNTER64VAL 9
+ {EXPVALUECOUNTER64VAL, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_expValueTable, 2, {1, 9}}
+};
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+extern struct header_complex_index *expExpressionTableStorage;
+extern struct header_complex_index *expObjectTableStorage;
+struct header_complex_index *expValueTableStorage = NULL;
+struct snmp_session session;
+
+/*
+ * init_expValueTable():
+ * Initialization routine. This is called when the agent starts up.
+ * At a minimum, registration of your variables should take place here.
+ */
+void
+init_expValueTable(void)
+{
+ DEBUGMSGTL(("expValueTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("expValueTable",
+ expValueTable_variables, variable2,
+ expValueTable_variables_oid);
+ init_snmp("snmpapp");
+
+ /*
+ * Initialize a "session" that defines who we're going to talk to
+ */
+ snmp_sess_init(&session); /* set up defaults */
+ session.peername = strdup("localhost");
+
+ DEBUGMSGTL(("expValueTable", "done.\n"));
+}
+
+struct expValueTable_data *
+create_expValueTable_data(void)
+{
+ struct expValueTable_data *StorageNew;
+
+ StorageNew = SNMP_MALLOC_STRUCT(expValueTable_data);
+
+ /*
+ * fill in default row values here into StorageNew
+ */
+ /*
+ * fill in values for all tables (even if not
+ * appropriate), since its easier to do here than anywhere
+ * else
+ */
+ StorageNew->expExpressionOwner = strdup("");
+ StorageNew->expExpressionName = strdup("");
+ StorageNew->expValueInstance = calloc(1, sizeof(oid) * sizeof(2)); /* 0.0.0 */
+ StorageNew->expValueInstanceLen = 3;
+ return StorageNew;
+}
+
+/*
+ * mteTriggerTable_add(): adds a structure node to our data set
+ */
+int
+expValueTable_add(struct expExpressionTable_data *expression_data,
+ char *owner, size_t owner_len, char *name,
+ size_t name_len, oid * index, size_t index_len)
+{
+ netsnmp_variable_list *vars = NULL;
+ struct expValueTable_data *thedata, *StorageTmp;
+ struct header_complex_index *hcindex;
+ int founded = 0;
+ thedata = create_expValueTable_data();
+ thedata->expValueCounter32Val = 0;
+ thedata->expExpressionOwner = owner;
+ thedata->expExpressionOwnerLen = owner_len;
+ thedata->expExpressionName = name;
+ thedata->expExpressionNameLen = name_len;
+ thedata->expValueInstance = index;
+ thedata->expValueInstanceLen = index_len;
+ thedata->expression_data = expression_data;
+ DEBUGMSGTL(("expValueTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->expExpressionOwner, thedata->expExpressionOwnerLen); /* expExpressionOwner */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->expExpressionName, thedata->expExpressionNameLen); /* expExpressionName */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_PRIV_IMPLIED_OBJECT_ID,
+ (u_char *) thedata->expValueInstance,
+ thedata->expValueInstanceLen * sizeof(oid));
+
+ for (hcindex = expValueTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct expValueTable_data *) hcindex->data;
+ if (!strcmp
+ (StorageTmp->expExpressionOwner, thedata->expExpressionOwner)
+ && (StorageTmp->expExpressionOwnerLen ==
+ thedata->expExpressionOwnerLen)
+ && !strcmp(StorageTmp->expExpressionName,
+ thedata->expExpressionName)
+ && (StorageTmp->expExpressionNameLen ==
+ thedata->expExpressionNameLen)
+ && !snmp_oid_compare(StorageTmp->expValueInstance,
+ StorageTmp->expValueInstanceLen,
+ thedata->expValueInstance,
+ thedata->expValueInstanceLen)) {
+ founded = 1;
+ break;
+ }
+
+ }
+ if (!founded) {
+ header_complex_add_data(&expValueTableStorage, vars, thedata);
+ DEBUGMSGTL(("expValueTable", "registered an entry\n"));
+ } else {
+ SNMP_FREE(thedata);
+ DEBUGMSGTL(("expValueTable",
+ "already have an entry, dont registe\n"));
+ }
+
+
+ DEBUGMSGTL(("expValueTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+
+
+
+unsigned long
+Evaluate_Expression(struct expValueTable_data *vtable_data)
+{
+
+ struct header_complex_index *hcindex;
+ struct expObjectTable_data *objstorage, *objfound;
+ struct expValueTable_data *valstorage;
+ valstorage = vtable_data;
+
+ char *expression;
+ char *result, *resultbak;
+ char *temp, *tempbak;
+ char intchar[10];
+ int i = 0, j, k, l;
+ long value;
+ unsigned long result_u_long;
+ temp = malloc(100);
+ result = malloc(100);
+ tempbak = temp;
+ memset(result, 0, 100);
+ *result = '\0';
+ resultbak = result;
+
+ expression = vtable_data->expression_data->expExpression;
+
+ while (*expression != '\0') {
+ if (*expression == '$') {
+ objfound = NULL;
+ i++;
+ for (j = 1; j < 100; j++) {
+ if ((*(expression + j) == '+') ||
+ (*(expression + j) == '-') ||
+ (*(expression + j) == '*') ||
+ (*(expression + j) == '/') ||
+ (*(expression + j) == '(') ||
+ (*(expression + j) == ')') ||
+ *(expression + j) == '\0') {
+ break;
+ }
+ }
+ sprintf(temp, "%.*s", j - 1, expression + 1);
+ l = atoi(temp);
+ expression = expression + j;
+ /*
+ * here use snmpget to get value
+ */
+ for (hcindex = expObjectTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ objstorage = (struct expObjectTable_data *) hcindex->data;
+ if (!strcmp
+ (objstorage->expExpressionOwner,
+ valstorage->expExpressionOwner)
+ && (objstorage->expExpressionOwnerLen ==
+ valstorage->expExpressionOwnerLen)
+ && !strcmp(objstorage->expExpressionName,
+ valstorage->expExpressionName)
+ && (objstorage->expExpressionNameLen ==
+ valstorage->expExpressionNameLen)
+ && (l == objstorage->expObjectIndex)) {
+ objfound = objstorage;
+ break;
+ }
+ }
+
+
+ if (!objfound) {
+ /* have err */
+ return 0;
+ }
+ struct snmp_session *ss;
+ struct snmp_pdu *pdu;
+ struct snmp_pdu *response;
+
+ oid anOID[MAX_OID_LEN];
+ size_t anOID_len;
+
+ memcpy(anOID, objfound->expObjectID,
+ objfound->expObjectIDLen * sizeof(oid));
+ anOID_len = objfound->expObjectIDLen;
+ if (objfound->expObjectIDWildcard == EXPOBJCETIDWILDCARD_TRUE) {
+ anOID_len =
+ anOID_len + valstorage->expValueInstanceLen - 2;
+ memcpy(anOID + objfound->expObjectIDLen,
+ valstorage->expValueInstance + 2,
+ (valstorage->expValueInstanceLen -
+ 2) * sizeof(oid));
+ }
+ struct variable_list *vars;
+ int status;
+
+ /*
+ * Initialize the SNMP library
+ */
+
+ /*
+ * Initialize a "session" that defines who we're going to talk to
+ */
+ session.version = vtable_data->expression_data->pdu_version;
+
+ /*
+ * set the SNMPv1 community name used for authentication
+ */
+ session.community =
+ vtable_data->expression_data->pdu_community;
+ session.community_len =
+ vtable_data->expression_data->pdu_community_len;
+ /*
+ * Open the session
+ */
+ SOCK_STARTUP;
+ ss = snmp_open(&session); /* establish the session */
+
+ if (!ss) {
+ /* err */
+ exit(2);
+ }
+ pdu = snmp_pdu_create(SNMP_MSG_GET);
+ snmp_add_null_var(pdu, anOID, anOID_len);
+
+ /*
+ * Send the Request out.
+ */
+ status = snmp_synch_response(ss, pdu, &response);
+
+ /*
+ * Process the response.
+ */
+ if (status == STAT_SUCCESS
+ && response->errstat == SNMP_ERR_NOERROR) {
+ /*
+ * SUCCESS: Print the result variables
+ */
+
+ vars = response->variables;
+ value = *(vars->val.integer);
+ sprintf(intchar, "%lu", value);
+ for (k = 1; k <= strlen(intchar); k++) {
+ *result = intchar[k - 1];
+ result++;
+ }
+
+ } else {
+ /*
+ * FAILURE: print what went wrong!
+ */
+
+ if (status == STAT_SUCCESS)
+ fprintf(stderr, "Error in packet\nReason: %s\n",
+ snmp_errstring(response->errstat));
+ else
+ snmp_sess_perror("snmpget", ss);
+
+ }
+
+ /*
+ * Clean up:
+ * 1) free the response.
+ * 2) close the session.
+ */
+ if (response)
+ snmp_free_pdu(response);
+ snmp_close(ss);
+
+ SOCK_CLEANUP;
+
+ } else {
+ *result = *expression;
+ result++;
+ expression++;
+ }
+ }
+ result_u_long = get_result(resultbak);
+ free(tempbak);
+ free(resultbak);
+ return result_u_long;
+}
+
+
+
+
+
+
+
+
+void
+expValueTable_clean(void *data)
+{
+ struct expValueTable_data *cleanme =
+ (struct expValueTable_data *) data;
+ SNMP_FREE(cleanme->expValueInstance);
+ SNMP_FREE(cleanme->expValueIpAddressVal);
+ SNMP_FREE(cleanme->expValueOctetStringVal);
+ SNMP_FREE(cleanme->expValueOidVal);
+ SNMP_FREE(cleanme);
+}
+
+
+
+void
+build_valuetable(void)
+{
+ struct expExpressionTable_data *expstorage;
+ struct expObjectTable_data *objstorage, *objfound = NULL;
+ struct header_complex_index *hcindex, *object_hcindex;
+ char *expression;
+ oid *index;
+ int i = 0, j, l;
+
+ DEBUGMSGTL(("expValueTable", "building valuetable... \n"));
+
+ for (hcindex = expExpressionTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ expstorage = (struct expExpressionTable_data *) hcindex->data;
+ if (expstorage->expExpressionEntryStatus == RS_ACTIVE) {
+ expression = expstorage->expExpression;
+ while (*expression != '\0') {
+ if (*expression == '$') {
+ i++;
+ for (j = 1; j < 100; j++) {
+ if ((*(expression + j) == '+') ||
+ (*(expression + j) == '-') ||
+ (*(expression + j) == '*') ||
+ (*(expression + j) == '/') ||
+ (*(expression + j) == '(') ||
+ (*(expression + j) == ')') ||
+ *(expression + j) == '\0') {
+ break;
+ }
+ }
+ {
+ char temp[100];
+
+ sprintf(temp, "%.*s", j - 1, expression + 1);
+ l = atoi(temp);
+ }
+ for (object_hcindex = expObjectTableStorage;
+ object_hcindex != NULL;
+ object_hcindex = object_hcindex->next) {
+ objstorage =
+ (struct expObjectTable_data *) object_hcindex->
+ data;
+ if (!strcmp
+ (objstorage->expExpressionOwner,
+ expstorage->expExpressionOwner)
+ && (objstorage->expExpressionOwnerLen ==
+ expstorage->expExpressionOwnerLen)
+ && !strcmp(objstorage->expExpressionName,
+ expstorage->expExpressionName)
+ && (objstorage->expExpressionNameLen ==
+ expstorage->expExpressionNameLen)
+ && (l == objstorage->expObjectIndex)) {
+ if (objfound == NULL) {
+ objfound = objstorage;
+ }
+ if (objstorage->expObjectIDWildcard ==
+ EXPOBJCETIDWILDCARD_TRUE)
+ objfound = objstorage;
+ }
+ }
+ expression = expression + j;
+ } else {
+ expression++;
+ }
+ };
+ }
+
+ if (!objfound) {
+ continue;
+ }
+ if (objfound->expObjectIDWildcard == EXPOBJCETIDWILDCARD_FALSE) {
+ index = calloc(1, MAX_OID_LEN);
+ *index = 0;
+ *(index + 1) = 0;
+ *(index + 2) = 0;
+ expValueTable_add(expstorage, objfound->expExpressionOwner,
+ objfound->expExpressionOwnerLen,
+ objfound->expExpressionName,
+ objfound->expExpressionNameLen, index, 3);
+ } else {
+ oid *targetOID;
+ size_t taggetOID_len;
+ targetOID = objfound->expObjectID;
+ struct snmp_pdu *pdu;
+ struct snmp_pdu *response;
+ oid *next_OID;
+ size_t next_OID_len;
+ taggetOID_len = objfound->expObjectIDLen;
+ int status;
+ struct snmp_session *ss;
+ /*
+ * Initialize the SNMP library
+ */
+
+
+ /*
+ * set the SNMP version number
+ */
+ session.version = expstorage->pdu_version;
+
+ /*
+ * set the SNMPv1 community name used for authentication
+ */
+ session.community = expstorage->pdu_community;
+ session.community_len = expstorage->pdu_community_len;
+
+ /*
+ * Open the session
+ */
+ SOCK_STARTUP;
+ ss = snmp_open(&session); /* establish the session */
+ if (!ss) {
+ snmp_perror("ack");
+ snmp_log(LOG_ERR, "something horrible happened!!!\n");
+ exit(2);
+ }
+
+ next_OID = targetOID;
+ next_OID_len = taggetOID_len;
+ do {
+ index = calloc(1, MAX_OID_LEN);
+ pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
+
+ snmp_add_null_var(pdu, next_OID, next_OID_len);
+
+ /*
+ * Send the Request out.
+ */
+ status = snmp_synch_response(ss, pdu, &response);
+
+ /*
+ * Process the response.
+ */
+ if (status == STAT_SUCCESS
+ && response->errstat == SNMP_ERR_NOERROR) {
+ /*
+ * SUCCESS: Print the result variables
+ */
+
+ if (((response->variables->type >= SNMP_NOSUCHOBJECT &&
+ response->variables->type <= SNMP_ENDOFMIBVIEW)
+ || snmp_oid_compare(targetOID, taggetOID_len,
+ response->variables->name,
+ taggetOID_len) != 0)) {
+ break;
+ }
+ /* add to expValueTable */
+
+ *index = 0;
+ *(index + 1) = 0;
+ memcpy(index + 2,
+ response->variables->name + taggetOID_len,
+ (response->variables->name_length -
+ taggetOID_len) * sizeof(oid));
+ expValueTable_add(expstorage,
+ objfound->expExpressionOwner,
+ objfound->expExpressionOwnerLen,
+ objfound->expExpressionName,
+ objfound->expExpressionNameLen,
+ index,
+ response->variables->name_length -
+ taggetOID_len + 2);
+
+ next_OID = response->variables->name;
+
+ next_OID_len = response->variables->name_length;
+
+
+
+
+ } else {
+ /*
+ * FAILURE: print what went wrong!
+ */
+ if (status == STAT_SUCCESS)
+ fprintf(stderr, "Error in packet\nReason: %s\n",
+ snmp_errstring(response->errstat));
+ else
+ snmp_sess_perror("snmpget", ss);
+ }
+ } while (TRUE);
+
+ }
+
+ }
+
+}
+
+
+
+/*
+ * var_expValueTable():
+ */
+unsigned char *
+var_expValueTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact, size_t *var_len, WriteMethod ** write_method)
+{
+
+ struct expValueTable_data *StorageTmp = NULL;
+
+
+
+
+ DEBUGMSGTL(("expValueTable", "var_expValueTable: Entering... \n"));
+
+ /*
+ * before we build valuetable we must free any other valutable if exist
+ */
+ header_complex_free_all(expValueTableStorage, expValueTable_clean);
+ expValueTableStorage = NULL;
+
+
+ build_valuetable();
+
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(expValueTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL)
+ return NULL;
+
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+ /*
+ * we only support counter32val
+ */
+
+ case EXPVALUECOUNTER32VAL:
+ StorageTmp->expValueCounter32Val = Evaluate_Expression(StorageTmp);
+ *var_len = sizeof(StorageTmp->expValueCounter32Val);
+ return (u_char *) & StorageTmp->expValueCounter32Val;
+
+ case EXPVALUEUNSIGNED32VAL:
+ /* var_len = sizeof(StorageTmp->expValueUnsigned32Val); */
+ /* return (u_char *) & StorageTmp->expValueUnsigned32Val; */
+ return NULL;
+
+ case EXPVALUETIMETICKSVAL:
+ /* var_len = sizeof(StorageTmp->expValueTimeTicksVal); */
+ /* return (u_char *) & StorageTmp->expValueTimeTicksVal; */
+ return NULL;
+
+ case EXPVALUEINTEGER32VAL:
+ /* var_len = sizeof(StorageTmp->expValueInteger32Val); */
+ /* return (u_char *) & StorageTmp->expValueInteger32Val; */
+ return NULL;
+
+ case EXPVALUEIPADDRESSVAL:
+ /* var_len = sizeof(StorageTmp->expValueIpAddressVal); */
+ /* return (u_char *) & StorageTmp->expValueIpAddressVal; */
+ return NULL;
+
+ case EXPVALUEOCTETSTRINGVAL:
+ /* var_len = sizeof(StorageTmp->expValueOctetStringVal); */
+ /* return (u_char *) & StorageTmp->expValueOctetStringVal; */
+ return NULL;
+
+ case EXPVALUEOIDVAL:
+ /* var_len = StorageTmp->expValueOidValLen; */
+ /* return (u_char *) & StorageTmp->expValueOidVal; */
+ return NULL;
+
+ case EXPVALUECOUNTER64VAL:
+ /* var_len = sizeof(StorageTmp->expValueCounter64Val); */
+ /* return (u_char *) & StorageTmp->expValueCounter64Val; */
+ return NULL;
+ default:
+ ERROR_MSG("");
+ return NULL;
+ }
+}
+
+
+
+
+
+void
+push(nodelink ** stack, unsigned long value)
+{
+ nodelink *newnode;
+ newnode = (nodelink *) malloc(sizeof(nodelink));
+ if (!newnode) {
+ printf("\nMemory allocation failure!");
+ return;
+ }
+ newnode->data = value;
+ newnode->next = *stack;
+ *stack = newnode;
+}
+
+unsigned long
+pop(nodelink ** stack)
+{
+ unsigned long value;
+ nodelink *top;
+ top = *stack;
+ *stack = (*stack)->next;
+ value = top->data;
+ free(top);
+ return value;
+}
+
+int
+priority(char operater)
+{
+ switch (operater) {
+ case '*':
+ case '/':
+ return 4;
+ case '+':
+ case '-':
+ return 3;
+ case ')':
+ return 2;
+ case '(':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+unsigned long
+calculate(int operater, unsigned long a, unsigned long b)
+{
+ switch (operater) {
+ case '+':
+ return (a + b);
+ case '-':
+ return (a - b);
+ case '*':
+ return (a * b);
+ case '/':
+ if (operater == '/' && b == 0) {
+ printf("\nDivision mustn\'t be 0!");
+ exit(0);
+ } else
+ return (a / b);
+ }
+ return 0;
+}
+
+unsigned long
+get_operand(char *p, int *length)
+{
+ char c[13];
+ int i = 0, k = 1;
+ unsigned long result = 0;
+ while (*p <= 57 && *p >= 48)
+ c[i++] = *(p++);
+ *length += --i;
+ for (; i >= 0; i--) {
+ result += (c[i] - 48) * k;
+ k *= 10;
+ }
+ return result;
+}
+
+int
+operator_class(char c)
+{
+ if (c <= 57 && c >= 48)
+ return 1;
+ if (c == 42 || c == 43 || c == 45 || c == 47)
+ return 2;
+ if (c == 41)
+ return 3;
+ if (c == 40)
+ return 4;
+ return 0;
+}
+
+unsigned long
+get_result(char *expr)
+{
+ int position = 0;
+ unsigned long op = 0, a = 0, b = 0, result = 0;
+ char *expression;
+ expression = expr;
+ while (*(expression + position) != '\0'
+ && *(expression + position) != '\n') {
+ switch (operator_class(*(expression + position))) {
+ case 1:
+ push(&operand, get_operand(expression + position, &position));
+ break;
+ case 2:
+ if (operater != NULL)
+ while (operater != NULL
+ && priority(*(expression + position)) <=
+ priority(operater->data)) {
+ a = pop(&operand);
+ b = pop(&operand);
+ op = pop(&operater);
+ push(&operand, calculate(op, b, a));
+ }
+ push(&operater, *(expression + position));
+ break;
+ case 3:
+ while (operater != NULL && operater->data != '(') {
+ a = pop(&operand);
+ b = pop(&operand);
+ op = pop(&operater);
+ push(&operand, calculate(op, b, a));
+ }
+ if (operater->data == '(')
+ pop(&operater);
+ break;
+ case 4:
+ push(&operater, '(');
+ break;
+ default:
+ printf("\nInvalid character in expression:");
+ a = 0;
+ while (*(expression + (int) a) != '\n'
+ && *(expression + (int) a) != '\0') {
+ if (a != position)
+ printf("%c", *(expression + (int) a));
+ else
+ printf("<%c>", *(expression + (int) a));
+ a++;
+ }
+ exit(0);
+ } /* end switch */
+ position++;
+ }
+ while (operater != NULL) {
+ op = pop(&operater);
+ a = pop(&operand);
+ b = pop(&operand);
+ push(&operand, calculate(op, b, a));
+ }
+ result = pop(&operand);
+ return result;
+}
diff --git a/agent/mibgroup/disman/expression/expValueTable.h b/agent/mibgroup/disman/expression/expValueTable.h
new file mode 100644
index 0000000..8569f9d
--- /dev/null
+++ b/agent/mibgroup/disman/expression/expValueTable.h
@@ -0,0 +1,63 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:expValueTable.h
+ *File Description: head file.
+ *
+ *Current Version:1.0
+ *Author:JianShun Tong
+ *Date:2004.8.20
+ */
+
+/*
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+
+/*
+ * we may use header_complex from the header_complex module
+ */
+config_require(header_complex)
+
+#ifndef _MIBGROUP_EXPVALUETABLE_H
+#define _MIBGROUP_EXPVALUETABLE_H
+ struct expValueTable_data {
+ char *expExpressionOwner;
+ size_t expExpressionOwnerLen;
+ char *expExpressionName;
+ size_t expExpressionNameLen;
+ oid *expValueInstance;
+ size_t expValueInstanceLen;
+ unsigned long expValueCounter32Val;
+ unsigned long expValueUnsigned32Val;
+ unsigned long expValueTimeTicksVal;
+ long expValueInteger32Val;
+ u_long *expValueIpAddressVal;
+ char *expValueOctetStringVal;
+ size_t expValueOctetStringValLen;
+ oid *expValueOidVal;
+ size_t expValueOidValLen;
+ long expValueCounter64Val;
+
+ /* internal var */
+ struct expExpressionTable_data *expression_data;
+ char *valuestr;
+ };
+
+
+ /*
+ * function prototypes
+ */
+ void init_expValueTable(void);
+ unsigned long get_result(char *expr);
+ FindVarMethod var_expValueTable;
+ int expValueTable_add(struct expExpressionTable_data
+ *expression_data, char *owner,
+ size_t owner_len, char *name,
+ size_t name_len, oid * index,
+ size_t index_len);
+
+#endif /* _MIBGROUP_EXPVALUETABLE_H */
diff --git a/agent/mibgroup/disman/mteEventNotificationTable.c b/agent/mibgroup/disman/mteEventNotificationTable.c
new file mode 100644
index 0000000..48add68
--- /dev/null
+++ b/agent/mibgroup/disman/mteEventNotificationTable.c
@@ -0,0 +1,110 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.create-dataset.conf,v 5.2 2002/07/17 14:41:53 dts12 Exp $
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "mteEventNotificationTable.h"
+
+netsnmp_feature_require(table_dataset)
+netsnmp_feature_require(table_set_multi_add_default_row)
+
+netsnmp_table_data_set *mteEventNotif_table_set;
+
+
+/** Initialize the mteEventNotificationTable table by defining its contents and how it's structured */
+void
+initialize_table_mteEventNotificationTable(void)
+{
+ static oid mteEventNotificationTable_oid[] =
+ { 1, 3, 6, 1, 2, 1, 88, 1, 4, 3 };
+ size_t mteEventNotificationTable_oid_len =
+ OID_LENGTH(mteEventNotificationTable_oid);
+
+ /*
+ * create the table structure itself
+ */
+ mteEventNotif_table_set = netsnmp_create_table_data_set("mteEventNotificationTable");
+
+ /*
+ * comment this out or delete if you don't support creation of new rows
+ */
+ mteEventNotif_table_set->allow_creation = 1;
+
+ /***************************************************
+ * Adding indexes
+ */
+ DEBUGMSGTL(("initialize_table_mteEventNotificationTable",
+ "adding indexes to table mteEventNotificationTable\n"));
+ netsnmp_table_set_add_indexes(mteEventNotif_table_set,
+ /* index: mteOwner */
+ ASN_OCTET_STR,
+ /* index: mteEventName */
+ ASN_PRIV_IMPLIED_OCTET_STR,
+ 0);
+
+ DEBUGMSGTL(("initialize_table_mteEventNotificationTable",
+ "adding column types to table mteEventNotificationTable\n"));
+ netsnmp_table_set_multi_add_default_row(mteEventNotif_table_set,
+ COLUMN_MTEEVENTNOTIFICATION,
+ ASN_OBJECT_ID, 1, NULL, 0,
+ COLUMN_MTEEVENTNOTIFICATIONOBJECTSOWNER,
+ ASN_OCTET_STR, 1, NULL, 0,
+ COLUMN_MTEEVENTNOTIFICATIONOBJECTS,
+ ASN_OCTET_STR, 1, NULL, 0, 0);
+
+ /* keep index values around for comparisons later */
+ mteEventNotif_table_set->table->store_indexes = 1;
+ /*
+ * registering the table with the master agent
+ */
+ /*
+ * note: if you don't need a subhandler to deal with any aspects
+ * of the request, change mteEventNotificationTable_handler to "NULL"
+ */
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ netsnmp_register_table_data_set(netsnmp_create_handler_registration
+ ("mteEventNotificationTable",
+ mteEventNotificationTable_handler,
+ mteEventNotificationTable_oid,
+ mteEventNotificationTable_oid_len,
+ HANDLER_CAN_RWRITE), mteEventNotif_table_set, NULL);
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+ netsnmp_register_table_data_set(netsnmp_create_handler_registration
+ ("mteEventNotificationTable",
+ mteEventNotificationTable_handler,
+ mteEventNotificationTable_oid,
+ mteEventNotificationTable_oid_len,
+ HANDLER_CAN_RONLY), mteEventNotif_table_set, NULL);
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+}
+
+/** Initializes the mteEventNotificationTable module */
+void
+init_mteEventNotificationTable(void)
+{
+
+ /*
+ * here we initialize all the tables we're planning on supporting
+ */
+ initialize_table_mteEventNotificationTable();
+}
+
+/** handles requests for the mteEventNotificationTable table, if anything else needs to be done */
+int
+mteEventNotificationTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+ /*
+ * perform anything here that you need to do. The requests have
+ * already been processed by the master table_dataset handler, but
+ * this gives you chance to act on the request in some other way
+ * if need be.
+ */
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/mteEventNotificationTable.h b/agent/mibgroup/disman/mteEventNotificationTable.h
new file mode 100644
index 0000000..dd9bdfa
--- /dev/null
+++ b/agent/mibgroup/disman/mteEventNotificationTable.h
@@ -0,0 +1,23 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.create-dataset.conf,v 5.2 2002/07/17 14:41:53 dts12 Exp $
+ */
+#ifndef MTEEVENTNOTIFICATIONTABLE_H
+#define MTEEVENTNOTIFICATIONTABLE_H
+
+/*
+ * function declarations
+ */
+void init_mteEventNotificationTable(void);
+void initialize_table_mteEventNotificationTable(void);
+Netsnmp_Node_Handler mteEventNotificationTable_handler;
+
+/*
+ * column number definitions for table mteEventNotificationTable
+ */
+#define COLUMN_MTEEVENTNOTIFICATION 1
+#define COLUMN_MTEEVENTNOTIFICATIONOBJECTSOWNER 2
+#define COLUMN_MTEEVENTNOTIFICATIONOBJECTS 3
+
+extern netsnmp_table_data_set *mteEventNotif_table_set;
+#endif /* MTEEVENTNOTIFICATIONTABLE_H */
diff --git a/agent/mibgroup/disman/mteEventTable.c b/agent/mibgroup/disman/mteEventTable.c
new file mode 100644
index 0000000..22bad73
--- /dev/null
+++ b/agent/mibgroup/disman/mteEventTable.c
@@ -0,0 +1,345 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.create-dataset.conf,v 5.2 2002/07/17 14:41:53 dts12 Exp $
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "mteTriggerTable.h"
+#include "mteEventTable.h"
+#include "mteEventNotificationTable.h"
+#include "mteObjectsTable.h"
+
+netsnmp_feature_require(table_dataset)
+netsnmp_feature_require(table_set_multi_add_default_row)
+
+static netsnmp_table_data_set *table_set = NULL;
+
+/** Initialize the mteEventTable table by defining its contents and how it's structured */
+void
+initialize_table_mteEventTable(void)
+{
+ static oid mteEventTable_oid[] =
+ { 1, 3, 6, 1, 2, 1, 88, 1, 4, 2 };
+ size_t mteEventTable_oid_len = OID_LENGTH(mteEventTable_oid);
+
+ /*
+ * create the table structure itself
+ */
+ table_set = netsnmp_create_table_data_set("mteEventTable");
+
+ /*
+ * comment this out or delete if you don't support creation of new rows
+ */
+ table_set->allow_creation = 1;
+ /* mark the row status column */
+ table_set->rowstatus_column = COLUMN_MTEEVENTENTRYSTATUS;
+
+ /***************************************************
+ * Adding indexes
+ */
+ DEBUGMSGTL(("initialize_table_mteEventTable",
+ "adding indexes to table mteEventTable\n"));
+ netsnmp_table_set_add_indexes(table_set,
+ ASN_OCTET_STR, /* index: mteOwner */
+ ASN_PRIV_IMPLIED_OCTET_STR, /* index: mteEventName */
+ 0);
+
+ DEBUGMSGTL(("initialize_table_mteEventTable",
+ "adding column types to table mteEventTable\n"));
+ netsnmp_table_set_multi_add_default_row(table_set,
+ COLUMN_MTEEVENTNAME,
+ ASN_OCTET_STR, 0, NULL, 0,
+ COLUMN_MTEEVENTCOMMENT,
+ ASN_OCTET_STR, 1, NULL, 0,
+ COLUMN_MTEEVENTACTIONS,
+ ASN_OCTET_STR, 1, NULL, 0,
+ COLUMN_MTEEVENTENABLED,
+ ASN_INTEGER, 1, NULL, 0,
+ COLUMN_MTEEVENTENTRYSTATUS,
+ ASN_INTEGER, 1, NULL, 0, 0);
+
+ /* keep index values around for comparisons later */
+ table_set->table->store_indexes = 1;
+ /*
+ * registering the table with the master agent
+ */
+ /*
+ * note: if you don't need a subhandler to deal with any aspects
+ * of the request, change mteEventTable_handler to "NULL"
+ */
+ netsnmp_register_table_data_set(netsnmp_create_handler_registration
+ ("mteEventTable",
+ mteEventTable_handler,
+ mteEventTable_oid,
+ mteEventTable_oid_len,
+ HANDLER_CAN_RWRITE), table_set, NULL);
+}
+
+/** Initializes the mteEventTable module */
+void
+init_mteEventTable(void)
+{
+
+ /*
+ * here we initialize all the tables we're planning on supporting
+ */
+ initialize_table_mteEventTable();
+
+ snmpd_register_config_handler("notificationEvent", parse_notificationEvent,
+ NULL,
+ "notificationEvent NAME TRAP_OID [[-w] EXTRA_OID ...]");
+
+ snmpd_register_config_handler("linkUpDownNotifications",
+ parse_linkUpDownNotifications,
+ NULL,
+ "linkUpDownNotifications (yes|no)");
+}
+
+/** handles requests for the mteEventTable table, if anything else needs to be done */
+int
+mteEventTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+ /*
+ * perform anything here that you need to do. The requests have
+ * already been processed by the master table_dataset handler, but
+ * this gives you chance to act on the request in some other way
+ * if need be.
+ */
+
+ /* XXX: on rowstatus = destroy, remove the corresponding rows from the
+ other tables: snmpEventNotificationTable and the set table */
+ return SNMP_ERR_NOERROR;
+}
+
+void
+parse_linkUpDownNotifications(const char *token, char *line) {
+ if (strncmp(line, "y", 1) == 0) {
+ parse_notificationEvent("notificationEvent", "linkUpTrap linkUp ifIndex ifAdminStatus ifOperStatus");
+ parse_notificationEvent("notificationEvent", "linkDownTrap linkDown ifIndex ifAdminStatus ifOperStatus");
+
+ parse_simple_monitor("monitor", "-r 60 -e linkUpTrap \"Generate linkUp\" ifOperStatus != 2");
+ parse_simple_monitor("monitor", "-r 60 -e linkDownTrap \"Generate linkDown\" ifOperStatus == 2");
+ }
+}
+
+void
+parse_notificationEvent(const char *token, char *line) {
+ char name_buf[64];
+ char oid_name_buf[SPRINT_MAX_LEN];
+ oid oid_buf[MAX_OID_LEN];
+ size_t oid_buf_len = MAX_OID_LEN;
+ int wild = 1;
+ netsnmp_table_row *row;
+ long tlong;
+ char tc;
+
+ /* get the owner */
+ const char *owner = "snmpd.conf";
+
+ /* get the name */
+ char *cp = copy_nword(line, name_buf, SPRINT_MAX_LEN);
+
+ if (!cp || name_buf[0] == '\0') {
+ config_perror("syntax error.");
+ return;
+ }
+
+ for(row = table_set->table->first_row; row; row = row->next) {
+ if (strcmp(row->indexes->val.string, owner) == 0 &&
+ strcmp(row->indexes->next_variable->val.string,
+ name_buf) == 0) {
+ config_perror("An eventd by that name has already been defined.");
+ return;
+ }
+ }
+
+ /* now, get all the trap oid */
+ cp = copy_nword(cp, oid_name_buf, SPRINT_MAX_LEN);
+
+ if (oid_name_buf[0] == '\0') {
+ config_perror("syntax error.");
+ return;
+ }
+ if (!snmp_parse_oid(oid_name_buf, oid_buf, &oid_buf_len)) {
+ snmp_log(LOG_ERR,"namebuf: %s\n",oid_name_buf);
+ config_perror("unable to parse trap oid");
+ return;
+ }
+
+ /*
+ * add to the mteEventNotificationtable to point to the
+ * notification and the objects.
+ */
+ row = netsnmp_create_table_data_row();
+
+ /* indexes */
+ netsnmp_table_row_add_index(row, ASN_OCTET_STR, owner, strlen(owner));
+ netsnmp_table_row_add_index(row, ASN_PRIV_IMPLIED_OCTET_STR,
+ name_buf, strlen(name_buf));
+
+
+ /* columns */
+ netsnmp_set_row_column(row, COLUMN_MTEEVENTNOTIFICATION, ASN_OBJECT_ID,
+ (char *) oid_buf, oid_buf_len * sizeof(oid));
+ netsnmp_set_row_column(row, COLUMN_MTEEVENTNOTIFICATIONOBJECTSOWNER,
+ ASN_OCTET_STR, owner, strlen(owner));
+ netsnmp_set_row_column(row, COLUMN_MTEEVENTNOTIFICATIONOBJECTS,
+ ASN_OCTET_STR, name_buf, strlen(name_buf));
+
+ netsnmp_table_data_add_row(mteEventNotif_table_set->table, row);
+
+ /*
+ * add to the mteEventTable to make it a notification to trigger
+ * notification and the objects.
+ */
+ row = netsnmp_create_table_data_row();
+
+ /* indexes */
+ netsnmp_table_row_add_index(row, ASN_OCTET_STR, owner, strlen(owner));
+ netsnmp_table_row_add_index(row, ASN_PRIV_IMPLIED_OCTET_STR,
+ name_buf, strlen(name_buf));
+
+
+ /* columns */
+ tc = (u_char)0x80;
+ netsnmp_set_row_column(row, COLUMN_MTEEVENTACTIONS, ASN_OCTET_STR,
+ &tc, 1);
+ tlong = MTETRIGGERENABLED_TRUE;
+ netsnmp_set_row_column(row, COLUMN_MTEEVENTENABLED,
+ ASN_INTEGER, (char *) &tlong, sizeof(tlong));
+ tlong = RS_ACTIVE;
+ netsnmp_set_row_column(row, COLUMN_MTEEVENTENTRYSTATUS,
+ ASN_INTEGER, (char *) &tlong, sizeof(tlong));
+
+ netsnmp_table_data_add_row(table_set->table, row);
+
+ /*
+ * now all the objects to put into the trap's object row
+ */
+ while(cp) {
+ cp = copy_nword(cp, oid_name_buf, SPRINT_MAX_LEN);
+ if (strcmp(oid_name_buf, "-w") == 0) {
+ wild = 0;
+ continue;
+ }
+ oid_buf_len = MAX_OID_LEN;
+ if (!snmp_parse_oid(oid_name_buf, oid_buf, &oid_buf_len)) {
+ config_perror("unable to parse an object oid");
+ return;
+ }
+ mte_add_object_to_table("snmpd.conf", name_buf,
+ oid_buf, oid_buf_len, wild);
+ wild = 1;
+ }
+}
+
+/*
+ * send trap
+ */
+void
+run_mte_events(struct mteTriggerTable_data *item,
+ oid * name_oid, size_t name_oid_len,
+ const char *eventobjowner, const char *eventobjname)
+{
+ static oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; /* snmpTrapIOD.0 */
+
+ netsnmp_variable_list *var_list = NULL;
+
+ netsnmp_table_row *row, *notif_row;
+ netsnmp_table_data_set_storage *col1, *tc, *no, *noo;
+
+ for(row = table_set->table->first_row; row; row = row->next) {
+ if (strcmp(row->indexes->val.string, eventobjowner) == 0 &&
+ strcmp(row->indexes->next_variable->val.string,
+ eventobjname) == 0) {
+ /* run this event */
+ col1 = (netsnmp_table_data_set_storage *) row->data;
+
+ tc = netsnmp_table_data_set_find_column(col1,
+ COLUMN_MTEEVENTACTIONS);
+ if (!tc->data.bitstring[0] & 0x80) {
+ /* not a notification. next! (XXX: do sets) */
+ continue;
+ }
+
+ tc = netsnmp_table_data_set_find_column(col1,
+ COLUMN_MTEEVENTENABLED);
+ if (*(tc->data.integer) != 1) {
+ /* not enabled. next! */
+ continue;
+ }
+
+ if (!mteEventNotif_table_set) {
+ /* no notification info */
+ continue;
+ }
+
+ /* send the notification */
+ var_list = NULL;
+
+ /* XXX: get notif information */
+ for(notif_row = mteEventNotif_table_set->table->first_row;
+ notif_row; notif_row = notif_row->next) {
+ if (strcmp(notif_row->indexes->val.string,
+ eventobjowner) == 0 &&
+ strcmp(notif_row->indexes->next_variable->val.string,
+ eventobjname) == 0) {
+
+ /* run this event */
+ col1 = (netsnmp_table_data_set_storage *) notif_row->data;
+
+ tc = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTNOTIFICATION);
+ no = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTNOTIFICATIONOBJECTS);
+ noo = netsnmp_table_data_set_find_column(col1, COLUMN_MTEEVENTNOTIFICATIONOBJECTSOWNER);
+ if (!tc)
+ continue; /* no notification to be had. XXX: return? */
+
+ /*
+ * snmpTrap oid
+ */
+ snmp_varlist_add_variable(&var_list, objid_snmptrap,
+ sizeof(objid_snmptrap) /
+ sizeof(oid),
+ ASN_OBJECT_ID,
+ (u_char *) tc->data.objid,
+ tc->data_len);
+
+ /* XXX: add objects from the mteObjectsTable */
+ DEBUGMSGTL(("mteEventTable:send_events", "no: %x, no->data: %s", no, no->data.string));
+ DEBUGMSGTL(("mteEventTable:send_events", "noo: %x, noo->data: %s", noo, noo->data.string));
+ DEBUGMSGTL(("mteEventTable:send_events", "name_oid: %x",name_oid));
+ if (no && no->data.string &&
+ noo && noo->data.string && name_oid) {
+ char *tmpowner =
+ netsnmp_strdup_and_null(noo->data.string,
+ noo->data_len);
+ char *tmpname =
+ netsnmp_strdup_and_null(no->data.string,
+ no->data_len);
+
+ DEBUGMSGTL(("mteEventTable:send_events", "Adding objects for owner=%s name=%s", tmpowner, tmpname));
+ mte_add_objects(var_list, item,
+ tmpowner, tmpname,
+ name_oid + item->mteTriggerValueIDLen,
+ name_oid_len - item->mteTriggerValueIDLen);
+ free(tmpowner);
+ free(tmpname);
+ }
+
+ DEBUGMSGTL(("mteEventTable:send_events", "sending an event "));
+ DEBUGMSGOID(("mteEventTable:send_events", tc->data.objid, tc->data_len / sizeof(oid)));
+ DEBUGMSG(("mteEventTable:send_events", "\n"));
+
+ send_v2trap(var_list);
+ snmp_free_varbind(var_list);
+ }
+ }
+ }
+ }
+}
diff --git a/agent/mibgroup/disman/mteEventTable.h b/agent/mibgroup/disman/mteEventTable.h
new file mode 100644
index 0000000..c67b880
--- /dev/null
+++ b/agent/mibgroup/disman/mteEventTable.h
@@ -0,0 +1,30 @@
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.create-dataset.conf,v 5.2 2002/07/17 14:41:53 dts12 Exp $
+ */
+#ifndef MTEEVENTTABLE_H
+#define MTEEVENTTABLE_H
+
+/*
+ * function declarations
+ */
+void init_mteEventTable(void);
+void initialize_table_mteEventTable(void);
+void run_mte_events(struct mteTriggerTable_data *item,
+ oid * name_oid, size_t name_oid_len,
+ const char *eventobjowner, const char *eventobjname);
+
+
+void parse_notificationEvent(const char *token, char *line);
+void parse_linkUpDownNotifications(const char *token, char *line);
+Netsnmp_Node_Handler mteEventTable_handler;
+
+/*
+ * column number definitions for table mteEventTable
+ */
+#define COLUMN_MTEEVENTNAME 1
+#define COLUMN_MTEEVENTCOMMENT 2
+#define COLUMN_MTEEVENTACTIONS 3
+#define COLUMN_MTEEVENTENABLED 4
+#define COLUMN_MTEEVENTENTRYSTATUS 5
+#endif /* MTEEVENTTABLE_H */
diff --git a/agent/mibgroup/disman/mteObjectsTable.c b/agent/mibgroup/disman/mteObjectsTable.c
new file mode 100644
index 0000000..c3f331d
--- /dev/null
+++ b/agent/mibgroup/disman/mteObjectsTable.c
@@ -0,0 +1,995 @@
+/*
+ * This file was generated by mib2c and is intended for use as
+ * a mib module for the ucd-snmp snmpd agent.
+ */
+
+
+/*
+ * This should always be included first before anything else
+ */
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(header_complex_find_entry)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+/*
+ * minimal include directives
+ */
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "header_complex.h"
+#include "mteTriggerTable.h"
+#include "mteObjectsTable.h"
+
+
+/*
+ * mteObjectsTable_variables_oid:
+ * this is the top level oid that we want to register under. This
+ * is essentially a prefix, with the suffix appearing in the
+ * variable below.
+ */
+
+
+oid mteObjectsTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 88, 1, 3, 1 };
+
+
+/*
+ * variable2 mteObjectsTable_variables:
+ * this variable defines function callbacks and type return information
+ * for the mteObjectsTable mib section
+ */
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+struct variable2 mteObjectsTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define MTEOBJECTSID 5
+ {MTEOBJECTSID, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
+ var_mteObjectsTable, 2, {1, 3}},
+#define MTEOBJECTSIDWILDCARD 6
+ {MTEOBJECTSIDWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteObjectsTable, 2, {1, 4}},
+#define MTEOBJECTSENTRYSTATUS 7
+ {MTEOBJECTSENTRYSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteObjectsTable, 2, {1, 5}},
+
+};
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+struct variable2 mteObjectsTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define MTEOBJECTSID 5
+ {MTEOBJECTSID, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY,
+ var_mteObjectsTable, 2, {1, 3}},
+#define MTEOBJECTSIDWILDCARD 6
+ {MTEOBJECTSIDWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteObjectsTable, 2, {1, 4}},
+#define MTEOBJECTSENTRYSTATUS 7
+ {MTEOBJECTSENTRYSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteObjectsTable, 2, {1, 5}},
+
+};
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+/*
+ * (L = length of the oidsuffix)
+ */
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+static struct header_complex_index *mteObjectsTableStorage = NULL;
+
+
+
+
+/*
+ * init_mteObjectsTable():
+ * Initialization routine. This is called when the agent starts up.
+ * At a minimum, registration of your variables should take place here.
+ */
+void
+init_mteObjectsTable(void)
+{
+ DEBUGMSGTL(("mteObjectsTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("mteObjectsTable", mteObjectsTable_variables, variable2,
+ mteObjectsTable_variables_oid);
+
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("mteObjectsTable", parse_mteObjectsTable,
+ NULL, NULL);
+
+
+ /*
+ * we need to be called back later to store our data
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_mteObjectsTable, NULL);
+
+
+ /*
+ * place any other initialization junk you need here
+ */
+
+
+ DEBUGMSGTL(("mteObjectsTable", "done.\n"));
+}
+
+
+/*
+ * mteObjectsTable_add(): adds a structure node to our data set
+ */
+int
+mteObjectsTable_add(struct mteObjectsTable_data *thedata)
+{
+ netsnmp_variable_list *vars = NULL;
+
+
+ DEBUGMSGTL(("mteObjectsTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->mteOwner, thedata->mteOwnerLen); /* mteOwner */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->mteObjectsName, thedata->mteObjectsNameLen); /* mteObjectsName */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_UNSIGNED, (char *) &thedata->mteObjectsIndex, sizeof(thedata->mteObjectsIndex)); /* mteObjectsIndex */
+
+
+
+ header_complex_add_data(&mteObjectsTableStorage, vars, thedata);
+ DEBUGMSGTL(("mteObjectsTable", "registered an entry\n"));
+
+
+ DEBUGMSGTL(("mteObjectsTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+/*
+ * parse_mteObjectsTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+void
+parse_mteObjectsTable(const char *token, char *line)
+{
+ size_t tmpint;
+ struct mteObjectsTable_data *StorageTmp =
+ SNMP_MALLOC_STRUCT(mteObjectsTable_data);
+
+ DEBUGMSGTL(("mteObjectsTable", "parsing config... "));
+
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line, &StorageTmp->mteOwner,
+ &StorageTmp->mteOwnerLen);
+ if (StorageTmp->mteOwner == NULL) {
+ config_perror("invalid specification for mteOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteObjectsName,
+ &StorageTmp->mteObjectsNameLen);
+ if (StorageTmp->mteObjectsName == NULL) {
+ config_perror("invalid specification for mteObjectsName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->mteObjectsIndex, &tmpint);
+
+ line =
+ read_config_read_data(ASN_OBJECT_ID, line,
+ &StorageTmp->mteObjectsID,
+ &StorageTmp->mteObjectsIDLen);
+ if (StorageTmp->mteObjectsID == NULL) {
+ config_perror("invalid specification for mteObjectsID");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteObjectsIDWildcard, &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteObjectsEntryStatus, &tmpint);
+
+
+
+
+ mteObjectsTable_add(StorageTmp);
+
+
+ DEBUGMSGTL(("mteObjectsTable", "done.\n"));
+}
+
+
+
+
+/*
+ * store_mteObjectsTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+int
+store_mteObjectsTable(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr;
+ size_t tmpint;
+ struct mteObjectsTable_data *StorageTmp;
+ struct header_complex_index *hcindex;
+
+
+ DEBUGMSGTL(("mteObjectsTable", "storing data... "));
+
+
+ for (hcindex = mteObjectsTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct mteObjectsTable_data *) hcindex->data;
+
+ if (StorageTmp->storagetype != ST_READONLY) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "mteObjectsTable ");
+ cptr = line + strlen(line);
+
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->mteOwner,
+ &StorageTmp->mteOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->mteObjectsName,
+ &StorageTmp->mteObjectsNameLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->mteObjectsIndex,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OBJECT_ID, cptr,
+ &StorageTmp->mteObjectsID,
+ &StorageTmp->mteObjectsIDLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->mteObjectsIDWildcard,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->mteObjectsEntryStatus,
+ &tmpint);
+
+
+
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("mteObjectsTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+
+
+/*
+ * var_mteObjectsTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_mteObjectsTable above.
+ */
+unsigned char *
+var_mteObjectsTable(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact,
+ size_t * var_len, WriteMethod ** write_method)
+{
+
+
+ struct mteObjectsTable_data *StorageTmp = NULL;
+
+
+ DEBUGMSGTL(("mteObjectsTable",
+ "var_mteObjectsTable: Entering... \n"));
+
+ /* set default value */
+ *write_method = NULL;
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(mteObjectsTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL) {
+ if (vp->magic == MTEOBJECTSENTRYSTATUS)
+ *write_method = write_mteObjectsEntryStatus;
+ return NULL;
+ }
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+
+
+ case MTEOBJECTSID:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteObjectsID;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = (StorageTmp->mteObjectsIDLen) * sizeof(oid);
+ return (u_char *) StorageTmp->mteObjectsID;
+
+ case MTEOBJECTSIDWILDCARD:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteObjectsIDWildcard;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteObjectsIDWildcard);
+ return (u_char *) & StorageTmp->mteObjectsIDWildcard;
+
+ case MTEOBJECTSENTRYSTATUS:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteObjectsEntryStatus;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteObjectsEntryStatus);
+ return (u_char *) & StorageTmp->mteObjectsEntryStatus;
+
+
+ default:
+ ERROR_MSG("");
+ }
+ return NULL;
+}
+
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+
+int
+write_mteObjectsID(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static oid *tmpvar;
+ struct mteObjectsTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len - (sizeof(mteObjectsTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteObjectsTable",
+ "write_mteObjectsID entering action=%d... \n", action));
+ if ((StorageTmp =
+ header_complex(mteObjectsTableStorage, NULL,
+ &name[sizeof(mteObjectsTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storagetype == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OBJECT_ID) {
+ snmp_log(LOG_ERR, "write to mteObjectsID not ASN_OBJECT_ID\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteObjectsID;
+ tmplen = StorageTmp->mteObjectsIDLen;
+ memdup((u_char **) & StorageTmp->mteObjectsID, var_val,
+ var_val_len);
+ StorageTmp->mteObjectsIDLen = var_val_len / sizeof(oid);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteObjectsID);
+ StorageTmp->mteObjectsID = tmpvar;
+ StorageTmp->mteObjectsIDLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+
+ snmp_store_needed(NULL);
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteObjectsIDWildcard(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteObjectsTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(mteObjectsTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteObjectsTable",
+ "write_mteObjectsIDWildcard entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteObjectsTableStorage, NULL,
+ &name[sizeof(mteObjectsTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storagetype == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to mteObjectsIDWildcard not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteObjectsIDWildcard;
+ StorageTmp->mteObjectsIDWildcard = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteObjectsIDWildcard = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ snmp_store_needed(NULL);
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+
+
+int
+write_mteObjectsEntryStatus(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ struct mteObjectsTable_data *StorageTmp = NULL;
+ static struct mteObjectsTable_data *StorageNew, *StorageDel;
+ size_t newlen =
+ name_len - (sizeof(mteObjectsTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+ static int old_value;
+ int set_value;
+ static netsnmp_variable_list *vars, *vp;
+ struct header_complex_index *hciptr;
+
+
+ StorageTmp =
+ header_complex(mteObjectsTableStorage, NULL,
+ &name[sizeof(mteObjectsTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL, NULL);
+
+ if (var_val_type != ASN_INTEGER || var_val == NULL) {
+ snmp_log(LOG_ERR,
+ "write to mteObjectsEntryStatus not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+
+ if (StorageTmp && StorageTmp->storagetype == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ set_value = *((long *) var_val);
+
+
+ /*
+ * check legal range, and notReady is reserved for us, not a user
+ */
+ if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY)
+ return SNMP_ERR_INCONSISTENTVALUE;
+
+
+ switch (action) {
+ case RESERVE1:
+ /*
+ * stage one: test validity
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * create the row now?
+ */
+
+
+ /*
+ * ditch illegal values now
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE)
+ return SNMP_ERR_INCONSISTENTVALUE;
+
+
+ /*
+ * destroying a non-existent row is actually legal
+ */
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+
+
+ /*
+ * illegal creation values
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ } else {
+ /*
+ * row exists. Check for a valid state change
+ */
+ if (set_value == RS_CREATEANDGO
+ || set_value == RS_CREATEANDWAIT) {
+ /*
+ * can't create a row that exists
+ */
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ /*
+ * XXX: interaction with row storage type needed
+ */
+ }
+ break;
+
+
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * creation
+ */
+ vars = NULL;
+
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* mteOwner */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* mteObjectsName */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_UNSIGNED, NULL, 0); /* mteObjectsIndex */
+
+ if (header_complex_parse_oid
+ (&
+ (name
+ [sizeof(mteObjectsTable_variables_oid) / sizeof(oid) +
+ 2]), newlen, vars) != SNMPERR_SUCCESS) {
+ /*
+ * XXX: free, zero vars
+ */
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+ vp = vars;
+
+
+ StorageNew = SNMP_MALLOC_STRUCT(mteObjectsTable_data);
+ if (StorageNew == NULL)
+ return SNMP_ERR_GENERR;
+ StorageNew->mteOwner = netsnmp_strdup_and_null(vp->val.string,
+ vp->val_len);
+ StorageNew->mteOwnerLen = vp->val_len;
+ vp = vp->next_variable;
+ StorageNew->mteObjectsName =
+ netsnmp_strdup_and_null(vp->val.string,
+ vp->val_len);
+ StorageNew->mteObjectsNameLen = vp->val_len;
+ vp = vp->next_variable;
+ StorageNew->mteObjectsIndex = *(vp->val.integer);
+
+ /*
+ * XXX: fill in default row values here into StorageNew
+ */
+ StorageNew->mteObjectsID = calloc(1, sizeof(oid) * sizeof(2)); /* 0.0 */
+ StorageNew->mteObjectsIDLen = 2;
+ StorageNew->mteObjectsIDWildcard = MTEOBJECTSIDWILDCARD_FALSE;
+
+ StorageNew->mteObjectsEntryStatus = set_value;
+ /*
+ * XXX: free, zero vars, no longer needed?
+ */
+ }
+
+
+ break;
+
+
+
+
+ case FREE:
+ /*
+ * XXX: free, zero vars
+ */
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in set_value for you to
+ * use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in
+ * the UNDO case
+ */
+
+
+ if (StorageTmp == NULL) {
+ /*
+ * row creation, so add it
+ */
+ if (StorageNew != NULL)
+ mteObjectsTable_add(StorageNew);
+ /*
+ * XXX: ack, and if it is NULL?
+ */
+ } else if (set_value != RS_DESTROY) {
+ /*
+ * set the flag?
+ */
+ old_value = StorageTmp->mteObjectsEntryStatus;
+ StorageTmp->mteObjectsEntryStatus = *((long *) var_val);
+ } else {
+ /*
+ * destroy... extract it for now
+ */
+ hciptr =
+ header_complex_find_entry(mteObjectsTableStorage,
+ StorageTmp);
+ StorageDel =
+ header_complex_extract_entry(&mteObjectsTableStorage,
+ hciptr);
+ }
+ break;
+
+
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * row creation, so remove it again
+ */
+ hciptr =
+ header_complex_find_entry(mteObjectsTableStorage,
+ StorageTmp);
+ StorageDel =
+ header_complex_extract_entry(&mteObjectsTableStorage,
+ hciptr);
+ /*
+ * XXX: free it
+ */
+ } else if (StorageDel != NULL) {
+ /*
+ * row deletion, so add it again
+ */
+ mteObjectsTable_add(StorageDel);
+ } else {
+ StorageTmp->mteObjectsEntryStatus = old_value;
+ }
+ break;
+
+
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ if (StorageDel != NULL) {
+ StorageDel = 0;
+ /*
+ * XXX: free it, its dead
+ */
+ } else {
+ if (StorageTmp
+ && StorageTmp->mteObjectsEntryStatus == RS_CREATEANDGO) {
+ StorageTmp->mteObjectsEntryStatus = RS_ACTIVE;
+ } else if (StorageTmp &&
+ StorageTmp->mteObjectsEntryStatus ==
+ RS_CREATEANDWAIT) {
+ StorageTmp->mteObjectsEntryStatus = RS_NOTINSERVICE;
+ }
+ }
+ snmp_store_needed(NULL);
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+
+void
+mte_add_objects(netsnmp_variable_list * vars,
+ struct mteTriggerTable_data *item, const char *owner,
+ const char *name, oid * suffix, size_t suffix_len)
+{
+ struct header_complex_index *hcptr = mteObjectsTableStorage;
+
+ DEBUGMSGTL(("mteObjectsTable",
+ "Searching for objects to add for owner=%s / name=%s\n",
+ owner, name));
+
+ if (vars == NULL || item == NULL || owner == NULL || name == NULL ||
+ hcptr == NULL)
+ return;
+
+ /*
+ * get to end of variable chain
+ */
+ while (vars->next_variable != NULL)
+ vars = vars->next_variable;
+
+
+ /*
+ * get to start of objects list
+ */
+ while (hcptr &&
+ (strcmp(((struct mteObjectsTable_data *) hcptr->data)->mteOwner,
+ owner) != 0 ||
+ strcmp(((struct mteObjectsTable_data *) hcptr->data)->
+ mteObjectsName, name) != 0))
+ hcptr = hcptr->next;
+
+ /*
+ * add all objects
+ */
+ while (hcptr &&
+ strcmp(((struct mteObjectsTable_data *) hcptr->data)->mteOwner,
+ owner) == 0 &&
+ strcmp(((struct mteObjectsTable_data *) hcptr->data)->
+ mteObjectsName, name) == 0) {
+ /*
+ * loop through objects
+ */
+ netsnmp_pdu *pdu = NULL, *response = NULL;
+ struct mteObjectsTable_data *node =
+ (struct mteObjectsTable_data *) hcptr->data;
+ oid theoid[MAX_OID_LEN];
+ size_t theoid_len;
+
+ /*
+ * copy in the suffix
+ */
+ memcpy(theoid, node->mteObjectsID,
+ node->mteObjectsIDLen * sizeof(oid));
+ theoid_len = node->mteObjectsIDLen;
+ if (node->mteObjectsIDWildcard == MTEOBJECTSIDWILDCARD_TRUE &&
+ suffix && suffix_len > 0) {
+ theoid_len += suffix_len;
+ if (theoid_len > MAX_OID_LEN) {
+ break; /* XXX: properly send trap or something? */
+ }
+
+ memcpy(&theoid[node->mteObjectsIDLen], suffix,
+ suffix_len * sizeof(oid));
+ }
+
+ /*
+ * retrieve the value
+ */
+ pdu = snmp_pdu_create(SNMP_MSG_GET);
+ snmp_add_null_var(pdu, theoid, theoid_len);
+ response = mte_get_response(item, pdu);
+
+ if (response) {
+ if (vars) {
+ vars->next_variable = response->variables;
+ vars = vars->next_variable;
+ DEBUGMSGTL(("mteObjectsTable", "Adding: "));
+ DEBUGMSGOID(("mteObjectsTable", response->variables->name,
+ response->variables->name_length));
+ DEBUGMSG(("mteObjectsTable", "\n"));
+ } else {
+ vars = response->variables;
+ }
+ /*
+ * erase response notion of the values we stole from it
+ */
+ response->variables = NULL;
+ snmp_free_pdu(response);
+ }
+
+ /*
+ * move along
+ */
+ hcptr = hcptr->next;
+ }
+ DEBUGMSGTL(("mteObjectsTable", "Done adding objects\n"));
+}
+
+int
+mte_add_object_to_table(const char *owner, const char *objname,
+ oid * oidname, size_t oidname_len, int iswild)
+{
+ struct header_complex_index *hcptr = mteObjectsTableStorage, *lastnode;
+ static struct mteObjectsTable_data *StorageNew;
+
+ /*
+ * malloc initial struct
+ */
+ StorageNew = SNMP_MALLOC_STRUCT(mteObjectsTable_data);
+ if (StorageNew == NULL)
+ return SNMP_ERR_GENERR;
+ StorageNew->mteOwner = netsnmp_strdup_and_null(owner, strlen(owner));
+ StorageNew->mteOwnerLen = strlen(owner);
+ StorageNew->mteObjectsName = netsnmp_strdup_and_null(objname,
+ strlen(objname));
+ StorageNew->mteObjectsNameLen = strlen(objname);
+
+ /*
+ * find the next number
+ */
+ /*
+ * get to start of objects list
+ */
+ while (hcptr &&
+ (strcmp(((struct mteObjectsTable_data *) hcptr->data)->mteOwner,
+ owner) != 0 ||
+ strcmp(((struct mteObjectsTable_data *) hcptr->data)->
+ mteObjectsName, objname) != 0))
+ hcptr = hcptr->next;
+
+ if (hcptr) {
+ /*
+ * an object existed. Find the first one past and increment
+ * the previous number
+ */
+ lastnode = hcptr;
+ while (hcptr &&
+ strcmp(((struct mteObjectsTable_data *) hcptr->data)->
+ mteOwner, owner) == 0
+ && strcmp(((struct mteObjectsTable_data *) hcptr->data)->
+ mteObjectsName, objname) == 0) {
+ lastnode = hcptr;
+ hcptr = hcptr->next;
+ }
+ StorageNew->mteObjectsIndex =
+ ((struct mteObjectsTable_data *) lastnode->data)->
+ mteObjectsIndex + 1;
+ } else {
+ StorageNew->mteObjectsIndex = 1;
+ }
+
+ /*
+ * XXX: fill in default row values here into StorageNew
+ */
+ StorageNew->mteObjectsID = snmp_duplicate_objid(oidname, oidname_len);
+ StorageNew->mteObjectsIDLen = oidname_len;
+
+ if (iswild)
+ StorageNew->mteObjectsIDWildcard = MTEOBJECTSIDWILDCARD_TRUE;
+ else
+ StorageNew->mteObjectsIDWildcard = MTEOBJECTSIDWILDCARD_FALSE;
+
+ StorageNew->mteObjectsEntryStatus = RS_ACTIVE;
+ StorageNew->storagetype = ST_READONLY;
+ return mteObjectsTable_add(StorageNew);
+}
diff --git a/agent/mibgroup/disman/mteObjectsTable.h b/agent/mibgroup/disman/mteObjectsTable.h
new file mode 100644
index 0000000..4d44c87
--- /dev/null
+++ b/agent/mibgroup/disman/mteObjectsTable.h
@@ -0,0 +1,71 @@
+/*
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+
+#ifndef _MIBGROUP_MTEOBJECTSTABLE_H
+#define _MIBGROUP_MTEOBJECTSTABLE_H
+
+
+/*
+ * we may use header_complex from the header_complex module
+ */
+
+
+config_require(header_complex)
+
+
+ /*
+ * our storage structure(s)
+ */
+ struct mteObjectsTable_data {
+
+ char *mteOwner;
+ size_t mteOwnerLen;
+ char *mteObjectsName;
+ size_t mteObjectsNameLen;
+ unsigned long mteObjectsIndex;
+ oid *mteObjectsID;
+ size_t mteObjectsIDLen;
+ long mteObjectsIDWildcard;
+ long mteObjectsEntryStatus;
+ int storagetype;
+ };
+
+/*
+ * enum definitions from the covered mib sections
+ */
+
+
+#define MTEOBJECTSIDWILDCARD_TRUE 1
+#define MTEOBJECTSIDWILDCARD_FALSE 2
+
+/*
+ * function prototypes
+ */
+
+
+ void init_mteObjectsTable(void);
+ FindVarMethod var_mteObjectsTable;
+ void parse_mteObjectsTable(const char *, char *);
+ SNMPCallback store_mteObjectsTable;
+ void mte_add_objects(netsnmp_variable_list *,
+ struct mteTriggerTable_data *,
+ const char *, const char *, oid *,
+ size_t);
+ int mte_add_object_to_table(const char *owner,
+ const char *objname,
+ oid * oidname,
+ size_t oidname_len,
+ int iswild);
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ WriteMethod write_mteObjectsID;
+ WriteMethod write_mteObjectsIDWildcard;
+ WriteMethod write_mteObjectsEntryStatus;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+
+
+#endif /* _MIBGROUP_MTEOBJECTSTABLE_H */
diff --git a/agent/mibgroup/disman/mteTriggerBooleanTable.c b/agent/mibgroup/disman/mteTriggerBooleanTable.c
new file mode 100644
index 0000000..5b17927
--- /dev/null
+++ b/agent/mibgroup/disman/mteTriggerBooleanTable.c
@@ -0,0 +1,852 @@
+/*
+ * This file was generated by mib2c and is intended for use as
+ * a mib module for the ucd-snmp snmpd agent.
+ */
+
+
+/*
+ * This should always be included first before anything else
+ */
+#include <net-snmp/net-snmp-config.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+
+/*
+ * minimal include directives
+ */
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "header_complex.h"
+#include "mteTriggerBooleanTable.h"
+#include "mteTriggerTable.h"
+
+
+/*
+ * mteTriggerBooleanTable_variables_oid:
+ * this is the top level oid that we want to register under. This
+ * is essentially a prefix, with the suffix appearing in the
+ * variable below.
+ */
+
+
+oid mteTriggerBooleanTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 88, 1, 2, 5 };
+
+
+/*
+ * variable2 mteTriggerBooleanTable_variables:
+ * this variable defines function callbacks and type return information
+ * for the mteTriggerBooleanTable mib section
+ */
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+struct variable2 mteTriggerBooleanTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define MTETRIGGERBOOLEANCOMPARISON 3
+ {MTETRIGGERBOOLEANCOMPARISON, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerBooleanTable, 2, {1, 1}},
+#define MTETRIGGERBOOLEANVALUE 4
+ {MTETRIGGERBOOLEANVALUE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerBooleanTable, 2, {1, 2}},
+#define MTETRIGGERBOOLEANSTARTUP 5
+ {MTETRIGGERBOOLEANSTARTUP, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerBooleanTable, 2, {1, 3}},
+#define MTETRIGGERBOOLEANOBJECTSOWNER 6
+ {MTETRIGGERBOOLEANOBJECTSOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerBooleanTable, 2, {1, 4}},
+#define MTETRIGGERBOOLEANOBJECTS 7
+ {MTETRIGGERBOOLEANOBJECTS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerBooleanTable, 2, {1, 5}},
+#define MTETRIGGERBOOLEANEVENTOWNER 8
+ {MTETRIGGERBOOLEANEVENTOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerBooleanTable, 2, {1, 6}},
+#define MTETRIGGERBOOLEANEVENT 9
+ {MTETRIGGERBOOLEANEVENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerBooleanTable, 2, {1, 7}},
+};
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+struct variable2 mteTriggerBooleanTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define MTETRIGGERBOOLEANCOMPARISON 3
+ {MTETRIGGERBOOLEANCOMPARISON, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerBooleanTable, 2, {1, 1}},
+#define MTETRIGGERBOOLEANVALUE 4
+ {MTETRIGGERBOOLEANVALUE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerBooleanTable, 2, {1, 2}},
+#define MTETRIGGERBOOLEANSTARTUP 5
+ {MTETRIGGERBOOLEANSTARTUP, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerBooleanTable, 2, {1, 3}},
+#define MTETRIGGERBOOLEANOBJECTSOWNER 6
+ {MTETRIGGERBOOLEANOBJECTSOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerBooleanTable, 2, {1, 4}},
+#define MTETRIGGERBOOLEANOBJECTS 7
+ {MTETRIGGERBOOLEANOBJECTS, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerBooleanTable, 2, {1, 5}},
+#define MTETRIGGERBOOLEANEVENTOWNER 8
+ {MTETRIGGERBOOLEANEVENTOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerBooleanTable, 2, {1, 6}},
+#define MTETRIGGERBOOLEANEVENT 9
+ {MTETRIGGERBOOLEANEVENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerBooleanTable, 2, {1, 7}},
+};
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+/*
+ * (L = length of the oidsuffix)
+ */
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+extern struct header_complex_index *mteTriggerTableStorage;
+
+
+/*
+ * init_mteTriggerBooleanTable():
+ * Initialization routine. This is called when the agent starts up.
+ * At a minimum, registration of your variables should take place here.
+ */
+void
+init_mteTriggerBooleanTable(void)
+{
+ DEBUGMSGTL(("mteTriggerBooleanTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("mteTriggerBooleanTable",
+ mteTriggerBooleanTable_variables, variable2,
+ mteTriggerBooleanTable_variables_oid);
+
+ DEBUGMSGTL(("mteTriggerBooleanTable", "done.\n"));
+}
+
+/*
+ * var_mteTriggerBooleanTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_mteTriggerBooleanTable above.
+ */
+unsigned char *
+var_mteTriggerBooleanTable(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact,
+ size_t * var_len, WriteMethod ** write_method)
+{
+
+
+ struct mteTriggerTable_data *StorageTmp = NULL;
+
+
+ DEBUGMSGTL(("mteTriggerBooleanTable",
+ "var_mteTriggerBooleanTable: Entering... \n"));
+
+ /* set default value */
+ *write_method = NULL;
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL)
+ return NULL;
+
+ if (!(StorageTmp->mteTriggerTest[0] & MTETRIGGERTEST_BOOLEAN))
+ return NULL;
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+
+
+ case MTETRIGGERBOOLEANCOMPARISON:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerBooleanComparison;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerBooleanComparison);
+ return (u_char *) & StorageTmp->mteTriggerBooleanComparison;
+
+ case MTETRIGGERBOOLEANVALUE:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerBooleanValue;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerBooleanValue);
+ return (u_char *) & StorageTmp->mteTriggerBooleanValue;
+
+ case MTETRIGGERBOOLEANSTARTUP:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerBooleanStartup;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerBooleanStartup);
+ return (u_char *) & StorageTmp->mteTriggerBooleanStartup;
+
+ case MTETRIGGERBOOLEANOBJECTSOWNER:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerBooleanObjectsOwner;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerBooleanObjectsOwnerLen;
+ return (u_char *) StorageTmp->mteTriggerBooleanObjectsOwner;
+
+ case MTETRIGGERBOOLEANOBJECTS:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerBooleanObjects;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerBooleanObjectsLen;
+ return (u_char *) StorageTmp->mteTriggerBooleanObjects;
+
+ case MTETRIGGERBOOLEANEVENTOWNER:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerBooleanEventOwner;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerBooleanEventOwnerLen;
+ return (u_char *) StorageTmp->mteTriggerBooleanEventOwner;
+
+ case MTETRIGGERBOOLEANEVENT:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerBooleanEvent;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerBooleanEventLen;
+ return (u_char *) StorageTmp->mteTriggerBooleanEvent;
+
+
+ default:
+ ERROR_MSG("");
+ }
+ return NULL;
+}
+
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+
+int
+write_mteTriggerBooleanComparison(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerBooleanTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerBooleanTable",
+ "write_mteTriggerBooleanComparison entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerBooleanTable_variables_oid)
+ / sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ fprintf(stderr,
+ "write to mteTriggerBooleanComparison not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerBooleanComparison;
+ StorageTmp->mteTriggerBooleanComparison = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerBooleanComparison = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerBooleanValue(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerBooleanTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerBooleanTable",
+ "write_mteTriggerBooleanValue entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerBooleanTable_variables_oid)
+ / sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ fprintf(stderr,
+ "write to mteTriggerBooleanValue not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerBooleanValue;
+ StorageTmp->mteTriggerBooleanValue = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerBooleanValue = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerBooleanStartup(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerBooleanTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerBooleanTable",
+ "write_mteTriggerBooleanStartup entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerBooleanTable_variables_oid)
+ / sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ fprintf(stderr,
+ "write to mteTriggerBooleanStartup not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerBooleanStartup;
+ StorageTmp->mteTriggerBooleanStartup = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerBooleanStartup = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerBooleanObjectsOwner(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerBooleanTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerBooleanTable",
+ "write_mteTriggerBooleanObjectsOwner entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerBooleanTable_variables_oid)
+ / sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerBooleanObjectsOwner not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerBooleanObjectsOwner;
+ tmplen = StorageTmp->mteTriggerBooleanObjectsOwnerLen;
+ StorageTmp->mteTriggerBooleanObjectsOwner =
+ netsnmp_strdup_and_null(var_val, var_val_len);
+ StorageTmp->mteTriggerBooleanObjectsOwnerLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerBooleanObjectsOwner);
+ StorageTmp->mteTriggerBooleanObjectsOwner = tmpvar;
+ StorageTmp->mteTriggerBooleanObjectsOwnerLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerBooleanObjects(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerBooleanTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerBooleanTable",
+ "write_mteTriggerBooleanObjects entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerBooleanTable_variables_oid)
+ / sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerBooleanObjects not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerBooleanObjects;
+ tmplen = StorageTmp->mteTriggerBooleanObjectsLen;
+ StorageTmp->mteTriggerBooleanObjects =
+ netsnmp_strdup_and_null(var_val, var_val_len);
+ StorageTmp->mteTriggerBooleanObjectsLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerBooleanObjects);
+ StorageTmp->mteTriggerBooleanObjects = tmpvar;
+ StorageTmp->mteTriggerBooleanObjectsLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerBooleanEventOwner(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerBooleanTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerBooleanTable",
+ "write_mteTriggerBooleanEventOwner entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerBooleanTable_variables_oid)
+ / sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerBooleanEventOwner not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerBooleanEventOwner;
+ tmplen = StorageTmp->mteTriggerBooleanEventOwnerLen;
+ StorageTmp->mteTriggerBooleanEventOwner =
+ netsnmp_strdup_and_null(var_val, var_val_len);
+ StorageTmp->mteTriggerBooleanEventOwnerLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerBooleanEventOwner);
+ StorageTmp->mteTriggerBooleanEventOwner = tmpvar;
+ StorageTmp->mteTriggerBooleanEventOwnerLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerBooleanEvent(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerBooleanTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerBooleanTable",
+ "write_mteTriggerBooleanEvent entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerBooleanTable_variables_oid)
+ / sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerBooleanEvent not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerBooleanEvent;
+ tmplen = StorageTmp->mteTriggerBooleanEventLen;
+ StorageTmp->mteTriggerBooleanEvent =
+ netsnmp_strdup_and_null(var_val, var_val_len);
+ StorageTmp->mteTriggerBooleanEventLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerBooleanEvent);
+ StorageTmp->mteTriggerBooleanEvent = tmpvar;
+ StorageTmp->mteTriggerBooleanEventLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
diff --git a/agent/mibgroup/disman/mteTriggerBooleanTable.h b/agent/mibgroup/disman/mteTriggerBooleanTable.h
new file mode 100644
index 0000000..6413da5
--- /dev/null
+++ b/agent/mibgroup/disman/mteTriggerBooleanTable.h
@@ -0,0 +1,47 @@
+/*
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+
+#ifndef _MIBGROUP_MTETRIGGERBOOLEANTABLE_H
+#define _MIBGROUP_MTETRIGGERBOOLEANTABLE_H
+
+
+/*
+ * we may use header_complex from the header_complex module
+ */
+
+
+config_require(header_complex)
+ /*
+ * enum definitions from the covered mib sections
+ */
+#define MTETRIGGERBOOLEANCOMPARISON_UNEQUAL 1
+#define MTETRIGGERBOOLEANCOMPARISON_EQUAL 2
+#define MTETRIGGERBOOLEANCOMPARISON_LESS 3
+#define MTETRIGGERBOOLEANCOMPARISON_LESSOREQUAL 4
+#define MTETRIGGERBOOLEANCOMPARISON_GREATER 5
+#define MTETRIGGERBOOLEANCOMPARISON_GREATEROREQUAL 6
+#define MTETRIGGERBOOLEANSTARTUP_TRUE 1
+#define MTETRIGGERBOOLEANSTARTUP_FALSE 2
+ /*
+ * function prototypes
+ */
+ void init_mteTriggerBooleanTable(void);
+ FindVarMethod var_mteTriggerBooleanTable;
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ WriteMethod write_mteTriggerBooleanComparison;
+ WriteMethod write_mteTriggerBooleanValue;
+ WriteMethod write_mteTriggerBooleanStartup;
+ WriteMethod write_mteTriggerBooleanObjectsOwner;
+ WriteMethod write_mteTriggerBooleanObjects;
+ WriteMethod write_mteTriggerBooleanEventOwner;
+ WriteMethod write_mteTriggerBooleanEvent;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+
+
+
+#endif /* _MIBGROUP_MTETRIGGERBOOLEANTABLE_H */
diff --git a/agent/mibgroup/disman/mteTriggerDeltaTable.c b/agent/mibgroup/disman/mteTriggerDeltaTable.c
new file mode 100644
index 0000000..b5d2244
--- /dev/null
+++ b/agent/mibgroup/disman/mteTriggerDeltaTable.c
@@ -0,0 +1,443 @@
+/*
+ * This file was generated by mib2c and is intended for use as
+ * a mib module for the ucd-snmp snmpd agent.
+ */
+
+
+/*
+ * This should always be included first before anything else
+ */
+#include <net-snmp/net-snmp-config.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+
+/*
+ * minimal include directives
+ */
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "header_complex.h"
+#include "mteTriggerDeltaTable.h"
+#include "mteTriggerTable.h"
+
+
+/*
+ * mteTriggerDeltaTable_variables_oid:
+ * this is the top level oid that we want to register under. This
+ * is essentially a prefix, with the suffix appearing in the
+ * variable below.
+ */
+
+
+oid mteTriggerDeltaTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 88, 1, 2, 3 };
+
+
+/*
+ * variable2 mteTriggerDeltaTable_variables:
+ * this variable defines function callbacks and type return information
+ * for the mteTriggerDeltaTable mib section
+ */
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+struct variable2 mteTriggerDeltaTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define MTETRIGGERDELTADISCONTINUITYID 3
+ {MTETRIGGERDELTADISCONTINUITYID, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerDeltaTable, 2, {1, 1}},
+#define MTETRIGGERDELTADISCONTINUITYIDWILDCARD 4
+ {MTETRIGGERDELTADISCONTINUITYIDWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerDeltaTable, 2, {1, 2}},
+#define MTETRIGGERDELTADISCONTINUITYIDTYPE 5
+ {MTETRIGGERDELTADISCONTINUITYIDTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerDeltaTable, 2, {1, 3}},
+};
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+struct variable2 mteTriggerDeltaTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define MTETRIGGERDELTADISCONTINUITYID 3
+ {MTETRIGGERDELTADISCONTINUITYID, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerDeltaTable, 2, {1, 1}},
+#define MTETRIGGERDELTADISCONTINUITYIDWILDCARD 4
+ {MTETRIGGERDELTADISCONTINUITYIDWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerDeltaTable, 2, {1, 2}},
+#define MTETRIGGERDELTADISCONTINUITYIDTYPE 5
+ {MTETRIGGERDELTADISCONTINUITYIDTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerDeltaTable, 2, {1, 3}},
+};
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+/*
+ * (L = length of the oidsuffix)
+ */
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+extern struct header_complex_index *mteTriggerTableStorage;
+
+
+
+/*
+ * init_mteTriggerDeltaTable():
+ * Initialization routine. This is called when the agent starts up.
+ * At a minimum, registration of your variables should take place here.
+ */
+void
+init_mteTriggerDeltaTable(void)
+{
+ DEBUGMSGTL(("mteTriggerDeltaTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("mteTriggerDeltaTable", mteTriggerDeltaTable_variables,
+ variable2, mteTriggerDeltaTable_variables_oid);
+
+ DEBUGMSGTL(("mteTriggerDeltaTable", "done.\n"));
+}
+
+/*
+ * var_mteTriggerDeltaTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_mteTriggerDeltaTable above.
+ */
+unsigned char *
+var_mteTriggerDeltaTable(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact,
+ size_t * var_len, WriteMethod ** write_method)
+{
+
+
+ struct mteTriggerTable_data *StorageTmp = NULL;
+
+
+ DEBUGMSGTL(("mteTriggerDeltaTable",
+ "var_mteTriggerDeltaTable: Entering... \n"));
+
+ /* set default value */
+ *write_method = NULL;
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL)
+ return NULL;
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+
+
+ case MTETRIGGERDELTADISCONTINUITYID:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerDeltaDiscontinuityID;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len =
+ StorageTmp->mteTriggerDeltaDiscontinuityIDLen * sizeof(oid);
+ return (u_char *) StorageTmp->mteTriggerDeltaDiscontinuityID;
+
+ case MTETRIGGERDELTADISCONTINUITYIDWILDCARD:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerDeltaDiscontinuityIDWildcard;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len =
+ sizeof(StorageTmp->mteTriggerDeltaDiscontinuityIDWildcard);
+ return (u_char *) & StorageTmp->
+ mteTriggerDeltaDiscontinuityIDWildcard;
+
+ case MTETRIGGERDELTADISCONTINUITYIDTYPE:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerDeltaDiscontinuityIDType;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerDeltaDiscontinuityIDType);
+ return (u_char *) & StorageTmp->mteTriggerDeltaDiscontinuityIDType;
+
+ default:
+ ERROR_MSG("");
+ }
+ return NULL;
+}
+
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+int
+write_mteTriggerDeltaDiscontinuityID(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static oid *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerDeltaTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerDeltaTable",
+ "write_mteTriggerDeltaDiscontinuityID entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerDeltaTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OBJECT_ID) {
+ fprintf(stderr,
+ "write to mteTriggerDeltaDiscontinuityID not ASN_OBJECT_ID\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerDeltaDiscontinuityID;
+ tmplen = StorageTmp->mteTriggerDeltaDiscontinuityIDLen;
+ memdup((u_char **) & StorageTmp->mteTriggerDeltaDiscontinuityID,
+ var_val, var_val_len);
+ StorageTmp->mteTriggerDeltaDiscontinuityIDLen =
+ var_val_len / sizeof(oid);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerDeltaDiscontinuityID);
+ StorageTmp->mteTriggerDeltaDiscontinuityID = tmpvar;
+ StorageTmp->mteTriggerDeltaDiscontinuityIDLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerDeltaDiscontinuityIDWildcard(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerDeltaTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerDeltaTable",
+ "write_mteTriggerDeltaDiscontinuityIDWildcard entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerDeltaTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ fprintf(stderr,
+ "write to mteTriggerDeltaDiscontinuityIDWildcard not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerDeltaDiscontinuityIDWildcard;
+ StorageTmp->mteTriggerDeltaDiscontinuityIDWildcard =
+ *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerDeltaDiscontinuityIDWildcard = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerDeltaDiscontinuityIDType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerDeltaTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerDeltaTable",
+ "write_mteTriggerDeltaDiscontinuityIDType entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerDeltaTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ fprintf(stderr,
+ "write to mteTriggerDeltaDiscontinuityIDType not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerDeltaDiscontinuityIDType;
+ StorageTmp->mteTriggerDeltaDiscontinuityIDType =
+ *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerDeltaDiscontinuityIDType = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
diff --git a/agent/mibgroup/disman/mteTriggerDeltaTable.h b/agent/mibgroup/disman/mteTriggerDeltaTable.h
new file mode 100644
index 0000000..fa4872a
--- /dev/null
+++ b/agent/mibgroup/disman/mteTriggerDeltaTable.h
@@ -0,0 +1,39 @@
+/*
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+
+#ifndef _MIBGROUP_MTETRIGGERDELTATABLE_H
+#define _MIBGROUP_MTETRIGGERDELTATABLE_H
+
+
+/*
+ * we may use header_complex from the header_complex module
+ */
+
+
+config_require(header_complex)
+
+
+ /*
+ * enum definitions from the covered mib sections
+ */
+#define MTETRIGGERDELTADISCONTINUITYIDWILDCARD_TRUE 1
+#define MTETRIGGERDELTADISCONTINUITYIDWILDCARD_FALSE 2
+#define MTETRIGGERDELTADISCONTINUITYIDTYPE_TIMETICKS 1
+#define MTETRIGGERDELTADISCONTINUITYIDTYPE_TIMESTAMP 2
+#define MTETRIGGERDELTADISCONTINUITYIDTYPE_DATEANDTIME 3
+ /*
+ * function prototypes
+ */
+ void init_mteTriggerDeltaTable(void);
+ FindVarMethod var_mteTriggerDeltaTable;
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ WriteMethod write_mteTriggerDeltaDiscontinuityID;
+ WriteMethod write_mteTriggerDeltaDiscontinuityIDWildcard;
+ WriteMethod write_mteTriggerDeltaDiscontinuityIDType;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+#endif /* _MIBGROUP_MTETRIGGERDELTATABLE_H */
diff --git a/agent/mibgroup/disman/mteTriggerExistenceTable.c b/agent/mibgroup/disman/mteTriggerExistenceTable.c
new file mode 100644
index 0000000..fdfdaf2
--- /dev/null
+++ b/agent/mibgroup/disman/mteTriggerExistenceTable.c
@@ -0,0 +1,782 @@
+/*
+ * This file was generated by mib2c and is intended for use as
+ * a mib module for the ucd-snmp snmpd agent.
+ */
+
+
+/*
+ * This should always be included first before anything else
+ */
+#include <net-snmp/net-snmp-config.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+
+/*
+ * minimal include directives
+ */
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "header_complex.h"
+#include "mteTriggerExistenceTable.h"
+#include "mteTriggerTable.h"
+
+
+/*
+ * mteTriggerExistenceTable_variables_oid:
+ * this is the top level oid that we want to register under. This
+ * is essentially a prefix, with the suffix appearing in the
+ * variable below.
+ */
+
+
+oid mteTriggerExistenceTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 88, 1, 2, 4 };
+
+
+/*
+ * variable2 mteTriggerExistenceTable_variables:
+ * this variable defines function callbacks and type return information
+ * for the mteTriggerExistenceTable mib section
+ */
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+struct variable2 mteTriggerExistenceTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define MTETRIGGEREXISTENCETEST 3
+ {MTETRIGGEREXISTENCETEST, ASN_BIT_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerExistenceTable, 2, {1, 1}},
+#define MTETRIGGEREXISTENCESTARTUP 4
+ {MTETRIGGEREXISTENCESTARTUP, ASN_BIT_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerExistenceTable, 2, {1, 2}},
+#define MTETRIGGEREXISTENCEOBJECTSOWNER 5
+ {MTETRIGGEREXISTENCEOBJECTSOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerExistenceTable, 2, {1, 3}},
+#define MTETRIGGEREXISTENCEOBJECTS 6
+ {MTETRIGGEREXISTENCEOBJECTS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerExistenceTable, 2, {1, 4}},
+#define MTETRIGGEREXISTENCEEVENTOWNER 7
+ {MTETRIGGEREXISTENCEEVENTOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerExistenceTable, 2, {1, 5}},
+#define MTETRIGGEREXISTENCEEVENT 8
+ {MTETRIGGEREXISTENCEEVENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerExistenceTable, 2, {1, 6}},
+};
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+struct variable2 mteTriggerExistenceTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define MTETRIGGEREXISTENCETEST 3
+ {MTETRIGGEREXISTENCETEST, ASN_BIT_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerExistenceTable, 2, {1, 1}},
+#define MTETRIGGEREXISTENCESTARTUP 4
+ {MTETRIGGEREXISTENCESTARTUP, ASN_BIT_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerExistenceTable, 2, {1, 2}},
+#define MTETRIGGEREXISTENCEOBJECTSOWNER 5
+ {MTETRIGGEREXISTENCEOBJECTSOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerExistenceTable, 2, {1, 3}},
+#define MTETRIGGEREXISTENCEOBJECTS 6
+ {MTETRIGGEREXISTENCEOBJECTS, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerExistenceTable, 2, {1, 4}},
+#define MTETRIGGEREXISTENCEEVENTOWNER 7
+ {MTETRIGGEREXISTENCEEVENTOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerExistenceTable, 2, {1, 5}},
+#define MTETRIGGEREXISTENCEEVENT 8
+ {MTETRIGGEREXISTENCEEVENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerExistenceTable, 2, {1, 6}},
+};
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+/*
+ * (L = length of the oidsuffix)
+ */
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+extern struct header_complex_index *mteTriggerTableStorage;
+
+
+
+
+/*
+ * init_mteTriggerExistenceTable():
+ * Initialization routine. This is called when the agent starts up.
+ * At a minimum, registration of your variables should take place here.
+ */
+void
+init_mteTriggerExistenceTable(void)
+{
+ DEBUGMSGTL(("mteTriggerExistenceTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("mteTriggerExistenceTable",
+ mteTriggerExistenceTable_variables, variable2,
+ mteTriggerExistenceTable_variables_oid);
+
+
+ /*
+ * place any other initialization junk you need here
+ */
+
+
+ DEBUGMSGTL(("mteTriggerExistenceTable", "done.\n"));
+}
+
+/*
+ * var_mteTriggerExistenceTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_mteTriggerExistenceTable above.
+ */
+unsigned char *
+var_mteTriggerExistenceTable(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact,
+ size_t * var_len, WriteMethod ** write_method)
+{
+
+
+ struct mteTriggerTable_data *StorageTmp = NULL;
+
+
+ DEBUGMSGTL(("mteTriggerExistenceTable",
+ "var_mteTriggerExistenceTable: Entering... \n"));
+
+ /* set default value */
+ *write_method = NULL;
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL)
+ return NULL;
+
+ if (!(StorageTmp->mteTriggerTest[0] & MTETRIGGERTEST_EXISTENCE))
+ return NULL;
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+
+
+ case MTETRIGGEREXISTENCETEST:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerExistenceTest;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerExistenceTestLen;
+ return (u_char *) StorageTmp->mteTriggerExistenceTest;
+
+ case MTETRIGGEREXISTENCESTARTUP:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerExistenceStartup;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerExistenceStartupLen;
+ return (u_char *) StorageTmp->mteTriggerExistenceStartup;
+
+ case MTETRIGGEREXISTENCEOBJECTSOWNER:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerExistenceObjectsOwner;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerExistenceObjectsOwnerLen;
+ return (u_char *) StorageTmp->mteTriggerExistenceObjectsOwner;
+
+ case MTETRIGGEREXISTENCEOBJECTS:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerExistenceObjects;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerExistenceObjectsLen;
+ return (u_char *) StorageTmp->mteTriggerExistenceObjects;
+
+ case MTETRIGGEREXISTENCEEVENTOWNER:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerExistenceEventOwner;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerExistenceEventOwnerLen;
+ return (u_char *) StorageTmp->mteTriggerExistenceEventOwner;
+
+ case MTETRIGGEREXISTENCEEVENT:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerExistenceEvent;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerExistenceEventLen;
+ return (u_char *) StorageTmp->mteTriggerExistenceEvent;
+
+
+ default:
+ ERROR_MSG("");
+ }
+ return NULL;
+}
+
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+
+int
+write_mteTriggerExistenceTest(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerExistenceTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerExistenceTable",
+ "write_mteTriggerExistenceTest entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerExistenceTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerExistenceTest not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerExistenceTest;
+ tmplen = StorageTmp->mteTriggerExistenceTestLen;
+ memdup((u_char **) & StorageTmp->mteTriggerExistenceTest, var_val,
+ var_val_len);
+ StorageTmp->mteTriggerExistenceTestLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerExistenceTest);
+ StorageTmp->mteTriggerExistenceTest = tmpvar;
+ StorageTmp->mteTriggerExistenceTestLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerExistenceStartup(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerExistenceTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerExistenceTable",
+ "write_mteTriggerExistenceStartup entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerExistenceTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerExistenceStartup not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerExistenceStartup;
+ tmplen = StorageTmp->mteTriggerExistenceStartupLen;
+ memdup((u_char **) & StorageTmp->mteTriggerExistenceStartup,
+ var_val, var_val_len);
+ StorageTmp->mteTriggerExistenceStartupLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerExistenceStartup);
+ StorageTmp->mteTriggerExistenceStartup = tmpvar;
+ StorageTmp->mteTriggerExistenceStartupLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerExistenceObjectsOwner(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerExistenceTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerExistenceTable",
+ "write_mteTriggerExistenceObjectsOwner entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerExistenceTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerExistenceObjectsOwner not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerExistenceObjectsOwner;
+ tmplen = StorageTmp->mteTriggerExistenceObjectsOwnerLen;
+ memdup((u_char **) & StorageTmp->mteTriggerExistenceObjectsOwner,
+ var_val, var_val_len);
+ StorageTmp->mteTriggerExistenceObjectsOwnerLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerExistenceObjectsOwner);
+ StorageTmp->mteTriggerExistenceObjectsOwner = tmpvar;
+ StorageTmp->mteTriggerExistenceObjectsOwnerLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerExistenceObjects(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerExistenceTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerExistenceTable",
+ "write_mteTriggerExistenceObjects entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerExistenceTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerExistenceObjects not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerExistenceObjects;
+ tmplen = StorageTmp->mteTriggerExistenceObjectsLen;
+ memdup((u_char **) & StorageTmp->mteTriggerExistenceObjects,
+ var_val, var_val_len);
+ StorageTmp->mteTriggerExistenceObjectsLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerExistenceObjects);
+ StorageTmp->mteTriggerExistenceObjects = tmpvar;
+ StorageTmp->mteTriggerExistenceObjectsLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerExistenceEventOwner(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerExistenceTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerExistenceTable",
+ "write_mteTriggerExistenceEventOwner entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerExistenceTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerExistenceEventOwner not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerExistenceEventOwner;
+ tmplen = StorageTmp->mteTriggerExistenceEventOwnerLen;
+ memdup((u_char **) & StorageTmp->mteTriggerExistenceEventOwner,
+ var_val, var_val_len);
+ StorageTmp->mteTriggerExistenceEventOwnerLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerExistenceEventOwner);
+ StorageTmp->mteTriggerExistenceEventOwner = tmpvar;
+ StorageTmp->mteTriggerExistenceEventOwnerLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerExistenceEvent(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerExistenceTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerExistenceTable",
+ "write_mteTriggerExistenceEvent entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerExistenceTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerExistenceEvent not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerExistenceEvent;
+ tmplen = StorageTmp->mteTriggerExistenceEventLen;
+ memdup((u_char **) & StorageTmp->mteTriggerExistenceEvent, var_val,
+ var_val_len);
+ StorageTmp->mteTriggerExistenceEventLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerExistenceEvent);
+ StorageTmp->mteTriggerExistenceEvent = tmpvar;
+ StorageTmp->mteTriggerExistenceEventLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
diff --git a/agent/mibgroup/disman/mteTriggerExistenceTable.h b/agent/mibgroup/disman/mteTriggerExistenceTable.h
new file mode 100644
index 0000000..75c6427
--- /dev/null
+++ b/agent/mibgroup/disman/mteTriggerExistenceTable.h
@@ -0,0 +1,41 @@
+/*
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+
+#ifndef _MIBGROUP_MTETRIGGEREXISTENCETABLE_H
+#define _MIBGROUP_MTETRIGGEREXISTENCETABLE_H
+
+
+/*
+ * we may use header_complex from the header_complex module
+ */
+
+
+config_require(header_complex)
+
+ /*
+ * enum definitions from the covered mib sections
+ */
+#define MTETRIGGEREXISTENCETEST_PRESENT 0x80
+#define MTETRIGGEREXISTENCETEST_ABSENT 0x40
+#define MTETRIGGEREXISTENCETEST_CHANGED 0x20
+#define MTETRIGGEREXISTENCESTARTUP_PRESENT 0x80
+#define MTETRIGGEREXISTENCESTARTUP_ABSENT 0x40
+ /*
+ * function prototypes
+ */
+ void init_mteTriggerExistenceTable(void);
+ FindVarMethod var_mteTriggerExistenceTable;
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ WriteMethod write_mteTriggerExistenceTest;
+ WriteMethod write_mteTriggerExistenceStartup;
+ WriteMethod write_mteTriggerExistenceObjectsOwner;
+ WriteMethod write_mteTriggerExistenceObjects;
+ WriteMethod write_mteTriggerExistenceEventOwner;
+ WriteMethod write_mteTriggerExistenceEvent;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+#endif /* _MIBGROUP_MTETRIGGEREXISTENCETABLE_H */
diff --git a/agent/mibgroup/disman/mteTriggerTable.c b/agent/mibgroup/disman/mteTriggerTable.c
new file mode 100644
index 0000000..a2306f7
--- /dev/null
+++ b/agent/mibgroup/disman/mteTriggerTable.c
@@ -0,0 +1,3814 @@
+/*
+ * This file was generated by mib2c and is intended for use as
+ * a mib module for the ucd-snmp snmpd agent.
+ */
+
+
+/*
+ * This should always be included first before anything else
+ */
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+netsnmp_feature_require(mib_snprint_variable)
+netsnmp_feature_require(tdomain_support)
+netsnmp_feature_require(check_vb_uint)
+netsnmp_feature_require(string_time_to_secs)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(header_complex_find_entry)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+/*
+ * minimal include directives
+ */
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "header_complex.h"
+#include "mteTriggerTable.h"
+#include "mteTriggerBooleanTable.h"
+#include "mteTriggerDeltaTable.h"
+#include "mteTriggerExistenceTable.h"
+#include "mteTriggerThresholdTable.h"
+#include "mteEventTable.h"
+#include "mteObjectsTable.h"
+
+/*
+ * mteTriggerTable_variables_oid:
+ * this is the top level oid that we want to register under. This
+ * is essentially a prefix, with the suffix appearing in the
+ * variable below.
+ */
+
+/*
+ * trap definitions
+ */
+oid mteTriggerFired[] = { 1, 3, 6, 1, 2, 1, 88, 2, 0, 1 };
+oid mteTriggerRising[] = { 1, 3, 6, 1, 2, 1, 88, 2, 0, 2 };
+oid mteTriggerFalling[] = { 1, 3, 6, 1, 2, 1, 88, 2, 0, 3 };
+oid mteTriggerFailure[] = { 1, 3, 6, 1, 2, 1, 88, 2, 0, 4 };
+oid mteEventSetFailure[] = { 1, 3, 6, 1, 2, 1, 88, 2, 0, 5 };
+
+/*
+ * trap objects
+ */
+oid mteHotTrigger[] = { 1, 3, 6, 1, 2, 1, 88, 2, 1, 1 };
+oid mteHotTargetName[] = { 1, 3, 6, 1, 2, 1, 88, 2, 1, 2 };
+oid mteHotContextName[] = { 1, 3, 6, 1, 2, 1, 88, 2, 1, 3 };
+oid mteHotOID[] = { 1, 3, 6, 1, 2, 1, 88, 2, 1, 4 };
+oid mteHotValue[] = { 1, 3, 6, 1, 2, 1, 88, 2, 1, 5 };
+oid mteFailedReason[] = { 1, 3, 6, 1, 2, 1, 88, 2, 1, 6 };
+
+/*
+ * For discontinuity checking.
+ */
+oid sysUpTimeInstance[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 };
+
+oid mteTriggerTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 88, 1, 2, 2 };
+
+
+/*
+ * variable2 mteTriggerTable_variables:
+ * this variable defines function callbacks and type return information
+ * for the mteTriggerTable mib section
+ */
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+struct variable2 mteTriggerTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define MTETRIGGERCOMMENT 5
+ {MTETRIGGERCOMMENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 3}},
+#define MTETRIGGERTEST 6
+ {MTETRIGGERTEST, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 4}},
+#define MTETRIGGERSAMPLETYPE 7
+ {MTETRIGGERSAMPLETYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 5}},
+#define MTETRIGGERVALUEID 8
+ {MTETRIGGERVALUEID, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 6}},
+#define MTETRIGGERVALUEIDWILDCARD 9
+ {MTETRIGGERVALUEIDWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 7}},
+#define MTETRIGGERTARGETTAG 10
+ {MTETRIGGERTARGETTAG, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 8}},
+#define MTETRIGGERCONTEXTNAME 11
+ {MTETRIGGERCONTEXTNAME, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 9}},
+#define MTETRIGGERCONTEXTNAMEWILDCARD 12
+ {MTETRIGGERCONTEXTNAMEWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 10}},
+#define MTETRIGGERFREQUENCY 13
+ {MTETRIGGERFREQUENCY, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 11}},
+#define MTETRIGGEROBJECTSOWNER 14
+ {MTETRIGGEROBJECTSOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 12}},
+#define MTETRIGGEROBJECTS 15
+ {MTETRIGGEROBJECTS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 13}},
+#define MTETRIGGERENABLED 16
+ {MTETRIGGERENABLED, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 14}},
+#define MTETRIGGERENTRYSTATUS 17
+ {MTETRIGGERENTRYSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerTable, 2, {1, 15}},
+};
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+struct variable2 mteTriggerTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define MTETRIGGERCOMMENT 5
+ {MTETRIGGERCOMMENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 3}},
+#define MTETRIGGERTEST 6
+ {MTETRIGGERTEST, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 4}},
+#define MTETRIGGERSAMPLETYPE 7
+ {MTETRIGGERSAMPLETYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 5}},
+#define MTETRIGGERVALUEID 8
+ {MTETRIGGERVALUEID, ASN_OBJECT_ID, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 6}},
+#define MTETRIGGERVALUEIDWILDCARD 9
+ {MTETRIGGERVALUEIDWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 7}},
+#define MTETRIGGERTARGETTAG 10
+ {MTETRIGGERTARGETTAG, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 8}},
+#define MTETRIGGERCONTEXTNAME 11
+ {MTETRIGGERCONTEXTNAME, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 9}},
+#define MTETRIGGERCONTEXTNAMEWILDCARD 12
+ {MTETRIGGERCONTEXTNAMEWILDCARD, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 10}},
+#define MTETRIGGERFREQUENCY 13
+ {MTETRIGGERFREQUENCY, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 11}},
+#define MTETRIGGEROBJECTSOWNER 14
+ {MTETRIGGEROBJECTSOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 12}},
+#define MTETRIGGEROBJECTS 15
+ {MTETRIGGEROBJECTS, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 13}},
+#define MTETRIGGERENABLED 16
+ {MTETRIGGERENABLED, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 14}},
+#define MTETRIGGERENTRYSTATUS 17
+ {MTETRIGGERENTRYSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerTable, 2, {1, 15}},
+};
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+/*
+ * (L = length of the oidsuffix)
+ */
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+struct header_complex_index *mteTriggerTableStorage = NULL;
+
+netsnmp_session *mte_callback_sess = NULL;
+extern int callback_master_num;
+
+/*
+ * init_mteTriggerTable():
+ * Initialization routine. This is called when the agent starts up.
+ * At a minimum, registration of your variables should take place here.
+ */
+void
+init_mteTriggerTable(void)
+{
+ DEBUGMSGTL(("mteTriggerTable", "initializing... "));
+
+#ifndef NETSNMP_TRANSPORT_CALLBACK_DOMAIN
+ snmp_log(LOG_WARNING,"mteTriggerTable has been disabled because "
+ "the callback transport is not available.\n");
+ return;
+#endif
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("mteTriggerTable", mteTriggerTable_variables, variable2,
+ mteTriggerTable_variables_oid);
+
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("mteTriggerTable", parse_mteTriggerTable,
+ NULL, NULL);
+
+ snmpd_register_config_handler("monitor", parse_simple_monitor, NULL,
+ "[options] monitor_expression [see \"man snmpd.conf\"]");
+ snmpd_register_config_handler("defaultMonitors",
+ parse_default_monitors, NULL, "yes|no");
+
+ /*
+ * we need to be called back later to store our data
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_mteTriggerTable, NULL);
+
+
+ /*
+ * place any other initialization junk you need here
+ */
+ se_add_pair_to_slist("mteBooleanOperators", strdup("!="),
+ MTETRIGGERBOOLEANCOMPARISON_UNEQUAL);
+ se_add_pair_to_slist("mteBooleanOperators", strdup("=="),
+ MTETRIGGERBOOLEANCOMPARISON_EQUAL);
+ se_add_pair_to_slist("mteBooleanOperators", strdup("<"),
+ MTETRIGGERBOOLEANCOMPARISON_LESS);
+ se_add_pair_to_slist("mteBooleanOperators", strdup("<="),
+ MTETRIGGERBOOLEANCOMPARISON_LESSOREQUAL);
+ se_add_pair_to_slist("mteBooleanOperators", strdup(">"),
+ MTETRIGGERBOOLEANCOMPARISON_GREATER);
+ se_add_pair_to_slist("mteBooleanOperators", strdup(">="),
+ MTETRIGGERBOOLEANCOMPARISON_GREATEROREQUAL);
+
+ DEBUGMSGTL(("mteTriggerTable", "done.\n"));
+}
+
+struct mteTriggerTable_data *
+create_mteTriggerTable_data(void)
+{
+ struct mteTriggerTable_data *StorageNew;
+
+ StorageNew = SNMP_MALLOC_STRUCT(mteTriggerTable_data);
+
+ /*
+ * fill in default row values here into StorageNew
+ */
+ /*
+ * fill in values for all tables (even if not
+ * appropriate), since its easier to do here than anywhere
+ * else
+ */
+ StorageNew->mteTriggerComment = strdup("");
+ StorageNew->mteTriggerTest = strdup("");
+ StorageNew->mteTriggerTest[0] |= (char) MTETRIGGERTEST_BOOLEAN;
+ StorageNew->mteTriggerTestLen = 1;
+ StorageNew->mteTriggerSampleType = MTETRIGGERSAMPLETYPE_ABSOLUTEVALUE;
+ StorageNew->mteTriggerValueID = calloc(1, sizeof(oid) * sizeof(2)); /* 0.0 */
+ StorageNew->mteTriggerValueIDLen = 2;
+ StorageNew->mteTriggerValueIDWildcard =
+ MTETRIGGERVALUEIDWILDCARD_FALSE;
+ StorageNew->mteTriggerTargetTag = strdup("");
+ StorageNew->mteTriggerContextName = strdup("");
+ StorageNew->mteTriggerContextNameWildcard =
+ MTETRIGGERCONTEXTNAMEWILDCARD_FALSE;
+ StorageNew->mteTriggerFrequency = 600;
+ StorageNew->mteTriggerObjectsOwner = strdup("");
+ StorageNew->mteTriggerObjects = strdup("");
+ StorageNew->mteTriggerEnabled = MTETRIGGERENABLED_FALSE;
+ memdup((unsigned char **)
+ &(StorageNew->mteTriggerDeltaDiscontinuityID),
+ (unsigned char *) sysUpTimeInstance, sizeof(sysUpTimeInstance));
+ StorageNew->mteTriggerDeltaDiscontinuityIDLen =
+ sizeof(sysUpTimeInstance) / sizeof(oid);
+ StorageNew->mteTriggerDeltaDiscontinuityIDWildcard = TV_FALSE;
+ StorageNew->mteTriggerDeltaDiscontinuityIDType =
+ MTETRIGGERDELTADISCONTINUITYIDTYPE_TIMETICKS;
+ StorageNew->mteTriggerExistenceTest = strdup("");
+ StorageNew->mteTriggerExistenceTest[0] =
+ (char) (MTETRIGGEREXISTENCETEST_PRESENT |
+ MTETRIGGEREXISTENCETEST_ABSENT);
+ StorageNew->mteTriggerExistenceTestLen = 1;
+ StorageNew->mteTriggerExistenceStartup = strdup("");
+ StorageNew->mteTriggerExistenceStartup[0] =
+ (char) (MTETRIGGEREXISTENCESTARTUP_PRESENT);
+ StorageNew->mteTriggerExistenceStartupLen = 1;
+ StorageNew->mteTriggerExistenceObjectsOwner = strdup("");
+ StorageNew->mteTriggerExistenceObjects = strdup("");
+ StorageNew->mteTriggerExistenceEventOwner = strdup("");
+ StorageNew->mteTriggerExistenceEvent = strdup("");
+ StorageNew->mteTriggerBooleanComparison =
+ MTETRIGGERBOOLEANCOMPARISON_UNEQUAL;
+ StorageNew->mteTriggerBooleanStartup = MTETRIGGERBOOLEANSTARTUP_TRUE;
+ StorageNew->mteTriggerBooleanObjectsOwner = strdup("");
+ StorageNew->mteTriggerBooleanObjects = strdup("");
+ StorageNew->mteTriggerBooleanEventOwner = strdup("");
+ StorageNew->mteTriggerBooleanEvent = strdup("");
+ StorageNew->mteTriggerThresholdStartup =
+ MTETRIGGERTHRESHOLDSTARTUP_RISINGORFALLING;
+ StorageNew->mteTriggerThresholdObjectsOwner = strdup("");
+ StorageNew->mteTriggerThresholdObjects = strdup("");
+ StorageNew->mteTriggerThresholdRisingEventOwner = strdup("");
+ StorageNew->mteTriggerThresholdRisingEvent = strdup("");
+ StorageNew->mteTriggerThresholdFallingEventOwner = strdup("");
+ StorageNew->mteTriggerThresholdFallingEvent = strdup("");
+ StorageNew->mteTriggerThresholdDeltaRisingEventOwner = strdup("");
+ StorageNew->mteTriggerThresholdDeltaRisingEvent = strdup("");
+ StorageNew->mteTriggerThresholdDeltaFallingEventOwner = strdup("");
+ StorageNew->mteTriggerThresholdDeltaFallingEvent = strdup("");
+ StorageNew->lastboolresult = -1;
+ StorageNew->storageType = ST_NONVOLATILE;
+ StorageNew->prevDiscoTicks = 0;
+ StorageNew->prevUptimeTicks = 0;
+ return StorageNew;
+}
+
+/*
+ * mteTriggerTable_add(): adds a structure node to our data set
+ */
+int
+mteTriggerTable_add(struct mteTriggerTable_data *thedata)
+{
+ netsnmp_variable_list *vars = NULL;
+
+
+ DEBUGMSGTL(("mteTriggerTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->mteOwner, thedata->mteOwnerLen); /* mteOwner */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_PRIV_IMPLIED_OCTET_STR, (char *) thedata->mteTriggerName, thedata->mteTriggerNameLen); /* mteTriggerName */
+
+
+
+ header_complex_add_data(&mteTriggerTableStorage, vars, thedata);
+ DEBUGMSGTL(("mteTriggerTable", "registered an entry\n"));
+
+
+ DEBUGMSGTL(("mteTriggerTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+#define MTE_PROCESS_LINE(line) \
+ snprintf(buf, SPRINT_MAX_LEN, "-u %s %s", mte_default_user, line); \
+ parse_simple_monitor("monitor", buf);
+
+void
+parse_default_monitors(const char *token, char *line)
+{
+ char buf[SPRINT_MAX_LEN];
+ char *mte_default_user =
+ netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_INTERNAL_SECNAME);
+
+ if (strncmp(line, "yes", 3) == 0) {
+
+ DEBUGMSGTL(("mteTriggerTable", "registering default monitors\n"));
+
+ if (mte_default_user == NULL) {
+ config_perror
+ ("You must specify a user name first using the agentSecName token\n");
+ return;
+ }
+
+ /*
+ * we don't include many additional objects here as most of
+ * the error messages are complete with the needed
+ * information
+ */
+ MTE_PROCESS_LINE
+ ("-o prNames -o prErrMessage \"process table\" prErrorFlag != 0");
+ MTE_PROCESS_LINE
+ ("-o memErrorName -o memSwapErrorMsg \"memory\" memSwapError != 0");
+ MTE_PROCESS_LINE
+ ("-o extNames -o extOutput \"extTable\" extResult != 0");
+ MTE_PROCESS_LINE
+ ("-o dskPath -o dskErrorMsg \"dskTable\" dskErrorFlag != 0");
+ MTE_PROCESS_LINE
+ ("-o laNames -o laErrMessage \"laTable\" laErrorFlag != 0");
+ MTE_PROCESS_LINE
+ ("-o fileName -o fileErrorMsg \"fileTable\" fileErrorFlag != 0");
+ /*
+ * this one is not *all* that useful, because the error is
+ * only kept for 30 seconds at most. Maybe scan it every 30
+ * seconds, but I'm not doing so without seeking other peoples
+ * opinions first.
+ */
+ MTE_PROCESS_LINE
+ ("-o snmperrErrMessage \"snmperrs\" snmperrErrorFlag != 0");
+ }
+}
+
+static int monitor_call_count = 0;
+void
+parse_simple_monitor(const char *token, char *line)
+{
+ char buf[SPRINT_MAX_LEN], *cp, eventname[64];
+ oid obuf[MAX_OID_LEN];
+ size_t obufLen;
+ struct mteTriggerTable_data *StorageNew;
+
+ monitor_call_count++;
+ eventname[0] = '\0';
+
+ StorageNew = create_mteTriggerTable_data();
+ StorageNew->storageType = ST_READONLY;
+ StorageNew->mteTriggerEnabled = MTETRIGGERENABLED_TRUE;
+ StorageNew->mteTriggerEntryStatus = RS_ACTIVE;
+ StorageNew->mteTriggerValueIDWildcard = MTETRIGGERVALUEIDWILDCARD_TRUE;
+ StorageNew->mteTriggerBooleanStartup = MTETRIGGERBOOLEANSTARTUP_TRUE;
+ StorageNew->mteTriggerThresholdStartup =
+ MTETRIGGERTHRESHOLDSTARTUP_RISINGORFALLING;
+ StorageNew->mteTriggerExistenceTest[0] = 0;
+
+ /*
+ * owner = snmpd.conf, why not?
+ */
+ StorageNew->mteOwner = strdup("snmpd.conf");
+ StorageNew->mteOwnerLen = strlen(StorageNew->mteOwner);
+ StorageNew->pdu_version = SNMP_VERSION_3;
+ StorageNew->pdu_securityModel = SNMP_SEC_MODEL_USM;
+ StorageNew->pdu_securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
+
+ cp = line;
+
+ while (cp && *cp == '-') {
+ cp = copy_nword(cp, buf, sizeof(buf));
+ switch (buf[1]) {
+ case 't':
+ /*
+ * Threshold toggle
+ */
+ StorageNew->mteTriggerTest[0] = MTETRIGGERTEST_THRESHOLD;
+ break;
+ case 'i':
+ /*
+ * Single instance
+ */
+ StorageNew->mteTriggerValueIDWildcard = MTETRIGGERVALUEIDWILDCARD_FALSE;
+ break;
+ case 'r':
+ if (cp) {
+ int freq;
+ cp = copy_nword(cp, buf, sizeof(buf));
+ freq = netsnmp_string_time_to_secs(buf);
+ if (freq == -1) {
+ config_perror("Invalid -r value\n");
+ /*
+ * XXX: free StorageNew
+ */
+ return;
+ }
+ StorageNew->mteTriggerFrequency = (unsigend long) freq;
+ } else {
+ config_perror("No parameter after -r given\n");
+ /*
+ * XXX: free StorageNew
+ */
+ return;
+ }
+ break;
+ case 'u':
+ if (cp) {
+ cp = copy_nword(cp, buf, sizeof(buf));
+ StorageNew->pdu_securityName = strdup(buf);
+ StorageNew->pdu_securityNameLen = strlen(buf);
+ } else {
+ config_perror("No parameter after -u given\n");
+ /*
+ * XXX: free StorageNew
+ */
+ return;
+ }
+ break;
+ case 'e':
+ if (cp) {
+ cp = copy_nword(cp, eventname, sizeof(eventname));
+ } else {
+ config_perror("No parameter after -e given\n");
+ /*
+ * XXX: free StorageNew
+ */
+ return;
+ }
+ break;
+ case 'o':
+ /*
+ * oid
+ */
+ cp = copy_nword(cp, buf, sizeof(buf));
+ obufLen = MAX_OID_LEN;
+ if (!snmp_parse_oid(buf, obuf, &obufLen)) {
+ netsnmp_config_error("unable to parse oid: %s", buf);
+ /*
+ * XXX: free StorageNew
+ */
+ return;
+ }
+ sprintf(buf, "snmpd.conf%d", monitor_call_count);
+ mte_add_object_to_table("snmpd.conf", buf, obuf, obufLen, 1);
+
+ if (StorageNew->mteTriggerObjectsOwnerLen == 0) {
+ SNMP_FREE(StorageNew->mteTriggerObjectsOwner);
+ StorageNew->mteTriggerObjectsOwner = strdup("snmpd.conf");
+ StorageNew->mteTriggerObjectsOwnerLen =
+ strlen("snmpd.conf");
+ }
+
+ if (StorageNew->mteTriggerObjectsLen == 0) {
+ SNMP_FREE(StorageNew->mteTriggerObjects);
+ StorageNew->mteTriggerObjects = strdup(buf);
+ StorageNew->mteTriggerObjectsLen = strlen(buf);
+ }
+ break;
+ }
+ }
+
+ if (StorageNew->pdu_securityNameLen == 0) {
+ char *mte_default_user =
+ netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_INTERNAL_SECNAME);
+ if (mte_default_user) {
+ StorageNew->pdu_securityName = strdup(mte_default_user);
+ StorageNew->pdu_securityNameLen = strlen(mte_default_user);
+ } else {
+ config_perror("-u USER parameter required\n");
+ /*
+ * XXX: free StorageNew
+ */
+ return;
+ }
+ }
+
+ /*
+ * name
+ */
+ cp = copy_nword(cp, buf, sizeof(buf));
+ if (!cp) {
+ config_perror("illegal monitor: no name specified");
+ /*
+ * XXX: free StorageNew
+ */
+ return;
+ }
+
+ StorageNew->mteTriggerName = strdup(buf);
+ StorageNew->mteTriggerNameLen = strlen(StorageNew->mteTriggerName);
+
+ /*
+ * oid
+ */
+ cp = copy_nword(cp, buf, sizeof(buf));
+ obufLen = MAX_OID_LEN;
+ if (!snmp_parse_oid(buf, obuf, &obufLen)) {
+ netsnmp_config_error("unable to parse oid: %s", buf);
+ /*
+ * XXX: free StorageNew
+ */
+ return;
+ }
+ if (StorageNew->mteTriggerValueID)
+ free(StorageNew->mteTriggerValueID);
+ StorageNew->mteTriggerValueID = snmp_duplicate_objid(obuf, obufLen);
+ StorageNew->mteTriggerValueIDLen = obufLen;
+
+ if (StorageNew->mteTriggerTest[0] == MTETRIGGERTEST_THRESHOLD) {
+ /*
+ * it's a threshold
+ * grab 'low' and 'high' params
+ */
+ if (!cp) {
+ config_perror("no lower threshold value specified");
+ }
+ cp = copy_nword(cp, buf, sizeof(buf));
+ StorageNew->mteTriggerThresholdFalling = strtol(buf, NULL, 0);
+
+ if (!cp) {
+ config_perror("no upper threshold value specified");
+ }
+ cp = copy_nword(cp, buf, sizeof(buf));
+ StorageNew->mteTriggerThresholdRising = strtol(buf, NULL, 0);
+ } else {
+ /*
+ * if nothing beyond here, it's an existence test
+ */
+ if (!cp) {
+ StorageNew->mteTriggerTest[0] = (u_char)MTETRIGGERTEST_EXISTENCE;
+ if (eventname[0] != '\0') {
+ StorageNew->mteTriggerExistenceEventOwner =
+ strdup("snmpd.conf");
+ StorageNew->mteTriggerExistenceEventOwnerLen =
+ strlen(StorageNew->mteTriggerExistenceEventOwner);
+ StorageNew->mteTriggerExistenceEvent =
+ strdup(eventname);
+ StorageNew->mteTriggerExistenceEventLen =
+ strlen(eventname);
+ }
+ mteTriggerTable_add(StorageNew);
+ return;
+ }
+
+ /*
+ * assume boolean (need to deal with threshold statements)
+ */
+ cp = copy_nword(cp, buf, sizeof(buf));
+ if ((StorageNew->mteTriggerBooleanComparison =
+ se_find_value_in_slist("mteBooleanOperators", buf)) == -1) {
+ config_perror("illegal boolean operator");
+ return;
+ }
+
+ /*
+ * XXX: add threshold
+ */
+ StorageNew->mteTriggerTest[0] = MTETRIGGERTEST_BOOLEAN;
+ if (!cp) {
+ config_perror("no comparison value specified");
+ /*
+ * XXX: free StorageNew
+ */
+ return;
+ }
+
+ cp = copy_nword(cp, buf, sizeof(buf));
+ StorageNew->mteTriggerBooleanValue = strtol(buf, NULL, 0);
+
+ if (eventname[0] != '\0') {
+ StorageNew->mteTriggerBooleanEventOwner =
+ strdup("snmpd.conf");
+ StorageNew->mteTriggerBooleanEventOwnerLen =
+ strlen(StorageNew->mteTriggerBooleanEventOwner);
+ StorageNew->mteTriggerBooleanEvent =
+ strdup(eventname);
+ StorageNew->mteTriggerBooleanEventLen =
+ strlen(eventname);
+ }
+ }
+ mteTriggerTable_add(StorageNew);
+ mte_enable_trigger(StorageNew);
+
+ DEBUGMSGTL(("mteTriggerTable", "added simple monitor: %s\n",
+ StorageNew->mteTriggerName));
+} /* parse_simple_monitor */
+
+
+/*
+ * parse_mteTriggerTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+void
+parse_mteTriggerTable(const char *token, char *line)
+{
+ size_t tmpint;
+ oid *tmpoid = NULL;
+ struct mteTriggerTable_data *StorageTmp =
+ SNMP_MALLOC_STRUCT(mteTriggerTable_data);
+
+ DEBUGMSGTL(("mteTriggerTable", "parsing config... "));
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line, &StorageTmp->mteOwner,
+ &StorageTmp->mteOwnerLen);
+ if (StorageTmp->mteOwner == NULL) {
+ config_perror("invalid specification for mteOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerName,
+ &StorageTmp->mteTriggerNameLen);
+ if (StorageTmp->mteTriggerName == NULL) {
+ config_perror("invalid specification for mteTriggerName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerComment,
+ &StorageTmp->mteTriggerCommentLen);
+ if (StorageTmp->mteTriggerComment == NULL) {
+ config_perror("invalid specification for mteTriggerComment");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerTest,
+ &StorageTmp->mteTriggerTestLen);
+ if (StorageTmp->mteTriggerTest == NULL) {
+ config_perror("invalid specification for mteTriggerTest");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerSampleType, &tmpint);
+
+ line =
+ read_config_read_data(ASN_OBJECT_ID, line,
+ &StorageTmp->mteTriggerValueID,
+ &StorageTmp->mteTriggerValueIDLen);
+ if (StorageTmp->mteTriggerValueID == NULL) {
+ config_perror("invalid specification for mteTriggerValueID");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerValueIDWildcard,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerTargetTag,
+ &StorageTmp->mteTriggerTargetTagLen);
+ if (StorageTmp->mteTriggerTargetTag == NULL) {
+ config_perror("invalid specification for mteTriggerTargetTag");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerContextName,
+ &StorageTmp->mteTriggerContextNameLen);
+ if (StorageTmp->mteTriggerContextName == NULL) {
+ config_perror("invalid specification for mteTriggerContextName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerContextNameWildcard,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->mteTriggerFrequency, &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerObjectsOwner,
+ &StorageTmp->mteTriggerObjectsOwnerLen);
+ if (StorageTmp->mteTriggerObjectsOwner == NULL) {
+ config_perror("invalid specification for mteTriggerObjectsOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerObjects,
+ &StorageTmp->mteTriggerObjectsLen);
+ if (StorageTmp->mteTriggerObjects == NULL) {
+ config_perror("invalid specification for mteTriggerObjects");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerEnabled, &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerEntryStatus, &tmpint);
+
+ /*
+ * delta table
+ */
+ line =
+ read_config_read_data(ASN_OBJECT_ID, line,
+ &StorageTmp->mteTriggerDeltaDiscontinuityID,
+ &StorageTmp->
+ mteTriggerDeltaDiscontinuityIDLen);
+ if (StorageTmp->mteTriggerDeltaDiscontinuityID == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerDeltaDiscontinuityID");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->
+ mteTriggerDeltaDiscontinuityIDWildcard,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->
+ mteTriggerDeltaDiscontinuityIDType, &tmpint);
+
+ /*
+ * existence table
+ */
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerExistenceTest,
+ &StorageTmp->mteTriggerExistenceTestLen);
+ if (StorageTmp->mteTriggerExistenceTest == NULL) {
+ config_perror("invalid specification for mteTriggerExistenceTest");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerExistenceStartup,
+ &StorageTmp->mteTriggerExistenceStartupLen);
+ if (StorageTmp->mteTriggerExistenceStartup == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerExistenceStartup");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerExistenceObjectsOwner,
+ &StorageTmp->
+ mteTriggerExistenceObjectsOwnerLen);
+ if (StorageTmp->mteTriggerExistenceObjectsOwner == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerExistenceObjectsOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerExistenceObjects,
+ &StorageTmp->mteTriggerExistenceObjectsLen);
+ if (StorageTmp->mteTriggerExistenceObjects == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerExistenceObjects");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerExistenceEventOwner,
+ &StorageTmp->
+ mteTriggerExistenceEventOwnerLen);
+ if (StorageTmp->mteTriggerExistenceEventOwner == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerExistenceEventOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerExistenceEvent,
+ &StorageTmp->mteTriggerExistenceEventLen);
+ if (StorageTmp->mteTriggerExistenceEvent == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerExistenceEvent");
+ return;
+ }
+
+ /*
+ * boolean table
+ */
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerBooleanComparison,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerBooleanValue,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerBooleanStartup,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerBooleanObjectsOwner,
+ &StorageTmp->
+ mteTriggerBooleanObjectsOwnerLen);
+ if (StorageTmp->mteTriggerBooleanObjectsOwner == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerBooleanObjectsOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerBooleanObjects,
+ &StorageTmp->mteTriggerBooleanObjectsLen);
+ if (StorageTmp->mteTriggerBooleanObjects == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerBooleanObjects");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerBooleanEventOwner,
+ &StorageTmp->mteTriggerBooleanEventOwnerLen);
+ if (StorageTmp->mteTriggerBooleanEventOwner == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerBooleanEventOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerBooleanEvent,
+ &StorageTmp->mteTriggerBooleanEventLen);
+ if (StorageTmp->mteTriggerBooleanEvent == NULL) {
+ config_perror("invalid specification for mteTriggerBooleanEvent");
+ return;
+ }
+
+ /*
+ * threshold table
+ */
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerThresholdStartup,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerThresholdRising,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerThresholdFalling,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerThresholdDeltaRising,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->mteTriggerThresholdDeltaFalling,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerThresholdObjectsOwner,
+ &StorageTmp->
+ mteTriggerThresholdObjectsOwnerLen);
+ if (StorageTmp->mteTriggerThresholdObjectsOwner == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerThresholdObjectsOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerThresholdObjects,
+ &StorageTmp->mteTriggerThresholdObjectsLen);
+ if (StorageTmp->mteTriggerThresholdObjects == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerThresholdObjects");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->
+ mteTriggerThresholdRisingEventOwner,
+ &StorageTmp->
+ mteTriggerThresholdRisingEventOwnerLen);
+ if (StorageTmp->mteTriggerThresholdRisingEventOwner == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerThresholdRisingEventOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerThresholdRisingEvent,
+ &StorageTmp->
+ mteTriggerThresholdRisingEventLen);
+ if (StorageTmp->mteTriggerThresholdRisingEvent == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerThresholdRisingEvent");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->
+ mteTriggerThresholdFallingEventOwner,
+ &StorageTmp->
+ mteTriggerThresholdFallingEventOwnerLen);
+ if (StorageTmp->mteTriggerThresholdFallingEventOwner == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerThresholdFallingEventOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->mteTriggerThresholdFallingEvent,
+ &StorageTmp->
+ mteTriggerThresholdFallingEventLen);
+ if (StorageTmp->mteTriggerThresholdFallingEvent == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerThresholdFallingEvent");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->
+ mteTriggerThresholdDeltaRisingEventOwner,
+ &StorageTmp->
+ mteTriggerThresholdDeltaRisingEventOwnerLen);
+ if (StorageTmp->mteTriggerThresholdDeltaRisingEventOwner == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerThresholdDeltaRisingEventOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->
+ mteTriggerThresholdDeltaRisingEvent,
+ &StorageTmp->
+ mteTriggerThresholdDeltaRisingEventLen);
+ if (StorageTmp->mteTriggerThresholdDeltaRisingEvent == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerThresholdDeltaRisingEvent");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->
+ mteTriggerThresholdDeltaFallingEventOwner,
+ &StorageTmp->
+ mteTriggerThresholdDeltaFallingEventOwnerLen);
+ if (StorageTmp->mteTriggerThresholdDeltaFallingEventOwner == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerThresholdDeltaFallingEventOwner");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->
+ mteTriggerThresholdDeltaFallingEvent,
+ &StorageTmp->
+ mteTriggerThresholdDeltaFallingEventLen);
+ if (StorageTmp->mteTriggerThresholdDeltaFallingEvent == NULL) {
+ config_perror
+ ("invalid specification for mteTriggerThresholdDeltaFallingEvent");
+ return;
+ }
+
+ /*
+ * local internal variables
+ */
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->have_copied_auth_info, &tmpint);
+ if (StorageTmp->have_copied_auth_info) {
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pdu_version, &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pdu_securityModel, &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pdu_securityLevel, &tmpint);
+ line =
+ read_config_read_data(ASN_OBJECT_ID, line, &tmpoid, &tmpint);
+ if (!netsnmp_tdomain_support
+ (tmpoid, tmpint, &StorageTmp->pdu_tDomain,
+ &StorageTmp->pdu_tDomainLen)) {
+ config_perror
+ ("unsupported transport domain for mteTriggerEntry");
+ return;
+ }
+ if (tmpoid != NULL) {
+ free(tmpoid);
+ }
+
+ /*
+ * can be NULL? Yes.
+ */
+ line = read_config_read_data(ASN_OCTET_STR, line,
+ &(StorageTmp->pdu_transport),
+ &StorageTmp->pdu_transportLen);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pdu_community,
+ &StorageTmp->pdu_community_len);
+ if (StorageTmp->pdu_community == NULL) {
+ config_perror("invalid specification for pdu_community");
+ return;
+ }
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pdu_securityName,
+ &StorageTmp->pdu_securityNameLen);
+ if (StorageTmp->pdu_securityName == NULL) {
+ config_perror("invalid specification for pdu_securityName");
+ return;
+ }
+ }
+ StorageTmp->storageType = ST_NONVOLATILE; /* the only type stored */
+
+ mteTriggerTable_add(StorageTmp);
+
+ /*
+ * technically this is too early
+ */
+ if (StorageTmp->mteTriggerEnabled == MTETRIGGERENABLED_TRUE &&
+ StorageTmp->mteTriggerEntryStatus == RS_ACTIVE)
+ mte_enable_trigger(StorageTmp);
+
+ DEBUGMSGTL(("mteTriggerTable", "done.\n"));
+} /* parse_mteTriggerTable */
+
+
+/*
+ * store_mteTriggerTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+int
+store_mteTriggerTable(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr;
+ size_t tmpint;
+ struct mteTriggerTable_data *StorageTmp;
+ struct header_complex_index *hcindex;
+
+ DEBUGMSGTL(("mteTriggerTable", "storing data... "));
+
+ for (hcindex = mteTriggerTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct mteTriggerTable_data *) hcindex->data;
+
+
+ if (StorageTmp->storageType == ST_NONVOLATILE) {
+
+ memset(line, 0, sizeof(line));
+ strcat(line, "mteTriggerTable ");
+ cptr = line + strlen(line);
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->mteOwner,
+ &StorageTmp->mteOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->mteTriggerName,
+ &StorageTmp->mteTriggerNameLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->mteTriggerComment,
+ &StorageTmp->mteTriggerCommentLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->mteTriggerTest,
+ &StorageTmp->mteTriggerTestLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->mteTriggerSampleType,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OBJECT_ID, cptr,
+ &StorageTmp->mteTriggerValueID,
+ &StorageTmp->mteTriggerValueIDLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ mteTriggerValueIDWildcard, &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->mteTriggerTargetTag,
+ &StorageTmp->
+ mteTriggerTargetTagLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->mteTriggerContextName,
+ &StorageTmp->
+ mteTriggerContextNameLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ mteTriggerContextNameWildcard,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->mteTriggerFrequency,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->mteTriggerObjectsOwner,
+ &StorageTmp->
+ mteTriggerObjectsOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->mteTriggerObjects,
+ &StorageTmp->mteTriggerObjectsLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->mteTriggerEnabled,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->mteTriggerEntryStatus,
+ &tmpint);
+
+ /*
+ * delta table
+ */
+ cptr =
+ read_config_store_data(ASN_OBJECT_ID, cptr,
+ &StorageTmp->
+ mteTriggerDeltaDiscontinuityID,
+ &StorageTmp->
+ mteTriggerDeltaDiscontinuityIDLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ mteTriggerDeltaDiscontinuityIDWildcard,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ mteTriggerDeltaDiscontinuityIDType,
+ &tmpint);
+
+ /*
+ * existence table
+ */
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerExistenceTest,
+ &StorageTmp->
+ mteTriggerExistenceTestLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerExistenceStartup,
+ &StorageTmp->
+ mteTriggerExistenceStartupLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerExistenceObjectsOwner,
+ &StorageTmp->
+ mteTriggerExistenceObjectsOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerExistenceObjects,
+ &StorageTmp->
+ mteTriggerExistenceObjectsLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerExistenceEventOwner,
+ &StorageTmp->
+ mteTriggerExistenceEventOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerExistenceEvent,
+ &StorageTmp->
+ mteTriggerExistenceEventLen);
+
+ /*
+ * boolean table
+ */
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ mteTriggerBooleanComparison,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->mteTriggerBooleanValue,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ mteTriggerBooleanStartup, &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerBooleanObjectsOwner,
+ &StorageTmp->
+ mteTriggerBooleanObjectsOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerBooleanObjects,
+ &StorageTmp->
+ mteTriggerBooleanObjectsLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerBooleanEventOwner,
+ &StorageTmp->
+ mteTriggerBooleanEventOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->mteTriggerBooleanEvent,
+ &StorageTmp->
+ mteTriggerBooleanEventLen);
+
+ /*
+ * threshold table
+ */
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ mteTriggerThresholdStartup,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ mteTriggerThresholdRising, &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ mteTriggerThresholdFalling,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ mteTriggerThresholdDeltaRising,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ mteTriggerThresholdDeltaFalling,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerThresholdObjectsOwner,
+ &StorageTmp->
+ mteTriggerThresholdObjectsOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerThresholdObjects,
+ &StorageTmp->
+ mteTriggerThresholdObjectsLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerThresholdRisingEventOwner,
+ &StorageTmp->
+ mteTriggerThresholdRisingEventOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerThresholdRisingEvent,
+ &StorageTmp->
+ mteTriggerThresholdRisingEventLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerThresholdFallingEventOwner,
+ &StorageTmp->
+ mteTriggerThresholdFallingEventOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerThresholdFallingEvent,
+ &StorageTmp->
+ mteTriggerThresholdFallingEventLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerThresholdDeltaRisingEventOwner,
+ &StorageTmp->
+ mteTriggerThresholdDeltaRisingEventOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerThresholdDeltaRisingEvent,
+ &StorageTmp->
+ mteTriggerThresholdDeltaRisingEventLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerThresholdDeltaFallingEventOwner,
+ &StorageTmp->
+ mteTriggerThresholdDeltaFallingEventOwnerLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ mteTriggerThresholdDeltaFallingEvent,
+ &StorageTmp->
+ mteTriggerThresholdDeltaFallingEventLen);
+
+ /*
+ * local internal variables
+ */
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->have_copied_auth_info,
+ &tmpint);
+ if (StorageTmp->have_copied_auth_info) {
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pdu_version,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pdu_securityModel,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pdu_securityLevel,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OBJECT_ID, cptr,
+ (void *)(&StorageTmp->pdu_tDomain),
+ &StorageTmp->pdu_tDomainLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pdu_transport,
+ &StorageTmp->pdu_transportLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pdu_community,
+ &StorageTmp->pdu_community_len);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pdu_securityName,
+ &StorageTmp->
+ pdu_securityNameLen);
+ }
+
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("mteTriggerTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+
+
+/*
+ * var_mteTriggerTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_mteTriggerTable above.
+ */
+unsigned char *
+var_mteTriggerTable(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact,
+ size_t * var_len, WriteMethod ** write_method)
+{
+
+
+ struct mteTriggerTable_data *StorageTmp = NULL;
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "var_mteTriggerTable: Entering... \n"));
+
+ /* set default value */
+ *write_method = NULL;
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL) {
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ if (vp->magic == MTETRIGGERENTRYSTATUS)
+ *write_method = write_mteTriggerEntryStatus;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ return NULL;
+ }
+
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+
+
+ case MTETRIGGERCOMMENT:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerComment;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerCommentLen;
+ return (u_char *) StorageTmp->mteTriggerComment;
+
+ case MTETRIGGERTEST:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerTest;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerTestLen;
+ return (u_char *) StorageTmp->mteTriggerTest;
+
+ case MTETRIGGERSAMPLETYPE:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerSampleType;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerSampleType);
+ return (u_char *) & StorageTmp->mteTriggerSampleType;
+
+ case MTETRIGGERVALUEID:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerValueID;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerValueIDLen * sizeof(oid);
+ return (u_char *) StorageTmp->mteTriggerValueID;
+
+ case MTETRIGGERVALUEIDWILDCARD:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerValueIDWildcard;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerValueIDWildcard);
+ return (u_char *) & StorageTmp->mteTriggerValueIDWildcard;
+
+ case MTETRIGGERTARGETTAG:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerTargetTag;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerTargetTagLen;
+ return (u_char *) StorageTmp->mteTriggerTargetTag;
+
+ case MTETRIGGERCONTEXTNAME:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerContextName;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerContextNameLen;
+ return (u_char *) StorageTmp->mteTriggerContextName;
+
+ case MTETRIGGERCONTEXTNAMEWILDCARD:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerContextNameWildcard;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerContextNameWildcard);
+ return (u_char *) & StorageTmp->mteTriggerContextNameWildcard;
+
+ case MTETRIGGERFREQUENCY:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerFrequency;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerFrequency);
+ return (u_char *) & StorageTmp->mteTriggerFrequency;
+
+ case MTETRIGGEROBJECTSOWNER:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerObjectsOwner;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerObjectsOwnerLen;
+ return (u_char *) StorageTmp->mteTriggerObjectsOwner;
+
+ case MTETRIGGEROBJECTS:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerObjects;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerObjectsLen;
+ return (u_char *) StorageTmp->mteTriggerObjects;
+
+ case MTETRIGGERENABLED:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerEnabled;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerEnabled);
+ return (u_char *) & StorageTmp->mteTriggerEnabled;
+
+ case MTETRIGGERENTRYSTATUS:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerEntryStatus;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerEntryStatus);
+ return (u_char *) & StorageTmp->mteTriggerEntryStatus;
+
+
+ default:
+ ERROR_MSG("");
+ }
+ return NULL;
+}
+
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+int
+write_mteTriggerComment(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "write_mteTriggerComment entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to mteTriggerComment not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerComment;
+ tmplen = StorageTmp->mteTriggerCommentLen;
+ memdup((u_char **) & StorageTmp->mteTriggerComment, var_val,
+ var_val_len);
+ StorageTmp->mteTriggerCommentLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerComment);
+ StorageTmp->mteTriggerComment = tmpvar;
+ StorageTmp->mteTriggerCommentLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerComment */
+
+
+
+int
+write_mteTriggerTest(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "write_mteTriggerTest entering action=%d... \n", action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR, "write to mteTriggerTest not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerTest;
+ tmplen = StorageTmp->mteTriggerTestLen;
+ memdup((u_char **) & StorageTmp->mteTriggerTest, var_val,
+ var_val_len);
+ StorageTmp->mteTriggerTestLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerTest);
+ StorageTmp->mteTriggerTest = tmpvar;
+ StorageTmp->mteTriggerTestLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerTest */
+
+
+
+int
+write_mteTriggerSampleType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "write_mteTriggerSampleType entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to mteTriggerSampleType not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerSampleType;
+ StorageTmp->mteTriggerSampleType = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerSampleType = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerSampleType */
+
+
+
+int
+write_mteTriggerValueID(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static oid *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "write_mteTriggerValueID entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OBJECT_ID) {
+ snmp_log(LOG_ERR,
+ "write to mteTriggerValueID not ASN_OBJECT_ID\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerValueID;
+ tmplen = StorageTmp->mteTriggerValueIDLen;
+ memdup((u_char **) & StorageTmp->mteTriggerValueID, var_val,
+ var_val_len);
+ StorageTmp->mteTriggerValueIDLen = var_val_len / sizeof(oid);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerValueID);
+ StorageTmp->mteTriggerValueID = tmpvar;
+ StorageTmp->mteTriggerValueIDLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ /*
+ * XXX: if the valueID has actually changed, shouldn't we dump any
+ * previous values, as these are from a different object?
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerValueID */
+
+
+
+int
+write_mteTriggerValueIDWildcard(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "write_mteTriggerValueIDWildcard entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to mteTriggerValueIDWildcard not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerValueIDWildcard;
+ StorageTmp->mteTriggerValueIDWildcard = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerValueIDWildcard = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerValueIDWildcard */
+
+
+
+int
+write_mteTriggerTargetTag(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "write_mteTriggerTargetTag entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to mteTriggerTargetTag not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerTargetTag;
+ tmplen = StorageTmp->mteTriggerTargetTagLen;
+ memdup((u_char **) & StorageTmp->mteTriggerTargetTag, var_val,
+ var_val_len);
+ StorageTmp->mteTriggerTargetTagLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerTargetTag);
+ StorageTmp->mteTriggerTargetTag = tmpvar;
+ StorageTmp->mteTriggerTargetTagLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerTargetTag */
+
+
+
+int
+write_mteTriggerContextName(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "write_mteTriggerContextName entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to mteTriggerContextName not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerContextName;
+ tmplen = StorageTmp->mteTriggerContextNameLen;
+ memdup((u_char **) & StorageTmp->mteTriggerContextName, var_val,
+ var_val_len);
+ StorageTmp->mteTriggerContextNameLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerContextName);
+ StorageTmp->mteTriggerContextName = tmpvar;
+ StorageTmp->mteTriggerContextNameLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerContextName */
+
+
+
+int
+write_mteTriggerContextNameWildcard(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "write_mteTriggerContextNameWildcard entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to mteTriggerContextNameWildcard not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerContextNameWildcard;
+ StorageTmp->mteTriggerContextNameWildcard = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerContextNameWildcard = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerContextNameWildcard */
+
+
+
+int
+write_mteTriggerFrequency(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "write_mteTriggerFrequency entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to mteTriggerFrequency not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in ulong_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerFrequency;
+ StorageTmp->mteTriggerFrequency = *((unsigned long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerFrequency = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ if (StorageTmp->mteTriggerEnabled == MTETRIGGERENABLED_TRUE &&
+ StorageTmp->mteTriggerEntryStatus == RS_ACTIVE)
+ mte_enable_trigger(StorageTmp);
+
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerFrequency */
+
+
+
+int
+write_mteTriggerObjectsOwner(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "write_mteTriggerObjectsOwner entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to mteTriggerObjectsOwner not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerObjectsOwner;
+ tmplen = StorageTmp->mteTriggerObjectsOwnerLen;
+ memdup((u_char **) & StorageTmp->mteTriggerObjectsOwner, var_val,
+ var_val_len);
+ StorageTmp->mteTriggerObjectsOwnerLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerObjectsOwner);
+ StorageTmp->mteTriggerObjectsOwner = tmpvar;
+ StorageTmp->mteTriggerObjectsOwnerLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerObjectsOwner */
+
+
+
+int
+write_mteTriggerObjects(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "write_mteTriggerObjects entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to mteTriggerObjects not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerObjects;
+ tmplen = StorageTmp->mteTriggerObjectsLen;
+ memdup((u_char **) & StorageTmp->mteTriggerObjects, var_val,
+ var_val_len);
+ StorageTmp->mteTriggerObjectsLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerObjects);
+ StorageTmp->mteTriggerObjects = tmpvar;
+ StorageTmp->mteTriggerObjectsLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerObjects */
+
+
+
+int
+write_mteTriggerEnabled(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "write_mteTriggerEnabled entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to mteTriggerEnabled not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerEnabled;
+ StorageTmp->mteTriggerEnabled = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerEnabled = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ if (StorageTmp->mteTriggerEnabled == MTETRIGGERENABLED_TRUE &&
+ StorageTmp->mteTriggerEntryStatus == RS_ACTIVE)
+ mte_enable_trigger(StorageTmp);
+ else if (StorageTmp->mteTriggerEnabled == MTETRIGGERENABLED_FALSE)
+ mte_disable_trigger(StorageTmp);
+
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerEnabled */
+
+
+
+int
+write_mteTriggerEntryStatus(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static struct mteTriggerTable_data *StorageNew, *StorageDel;
+ size_t newlen =
+ name_len - (sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+ static int old_value;
+ int set_value;
+ static netsnmp_variable_list *vars, *vp;
+ struct header_complex_index *hciptr;
+
+ StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof(mteTriggerTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL, NULL);
+
+
+
+
+ if (var_val_type != ASN_INTEGER || var_val == NULL) {
+ snmp_log(LOG_ERR,
+ "write to mteTriggerEntryStatus not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ set_value = *((long *) var_val);
+
+
+ /*
+ * check legal range, and notReady is reserved for us, not a user
+ */
+ if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY)
+ return SNMP_ERR_INCONSISTENTVALUE;
+
+
+ switch (action) {
+ case RESERVE1:
+ /*
+ * stage one: test validity
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * create the row now?
+ */
+
+
+ /*
+ * ditch illegal values now
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE)
+ return SNMP_ERR_INCONSISTENTVALUE;
+
+
+ /*
+ * destroying a non-existent row is actually legal
+ */
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+
+
+ /*
+ * illegal creation values
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ } else {
+ /*
+ * row exists. Check for a valid state change
+ */
+ if (set_value == RS_CREATEANDGO
+ || set_value == RS_CREATEANDWAIT) {
+ /*
+ * can't create a row that exists
+ */
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+
+ if (StorageTmp->mteTriggerEntryStatus == RS_ACTIVE &&
+ set_value != RS_DESTROY) {
+ /*
+ * "Once made active an entry may not be modified except to
+ * delete it." XXX: doesn't this in fact apply to ALL
+ * columns of the table and not just this one?
+ */
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ break;
+
+
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * creation
+ */
+ vars = NULL;
+
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* mteOwner */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_PRIV_IMPLIED_OCTET_STR, NULL, 0); /* mteTriggerName */
+
+
+
+ if (header_complex_parse_oid
+ (&
+ (name
+ [sizeof(mteTriggerTable_variables_oid) / sizeof(oid) +
+ 2]), newlen, vars) != SNMPERR_SUCCESS) {
+ /*
+ * XXX: free, zero vars
+ */
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+ vp = vars;
+
+
+ StorageNew = create_mteTriggerTable_data();
+
+ StorageNew->mteOwner = malloc(vp->val_len + 1);
+ memcpy(StorageNew->mteOwner, vp->val.string, vp->val_len);
+ StorageNew->mteOwner[vp->val_len] = '\0';
+ StorageNew->mteOwnerLen = vp->val_len;
+
+ vp = vp->next_variable;
+ StorageNew->mteTriggerName = malloc(vp->val_len + 1);
+ memcpy(StorageNew->mteTriggerName, vp->val.string,
+ vp->val_len);
+ StorageNew->mteTriggerName[vp->val_len] = '\0';
+ StorageNew->mteTriggerNameLen = vp->val_len;
+
+ vp = vp->next_variable;
+
+ StorageNew->mteTriggerEntryStatus = set_value;
+
+ }
+
+
+ break;
+
+
+
+
+ case FREE:
+ /*
+ * XXX: free, zero vars
+ */
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in set_value for you to
+ * use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in
+ * the UNDO case
+ */
+
+
+ if (StorageTmp == NULL) {
+ /*
+ * row creation, so add it
+ */
+ if (StorageNew != NULL)
+ mteTriggerTable_add(StorageNew);
+ /*
+ * XXX: ack, and if it is NULL?
+ */
+ } else if (set_value != RS_DESTROY) {
+ /*
+ * set the flag?
+ */
+ old_value = StorageTmp->mteTriggerEntryStatus;
+ StorageTmp->mteTriggerEntryStatus = *((long *) var_val);
+ } else {
+ /*
+ * destroy... extract it for now
+ */
+ hciptr =
+ header_complex_find_entry(mteTriggerTableStorage,
+ StorageTmp);
+ StorageDel =
+ header_complex_extract_entry(&mteTriggerTableStorage,
+ hciptr);
+ }
+ break;
+
+
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * row creation, so remove it again
+ */
+ hciptr =
+ header_complex_find_entry(mteTriggerTableStorage,
+ StorageTmp);
+ StorageDel =
+ header_complex_extract_entry(&mteTriggerTableStorage,
+ hciptr);
+ /*
+ * XXX: free it
+ */
+ } else if (StorageDel != NULL) {
+ /*
+ * row deletion, so add it again
+ */
+ mteTriggerTable_add(StorageDel);
+ } else {
+ StorageTmp->mteTriggerEntryStatus = old_value;
+ }
+ break;
+
+
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ if (StorageDel != NULL) {
+ mte_disable_trigger(StorageDel);
+ StorageDel = 0;
+ /*
+ * XXX: free it, its dead
+ */
+ } else {
+ if (StorageTmp
+ && StorageTmp->mteTriggerEntryStatus == RS_CREATEANDGO) {
+ StorageTmp->mteTriggerEntryStatus = RS_ACTIVE;
+ } else if (StorageTmp &&
+ StorageTmp->mteTriggerEntryStatus ==
+ RS_CREATEANDWAIT) {
+ StorageTmp->mteTriggerEntryStatus = RS_NOTINSERVICE;
+ }
+ }
+ if (StorageTmp &&
+ StorageTmp->mteTriggerEntryStatus == RS_ACTIVE &&
+ !StorageTmp->have_copied_auth_info) {
+
+ netsnmp_agent_session *asp =
+ netsnmp_get_current_agent_session();
+ netsnmp_pdu *pdu = NULL;
+
+ if (!asp) {
+ snmp_log(LOG_ERR,
+ "snmpTriggerTable: can't get master session for authentication params\n");
+ } else {
+ pdu = asp->orig_pdu;
+ if (!pdu) {
+ snmp_log(LOG_ERR,
+ "snmpTriggerTable: can't get master pdu for authentication params\n");
+ }
+ }
+
+ if (pdu) {
+ DEBUGMSGTL(("mteTriggerTest", "copying PDU auth info\n"));
+ StorageTmp->pdu_version = pdu->version;
+ StorageTmp->pdu_securityModel = pdu->securityModel;
+ StorageTmp->pdu_securityLevel = pdu->securityLevel;
+ StorageTmp->pdu_tDomain = pdu->tDomain;
+ StorageTmp->pdu_tDomainLen = pdu->tDomainLen;
+ if (pdu->transport_data != NULL) {
+ StorageTmp->pdu_transport =
+ malloc(pdu->transport_data_length);
+ memcpy(StorageTmp->pdu_transport, pdu->transport_data,
+ pdu->transport_data_length);
+ }
+ StorageTmp->pdu_transportLen = pdu->transport_data_length;
+ if (pdu->community) {
+ StorageTmp->pdu_community =
+ calloc(1, pdu->community_len + 1);
+ memcpy(StorageTmp->pdu_community, pdu->community,
+ pdu->community_len);
+ StorageTmp->pdu_community_len = pdu->community_len;
+ } else {
+ StorageTmp->pdu_community = NULL;
+ StorageTmp->pdu_community_len = 0;
+ }
+ if (pdu->securityName) {
+ StorageTmp->pdu_securityName =
+ calloc(1, pdu->securityNameLen + 1);
+ memcpy(StorageTmp->pdu_securityName, pdu->securityName,
+ pdu->securityNameLen);
+ StorageTmp->pdu_securityNameLen = pdu->securityNameLen;
+ } else {
+ StorageTmp->pdu_securityName = NULL;
+ StorageTmp->pdu_securityNameLen = 0;
+ }
+ StorageTmp->have_copied_auth_info = 1;
+ }
+ }
+
+ if (StorageTmp &&
+ StorageTmp->mteTriggerEnabled == MTETRIGGERENABLED_TRUE &&
+ StorageTmp->mteTriggerEntryStatus == RS_ACTIVE)
+ mte_enable_trigger(StorageTmp);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+} /* write_mteTriggerEntryStatus */
+
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+
+
+/*
+ * send trap
+ */
+void
+send_mte_trap(struct mteTriggerTable_data *item,
+ oid * trap_oid, size_t trap_oid_len,
+ oid * name_oid, size_t name_oid_len,
+ long *value, const char *objowner, const char *objname,
+ const char *reason)
+{
+ static oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; /* snmpTrapIOD.0 */
+
+ netsnmp_variable_list *var_list = NULL;
+
+ /*
+ * snmpTrap oid
+ */
+ snmp_varlist_add_variable(&var_list, objid_snmptrap,
+ sizeof(objid_snmptrap) / sizeof(oid),
+ ASN_OBJECT_ID, (u_char *) trap_oid,
+ trap_oid_len * sizeof(oid));
+
+ /*
+ * mteHotTrigger
+ */
+ snmp_varlist_add_variable(&var_list, mteHotTrigger,
+ sizeof(mteHotTrigger) / sizeof(oid),
+ ASN_OCTET_STR,
+ (u_char *) item->mteTriggerName,
+ item->mteTriggerNameLen);
+
+ /*
+ * mteHotTargetName
+ */
+ snmp_varlist_add_variable(&var_list, mteHotTargetName, sizeof(mteHotTargetName) / sizeof(oid), ASN_OCTET_STR, (u_char *) item->mteTriggerTargetTag, /*XXX: targetName,not tag */
+ item->mteTriggerTargetTagLen); /*XXX */
+
+ /*
+ * mteHotContextName
+ */
+ snmp_varlist_add_variable(&var_list, mteHotContextName,
+ sizeof(mteHotContextName) / sizeof(oid),
+ ASN_OCTET_STR,
+ (u_char *) item->mteTriggerContextName,
+ item->mteTriggerContextNameLen);
+
+ snmp_varlist_add_variable(&var_list, mteHotOID,
+ sizeof(mteHotOID) / sizeof(oid),
+ ASN_OBJECT_ID, (u_char *) name_oid,
+ sizeof(oid) * name_oid_len);
+
+ if (trap_oid == mteTriggerFailure || trap_oid == mteEventSetFailure) {
+ /*
+ * mteFailedReason
+ */
+ snmp_varlist_add_variable(&var_list, mteFailedReason,
+ sizeof(mteFailedReason) / sizeof(oid),
+ ASN_INTEGER, (u_char *) value,
+ sizeof(value));
+ } else {
+ /*
+ * mteHotValue
+ */
+ snmp_varlist_add_variable(&var_list, mteHotValue,
+ sizeof(mteHotValue) / sizeof(oid),
+ ASN_INTEGER, (u_char *) value,
+ sizeof(value));
+ }
+
+ /*
+ * add in traps from main table
+ */
+ mte_add_objects(var_list, item, item->mteTriggerObjectsOwner,
+ item->mteTriggerObjects,
+ name_oid + item->mteTriggerValueIDLen,
+ name_oid_len - item->mteTriggerValueIDLen);
+ /*
+ * add in traps from sub table
+ */
+ mte_add_objects(var_list, item, objowner, objname,
+ name_oid + item->mteTriggerValueIDLen,
+ name_oid_len - item->mteTriggerValueIDLen);
+
+ /*
+ * XXX: stuff based on event table
+ */
+ DEBUGMSGTL(("mteTriggerTest:send_mte_trap", "sending the trap (%s): ",
+ reason));
+ DEBUGMSGOID(("mteTriggerTest:send_mte_trap", name_oid, name_oid_len));
+ DEBUGMSG(("mteTriggerTest:send_mte_trap", " = %ld\n", *value));
+
+ send_v2trap(var_list);
+ snmp_free_varbind(var_list);
+} /* send_mte_trap */
+
+
+void
+last_state_clean(void *data)
+{
+ struct last_state *cleanme = (struct last_state *) data;
+ SNMP_FREE(cleanme->value);
+ SNMP_FREE(cleanme);
+}
+
+
+/*
+ * retrieves requested info in pdu from the current target
+ */
+netsnmp_pdu *
+mte_get_response(struct mteTriggerTable_data *item, netsnmp_pdu *pdu)
+{
+ netsnmp_pdu *response = NULL;
+ int status = 0;
+ char buf[SPRINT_MAX_LEN];
+
+ /*
+ * local agent check
+ */
+ pdu->errstat = SNMPERR_SUCCESS;
+ pdu->errindex = 0;
+ pdu->version = item->pdu_version;
+ pdu->securityModel = item->pdu_securityModel;
+ pdu->securityLevel = item->pdu_securityLevel;
+ pdu->tDomain = item->pdu_tDomain;
+ pdu->tDomainLen = item->pdu_tDomainLen;
+ memdup((u_char **) & pdu->transport_data, item->pdu_transport,
+ item->pdu_transportLen);
+ pdu->transport_data_length = item->pdu_transportLen;
+ memdup(&pdu->community, item->pdu_community, item->pdu_community_len);
+ pdu->community_len = item->pdu_community_len;
+ memdup((u_char **) & pdu->contextName, item->mteTriggerContextName,
+ item->mteTriggerContextNameLen);
+ pdu->contextNameLen = item->mteTriggerContextNameLen;
+ memdup((u_char **) & pdu->securityName, item->pdu_securityName,
+ item->pdu_securityNameLen);
+ pdu->securityNameLen = item->pdu_securityNameLen;
+ DEBUGMSGTL(("mteTriggerTable",
+ "accessing locally with secName \"%s\" community \"%s\"\n",
+ item->pdu_securityName ? (char *) item->
+ pdu_securityName : "[NIL]",
+ item->pdu_community ? (char *) item->
+ pdu_community : "[NIL]"));
+
+ if (item->mteTriggerTargetTagLen == 0) {
+ /*
+ * send to the local agent
+ */
+
+ if (mte_callback_sess == NULL)
+ mte_callback_sess = netsnmp_query_get_default_session();
+ if (!mte_callback_sess)
+ return NULL;
+
+ status = snmp_synch_response(mte_callback_sess, pdu, &response);
+
+ if (status != SNMP_ERR_NOERROR ||
+ response->errstat != SNMP_ERR_NOERROR) {
+ /*
+ * xxx
+ */
+ char *errstr;
+ snmp_error(mte_callback_sess, 0, 0, &errstr);
+ if (response) {
+ DEBUGMSGTL(("mteTriggerTable",
+ "Error received: status=%d, sess_error=%s, pduerr=%d/%s, pdu version=%d\n",
+ status, errstr,
+ response->errstat,
+ snmp_api_errstring(response->errstat),
+ response->version));
+ } else {
+ DEBUGMSGTL(("mteTriggerTable",
+ "Error received: status=%d, sess_error=%s [no response pointer]\n",
+ status, errstr));
+ }
+ if (errstr)
+ free(errstr);
+ return NULL; /* XXX: proper failure, trap sent, etc */
+ }
+ } else {
+ /*
+ * remote target list
+ */
+ /*
+ * XXX
+ */
+ }
+ if (response->variables)
+ snprint_variable(buf, sizeof(buf), response->variables->name,
+ response->variables->name_length,
+ response->variables);
+ else
+ strcpy(buf, "empty");
+ buf[sizeof(buf) - 1] = '\0';
+ DEBUGMSGTL(("mteTriggerTable", "got a variables: %s\n", buf));
+ return response;
+} /* mte_get_response */
+
+
+/*
+ * Return 1 if `type' is an integer type; specifically, to quote RFC 2981,
+ * p. 13, "anything that ends up encoded for transmission (that is, in BER,
+ * not ASN.1) as an integer". Return 0 for all other types.
+ */
+
+int
+mte_is_integer_type(unsigned char type)
+{
+ switch (type) {
+ case ASN_INTEGER:
+ case ASN_COUNTER:
+ case ASN_GAUGE:
+ case ASN_TIMETICKS:
+ case ASN_UINTEGER:
+ case ASN_COUNTER64:
+#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
+ case ASN_OPAQUE_COUNTER64:
+ case ASN_OPAQUE_U64:
+ case ASN_OPAQUE_I64:
+#endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+/*
+ * Return 0 if the discontinuity object was checked and no discontinuity has
+ * occurred, 1 if the discontinuity object was checked and a discontinuity
+ * has occurred or -1 if the discontinuity object is not accessible.
+ */
+
+int
+mte_discontinuity_occurred(struct mteTriggerTable_data *item)
+{
+ netsnmp_pdu *pdu = NULL, *response = NULL;
+ unsigned long discoTicks = 0; /* cool var name */
+
+ if (item->mteTriggerDeltaDiscontinuityIDLen == 0 ||
+ (snmp_oid_compare(item->mteTriggerDeltaDiscontinuityID,
+ item->mteTriggerDeltaDiscontinuityIDLen,
+ sysUpTimeInstance,
+ sizeof(sysUpTimeInstance) / sizeof(oid)) == 0)) {
+ DEBUGMSGTL(("mte_disco",
+ "discoID either zero-length or sysUpTimeInstance\n"));
+ } else {
+ if (item->mteTriggerValueIDWildcard == TV_TRUE) {
+ pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
+ } else {
+ pdu = snmp_pdu_create(SNMP_MSG_GET);
+ }
+ snmp_add_null_var(pdu, item->mteTriggerDeltaDiscontinuityID,
+ item->mteTriggerDeltaDiscontinuityIDLen);
+ response = mte_get_response(item, pdu);
+ if (response == NULL) {
+ /*
+ * XXX: send a mteTriggerFailure notification with the appropriate
+ * error code here.
+ */
+ /*
+ * "If the object identified is not accessible the sample attempt is in
+ * error, with the error code as from an SNMP request."
+ */
+ DEBUGMSGTL(("mte_disco", "failure (auth?) getting discoID\n"));
+ return -1;
+ } else {
+ if (item->mteTriggerDeltaDiscontinuityIDType ==
+ MTETRIGGERDELTADISCONTINUITYIDTYPE_TIMETICKS ||
+ item->mteTriggerDeltaDiscontinuityIDType ==
+ MTETRIGGERDELTADISCONTINUITYIDTYPE_TIMESTAMP) {
+ if (response->errstat == SNMPERR_SUCCESS) {
+ if (response->variables != NULL &&
+ response->variables->type == ASN_TIMETICKS) {
+ DEBUGMSGTL(("mte_disco",
+ "got ASN_TIMETICKS-valued variable\n"));
+ discoTicks =
+ *((unsigned long *) response->variables->val.
+ integer);
+ if (item->prevDiscoTicks != 0) {
+ if (discoTicks != item->prevDiscoTicks) {
+ /*
+ * Danger Will Robinson: there has been a discontinuity!
+ */
+ DEBUGMSGTL(("mte_disco",
+ "a discontinuity has occurred\n"));
+ item->prevDiscoTicks = discoTicks;
+ snmp_free_pdu(response);
+ return 1;
+ }
+ }
+ item->prevDiscoTicks = discoTicks;
+ } else {
+ /*
+ * XXX: send a mteTriggerFailure notification with the
+ * appropriate error code here.
+ */
+ if (response->variables != NULL &&
+ (response->variables->type == SNMP_NOSUCHOBJECT
+ || response->variables->type ==
+ SNMP_NOSUCHINSTANCE
+ || response->variables->type ==
+ SNMP_ENDOFMIBVIEW)) {
+ /*
+ * noSuchName I guess.
+ */
+ } else {
+ /*
+ * badType.
+ */
+ }
+ DEBUGMSGTL(("mte_disco",
+ "failure getting discoID\n"));
+ snmp_free_pdu(response);
+ return -1;
+ }
+ } else {
+ /*
+ * XXX: send a mteTriggerFailure notification with the appropriate
+ * error code (just use response->errstat) here.
+ */
+ DEBUGMSGTL(("mte_disco", "failure getting discoID\n"));
+ snmp_free_pdu(response);
+ return -1;
+ }
+ } else {
+ /*
+ * Don't handle dateAndTime type queries yet.
+ */
+ DEBUGMSGTL(("mte_disco",
+ "dateAndTime query UNIMPLEMENTED\n"));
+ }
+ snmp_free_pdu(response);
+ }
+ }
+
+ /*
+ * "...if this object does not point to sysUpTime discontinuity checking
+ * MUST still check sysUpTime for an overall discontinuity."
+ */
+ if (snmp_oid_compare(item->mteTriggerDeltaDiscontinuityID,
+ item->mteTriggerDeltaDiscontinuityIDLen,
+ sysUpTimeInstance,
+ sizeof(sysUpTimeInstance) / sizeof(oid)) != 0) {
+ DEBUGMSGTL(("mte_disco", "discoID != sysUpTimeInstance\n"));
+ /*
+ * At the moment we only support checking the local system so there's no
+ * point doing anything extra here.
+ */
+ }
+
+ /*
+ * Well if we got all the way to here, then there has been neither a
+ * discontinuity nor an error.
+ */
+ DEBUGMSGTL(("mte_disco", "no discontinuity\n"));
+ return 0;
+} /* mte_discontinuity_occurred */
+
+
+void
+mte_run_trigger(unsigned int clientreg, void *clientarg)
+{
+
+ struct mteTriggerTable_data *item =
+ (struct mteTriggerTable_data *) clientarg;
+ netsnmp_pdu *pdu = NULL, *response = NULL;
+ char buf[SPRINT_MAX_LEN];
+ int msg_type = SNMP_MSG_GET, disco;
+
+ oid *next_oid;
+ size_t next_oid_len;
+ long *value, *old_value, x;
+ struct last_state *laststate;
+ char lastbool = 0, boolresult = 0, lastthresh = 0;
+
+ if (!item) {
+ /*
+ * ack
+ */
+ snmp_alarm_unregister(clientreg);
+ return;
+ }
+ DEBUGMSGTL(("mteTriggertable", "Running trigger for %s/%s\n",
+ item->mteOwner, item->mteTriggerName));
+
+ next_oid = item->mteTriggerValueID;
+ next_oid_len = item->mteTriggerValueIDLen;
+ if (item->mteTriggerValueIDWildcard == TV_TRUE)
+ msg_type = SNMP_MSG_GETNEXT;
+
+ item->hc_storage_old = item->hc_storage;
+ item->hc_storage = NULL;
+ do {
+ pdu = snmp_pdu_create(msg_type);
+ snmp_add_null_var(pdu, next_oid, next_oid_len);
+
+ if(response)
+ snmp_free_pdu(response);
+
+ response = mte_get_response(item, pdu);
+ if (!response)
+ break; /* XXX: proper failure */
+
+ if (item->mteTriggerValueIDWildcard == TV_TRUE &&
+ ((response->variables->type >= SNMP_NOSUCHOBJECT &&
+ response->variables->type <= SNMP_ENDOFMIBVIEW) ||
+ snmp_oid_compare(item->mteTriggerValueID,
+ item->mteTriggerValueIDLen,
+ response->variables->name,
+ item->mteTriggerValueIDLen) != 0)) {
+ DEBUGMSGTL(("mteTriggerTable",
+ "DONE, last varbind processed\n"));
+ break;
+ }
+
+ /*
+ * shorter pointers
+ */
+ next_oid = response->variables->name;
+ next_oid_len = response->variables->name_length;
+
+ /*
+ * Send a "bad type" notification if the type of the target object is
+ * non-INTEGER and the test type is either `boolean' or `threshold'
+ * (which want to do arithmetic).
+ */
+ if (((item->mteTriggerTest[0] & MTETRIGGERTEST_BOOLEAN) ||
+ (item->mteTriggerTest[0] & MTETRIGGERTEST_THRESHOLD)) &&
+ response->errstat == SNMPERR_SUCCESS &&
+ !mte_is_integer_type(response->variables->type)) {
+ long failure = MTE_FAILURE_BADTYPE;
+ send_mte_trap(item, mteTriggerFailure,
+ sizeof(mteTriggerFailure) / sizeof(oid),
+ next_oid, next_oid_len, &failure,
+ NULL, NULL, "failure: bad type");
+ /*
+ * RFC2981, p.15: "If the value syntax of those objects
+ * [returned by a getNext-style match] is not usable, that
+ * results in a `badType' error THAT TERMINATES THE SCAN."
+ * (my emphasis).
+ */
+ break;
+ }
+
+ /*
+ * Clone the value. XXX: What happens if it's an unsigned type? Or a
+ * 64-bit type, or an OCTET STRING for the sake of argument. Do
+ * everything in 64-bit arithmetic perhaps? Generate "bad type"
+ * notifications for non-INTEGER cases (except for existence).
+ */
+ if (response->errstat == SNMPERR_SUCCESS &&
+ response->variables->val.integer)
+ memdup((unsigned char **) &value,
+ (unsigned char *) response->variables->val.integer,
+ sizeof(*response->variables->val.integer));
+ else
+ value = NULL;
+
+ snprint_variable(buf, sizeof(buf),
+ next_oid, next_oid_len, response->variables);
+ buf[sizeof(buf) - 1] = '\0';
+ DEBUGMSGTL(("mteTriggerTable", "received %s (type %d)\n", buf,
+ response->variables->type));
+
+ /*
+ * see if we have old values for this
+ */
+ laststate = header_complex_get_from_oid(item->hc_storage_old,
+ next_oid, next_oid_len);
+ if (laststate) {
+ old_value = laststate->value;
+ lastbool = laststate->lastbool;
+ lastthresh = laststate->lastthreshold;
+ } else {
+ old_value = NULL;
+ lastthresh = MTE_THRESHOLD_BEGIN;
+ }
+
+ /*
+ * deal with existence tests
+ */
+ if (item->mteTriggerTest[0] & MTETRIGGERTEST_EXISTENCE) {
+ if ((item->mteTriggerExistenceTest[0] &
+ MTETRIGGEREXISTENCETEST_PRESENT)
+ && value && !old_value &&
+ (item->started ||
+ (item->mteTriggerExistenceStartup[0] &
+ MTETRIGGEREXISTENCESTARTUP_PRESENT))) {
+ /*
+ * XXX: if mteTriggerExistenceTest is not "present", for
+ * example, and then turned on when has been previously
+ * off, do we respect the value of the last known
+ * existence status?
+ */
+ send_mte_trap(item, mteTriggerFired,
+ sizeof(mteTriggerFired) / sizeof(oid),
+ next_oid, next_oid_len,
+ value, item->mteTriggerExistenceObjectsOwner,
+ item->mteTriggerExistenceObjects,
+ "existence: present");
+ run_mte_events(item, next_oid, next_oid_len,
+ item->mteTriggerExistenceEventOwner,
+ item->mteTriggerExistenceEvent);
+ }
+
+ if ((item->mteTriggerExistenceTest[0] &
+ MTETRIGGEREXISTENCETEST_CHANGED)
+ && value && old_value && *old_value != *value) {
+ /*
+ * XXX: if mteTriggerExistenceTest is not "present", for
+ * example, and then turned on when has been previously
+ * off, do we respect the value of the last known
+ * existence status?
+ */
+ send_mte_trap(item, mteTriggerFired,
+ sizeof(mteTriggerFired) / sizeof(oid),
+ next_oid, next_oid_len,
+ value, item->mteTriggerExistenceObjectsOwner,
+ item->mteTriggerExistenceObjects,
+ "existence: changed");
+ run_mte_events(item, next_oid, next_oid_len,
+ item->mteTriggerExistenceEventOwner,
+ item->mteTriggerExistenceEvent);
+ }
+ }
+
+ /*
+ * Deal with boolean tests.
+ */
+ if ((item->mteTriggerTest[0] & MTETRIGGERTEST_BOOLEAN) &&
+ ((item->mteTriggerSampleType ==
+ MTETRIGGERSAMPLETYPE_ABSOLUTEVALUE && value)
+ || (item->mteTriggerSampleType ==
+ MTETRIGGERSAMPLETYPE_DELTAVALUE && value && old_value))) {
+ if (item->mteTriggerSampleType ==
+ MTETRIGGERSAMPLETYPE_DELTAVALUE) {
+ /*
+ * XXX: Must check the discontinuity OID here.
+ */
+ disco = mte_discontinuity_occurred(item);
+ if (disco == -1) {
+ /*
+ * An error notification has already been sent; just bail
+ * out now.
+ */
+ /*
+ * XXX: should save values here?
+ */
+ return;
+ } else if (disco == 1) {
+ /*
+ * A discontinuity has occurred; the right thing to do here
+ * depends on the exact type. FOR NOW, assume long.
+ */
+ x = *((long *) value) + (INT_MAX -
+ *((long *) old_value));
+ } else {
+ x = *((long *) value) - *((long *) old_value);
+ }
+ } else {
+ x = *((long *) value);
+ }
+
+ switch (item->mteTriggerBooleanComparison) {
+ case MTETRIGGERBOOLEANCOMPARISON_UNEQUAL:
+ boolresult = (x != item->mteTriggerBooleanValue);
+ break;
+
+ case MTETRIGGERBOOLEANCOMPARISON_EQUAL:
+ boolresult = (x == item->mteTriggerBooleanValue);
+ break;
+
+ case MTETRIGGERBOOLEANCOMPARISON_LESS:
+ boolresult = (x < item->mteTriggerBooleanValue);
+ break;
+
+ case MTETRIGGERBOOLEANCOMPARISON_LESSOREQUAL:
+ boolresult = (x <= item->mteTriggerBooleanValue);
+ break;
+
+ case MTETRIGGERBOOLEANCOMPARISON_GREATER:
+ boolresult = (x > item->mteTriggerBooleanValue);
+ break;
+
+ case MTETRIGGERBOOLEANCOMPARISON_GREATEROREQUAL:
+ boolresult = (x >= item->mteTriggerBooleanValue);
+ break;
+
+ default:
+ snmp_log(LOG_WARNING,
+ "illegal value in mteTriggerBooleanComparison object: %ld",
+ item->mteTriggerBooleanComparison);
+ boolresult = item->lastboolresult; /* to fail next test */
+ }
+
+ if (boolresult &&
+ ((item->mteTriggerBooleanStartup ==
+ MTETRIGGERBOOLEANSTARTUP_TRUE
+ && lastbool == (char)-1) || lastbool != boolresult)) {
+ send_mte_trap(item, mteTriggerFired,
+ sizeof(mteTriggerFired) / sizeof(oid),
+ next_oid, next_oid_len,
+ &x, item->mteTriggerBooleanObjectsOwner,
+ item->mteTriggerBooleanObjects,
+ "boolean: true");
+ run_mte_events(item, next_oid, next_oid_len,
+ item->mteTriggerBooleanEventOwner,
+ item->mteTriggerBooleanEvent);
+ }
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "value: %d %ld %lu x: %d %ld %lu\n", *value,
+ *value, *value, x, x, x));
+
+ DEBUGMSGTL(("mteTriggerTable",
+ "boolean result: x=%d %s configured=%d = %d\n",
+ x,
+ se_find_label_in_slist("mteBooleanOperators",
+ item->
+ mteTriggerBooleanComparison),
+ item->mteTriggerBooleanValue, boolresult));
+ }
+
+ /*
+ * Deal with threshold tests. XXX: doesn't handle "delta-type"
+ * sampling.
+ */
+ if ((item->mteTriggerTest[0] & MTETRIGGERTEST_THRESHOLD) &&
+ ((item->mteTriggerSampleType ==
+ MTETRIGGERSAMPLETYPE_ABSOLUTEVALUE && value)
+ || (item->mteTriggerSampleType ==
+ MTETRIGGERSAMPLETYPE_DELTAVALUE && value && old_value))) {
+ /*
+ * XXX: correct intepretation of mteTriggerThresholdStartup?
+ */
+ /*
+ * only fires when passed and just set to active? What
+ * about a newly discovered node that is past a
+ * threshold once we've been active for a turn at least?
+ */
+ /*
+ * XXX: Check notions of > vs >=
+ */
+ if (((item->started == MTE_STARTED && laststate &&
+ lastthresh == MTE_THRESHOLD_LOW) ||
+ (item->started != MTE_STARTED &&
+ (item->mteTriggerThresholdStartup ==
+ MTETRIGGERTHRESHOLDSTARTUP_RISING
+ || item->mteTriggerThresholdStartup ==
+ MTETRIGGERTHRESHOLDSTARTUP_RISINGORFALLING)))
+ && (*value >= item->mteTriggerThresholdRising)) {
+ send_mte_trap(item, mteTriggerRising,
+ sizeof(mteTriggerRising) / sizeof(oid),
+ next_oid, next_oid_len, value,
+ item->mteTriggerThresholdObjectsOwner,
+ item->mteTriggerThresholdObjects,
+ "threshold: rising");
+ run_mte_events(item, next_oid, next_oid_len,
+ item->mteTriggerThresholdRisingEventOwner,
+ item->mteTriggerThresholdRisingEvent);
+ }
+ if (((item->started == MTE_STARTED && laststate &&
+ lastthresh == MTE_THRESHOLD_HIGH) ||
+ (item->started != MTE_STARTED &&
+ (item->mteTriggerThresholdStartup ==
+ MTETRIGGERTHRESHOLDSTARTUP_FALLING
+ || item->mteTriggerThresholdStartup ==
+ MTETRIGGERTHRESHOLDSTARTUP_RISINGORFALLING)))
+ && (*value <= item->mteTriggerThresholdFalling)) {
+ send_mte_trap(item, mteTriggerFalling,
+ sizeof(mteTriggerFalling) / sizeof(oid),
+ next_oid, next_oid_len, value,
+ item->mteTriggerThresholdObjectsOwner,
+ item->mteTriggerThresholdObjects,
+ "threshold: falling");
+ run_mte_events(item, next_oid, next_oid_len,
+ item->mteTriggerThresholdFallingEventOwner,
+ item->mteTriggerThresholdFallingEvent);
+ }
+
+ }
+
+ if (value) {
+ struct last_state *new_last_state =
+ SNMP_MALLOC_STRUCT(last_state);
+ new_last_state->value = value;
+ new_last_state->lastbool = boolresult;
+ header_complex_add_data_by_oid(&item->hc_storage, next_oid,
+ next_oid_len, new_last_state);
+
+ /*
+ * set our notion of the current known threshold state
+ */
+ if (lastthresh == MTE_THRESHOLD_LOW &&
+ *value >= item->mteTriggerThresholdRising &&
+ *value > item->mteTriggerThresholdFalling)
+ new_last_state->lastthreshold = MTE_THRESHOLD_HIGH;
+ else if (lastthresh == MTE_THRESHOLD_HIGH &&
+ *value < item->mteTriggerThresholdRising &&
+ *value <= item->mteTriggerThresholdFalling)
+ new_last_state->lastthreshold = MTE_THRESHOLD_LOW;
+ else if (lastthresh == MTE_THRESHOLD_BEGIN) {
+ if (*value >= item->mteTriggerThresholdRising)
+ new_last_state->lastthreshold = MTE_THRESHOLD_HIGH;
+ else if (*value <= item->mteTriggerThresholdFalling)
+ new_last_state->lastthreshold = MTE_THRESHOLD_LOW;
+ /*
+ * XXX: else??? in between? undefined?
+ */
+ } else {
+ new_last_state->lastthreshold = lastthresh;
+ }
+ }
+
+ /*
+ * extract from old hc storage
+ */
+ if (laststate) {
+ header_complex_extract_entry(&item->hc_storage_old,
+ header_complex_find_entry(item->
+ hc_storage_old,
+ (void *)
+ laststate));
+ last_state_clean(laststate);
+ }
+
+ } while (item->mteTriggerValueIDWildcard == TV_TRUE);
+
+ if(response)
+ snmp_free_pdu(response);
+
+ /*
+ * loop through old values for DNE cases
+ */
+ if (item->mteTriggerExistenceTest[0] & MTETRIGGEREXISTENCETEST_ABSENT) {
+
+ struct header_complex_index *iter;
+
+ /*
+ * XXX: broken
+ */
+ if ((item->mteTriggerExistenceStartup[0] &
+ MTETRIGGEREXISTENCESTARTUP_ABSENT)) {
+ /*
+ * XXX: send trap that nothing was found?
+ */
+ /*
+ * only if !wild? (see mib)
+ */
+ }
+ for (iter = item->hc_storage_old; iter; iter = iter->next) {
+ laststate = (struct last_state *) iter->data;
+ send_mte_trap(item, mteTriggerFired,
+ sizeof(mteTriggerFired) / sizeof(oid),
+ iter->name, iter->namelen, laststate->value,
+ item->mteTriggerExistenceObjectsOwner,
+ item->mteTriggerExistenceObjects,
+ "existence: absent");
+ }
+ header_complex_free_all(item->hc_storage_old, last_state_clean);
+ item->hc_storage_old = NULL;
+ }
+
+ item->started = MTE_STARTED;
+} /* mte_run_trigger */
+
+
+
+/*
+ * handling routines
+ */
+void
+mte_enable_trigger(struct mteTriggerTable_data *item)
+{
+ if (!item)
+ return;
+
+ if (item->alarmreg)
+ snmp_alarm_unregister(item->alarmreg);
+
+ if (item->mteTriggerFrequency > 0) {
+ DEBUGMSGTL(("mteTriggertable", "Enabling trigger for %s/%s @ %u\n",
+ item->mteOwner, item->mteTriggerName,
+ item->mteTriggerFrequency));
+ item->alarmreg =
+ snmp_alarm_register(item->mteTriggerFrequency, SA_REPEAT,
+ mte_run_trigger, item);
+ }
+}
+
+void
+mte_disable_trigger(struct mteTriggerTable_data *item)
+{
+ if (!item)
+ return;
+
+ if (item->alarmreg) {
+ DEBUGMSGTL(("mteTriggertable", "Disabling trigger for %s/%s\n",
+ item->mteOwner, item->mteTriggerName));
+ snmp_alarm_unregister(item->alarmreg);
+ item->alarmreg = 0;
+ }
+ item->started = MTE_NOTSTARTED;
+}
diff --git a/agent/mibgroup/disman/mteTriggerTable.h b/agent/mibgroup/disman/mteTriggerTable.h
new file mode 100644
index 0000000..c427602
--- /dev/null
+++ b/agent/mibgroup/disman/mteTriggerTable.h
@@ -0,0 +1,253 @@
+/*
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+
+#ifndef _MIBGROUP_MTETRIGGERTABLE_H
+#define _MIBGROUP_MTETRIGGERTABLE_H
+
+
+/*
+ * we may use header_complex from the header_complex module
+ */
+
+
+config_require(header_complex)
+config_require(utilities/iquery)
+
+#ifndef NETSNMP_TRANSPORT_CALLBACK_DOMAIN
+config_error(disman/mteTriggerTable depends on the Callback transport)
+#endif
+
+ /*
+ * our storage structure(s)
+ */
+ struct mteTriggerTable_data {
+
+
+ char *mteOwner;
+ size_t mteOwnerLen;
+ char *mteTriggerName;
+ size_t mteTriggerNameLen;
+ char *mteTriggerComment;
+ size_t mteTriggerCommentLen;
+ char *mteTriggerTest;
+ size_t mteTriggerTestLen;
+ long mteTriggerSampleType;
+ oid *mteTriggerValueID;
+ size_t mteTriggerValueIDLen;
+ long mteTriggerValueIDWildcard;
+ char *mteTriggerTargetTag;
+ size_t mteTriggerTargetTagLen;
+ char *mteTriggerContextName;
+ size_t mteTriggerContextNameLen;
+ long mteTriggerContextNameWildcard;
+ unsigned long mteTriggerFrequency;
+ char *mteTriggerObjectsOwner;
+ size_t mteTriggerObjectsOwnerLen;
+ char *mteTriggerObjects;
+ size_t mteTriggerObjectsLen;
+ long mteTriggerEnabled;
+ long mteTriggerEntryStatus;
+
+ /*
+ * delta table
+ */
+ oid *mteTriggerDeltaDiscontinuityID;
+ size_t mteTriggerDeltaDiscontinuityIDLen;
+ long mteTriggerDeltaDiscontinuityIDWildcard;
+ long mteTriggerDeltaDiscontinuityIDType;
+ unsigned long prevDiscoTicks;
+ unsigned long prevUptimeTicks;
+
+ /*
+ * existence table
+ */
+ char *mteTriggerExistenceTest;
+ size_t mteTriggerExistenceTestLen;
+ char *mteTriggerExistenceStartup;
+ size_t mteTriggerExistenceStartupLen;
+ char *mteTriggerExistenceObjectsOwner;
+ size_t mteTriggerExistenceObjectsOwnerLen;
+ char *mteTriggerExistenceObjects;
+ size_t mteTriggerExistenceObjectsLen;
+ char *mteTriggerExistenceEventOwner;
+ size_t mteTriggerExistenceEventOwnerLen;
+ char *mteTriggerExistenceEvent;
+ size_t mteTriggerExistenceEventLen;
+
+ /*
+ * boolean table
+ */
+ long mteTriggerBooleanComparison;
+ long mteTriggerBooleanValue;
+ long mteTriggerBooleanStartup;
+ char *mteTriggerBooleanObjectsOwner;
+ size_t mteTriggerBooleanObjectsOwnerLen;
+ char *mteTriggerBooleanObjects;
+ size_t mteTriggerBooleanObjectsLen;
+ char *mteTriggerBooleanEventOwner;
+ size_t mteTriggerBooleanEventOwnerLen;
+ char *mteTriggerBooleanEvent;
+ size_t mteTriggerBooleanEventLen;
+
+ /*
+ * threshold table
+ */
+ long mteTriggerThresholdStartup;
+ long mteTriggerThresholdRising;
+ long mteTriggerThresholdFalling;
+ long mteTriggerThresholdDeltaRising;
+ long mteTriggerThresholdDeltaFalling;
+ char *mteTriggerThresholdObjectsOwner;
+ size_t mteTriggerThresholdObjectsOwnerLen;
+ char *mteTriggerThresholdObjects;
+ size_t mteTriggerThresholdObjectsLen;
+ char *mteTriggerThresholdRisingEventOwner;
+ size_t mteTriggerThresholdRisingEventOwnerLen;
+ char *mteTriggerThresholdRisingEvent;
+ size_t mteTriggerThresholdRisingEventLen;
+ char *mteTriggerThresholdFallingEventOwner;
+ size_t mteTriggerThresholdFallingEventOwnerLen;
+ char *mteTriggerThresholdFallingEvent;
+ size_t mteTriggerThresholdFallingEventLen;
+ char *mteTriggerThresholdDeltaRisingEventOwner;
+ size_t mteTriggerThresholdDeltaRisingEventOwnerLen;
+ char *mteTriggerThresholdDeltaRisingEvent;
+ size_t mteTriggerThresholdDeltaRisingEventLen;
+ char *mteTriggerThresholdDeltaFallingEventOwner;
+ size_t mteTriggerThresholdDeltaFallingEventOwnerLen;
+ char *mteTriggerThresholdDeltaFallingEvent;
+ size_t mteTriggerThresholdDeltaFallingEventLen;
+
+ /*
+ * internal variables
+ */
+ int storageType;
+ unsigned int alarmreg;
+ int lastboolresult;
+ int started;
+ long lastvalue;
+ struct header_complex_index *hc_storage, *hc_storage_old;
+ unsigned long threshold_state;
+
+ /*
+ * pdu auth contents
+ */
+ long have_copied_auth_info;
+ long pdu_version;
+ long pdu_securityModel;
+ long pdu_securityLevel;
+ void *pdu_transport;
+ size_t pdu_transportLen;
+ const oid *pdu_tDomain;
+ size_t pdu_tDomainLen;
+ u_char *pdu_community;
+ size_t pdu_community_len;
+ char *pdu_contextName;
+ size_t pdu_contextNameLen;
+ char *pdu_securityName;
+ size_t pdu_securityNameLen;
+ };
+
+ struct last_state {
+ long *value;
+ char lastbool;
+ char lastthreshold;
+ };
+
+
+/*
+ * enum definitions from the covered mib sections
+ */
+
+
+
+
+
+
+
+#define MTETRIGGERTEST_EXISTENCE 0x80
+#define MTETRIGGERTEST_BOOLEAN 0x40
+#define MTETRIGGERTEST_THRESHOLD 0x20
+
+#define MTETRIGGERSAMPLETYPE_ABSOLUTEVALUE 1
+#define MTETRIGGERSAMPLETYPE_DELTAVALUE 2
+
+
+/*
+ * What's wrong with using the regular TruthValue definitions TV_TRUE
+ * and TV_FALSE (snmp-tc.h) which are up to 77% shorter?
+ */
+
+#define MTETRIGGERVALUEIDWILDCARD_TRUE 1
+#define MTETRIGGERVALUEIDWILDCARD_FALSE 2
+
+
+
+#define MTETRIGGERCONTEXTNAMEWILDCARD_TRUE 1
+#define MTETRIGGERCONTEXTNAMEWILDCARD_FALSE 2
+
+
+
+
+#define MTETRIGGERENABLED_TRUE 1
+#define MTETRIGGERENABLED_FALSE 2
+
+#define MTE_NOTSTARTED 0
+#define MTE_STARTED 1
+
+#define MTE_THRESHOLD_BEGIN 0
+#define MTE_THRESHOLD_HIGH 1
+#define MTE_THRESHOLD_LOW 2
+
+/*
+ * Just the first (MTE-specific) groups of errors defined here;
+ * others are numerically equal to the regular SNMP errors.
+ */
+
+#define MTE_FAILURE_LOCALRESOURCELACK -1
+#define MTE_FAILURE_BADDESTINATION -2
+#define MTE_FAILURE_DESTINATIONUNREACHABLE -3
+#define MTE_FAILURE_NORESPONSE -4
+#define MTE_FAILURE_BADTYPE -5
+#define MTE_FAILURE_SAMPLEOVERRUN -6
+
+
+/*
+ * function prototypes
+ */
+
+
+ void init_mteTriggerTable(void);
+ FindVarMethod var_mteTriggerTable;
+ void parse_mteTriggerTable(const char *, char *);
+ void parse_simple_monitor(const char *, char *);
+ void parse_default_monitors(const char *, char *);
+ SNMPCallback store_mteTriggerTable;
+ netsnmp_pdu *mte_get_response(struct mteTriggerTable_data *,
+ netsnmp_pdu *);
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ WriteMethod write_mteTriggerComment;
+ WriteMethod write_mteTriggerTest;
+ WriteMethod write_mteTriggerSampleType;
+ WriteMethod write_mteTriggerValueID;
+ WriteMethod write_mteTriggerValueIDWildcard;
+ WriteMethod write_mteTriggerTargetTag;
+ WriteMethod write_mteTriggerContextName;
+ WriteMethod write_mteTriggerContextNameWildcard;
+ WriteMethod write_mteTriggerFrequency;
+ WriteMethod write_mteTriggerObjectsOwner;
+ WriteMethod write_mteTriggerObjects;
+ WriteMethod write_mteTriggerEnabled;
+ WriteMethod write_mteTriggerEntryStatus;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+ void mte_enable_trigger(struct mteTriggerTable_data *item);
+ void mte_disable_trigger(struct mteTriggerTable_data
+ *item);
+ SNMPAlarmCallback mte_run_trigger;
+
+#endif /* _MIBGROUP_MTETRIGGERTABLE_H */
diff --git a/agent/mibgroup/disman/mteTriggerThresholdTable.c b/agent/mibgroup/disman/mteTriggerThresholdTable.c
new file mode 100644
index 0000000..93c02b2
--- /dev/null
+++ b/agent/mibgroup/disman/mteTriggerThresholdTable.c
@@ -0,0 +1,1700 @@
+/*
+ * This file was generated by mib2c and is intended for use as
+ * a mib module for the ucd-snmp snmpd agent.
+ */
+
+
+/*
+ * This should always be included first before anything else
+ */
+#include <net-snmp/net-snmp-config.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+
+/*
+ * minimal include directives
+ */
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "header_complex.h"
+#include "mteTriggerThresholdTable.h"
+#include "mteTriggerTable.h"
+
+
+/*
+ * mteTriggerThresholdTable_variables_oid:
+ * this is the top level oid that we want to register under. This
+ * is essentially a prefix, with the suffix appearing in the
+ * variable below.
+ */
+
+
+oid mteTriggerThresholdTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 88, 1, 2, 6 };
+
+
+/*
+ * variable2 mteTriggerThresholdTable_variables:
+ * this variable defines function callbacks and type return information
+ * for the mteTriggerThresholdTable mib section
+ */
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+struct variable2 mteTriggerThresholdTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define MTETRIGGERTHRESHOLDSTARTUP 3
+ {MTETRIGGERTHRESHOLDSTARTUP, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 1}},
+#define MTETRIGGERTHRESHOLDRISING 4
+ {MTETRIGGERTHRESHOLDRISING, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 2}},
+#define MTETRIGGERTHRESHOLDFALLING 5
+ {MTETRIGGERTHRESHOLDFALLING, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 3}},
+#define MTETRIGGERTHRESHOLDDELTARISING 6
+ {MTETRIGGERTHRESHOLDDELTARISING, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 4}},
+#define MTETRIGGERTHRESHOLDDELTAFALLING 7
+ {MTETRIGGERTHRESHOLDDELTAFALLING, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 5}},
+#define MTETRIGGERTHRESHOLDOBJECTSOWNER 8
+ {MTETRIGGERTHRESHOLDOBJECTSOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 6}},
+#define MTETRIGGERTHRESHOLDOBJECTS 9
+ {MTETRIGGERTHRESHOLDOBJECTS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 7}},
+#define MTETRIGGERTHRESHOLDRISINGEVENTOWNER 10
+ {MTETRIGGERTHRESHOLDRISINGEVENTOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 8}},
+#define MTETRIGGERTHRESHOLDRISINGEVENT 11
+ {MTETRIGGERTHRESHOLDRISINGEVENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 9}},
+#define MTETRIGGERTHRESHOLDFALLINGEVENTOWNER 12
+ {MTETRIGGERTHRESHOLDFALLINGEVENTOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 10}},
+#define MTETRIGGERTHRESHOLDFALLINGEVENT 13
+ {MTETRIGGERTHRESHOLDFALLINGEVENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 11}},
+#define MTETRIGGERTHRESHOLDDELTARISINGEVENTOWNER 14
+ {MTETRIGGERTHRESHOLDDELTARISINGEVENTOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 12}},
+#define MTETRIGGERTHRESHOLDDELTARISINGEVENT 15
+ {MTETRIGGERTHRESHOLDDELTARISINGEVENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 13}},
+#define MTETRIGGERTHRESHOLDDELTAFALLINGEVENTOWNER 16
+ {MTETRIGGERTHRESHOLDDELTAFALLINGEVENTOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 14}},
+#define MTETRIGGERTHRESHOLDDELTAFALLINGEVENT 17
+ {MTETRIGGERTHRESHOLDDELTAFALLINGEVENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_mteTriggerThresholdTable, 2, {1, 15}},
+};
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+struct variable2 mteTriggerThresholdTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+#define MTETRIGGERTHRESHOLDSTARTUP 3
+ {MTETRIGGERTHRESHOLDSTARTUP, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 1}},
+#define MTETRIGGERTHRESHOLDRISING 4
+ {MTETRIGGERTHRESHOLDRISING, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 2}},
+#define MTETRIGGERTHRESHOLDFALLING 5
+ {MTETRIGGERTHRESHOLDFALLING, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 3}},
+#define MTETRIGGERTHRESHOLDDELTARISING 6
+ {MTETRIGGERTHRESHOLDDELTARISING, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 4}},
+#define MTETRIGGERTHRESHOLDDELTAFALLING 7
+ {MTETRIGGERTHRESHOLDDELTAFALLING, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 5}},
+#define MTETRIGGERTHRESHOLDOBJECTSOWNER 8
+ {MTETRIGGERTHRESHOLDOBJECTSOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 6}},
+#define MTETRIGGERTHRESHOLDOBJECTS 9
+ {MTETRIGGERTHRESHOLDOBJECTS, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 7}},
+#define MTETRIGGERTHRESHOLDRISINGEVENTOWNER 10
+ {MTETRIGGERTHRESHOLDRISINGEVENTOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 8}},
+#define MTETRIGGERTHRESHOLDRISINGEVENT 11
+ {MTETRIGGERTHRESHOLDRISINGEVENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 9}},
+#define MTETRIGGERTHRESHOLDFALLINGEVENTOWNER 12
+ {MTETRIGGERTHRESHOLDFALLINGEVENTOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 10}},
+#define MTETRIGGERTHRESHOLDFALLINGEVENT 13
+ {MTETRIGGERTHRESHOLDFALLINGEVENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 11}},
+#define MTETRIGGERTHRESHOLDDELTARISINGEVENTOWNER 14
+ {MTETRIGGERTHRESHOLDDELTARISINGEVENTOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 12}},
+#define MTETRIGGERTHRESHOLDDELTARISINGEVENT 15
+ {MTETRIGGERTHRESHOLDDELTARISINGEVENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 13}},
+#define MTETRIGGERTHRESHOLDDELTAFALLINGEVENTOWNER 16
+ {MTETRIGGERTHRESHOLDDELTAFALLINGEVENTOWNER, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 14}},
+#define MTETRIGGERTHRESHOLDDELTAFALLINGEVENT 17
+ {MTETRIGGERTHRESHOLDDELTAFALLINGEVENT, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_mteTriggerThresholdTable, 2, {1, 15}},
+};
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+
+/*
+ * (L = length of the oidsuffix)
+ */
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+extern struct header_complex_index *mteTriggerTableStorage;
+
+
+/*
+ * init_mteTriggerThresholdTable():
+ * Initialization routine. This is called when the agent starts up.
+ * At a minimum, registration of your variables should take place here.
+ */
+void
+init_mteTriggerThresholdTable(void)
+{
+ DEBUGMSGTL(("mteTriggerThresholdTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("mteTriggerThresholdTable",
+ mteTriggerThresholdTable_variables, variable2,
+ mteTriggerThresholdTable_variables_oid);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable", "done.\n"));
+}
+
+/*
+ * var_mteTriggerThresholdTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_mteTriggerThresholdTable above.
+ */
+unsigned char *
+var_mteTriggerThresholdTable(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact,
+ size_t * var_len, WriteMethod ** write_method)
+{
+
+
+ struct mteTriggerTable_data *StorageTmp = NULL;
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "var_mteTriggerThresholdTable: Entering... \n"));
+
+ /* set default value */
+ *write_method = NULL;
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL)
+ return NULL;
+
+
+ if (!(StorageTmp->mteTriggerTest[0] & MTETRIGGERTEST_THRESHOLD))
+ return NULL;
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+
+
+ case MTETRIGGERTHRESHOLDSTARTUP:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdStartup;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerThresholdStartup);
+ return (u_char *) & StorageTmp->mteTriggerThresholdStartup;
+
+ case MTETRIGGERTHRESHOLDRISING:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdRising;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerThresholdRising);
+ return (u_char *) & StorageTmp->mteTriggerThresholdRising;
+
+ case MTETRIGGERTHRESHOLDFALLING:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdFalling;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerThresholdFalling);
+ return (u_char *) & StorageTmp->mteTriggerThresholdFalling;
+
+ case MTETRIGGERTHRESHOLDDELTARISING:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdDeltaRising;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerThresholdDeltaRising);
+ return (u_char *) & StorageTmp->mteTriggerThresholdDeltaRising;
+
+ case MTETRIGGERTHRESHOLDDELTAFALLING:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdDeltaFalling;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->mteTriggerThresholdDeltaFalling);
+ return (u_char *) & StorageTmp->mteTriggerThresholdDeltaFalling;
+
+ case MTETRIGGERTHRESHOLDOBJECTSOWNER:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdObjectsOwner;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerThresholdObjectsOwnerLen;
+ return (u_char *) StorageTmp->mteTriggerThresholdObjectsOwner;
+
+ case MTETRIGGERTHRESHOLDOBJECTS:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdObjects;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerThresholdObjectsLen;
+ return (u_char *) StorageTmp->mteTriggerThresholdObjects;
+
+ case MTETRIGGERTHRESHOLDRISINGEVENTOWNER:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdRisingEventOwner;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerThresholdRisingEventOwnerLen;
+ return (u_char *) StorageTmp->mteTriggerThresholdRisingEventOwner;
+
+ case MTETRIGGERTHRESHOLDRISINGEVENT:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdRisingEvent;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerThresholdRisingEventLen;
+ return (u_char *) StorageTmp->mteTriggerThresholdRisingEvent;
+
+ case MTETRIGGERTHRESHOLDFALLINGEVENTOWNER:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdFallingEventOwner;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerThresholdFallingEventOwnerLen;
+ return (u_char *) StorageTmp->mteTriggerThresholdFallingEventOwner;
+
+ case MTETRIGGERTHRESHOLDFALLINGEVENT:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdFallingEvent;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerThresholdFallingEventLen;
+ return (u_char *) StorageTmp->mteTriggerThresholdFallingEvent;
+
+ case MTETRIGGERTHRESHOLDDELTARISINGEVENTOWNER:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdDeltaRisingEventOwner;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerThresholdDeltaRisingEventOwnerLen;
+ return (u_char *) StorageTmp->
+ mteTriggerThresholdDeltaRisingEventOwner;
+
+ case MTETRIGGERTHRESHOLDDELTARISINGEVENT:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdDeltaRisingEvent;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerThresholdDeltaRisingEventLen;
+ return (u_char *) StorageTmp->mteTriggerThresholdDeltaRisingEvent;
+
+ case MTETRIGGERTHRESHOLDDELTAFALLINGEVENTOWNER:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdDeltaFallingEventOwner;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len =
+ StorageTmp->mteTriggerThresholdDeltaFallingEventOwnerLen;
+ return (u_char *) StorageTmp->
+ mteTriggerThresholdDeltaFallingEventOwner;
+
+ case MTETRIGGERTHRESHOLDDELTAFALLINGEVENT:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_mteTriggerThresholdDeltaFallingEvent;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = StorageTmp->mteTriggerThresholdDeltaFallingEventLen;
+ return (u_char *) StorageTmp->mteTriggerThresholdDeltaFallingEvent;
+
+
+ default:
+ ERROR_MSG("");
+ }
+ return NULL;
+}
+
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+int
+write_mteTriggerThresholdStartup(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdStartup entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdStartup not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdStartup;
+ StorageTmp->mteTriggerThresholdStartup = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerThresholdStartup = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdRising(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdRising entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdRising not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdRising;
+ StorageTmp->mteTriggerThresholdRising = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerThresholdRising = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdFalling(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdFalling entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdFalling not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdFalling;
+ StorageTmp->mteTriggerThresholdFalling = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerThresholdFalling = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdDeltaRising(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdDeltaRising entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdDeltaRising not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdDeltaRising;
+ StorageTmp->mteTriggerThresholdDeltaRising = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerThresholdDeltaRising = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdDeltaFalling(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static int tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdDeltaFalling entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdDeltaFalling not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdDeltaFalling;
+ StorageTmp->mteTriggerThresholdDeltaFalling = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->mteTriggerThresholdDeltaFalling = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdObjectsOwner(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdObjectsOwner entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdObjectsOwner not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdObjectsOwner;
+ tmplen = StorageTmp->mteTriggerThresholdObjectsOwnerLen;
+ memdup((u_char **) & StorageTmp->mteTriggerThresholdObjectsOwner,
+ var_val, var_val_len);
+ StorageTmp->mteTriggerThresholdObjectsOwnerLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerThresholdObjectsOwner);
+ StorageTmp->mteTriggerThresholdObjectsOwner = tmpvar;
+ StorageTmp->mteTriggerThresholdObjectsOwnerLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdObjects(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdObjects entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdObjects not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdObjects;
+ tmplen = StorageTmp->mteTriggerThresholdObjectsLen;
+ memdup((u_char **) & StorageTmp->mteTriggerThresholdObjects,
+ var_val, var_val_len);
+ StorageTmp->mteTriggerThresholdObjectsLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerThresholdObjects);
+ StorageTmp->mteTriggerThresholdObjects = tmpvar;
+ StorageTmp->mteTriggerThresholdObjectsLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdRisingEventOwner(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdRisingEventOwner entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdRisingEventOwner not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdRisingEventOwner;
+ tmplen = StorageTmp->mteTriggerThresholdRisingEventOwnerLen;
+ memdup((u_char **) & StorageTmp->
+ mteTriggerThresholdRisingEventOwner, var_val, var_val_len);
+ StorageTmp->mteTriggerThresholdRisingEventOwnerLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerThresholdRisingEventOwner);
+ StorageTmp->mteTriggerThresholdRisingEventOwner = tmpvar;
+ StorageTmp->mteTriggerThresholdRisingEventOwnerLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdRisingEvent(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdRisingEvent entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdRisingEvent not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdRisingEvent;
+ tmplen = StorageTmp->mteTriggerThresholdRisingEventLen;
+ memdup((u_char **) & StorageTmp->mteTriggerThresholdRisingEvent,
+ var_val, var_val_len);
+ StorageTmp->mteTriggerThresholdRisingEventLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerThresholdRisingEvent);
+ StorageTmp->mteTriggerThresholdRisingEvent = tmpvar;
+ StorageTmp->mteTriggerThresholdRisingEventLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdFallingEventOwner(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdFallingEventOwner entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdFallingEventOwner not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdFallingEventOwner;
+ tmplen = StorageTmp->mteTriggerThresholdFallingEventOwnerLen;
+ memdup((u_char **) & StorageTmp->
+ mteTriggerThresholdFallingEventOwner, var_val, var_val_len);
+ StorageTmp->mteTriggerThresholdFallingEventOwnerLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerThresholdFallingEventOwner);
+ StorageTmp->mteTriggerThresholdFallingEventOwner = tmpvar;
+ StorageTmp->mteTriggerThresholdFallingEventOwnerLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdFallingEvent(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdFallingEvent entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdFallingEvent not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdFallingEvent;
+ tmplen = StorageTmp->mteTriggerThresholdFallingEventLen;
+ memdup((u_char **) & StorageTmp->mteTriggerThresholdFallingEvent,
+ var_val, var_val_len);
+ StorageTmp->mteTriggerThresholdFallingEventLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerThresholdFallingEvent);
+ StorageTmp->mteTriggerThresholdFallingEvent = tmpvar;
+ StorageTmp->mteTriggerThresholdFallingEventLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdDeltaRisingEventOwner(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdDeltaRisingEventOwner entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdDeltaRisingEventOwner not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdDeltaRisingEventOwner;
+ tmplen = StorageTmp->mteTriggerThresholdDeltaRisingEventOwnerLen;
+ memdup((u_char **) & StorageTmp->
+ mteTriggerThresholdDeltaRisingEventOwner, var_val,
+ var_val_len);
+ StorageTmp->mteTriggerThresholdDeltaRisingEventOwnerLen =
+ var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerThresholdDeltaRisingEventOwner);
+ StorageTmp->mteTriggerThresholdDeltaRisingEventOwner = tmpvar;
+ StorageTmp->mteTriggerThresholdDeltaRisingEventOwnerLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdDeltaRisingEvent(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdDeltaRisingEvent entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdDeltaRisingEvent not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdDeltaRisingEvent;
+ tmplen = StorageTmp->mteTriggerThresholdDeltaRisingEventLen;
+ memdup((u_char **) & StorageTmp->
+ mteTriggerThresholdDeltaRisingEvent, var_val, var_val_len);
+ StorageTmp->mteTriggerThresholdDeltaRisingEventLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerThresholdDeltaRisingEvent);
+ StorageTmp->mteTriggerThresholdDeltaRisingEvent = tmpvar;
+ StorageTmp->mteTriggerThresholdDeltaRisingEventLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdDeltaFallingEventOwner(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name,
+ size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdDeltaFallingEventOwner entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdDeltaFallingEventOwner not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdDeltaFallingEventOwner;
+ tmplen = StorageTmp->mteTriggerThresholdDeltaFallingEventOwnerLen;
+ memdup((u_char **) & StorageTmp->
+ mteTriggerThresholdDeltaFallingEventOwner, var_val,
+ var_val_len);
+ StorageTmp->mteTriggerThresholdDeltaFallingEventOwnerLen =
+ var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerThresholdDeltaFallingEventOwner);
+ StorageTmp->mteTriggerThresholdDeltaFallingEventOwner = tmpvar;
+ StorageTmp->mteTriggerThresholdDeltaFallingEventOwnerLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_mteTriggerThresholdDeltaFallingEvent(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP,
+ oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ struct mteTriggerTable_data *StorageTmp = NULL;
+ static size_t tmplen;
+ size_t newlen =
+ name_len -
+ (sizeof(mteTriggerThresholdTable_variables_oid) / sizeof(oid) + 3 -
+ 1);
+
+
+ DEBUGMSGTL(("mteTriggerThresholdTable",
+ "write_mteTriggerThresholdDeltaFallingEvent entering action=%d... \n",
+ action));
+ if ((StorageTmp =
+ header_complex(mteTriggerTableStorage, NULL,
+ &name[sizeof
+ (mteTriggerThresholdTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ fprintf(stderr,
+ "write to mteTriggerThresholdDeltaFallingEvent not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in string for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->mteTriggerThresholdDeltaFallingEvent;
+ tmplen = StorageTmp->mteTriggerThresholdDeltaFallingEventLen;
+ memdup((u_char **) & StorageTmp->
+ mteTriggerThresholdDeltaFallingEvent, var_val, var_val_len);
+ StorageTmp->mteTriggerThresholdDeltaFallingEventLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->mteTriggerThresholdDeltaFallingEvent);
+ StorageTmp->mteTriggerThresholdDeltaFallingEvent = tmpvar;
+ StorageTmp->mteTriggerThresholdDeltaFallingEventLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
diff --git a/agent/mibgroup/disman/mteTriggerThresholdTable.h b/agent/mibgroup/disman/mteTriggerThresholdTable.h
new file mode 100644
index 0000000..8f33011
--- /dev/null
+++ b/agent/mibgroup/disman/mteTriggerThresholdTable.h
@@ -0,0 +1,48 @@
+/*
+ * This file was generated by mib2c and is intended for use as a mib module
+ * for the ucd-snmp snmpd agent.
+ */
+
+
+#ifndef _MIBGROUP_MTETRIGGERTHRESHOLDTABLE_H
+#define _MIBGROUP_MTETRIGGERTHRESHOLDTABLE_H
+
+
+/*
+ * we may use header_complex from the header_complex module
+ */
+
+
+config_require(header_complex)
+
+ /*
+ * enum definitions from the covered mib sections
+ */
+#define MTETRIGGERTHRESHOLDSTARTUP_RISING 1
+#define MTETRIGGERTHRESHOLDSTARTUP_FALLING 2
+#define MTETRIGGERTHRESHOLDSTARTUP_RISINGORFALLING 3
+ /*
+ * function prototypes
+ */
+ void init_mteTriggerThresholdTable(void);
+ FindVarMethod var_mteTriggerThresholdTable;
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ WriteMethod write_mteTriggerThresholdStartup;
+ WriteMethod write_mteTriggerThresholdRising;
+ WriteMethod write_mteTriggerThresholdFalling;
+ WriteMethod write_mteTriggerThresholdDeltaRising;
+ WriteMethod write_mteTriggerThresholdDeltaFalling;
+ WriteMethod write_mteTriggerThresholdObjectsOwner;
+ WriteMethod write_mteTriggerThresholdObjects;
+ WriteMethod write_mteTriggerThresholdRisingEventOwner;
+ WriteMethod write_mteTriggerThresholdRisingEvent;
+ WriteMethod write_mteTriggerThresholdFallingEventOwner;
+ WriteMethod write_mteTriggerThresholdFallingEvent;
+ WriteMethod write_mteTriggerThresholdDeltaRisingEventOwner;
+ WriteMethod write_mteTriggerThresholdDeltaRisingEvent;
+ WriteMethod write_mteTriggerThresholdDeltaFallingEventOwner;
+ WriteMethod write_mteTriggerThresholdDeltaFallingEvent;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+#endif /* _MIBGROUP_MTETRIGGERTHRESHOLDTABLE_H */
diff --git a/agent/mibgroup/disman/nslookup-mib.h b/agent/mibgroup/disman/nslookup-mib.h
new file mode 100644
index 0000000..1c3fb1c
--- /dev/null
+++ b/agent/mibgroup/disman/nslookup-mib.h
@@ -0,0 +1,20 @@
+/*
+*Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+*
+*All right reserved
+*
+*File Name:nslookup-mib.h
+*File Description:Add DISMAN-NSLOOKUP-MIB.
+*
+*Current Version:1.0
+*Author:ChenJing
+*Date:2004.8.20
+*/
+
+/*
+ * wrapper for the disman name lookup mib code files
+ */
+config_require(disman/nslookup/lookupCtlTable)
+config_require(disman/nslookup/lookupResultsTable)
+config_add_mib(DISMAN-NSLOOKUP-MIB)
+
diff --git a/agent/mibgroup/disman/nslookup/lookupCtlTable.c b/agent/mibgroup/disman/nslookup/lookupCtlTable.c
new file mode 100644
index 0000000..3048999
--- /dev/null
+++ b/agent/mibgroup/disman/nslookup/lookupCtlTable.c
@@ -0,0 +1,1415 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:lookupCtlTable.c
+ *File Description:Rows of the lookupCtlTable MIB add , delete and read.Rows of lookupResultsTable
+ * MIB add and delete.
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+/*
+ * This should always be included first before anything else
+ */
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(header_complex_find_entry)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "lookupCtlTable.h"
+#include "lookupResultsTable.h"
+#include "header_complex.h"
+
+#ifndef INETADDRESSTYPE_ENUMS
+#define INETADDRESSTYPE_ENUMS
+
+#define INETADDRESSTYPE_UNKNOWN 0
+#define INETADDRESSTYPE_IPV4 1
+#define INETADDRESSTYPE_IPV6 2
+#define INETADDRESSTYPE_IPV4Z 3
+#define INETADDRESSTYPE_IPV6Z 4
+#define INETADDRESSTYPE_DNS 16
+
+#endif /* INETADDRESSTYPE_ENUMS */
+
+/*
+ *For discontinuity checking.
+ */
+
+oid lookupCtlTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 82, 1, 3 };
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+struct variable2 lookupCtlTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+ {COLUMN_LOOKUPCTLTARGETADDRESSTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_lookupCtlTable, 2, {1, 3}},
+ {COLUMN_LOOKUPCTLTARGETADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_lookupCtlTable, 2, {1, 4}},
+ {COLUMN_LOOKUPCTLOPERSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_lookupCtlTable, 2, {1, 5}},
+ {COLUMN_LOOKUPCTLTIME, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_lookupCtlTable, 2, {1, 6}},
+ {COLUMN_LOOKUPCTLRC, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_lookupCtlTable, 2, {1, 7}},
+ {COLUMN_LOOKUPCTLROWSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_lookupCtlTable, 2, {1, 8}}
+};
+#else /* !NETSNMP_NO_WRITE_SUPPORT */
+struct variable2 lookupCtlTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+ {COLUMN_LOOKUPCTLTARGETADDRESSTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_lookupCtlTable, 2, {1, 3}},
+ {COLUMN_LOOKUPCTLTARGETADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_lookupCtlTable, 2, {1, 4}},
+ {COLUMN_LOOKUPCTLOPERSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_lookupCtlTable, 2, {1, 5}},
+ {COLUMN_LOOKUPCTLTIME, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_lookupCtlTable, 2, {1, 6}},
+ {COLUMN_LOOKUPCTLRC, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_lookupCtlTable, 2, {1, 7}},
+ {COLUMN_LOOKUPCTLROWSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_lookupCtlTable, 2, {1, 8}}
+};
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+
+struct header_complex_index *lookupCtlTableStorage = NULL;
+struct header_complex_index *lookupResultsTableStorage = NULL;
+
+int modify_lookupCtlTime(struct lookupTable_data *thedata, unsigned long val);
+int modify_lookupCtlOperStatus(struct lookupTable_data *thedata, long val);
+int modify_lookupCtlRc(struct lookupTable_data *thedata, long val);
+
+void
+init_lookupCtlTable(void)
+{
+ DEBUGMSGTL(("lookupCtlTable", "initializing... "));
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("lookupCtlTable", lookupCtlTable_variables, variable2,
+ lookupCtlTable_variables_oid);
+
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("lookupCtlTable", parse_lookupCtlTable,
+ NULL, NULL);
+
+ /*
+ * we need to be called back later to store our data
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_lookupCtlTable, NULL);
+
+ DEBUGMSGTL(("lookupCtlTable", "done.\n"));
+}
+
+struct lookupTable_data *
+create_lookupTable_data(void)
+{
+ struct lookupTable_data *StorageNew = NULL;
+ StorageNew = SNMP_MALLOC_STRUCT(lookupTable_data);
+ if (StorageNew == NULL) {
+ snmp_log(LOG_ERR, "Out in memory in nslookup-mib/create_lookupTable_date\n");
+ exit(1);
+ }
+ StorageNew->lookupCtlTargetAddress = strdup("");
+ StorageNew->lookupCtlTargetAddressLen = 0;
+ StorageNew->lookupCtlOperStatus = 2L;
+ StorageNew->lookupCtlTime = 0;
+ StorageNew->storagetype = ST_NONVOLATILE;
+ return StorageNew;
+}
+
+/*
+ * lookupCtlTable_add(): adds a structure node to our data set
+ */
+int
+lookupCtlTable_add(struct lookupTable_data *thedata)
+{
+ netsnmp_variable_list *vars = NULL;
+
+ DEBUGMSGTL(("lookupCtlTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ (char *) thedata->lookupCtlOwnerIndex,
+ thedata->lookupCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ (char *) thedata->lookupCtlOperationName,
+ thedata->lookupCtlOperationNameLen);
+
+
+ if (header_complex_add_data(&lookupCtlTableStorage, vars, thedata) ==
+ NULL) {
+ return SNMPERR_GENERR;
+ }
+ DEBUGMSGTL(("lookupCtlTable", "registered an entry\n"));
+ vars = NULL;
+
+ DEBUGMSGTL(("lookupCtlTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+int
+lookupResultsTable_add(struct lookupTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list = NULL;
+ struct lookupResultsTable_data *p = NULL;
+ p = thedata->ResultsTable;
+ if (thedata->ResultsTable != NULL)
+ do {
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR,
+ (char *) p->lookupCtlOwnerIndex,
+ p->lookupCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR,
+ (char *) p->lookupCtlOperationName,
+ p->lookupCtlOperationNameLen);
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED,
+ (char *) &p->lookupResultsIndex,
+ sizeof(p->lookupResultsIndex));
+
+ DEBUGMSGTL(("lookupResultsTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ if (header_complex_add_data
+ (&lookupResultsTableStorage, vars_list, p) == NULL) {
+ return SNMPERR_GENERR;
+ }
+
+ DEBUGMSGTL(("lookupResultsTable", "out finished\n"));
+ vars_list = NULL;
+ p = p->next;
+ } while (p != NULL);
+
+ DEBUGMSGTL(("lookupResultsTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+void
+lookupCtlTable_cleaner(struct header_complex_index *thestuff)
+{
+ struct header_complex_index *hciptr = NULL;
+ struct lookupTable_data *StorageDel = NULL;
+ DEBUGMSGTL(("lookupCtlTable", "cleanerout "));
+ for (hciptr = thestuff; hciptr != NULL; hciptr = hciptr->next) {
+ StorageDel =
+ header_complex_extract_entry(&lookupCtlTableStorage, hciptr);
+ if (StorageDel != NULL) {
+ free(StorageDel->lookupCtlOwnerIndex);
+ StorageDel->lookupCtlOwnerIndex = NULL;
+ free(StorageDel->lookupCtlOperationName);
+ StorageDel->lookupCtlOperationName = NULL;
+ free(StorageDel->lookupCtlTargetAddress);
+ StorageDel->lookupCtlTargetAddress = NULL;
+ free(StorageDel);
+ StorageDel = NULL;
+
+ }
+ DEBUGMSGTL(("lookupCtlTable", "cleaner "));
+ }
+}
+
+/*
+ * parse_lookupCtlTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+void
+parse_lookupCtlTable(const char *token, char *line)
+{
+ size_t tmpint;
+ struct lookupTable_data *StorageTmp = SNMP_MALLOC_STRUCT(lookupTable_data);
+
+ DEBUGMSGTL(("lookupCtlTable", "parsing config... "));
+
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->lookupCtlOwnerIndex,
+ &StorageTmp->lookupCtlOwnerIndexLen);
+ if (StorageTmp->lookupCtlOwnerIndex == NULL) {
+ config_perror("invalid specification for lookupCtlOwnerIndex");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->lookupCtlOperationName,
+ &StorageTmp->lookupCtlOperationNameLen);
+ if (StorageTmp->lookupCtlOperationName == NULL) {
+ config_perror("invalid specification for lookupCtlOperationName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->lookupCtlTargetAddressType,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->lookupCtlTargetAddress,
+ &StorageTmp->lookupCtlTargetAddressLen);
+ if (StorageTmp->lookupCtlTargetAddress == NULL) {
+ config_perror("invalid specification for lookupCtlTargetAddress");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->lookupCtlOperStatus, &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->lookupCtlTime, &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->lookupCtlRc, &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->lookupCtlRowStatus, &tmpint);
+
+
+ StorageTmp->storagetype = ST_NONVOLATILE;
+ lookupCtlTable_add(StorageTmp);
+ /* lookupCtlTable_cleaner(lookupCtlTableStorage); */
+
+ DEBUGMSGTL(("lookupCtlTable", "done.\n"));
+}
+
+
+
+/*
+ * store_lookupCtlTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+int
+store_lookupCtlTable(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr;
+ size_t tmpint;
+ struct lookupTable_data *StorageTmp;
+ struct header_complex_index *hcindex;
+
+ DEBUGMSGTL(("lookupCtlTable", "storing data... "));
+
+ for (hcindex = lookupCtlTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct lookupTable_data *) hcindex->data;
+
+ if (StorageTmp->storagetype != ST_READONLY) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "lookupCtlTable ");
+ cptr = line + strlen(line);
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->lookupCtlOwnerIndex,
+ &StorageTmp->
+ lookupCtlOwnerIndexLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->lookupCtlOperationName,
+ &StorageTmp->
+ lookupCtlOperationNameLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ lookupCtlTargetAddressType,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->lookupCtlTargetAddress,
+ &StorageTmp->
+ lookupCtlTargetAddressLen);
+
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->lookupCtlOperStatus,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->lookupCtlTime,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->lookupCtlRc, &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->lookupCtlRowStatus,
+ &tmpint);
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("lookupCtlTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+
+
+/*
+ * var_lookupCtlTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_mteObjectsTable above.
+ */
+unsigned char *
+var_lookupCtlTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact, size_t *var_len, WriteMethod ** write_method)
+{
+ struct lookupTable_data *StorageTmp = NULL;
+ *write_method = NULL;
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(lookupCtlTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL) {
+ if (vp->magic == COLUMN_LOOKUPCTLROWSTATUS)
+ *write_method = write_lookupCtlRowStatus;
+ return NULL;
+ }
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+ case COLUMN_LOOKUPCTLTARGETADDRESSTYPE:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_lookupCtlTargetAddressType;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->lookupCtlTargetAddressType);
+ return (u_char *) & StorageTmp->lookupCtlTargetAddressType;
+
+ case COLUMN_LOOKUPCTLTARGETADDRESS:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_lookupCtlTargetAddress;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = (StorageTmp->lookupCtlTargetAddressLen);
+ return (u_char *) StorageTmp->lookupCtlTargetAddress;
+
+ case COLUMN_LOOKUPCTLOPERSTATUS:
+ *var_len = sizeof(StorageTmp->lookupCtlOperStatus);
+ return (u_char *) & StorageTmp->lookupCtlOperStatus;
+
+ case COLUMN_LOOKUPCTLTIME:
+ *var_len = sizeof(StorageTmp->lookupCtlTime);
+ return (u_char *) & StorageTmp->lookupCtlTime;
+
+ case COLUMN_LOOKUPCTLRC:
+ *var_len = sizeof(StorageTmp->lookupCtlRc);
+ return (u_char *) & StorageTmp->lookupCtlRc;
+
+ case COLUMN_LOOKUPCTLROWSTATUS:
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+ *write_method = write_lookupCtlRowStatus;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+ *var_len = sizeof(StorageTmp->lookupCtlRowStatus);
+ return (u_char *) & StorageTmp->lookupCtlRowStatus;
+
+ default:
+ ERROR_MSG("");
+ }
+ return NULL;
+}
+
+
+static struct lookupResultsTable_data *
+add_result(struct lookupTable_data *item, int index,
+ int iatype, const void *data, size_t data_len)
+{
+ struct lookupResultsTable_data *temp;
+ temp = SNMP_MALLOC_STRUCT(lookupResultsTable_data);
+ if (temp == NULL) {
+ snmp_log(LOG_ERR, "Out of memory in nslookup-mib/run_lookup\n");
+ return NULL;
+ }
+ temp->lookupResultsIndex = index;
+ temp->next = NULL;
+
+ temp->lookupCtlOwnerIndex = malloc(item->lookupCtlOwnerIndexLen + 1);
+ if (temp->lookupCtlOwnerIndex == NULL) {
+ snmp_log(LOG_ERR, "Out of memory in nslookup-mib/run_lookup\n");
+ free(temp);
+ return NULL;
+ }
+ memcpy(temp->lookupCtlOwnerIndex,
+ item->lookupCtlOwnerIndex,
+ item->lookupCtlOwnerIndexLen + 1);
+ temp->lookupCtlOwnerIndex[item->lookupCtlOwnerIndexLen] = '\0';
+ temp->lookupCtlOwnerIndexLen = item->lookupCtlOwnerIndexLen;
+
+ temp->lookupCtlOperationName = malloc(item->lookupCtlOperationNameLen + 1);
+ if (temp->lookupCtlOperationName == NULL) {
+ snmp_log(LOG_ERR, "Out of memory in nslookup-mib/run_lookup\n");
+ free(temp->lookupCtlOwnerIndex);
+ free(temp);
+ return NULL;
+ }
+ memcpy(temp->lookupCtlOperationName,
+ item->lookupCtlOperationName,
+ item->lookupCtlOperationNameLen + 1);
+ temp->lookupCtlOperationName[item->lookupCtlOperationNameLen] = '\0';
+ temp->lookupCtlOperationNameLen = item->lookupCtlOperationNameLen;
+
+ temp->lookupResultsAddressType = iatype;
+ temp->lookupResultsAddress = malloc(data_len + 1);
+ memcpy(temp->lookupResultsAddress, data, data_len);
+ temp->lookupResultsAddress[data_len] = '\0';
+ temp->lookupResultsAddressLen = data_len;
+ if (!item->ResultsTable)
+ item->ResultsTable = temp;
+
+ return temp;
+}
+
+void
+run_lookup(struct lookupTable_data *item)
+{
+ long addressType;
+ char *address = NULL;
+ size_t addresslen;
+ struct lookupResultsTable_data *current = NULL;
+ struct lookupResultsTable_data *temp = NULL;
+ int i = 0, n = 1;
+
+ struct timeval tpstart, tpend;
+ unsigned long timeuse, timeuse4 = 0, timeuse6 = 0;
+
+ if (item == NULL)
+ return;
+
+ addressType = (long) item->lookupCtlTargetAddressType;
+ addresslen = (size_t) item->lookupCtlTargetAddressLen;
+ address = (char *) malloc(addresslen + 1);
+ memcpy(address, item->lookupCtlTargetAddress, addresslen + 1);
+ address[addresslen] = '\0';
+
+ if (addressType == INETADDRESSTYPE_IPV4) {
+ struct in_addr addr_in;
+ struct hostent *lookup;
+
+ if (!inet_aton(address, &addr_in)) {
+ DEBUGMSGTL(("lookupResultsTable", "Invalid argument: %s\n",
+ address));
+ modify_lookupCtlRc(item, 99);
+ return;
+ }
+
+ netsnmp_get_monotonic_clock(&tpstart);
+ lookup = netsnmp_gethostbyaddr(&addr_in, sizeof(addr_in), AF_INET);
+ netsnmp_get_monotonic_clock(&tpend);
+ timeuse = 1000000 * (tpend.tv_sec - tpstart.tv_sec) +
+ tpend.tv_usec - tpstart.tv_usec;
+ timeuse /= 1000;
+ modify_lookupCtlTime(item, timeuse);
+ modify_lookupCtlOperStatus(item, 3L);
+
+ if (lookup == NULL) {
+ DEBUGMSGTL(("lookupCtlTable",
+ "Can't get a network host entry for ipv4 address: %s\n",
+ address));
+ modify_lookupCtlRc(item, h_errno);
+ return;
+ } else {
+ modify_lookupCtlRc(item, 0L);
+ if (lookup->h_name != NULL) {
+ current = temp = add_result(item, n, INETADDRESSTYPE_DNS,
+ lookup->h_name, strlen(lookup->h_name));
+ n = n + 1;
+ }
+
+ i = 0;
+ while (lookup->h_aliases[i]) {
+ temp = add_result(item, n, INETADDRESSTYPE_DNS,
+ lookup->h_aliases[i], strlen(lookup->h_aliases[i]));
+ current->next = temp;
+ current = temp;
+ i = i + 1;
+ n = n + 1;
+ }
+ }
+
+ if (item->ResultsTable != NULL)
+ if (lookupResultsTable_add(item) != SNMPERR_SUCCESS)
+ DEBUGMSGTL(("lookupResultsTable",
+ "registered an entry error\n"));
+ SNMP_FREE(address);
+ return;
+ }
+
+ else if (addressType == INETADDRESSTYPE_DNS) {
+ struct hostent *lookup;
+#if HAVE_GETADDRINFO
+ int res;
+ struct addrinfo *ais;
+ struct addrinfo hints = { 0, AF_INET6, SOCK_DGRAM };
+#endif
+
+ netsnmp_get_monotonic_clock(&tpstart);
+ lookup = netsnmp_gethostbyname(address);
+ netsnmp_get_monotonic_clock(&tpend);
+ timeuse4 = 1000000 * (tpend.tv_sec - tpstart.tv_sec) +
+ tpend.tv_usec - tpstart.tv_usec;
+ if (lookup == NULL) {
+ DEBUGMSGTL(("lookupCtlTable",
+ "Can't get a network host entry for %s\n",
+ address));
+ modify_lookupCtlRc(item, h_errno);
+ } else {
+ while (lookup->h_addr_list[i]) {
+ char buf[64];
+ int buflen;
+
+ inet_ntop(lookup->h_addrtype, lookup->h_addr_list[i], buf, sizeof(buf));
+ buflen = strlen(buf);
+ switch (lookup->h_addrtype) {
+ case AF_INET:
+ temp = add_result(item, n, INETADDRESSTYPE_IPV4, buf, buflen);
+ break;
+ case AF_INET6:
+ temp = add_result(item, n, INETADDRESSTYPE_IPV6, buf, buflen);
+ break;
+ default:
+ snmp_log(LOG_ERR, "nslookup-mib/run_lookup: Unknown address type %d\n", lookup->h_addrtype);
+ temp = add_result(item, n, INETADDRESSTYPE_UNKNOWN, "", 0);
+ break;
+ }
+ DEBUGMSGTL(("lookupCtlTable", "Adding %d %s\n", n, buf));
+
+ if (n == 1)
+ item->ResultsTable = temp;
+ else
+ current->next = temp;
+ current = temp;
+ n = n + 1;
+ i = i + 1;
+ }
+ }
+
+#if HAVE_GETADDRINFO
+ netsnmp_get_monotonic_clock(&tpstart);
+ res = netsnmp_getaddrinfo(address, NULL, &hints, &ais);
+ netsnmp_get_monotonic_clock(&tpend);
+ timeuse6 = 1000000 * (tpend.tv_sec - tpstart.tv_sec) +
+ tpend.tv_usec - tpstart.tv_usec;
+
+ if (res != 0) {
+ DEBUGMSGTL(("lookupCtlTable",
+ "Can't get a ipv6 network host entry for %s\n",
+ address));
+ modify_lookupCtlRc(item, res);
+ } else {
+ struct addrinfo *aip = ais;
+ while (aip) {
+ char buf[64];
+ int buflen;
+
+ switch (aip->ai_family) {
+ case AF_INET:
+ inet_ntop(aip->ai_family,
+ &((struct sockaddr_in *)aip->ai_addr)->sin_addr,
+ buf, sizeof(buf));
+ buflen = strlen(buf);
+ temp = add_result(item, n, INETADDRESSTYPE_IPV4, buf, buflen);
+ break;
+ case AF_INET6:
+ inet_ntop(aip->ai_family,
+ &((struct sockaddr_in6 *)aip->ai_addr)->sin6_addr,
+ buf, sizeof(buf));
+ buflen = strlen(buf);
+ temp = add_result(item, n, INETADDRESSTYPE_IPV6, buf, buflen);
+ break;
+ default:
+ snmp_log(LOG_ERR, "nslookup-mib/run_lookup: Unknown address type %d\n", aip->ai_family);
+ temp = add_result(item, n, INETADDRESSTYPE_UNKNOWN, "", 0);
+ break;
+ }
+ DEBUGMSGTL(("lookupCtlTable", "Adding %d %s\n", n, buf));
+
+ if (n == 1)
+ item->ResultsTable = temp;
+ else
+ current->next = temp;
+ current = temp;
+ n = n + 1;
+ aip = aip->ai_next;
+ }
+ freeaddrinfo(ais);
+ }
+#elif HAVE_GETHOSTBYNAME2
+ netsnmp_get_monotonic_clock(&tpstart);
+ lookup = gethostbyname2(address, AF_INET6);
+ netsnmp_get_monotonic_clock(&tpend);
+ timeuse6 = 1000000 * (tpend.tv_sec - tpstart.tv_sec) +
+ tpend.tv_usec - tpstart.tv_usec;
+
+ if (lookup == NULL) {
+ DEBUGMSGTL(("lookupCtlTable",
+ "Can't get a ipv6 network host entry for %s\n",
+ address));
+ modify_lookupCtlRc(item, h_errno);
+ } else {
+ i = 0;
+ while (lookup->h_addr_list[i]) {
+ char buf[64];
+ int buflen;
+
+ inet_ntop(lookup->h_addrtype, lookup->h_addr_list[i],
+ buf, sizeof(buf));
+ buflen = strlen(buf);
+ switch (lookup->h_addrtype) {
+ case AF_INET:
+ temp = add_result(item, n, INETADDRESSTYPE_IPV4, buf, buflen);
+ break;
+ case AF_INET6:
+ temp = add_result(item, n, INETADDRESSTYPE_IPV6, buf, buflen);
+ break;
+ default:
+ snmp_log(LOG_ERR, "nslookup-mib/run_lookup: Unknown address type %d\n", lookup->h_addrtype);
+ temp = add_result(item, n, INETADDRESSTYPE_UNKNOWN, "", 0);
+ break;
+ }
+ DEBUGMSGTL(("lookupCtlTable", "Adding %d %s\n", n, buf));
+
+ if (n == 1)
+ item->ResultsTable = temp;
+ else
+ current->next = temp;
+ current = temp;
+ n = n + 1;
+ i = i + 1;
+ }
+ }
+#endif
+
+ timeuse = timeuse4 + timeuse6;
+ timeuse /= 1000;
+ modify_lookupCtlTime(item, timeuse);
+ modify_lookupCtlOperStatus(item, 3L);
+
+ if (item->ResultsTable != NULL) {
+ modify_lookupCtlRc(item, 0L);
+ if (lookupResultsTable_add(item) != SNMPERR_SUCCESS)
+ DEBUGMSGTL(("lookupResultsTable",
+ "registered an entry error\n"));
+ }
+ SNMP_FREE(address);
+ return;
+ }
+
+ else if (addressType == INETADDRESSTYPE_IPV6) {
+ struct in6_addr addr_in6;
+ struct hostent *lookup;
+
+ if (inet_pton(AF_INET6, address, &addr_in6) == 1)
+ DEBUGMSGTL(("lookupCtlTable", "success! \n"));
+ else
+ DEBUGMSGTL(("lookupCtlTable", "error! \n"));
+
+ netsnmp_get_monotonic_clock(&tpstart);
+ lookup = netsnmp_gethostbyaddr(&addr_in6, sizeof(addr_in6), AF_INET6);
+ netsnmp_get_monotonic_clock(&tpend);
+ timeuse = 1000000 * (tpend.tv_sec - tpstart.tv_sec) +
+ tpend.tv_usec - tpstart.tv_usec;
+ timeuse /= 1000;
+ modify_lookupCtlTime(item, timeuse);
+ modify_lookupCtlOperStatus(item, 3L);
+
+ if (lookup == NULL) {
+ DEBUGMSGTL(("lookupCtlTable",
+ "Can't get a network host entry for %s\n",
+ address));
+ modify_lookupCtlRc(item, h_errno);
+ return;
+ } else {
+ modify_lookupCtlRc(item, 0L);
+ if (lookup->h_name != NULL) {
+ current = temp = add_result(item, n, INETADDRESSTYPE_DNS,
+ lookup->h_name, strlen(lookup->h_name));
+ n = n + 1;
+ }
+
+ i = 0;
+ while (lookup->h_aliases[i]) {
+ current = temp = add_result(item, n, INETADDRESSTYPE_DNS,
+ lookup->h_aliases[i], strlen(lookup->h_aliases[i]));
+ current->next = temp;
+ current = temp;
+ i = i + 1;
+ n = n + 1;
+ }
+
+ if (item->ResultsTable != NULL)
+ current->next = NULL;
+ else
+ current = NULL;
+ }
+
+ if (item->ResultsTable != NULL)
+ if (lookupResultsTable_add(item) != SNMPERR_SUCCESS)
+ DEBUGMSGTL(("lookupResultsTable",
+ "registered an entry error\n"));
+ SNMP_FREE(address);
+ return;
+ } else {
+ SNMP_FREE(address);
+ return;
+ }
+}
+
+
+int
+modify_lookupCtlOperStatus(struct lookupTable_data *thedata, long val)
+{
+ netsnmp_variable_list *vars = NULL;
+ struct lookupTable_data *StorageTmp = NULL;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ (char *) thedata->lookupCtlOwnerIndex, thedata->lookupCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ (char *) thedata->lookupCtlOperationName,
+ thedata->lookupCtlOperationNameLen);
+
+
+ if ((StorageTmp =
+ header_complex_get(lookupCtlTableStorage, vars)) == NULL) {
+ snmp_free_varbind(vars);
+ vars = NULL;
+ return SNMP_ERR_NOSUCHNAME;
+ }
+ StorageTmp->lookupCtlOperStatus = val;
+
+ snmp_free_varbind(vars);
+ vars = NULL;
+
+ DEBUGMSGTL(("lookupOperStatus", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+int
+modify_lookupCtlTime(struct lookupTable_data *thedata, unsigned long val)
+{
+ netsnmp_variable_list *vars = NULL;
+ struct lookupTable_data *StorageTmp = NULL;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ (char *) thedata->lookupCtlOwnerIndex, thedata->lookupCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ (char *) thedata->lookupCtlOperationName,
+ thedata->lookupCtlOperationNameLen);
+
+
+ if ((StorageTmp =
+ header_complex_get(lookupCtlTableStorage, vars)) == NULL) {
+ snmp_free_varbind(vars);
+ vars = NULL;
+ return SNMP_ERR_NOSUCHNAME;
+ }
+ StorageTmp->lookupCtlTime = val;
+
+ snmp_free_varbind(vars);
+ vars = NULL;
+
+ DEBUGMSGTL(("lookupCtlTime", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+int
+modify_lookupCtlRc(struct lookupTable_data *thedata, long val)
+{
+ netsnmp_variable_list *vars = NULL;
+ struct lookupTable_data *StorageTmp = NULL;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ (char *) thedata->lookupCtlOwnerIndex, thedata->lookupCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ (char *) thedata->lookupCtlOperationName,
+ thedata->lookupCtlOperationNameLen);
+
+
+ if ((StorageTmp =
+ header_complex_get(lookupCtlTableStorage, vars)) == NULL) {
+ snmp_free_varbind(vars);
+ vars = NULL;
+ return SNMP_ERR_NOSUCHNAME;
+ }
+ StorageTmp->lookupCtlRc = val;
+
+ snmp_free_varbind(vars);
+ vars = NULL;
+ DEBUGMSGTL(("lookupOperStatus", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+int
+lookupResultsTable_del(struct lookupTable_data *thedata)
+{
+ struct header_complex_index *hciptr2 = NULL;
+ struct lookupResultsTable_data *StorageDel = NULL;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ (char *) thedata->lookupCtlOwnerIndex, thedata->lookupCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ (char *) thedata->lookupCtlOperationName,
+ thedata->lookupCtlOperationNameLen);
+ memset(newoid, '\0', MAX_OID_LEN * sizeof(oid));
+ header_complex_generate_oid(newoid, &newoid_len, NULL, 0, vars);
+
+
+ snmp_free_varbind(vars);
+ vars = NULL;
+ for (hciptr2 = lookupResultsTableStorage; hciptr2 != NULL;
+ hciptr2 = hciptr2->next) {
+ if (snmp_oid_compare(newoid, newoid_len, hciptr2->name, newoid_len)
+ == 0) {
+ StorageDel =
+ header_complex_extract_entry(&lookupResultsTableStorage,
+ hciptr2);
+ if (StorageDel != NULL) {
+ SNMP_FREE(StorageDel->lookupCtlOwnerIndex);
+ SNMP_FREE(StorageDel->lookupCtlOperationName);
+ SNMP_FREE(StorageDel->lookupResultsAddress);
+ SNMP_FREE(StorageDel);
+ }
+ DEBUGMSGTL(("lookupResultsTable", "delete success!\n"));
+
+ }
+ }
+ return SNMPERR_SUCCESS;
+}
+
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+int
+write_lookupCtlTargetAddressType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static size_t tmpvar;
+ struct lookupTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(lookupCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(lookupCtlTableStorage, NULL,
+ &name[sizeof(lookupCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storagetype == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->lookupCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to lookupCtlTargetAddressType not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->lookupCtlTargetAddressType;
+ StorageTmp->lookupCtlTargetAddressType = *((long *) var_val);
+ break;
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->lookupCtlTargetAddressType = tmpvar;
+ break;
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ /** set up to save persistent store */
+ snmp_store_needed(NULL);
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_lookupCtlTargetAddress(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar = NULL;
+ static size_t tmplen;
+ struct lookupTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(lookupCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+ if ((StorageTmp =
+ header_complex(lookupCtlTableStorage, NULL,
+ &name[sizeof(lookupCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storagetype == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->lookupCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to lookupCtlTargetAddress not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->lookupCtlTargetAddress;
+ tmplen = StorageTmp->lookupCtlTargetAddressLen;
+
+ if ((StorageTmp->lookupCtlTargetAddress =
+ (char *) malloc(var_val_len + 1)) == NULL) {
+ snmp_log(LOG_ERR, "Out of memory in nslookup-mib/write_lookupCtlTargetAddress\n");
+ exit(1);
+ }
+ memcpy(StorageTmp->lookupCtlTargetAddress, var_val, var_val_len);
+ StorageTmp->lookupCtlTargetAddress[var_val_len] = '\0';
+ StorageTmp->lookupCtlTargetAddressLen = var_val_len;
+
+ break;
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ free(StorageTmp->lookupCtlTargetAddress);
+ StorageTmp->lookupCtlTargetAddress = NULL;
+ StorageTmp->lookupCtlTargetAddress = tmpvar;
+ StorageTmp->lookupCtlTargetAddressLen = tmplen;
+
+ break;
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ free(tmpvar);
+ tmpvar = NULL;
+
+ /** set up to save persistent store */
+ snmp_store_needed(NULL);
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_lookupCtlRowStatus(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ struct lookupTable_data *StorageTmp = NULL;
+ static struct lookupTable_data *StorageNew = NULL, *StorageDel = NULL;
+ size_t newlen =
+ name_len - (sizeof(lookupCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+ static int old_value;
+ int set_value;
+ static netsnmp_variable_list *vars, *vp;
+ struct header_complex_index *hciptr = NULL;
+
+ StorageTmp =
+ header_complex(lookupCtlTableStorage, NULL,
+ &name[sizeof(lookupCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL, NULL);
+
+ if (var_val_type != ASN_INTEGER || var_val == NULL) {
+ snmp_log(LOG_ERR, "write to lookupCtlRowStatus not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp && StorageTmp->storagetype == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ set_value = *((long *) var_val);
+
+
+ /*
+ * check legal range, and notReady is reserved for us, not a user
+ */
+ if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY)
+ return SNMP_ERR_INCONSISTENTVALUE;
+
+
+ switch (action) {
+ case RESERVE1:
+ /*
+ * stage one: test validity
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * create the row now?
+ */
+
+
+ /*
+ * ditch illegal values now
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+
+ /*
+ * destroying a non-existent row is actually legal
+ */
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+
+
+ /*
+ * illegal creation values
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ } else {
+ /*
+ * row exists. Check for a valid state change
+ */
+ if (set_value == RS_CREATEANDGO
+ || set_value == RS_CREATEANDWAIT) {
+ /*
+ * can't create a row that exists
+ */
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+
+ /*
+ * XXX: interaction with row storage type needed
+ */
+
+ if (StorageTmp->lookupCtlRowStatus == RS_ACTIVE &&
+ set_value != RS_DESTROY) {
+ /*
+ * "Once made active an entry may not be modified except to
+ * delete it." XXX: doesn't this in fact apply to ALL
+ * columns of the table and not just this one?
+ */
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ if (StorageTmp->storagetype != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ break;
+
+
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * creation
+ */
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+ vars = NULL;
+
+ /*
+ * ½«nameΪ¿ÕµÄÈý¸öË÷Òý×ֶμӵ½var±äÁ¿ÁбíµÄĩβ
+ */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* lookupCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* lookupCtlOperationName */
+
+ if (header_complex_parse_oid
+ (&
+ (name
+ [sizeof(lookupCtlTable_variables_oid) / sizeof(oid) +
+ 2]), newlen, vars) != SNMPERR_SUCCESS) {
+ /*
+ * XXX: free, zero vars
+ */
+ snmp_free_varbind(vars);
+ vars = NULL;
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+ vp = vars;
+ StorageNew = create_lookupTable_data();
+ StorageNew->lookupCtlOwnerIndex = malloc(vp->val_len + 1);
+ memcpy(StorageNew->lookupCtlOwnerIndex, vp->val.string,
+ vp->val_len);
+ StorageNew->lookupCtlOwnerIndex[vp->val_len] = '\0';
+ StorageNew->lookupCtlOwnerIndexLen = vp->val_len;
+ vp = vp->next_variable;
+
+ StorageNew->lookupCtlOperationName = malloc(vp->val_len + 1);
+ memcpy(StorageNew->lookupCtlOperationName, vp->val.string,
+ vp->val_len);
+ StorageNew->lookupCtlOperationName[vp->val_len] = '\0';
+ StorageNew->lookupCtlOperationNameLen = vp->val_len;
+ vp = vp->next_variable;
+
+ /*
+ * XXX: fill in default row values here into StorageNew
+ */
+
+ StorageNew->lookupCtlTargetAddressType = INETADDRESSTYPE_IPV4;
+
+ StorageNew->lookupCtlRowStatus = set_value;
+
+ snmp_free_varbind(vars);
+ vars = NULL;
+
+ /*
+ * XXX: free, zero vars, no longer needed?
+ */
+ }
+ break;
+
+ case FREE:
+ /*
+ * XXX: free, zero vars
+ */
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+ case ACTION:
+ /*
+ * The variable has been stored in set_value for you to
+ * use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in
+ * the UNDO case
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * row creation, so add it
+ */
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+ if (StorageNew != NULL)
+ DEBUGMSGTL(("lookupCtlTable",
+ "write_lookupCtlRowStatus entering new=%d... \n",
+ action));
+ lookupCtlTable_add(StorageNew);
+ /*
+ * XXX: ack, and if it is NULL?
+ */
+ } else if (set_value != RS_DESTROY) {
+ /*
+ * set the flag?
+ */
+ old_value = StorageTmp->lookupCtlRowStatus;
+ StorageTmp->lookupCtlRowStatus = *((long *) var_val);
+ } else {
+ /*
+ * destroy... extract it for now
+ */
+ DEBUGMSGTL(("lookupCtlTable",
+ "write_lookupCtlTable_delete 1 \n"));
+ hciptr =
+ header_complex_find_entry(lookupCtlTableStorage,
+ StorageTmp);
+
+ StorageDel =
+ header_complex_extract_entry(&lookupCtlTableStorage,
+ hciptr);
+ lookupResultsTable_del(StorageTmp);
+
+ DEBUGMSGTL(("lookupCtlTable",
+ "write_lookupCtlTable_delete \n"));
+
+ }
+ break;
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * row creation, so remove it again
+ */
+ hciptr =
+ header_complex_find_entry(lookupCtlTableStorage,
+ StorageTmp);
+ StorageDel =
+ header_complex_extract_entry(&lookupCtlTableStorage,
+ hciptr);
+
+ lookupResultsTable_del(StorageTmp);
+
+ /*
+ * XXX: free it
+ */
+ } else if (StorageDel != NULL) {
+ /*
+ * row deletion, so add it again
+ */
+ lookupCtlTable_add(StorageDel);
+ lookupResultsTable_add(StorageDel);
+ } else {
+ StorageTmp->lookupCtlRowStatus = old_value;
+ }
+ break;
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ if (StorageTmp == NULL) {
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+ }
+
+ if (StorageDel != NULL) {
+ SNMP_FREE(StorageDel->lookupCtlOwnerIndex);
+ SNMP_FREE(StorageDel->lookupCtlOperationName);
+ SNMP_FREE(StorageDel->lookupCtlTargetAddress);
+ SNMP_FREE(StorageDel);
+ /*
+ * XXX: free it, its dead
+ */
+ } else {
+ if (StorageTmp
+ && StorageTmp->lookupCtlRowStatus == RS_CREATEANDGO) {
+ StorageTmp->lookupCtlRowStatus = RS_ACTIVE;
+ } else if (StorageTmp &&
+ StorageTmp->lookupCtlRowStatus ==
+ RS_CREATEANDWAIT) {
+
+ StorageTmp->lookupCtlRowStatus = RS_NOTINSERVICE;
+ }
+ }
+ if (StorageTmp && StorageTmp->lookupCtlRowStatus == RS_ACTIVE) {
+ DEBUGMSGTL(("lookupCtlTable",
+ "write_lookupCtlRowStatus entering runbefore=%ld... \n",
+ StorageTmp->lookupCtlTargetAddressType));
+
+ modify_lookupCtlOperStatus(StorageTmp, 2L);
+ run_lookup((struct lookupTable_data *) StorageTmp);
+
+ }
+
+ /** set up to save persistent store */
+ snmp_store_needed(NULL);
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
diff --git a/agent/mibgroup/disman/nslookup/lookupCtlTable.h b/agent/mibgroup/disman/nslookup/lookupCtlTable.h
new file mode 100644
index 0000000..085b25b
--- /dev/null
+++ b/agent/mibgroup/disman/nslookup/lookupCtlTable.h
@@ -0,0 +1,87 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:lookupCtlTable.h
+ *File Description:The head file of lookupCtlTable.c
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+#ifndef LOOKUPCTLTABLE_H
+#define LOOKUPCTLTABLE_H
+
+/*
+ * we may use header_complex from the header_complex module
+ */
+
+
+config_require(header_complex);
+
+ /*
+ * our storage structure(s)
+ */
+
+struct lookupTable_data {
+ char *lookupCtlOwnerIndex; /* string */
+ size_t lookupCtlOwnerIndexLen;
+ char *lookupCtlOperationName; /* string */
+ size_t lookupCtlOperationNameLen;
+ long lookupCtlTargetAddressType; /* integer32 */
+ char *lookupCtlTargetAddress; /* string */
+ size_t lookupCtlTargetAddressLen;
+ long lookupCtlOperStatus; /* integer */
+ unsigned long lookupCtlTime; /* unsigned integer */
+ long lookupCtlRc; /* integer32 */
+ long lookupCtlRowStatus; /* integer */
+ int storagetype;
+
+ struct lookupResultsTable_data *ResultsTable;
+};
+
+
+struct lookupResultsTable_data {
+ struct lookupResultsTable_data *next;
+ char *lookupCtlOwnerIndex; /* string */
+ size_t lookupCtlOwnerIndexLen;
+ char *lookupCtlOperationName; /* string */
+ size_t lookupCtlOperationNameLen;
+ unsigned long lookupResultsIndex;
+ long lookupResultsAddressType;
+ char *lookupResultsAddress;
+ size_t lookupResultsAddressLen;
+ int storagetype;
+};
+
+/*
+ * function declarations
+ */
+void init_lookupCtlTable(void);
+FindVarMethod var_lookupCtlTable;
+void parse_lookupCtlTable(const char *, char *);
+SNMPCallback store_lookupCtlTable;
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+WriteMethod write_lookupCtlTargetAddressType;
+WriteMethod write_lookupCtlTargetAddress;
+WriteMethod write_lookupCtlRowStatus;
+
+WriteMethod write_lookupCtlRowStatus;
+#endif /* !NETSNMP_NO_WRITE_SUPPORT */
+
+/*
+ * column number definitions for table lookupCtlTable
+ */
+#define COLUMN_LOOKUPCTLOWNERINDEX 1
+#define COLUMN_LOOKUPCTLOPERATIONNAME 2
+#define COLUMN_LOOKUPCTLTARGETADDRESSTYPE 3
+#define COLUMN_LOOKUPCTLTARGETADDRESS 4
+#define COLUMN_LOOKUPCTLOPERSTATUS 5
+#define COLUMN_LOOKUPCTLTIME 6
+#define COLUMN_LOOKUPCTLRC 7
+#define COLUMN_LOOKUPCTLROWSTATUS 8
+
+#endif /* LOOKUPMIB_H */
diff --git a/agent/mibgroup/disman/nslookup/lookupResultsTable.c b/agent/mibgroup/disman/nslookup/lookupResultsTable.c
new file mode 100644
index 0000000..d6a937c
--- /dev/null
+++ b/agent/mibgroup/disman/nslookup/lookupResultsTable.c
@@ -0,0 +1,306 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:lookupResultsTable.c
+ *File Description:Rows of the lookupResultsTable MIB read.
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+/*
+ * This should always be included first before anything else
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "lookupCtlTable.h"
+#include "lookupResultsTable.h"
+#include "header_complex.h"
+
+
+oid lookupResultsTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 82, 1, 4 };
+
+struct variable2 lookupResultsTable_variables[] = {
+ {COLUMN_LOOKUPRESULTSADDRESSTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_lookupResultsTable, 2, {1, 2}},
+ {COLUMN_LOOKUPRESULTSADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_lookupResultsTable, 2, {1, 3}}
+};
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+
+extern struct header_complex_index *lookupCtlTableStorage;
+extern struct header_complex_index *lookupResultsTableStorage;
+
+int
+lookupResultsTable_inadd(struct lookupResultsTable_data *thedata);
+
+void
+lookupResultsTable_cleaner(struct header_complex_index *thestuff)
+{
+ struct header_complex_index *hciptr = NULL;
+ struct lookupResultsTable_data *StorageDel = NULL;
+ DEBUGMSGTL(("lookupResultsTable", "cleanerout "));
+ for (hciptr = thestuff; hciptr != NULL; hciptr = hciptr->next) {
+ StorageDel =
+ header_complex_extract_entry(&lookupResultsTableStorage,
+ hciptr);
+ if (StorageDel != NULL) {
+ SNMP_FREE(StorageDel->lookupCtlOwnerIndex);
+ SNMP_FREE(StorageDel->lookupCtlOperationName);
+ SNMP_FREE(StorageDel->lookupResultsAddress);
+ SNMP_FREE(StorageDel);
+ }
+ DEBUGMSGTL(("lookupResultsTable", "cleaner "));
+ }
+
+}
+void
+init_lookupResultsTable(void)
+{
+
+ DEBUGMSGTL(("lookupResultsTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("lookupResultsTable", lookupResultsTable_variables,
+ variable2, lookupResultsTable_variables_oid);
+
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("lookupResultsTable",
+ parse_lookupResultsTable, NULL, NULL);
+
+ /*
+ * we need to be called back later to store our data
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_lookupResultsTable, NULL);
+
+ DEBUGMSGTL(("lookupResultsTable", "done.\n"));
+}
+
+/*
+ * parse_mteObjectsTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+
+void
+parse_lookupResultsTable(const char *token, char *line)
+{
+ size_t tmpint;
+ struct lookupResultsTable_data *StorageTmp =
+ SNMP_MALLOC_STRUCT(lookupResultsTable_data);
+
+ DEBUGMSGTL(("lookupResultsTable", "parsing config... "));
+
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->lookupCtlOwnerIndex,
+ &StorageTmp->lookupCtlOwnerIndexLen);
+ if (StorageTmp->lookupCtlOwnerIndex == NULL) {
+ config_perror("invalid specification for lookupCtlOwnerIndex");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->lookupCtlOperationName,
+ &StorageTmp->lookupCtlOperationNameLen);
+ if (StorageTmp->lookupCtlOperationName == NULL) {
+ config_perror("invalid specification for lookupCtlOperationName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->lookupResultsIndex, &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->lookupResultsAddressType,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->lookupResultsAddress,
+ &StorageTmp->lookupResultsAddressLen);
+ if (StorageTmp->lookupResultsAddress == NULL) {
+ config_perror("invalid specification for lookupResultsAddress");
+ return;
+ }
+
+
+ lookupResultsTable_inadd(StorageTmp);
+
+ /* lookupResultsTable_cleaner(lookupResultsTableStorage); */
+
+ DEBUGMSGTL(("lookupResultsTable", "done.\n"));
+}
+
+
+
+
+
+/*
+ * store_lookupResultsTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+
+int
+store_lookupResultsTable(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr = NULL;
+ size_t tmpint;
+ struct lookupResultsTable_data *StorageTmp = NULL;
+ struct header_complex_index *hcindex = NULL;
+
+
+ DEBUGMSGTL(("lookupResultsTable", "storing data... "));
+
+
+ for (hcindex = lookupResultsTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct lookupResultsTable_data *) hcindex->data;
+
+ if (StorageTmp->storagetype != ST_READONLY) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "lookupResultsTable ");
+ cptr = line + strlen(line);
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->lookupCtlOwnerIndex,
+ &StorageTmp->
+ lookupCtlOwnerIndexLen);
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->lookupCtlOperationName,
+ &StorageTmp->
+ lookupCtlOperationNameLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->lookupResultsIndex,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ lookupResultsAddressType, &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->lookupResultsAddress,
+ &StorageTmp->
+ lookupResultsAddressLen);
+
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("lookupResultsTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+int
+lookupResultsTable_inadd(struct lookupResultsTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list = NULL;
+
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR,
+ (char *) thedata->lookupCtlOwnerIndex,
+ thedata->lookupCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR,
+ (char *) thedata->lookupCtlOperationName,
+ thedata->lookupCtlOperationNameLen);
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED,
+ (char *) &thedata->lookupResultsIndex,
+ sizeof(thedata->lookupResultsIndex));
+
+ /*
+ * XXX: fill in default row values here into StorageNew
+ *
+ */
+
+
+ DEBUGMSGTL(("lookupResultsTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ header_complex_add_data(&lookupResultsTableStorage, vars_list,
+ thedata);
+ DEBUGMSGTL(("lookupResultsTable", "registered an entry\n"));
+
+
+ DEBUGMSGTL(("lookupResultsTable", "done.\n"));
+ vars_list = NULL;
+ return SNMPERR_SUCCESS;
+}
+
+
+/*
+ * var_lookupResultsTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_lookupResultsTable above.
+ */
+unsigned char *
+var_lookupResultsTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact,
+ size_t *var_len, WriteMethod ** write_method)
+{
+
+
+ struct lookupResultsTable_data *StorageTmp = NULL;
+
+ *write_method = NULL;
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(lookupResultsTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL) {
+ return NULL;
+ }
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+
+ switch (vp->magic) {
+
+ case COLUMN_LOOKUPRESULTSADDRESSTYPE:
+ *var_len = sizeof(StorageTmp->lookupResultsAddressType);
+ return (u_char *) & StorageTmp->lookupResultsAddressType;
+
+ case COLUMN_LOOKUPRESULTSADDRESS:
+ *var_len = (StorageTmp->lookupResultsAddressLen);
+ return (u_char *) StorageTmp->lookupResultsAddress;
+
+ default:
+ ERROR_MSG("");
+ }
+
+ return NULL;
+}
diff --git a/agent/mibgroup/disman/nslookup/lookupResultsTable.h b/agent/mibgroup/disman/nslookup/lookupResultsTable.h
new file mode 100644
index 0000000..4abfb11
--- /dev/null
+++ b/agent/mibgroup/disman/nslookup/lookupResultsTable.h
@@ -0,0 +1,39 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:lookupResultsTable.h
+ *File Description:The head file of lookupResultsTable.c
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+
+#ifndef LOOKUPRESULTSTABLE_H
+#define LOOKUPRESULTSTABLE_H
+
+/*
+ * we may use header_complex from the header_complex module
+ */
+
+
+config_require(header_complex);
+
+/*
+ * function declarations
+ */
+void init_lookupResultsTable(void);
+FindVarMethod var_lookupResultsTable;
+void parse_lookupResultsTable(const char *, char *);
+SNMPCallback store_lookupResultsTable;
+
+/*
+ * column number definitions for table lookupResultsTable
+ */
+#define COLUMN_LOOKUPRESULTSINDEX 1
+#define COLUMN_LOOKUPRESULTSADDRESSTYPE 2
+#define COLUMN_LOOKUPRESULTSADDRESS 3
+#endif /* LOOKUPMIB_H */
diff --git a/agent/mibgroup/disman/old-event-mib.h b/agent/mibgroup/disman/old-event-mib.h
new file mode 100644
index 0000000..71ef1f5
--- /dev/null
+++ b/agent/mibgroup/disman/old-event-mib.h
@@ -0,0 +1,33 @@
+config_add_mib(DISMAN-EVENT-MIB)
+
+/*
+ * wrapper for the original disman event mib implementation code files
+ */
+config_require(disman/mteTriggerTable)
+config_require(disman/mteTriggerDeltaTable)
+config_require(disman/mteTriggerExistenceTable)
+config_require(disman/mteTriggerBooleanTable)
+config_require(disman/mteTriggerThresholdTable)
+config_require(disman/mteObjectsTable)
+config_require(disman/mteEventTable)
+config_require(disman/mteEventNotificationTable)
+
+/*
+ * conflicts with the new implementation
+ */
+config_exclude(disman/event/mteScalars)
+config_exclude(disman/event/mteTrigger)
+config_exclude(disman/event/mteTriggerTable)
+config_exclude(disman/event/mteTriggerDeltaTable)
+config_exclude(disman/event/mteTriggerExistenceTable)
+config_exclude(disman/event/mteTriggerBooleanTable)
+config_exclude(disman/event/mteTriggerThresholdTable)
+config_exclude(disman/event/mteTriggerConf)
+config_exclude(disman/event/mteEvent)
+config_exclude(disman/event/mteEventTable)
+config_exclude(disman/event/mteEventSetTable)
+config_exclude(disman/event/mteEventNotificationTable)
+config_exclude(disman/event/mteEventConf)
+config_exclude(disman/event/mteObjects)
+config_exclude(disman/event/mteObjectsTable)
+config_exclude(disman/event/mteObjectsConf)
diff --git a/agent/mibgroup/disman/ping-mib.h b/agent/mibgroup/disman/ping-mib.h
new file mode 100644
index 0000000..640b37f
--- /dev/null
+++ b/agent/mibgroup/disman/ping-mib.h
@@ -0,0 +1,20 @@
+/*
+*Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+*
+*All right reserved
+*
+*File Name:ping-mib.h
+*File Description:Add DISMAN-PING-MIB.
+*
+*Current Version:1.0
+*Author:ChenJing
+*Date:2004.8.20
+*/
+
+/*
+ * wrapper for the disman ping mib code files
+ */
+config_require(disman/ping/pingCtlTable)
+config_require(disman/ping/pingResultsTable)
+config_require(disman/ping/pingProbeHistoryTable)
+config_add_mib(DISMAN-PING-MIB)
diff --git a/agent/mibgroup/disman/ping/pingCtlTable.c b/agent/mibgroup/disman/ping/pingCtlTable.c
new file mode 100644
index 0000000..b9add8f
--- /dev/null
+++ b/agent/mibgroup/disman/ping/pingCtlTable.c
@@ -0,0 +1,5829 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:pingCtlTable.c
+ *File Description:Rows of the pingCtlTable MIB add , delete and read.Rows of lookupResultsTable
+ * MIB add and delete.Rows of pingProbeHistoryTable MIB add and delete.
+ * The main function is also here.
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+/*
+ * This should always be included first before anything else
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <netdb.h>
+#include <netinet/in.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include "pingCtlTable.h"
+#include "pingResultsTable.h"
+#include "pingProbeHistoryTable.h"
+#include "header_complex.h"
+
+static inline void tvsub(struct timeval *, struct timeval *);
+static inline int schedule_exit(int, int *, long *, long *, long *, long *);
+static inline int in_flight(__u16 *, long *, long *, long *);
+static inline void acknowledge(__u16, __u16 *, long *, int *);
+static inline void advance_ntransmitted(__u16 *, long *);
+static inline void update_interval(int, int, int *, int *);
+static long llsqrt(long long);
+static __inline__ int ipv6_addr_any(struct in6_addr *);
+static char *pr_addr(struct in6_addr *, int);
+static char *pr_addr_n(struct in6_addr *);
+void pingCtlTable_cleaner(struct header_complex_index *thestuff);
+
+/*
+ *pingCtlTable_variables_oid:
+ *
+ */
+
+
+oid pingCtlTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 80, 1, 2 };
+static const int pingCtlTable_variables_oid_len = sizeof(pingCtlTable_variables_oid)/sizeof(pingCtlTable_variables_oid[0]);
+
+/* trap */
+oid pingProbeFailed[] = { 1, 3, 6, 1, 2, 1, 80, 0, 1 };
+oid pingTestFailed[] = { 1, 3, 6, 1, 2, 1, 80, 0, 2 };
+oid pingTestCompleted[] = { 1, 3, 6, 1, 2, 1, 80, 0, 3 };
+
+
+struct variable2 pingCtlTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+ {COLUMN_PINGCTLTARGETADDRESSTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 3}},
+ {COLUMN_PINGCTLTARGETADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 4}},
+ {COLUMN_PINGCTLDATASIZE, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_pingCtlTable, 2, {1, 5}},
+ {COLUMN_PINGCTLTIMEOUT, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_pingCtlTable, 2, {1, 6}},
+ {COLUMN_PINGCTLPROBECOUNT, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_pingCtlTable, 2, {1, 7}},
+ {COLUMN_PINGCTLADMINSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 8}},
+ {COLUMN_PINGCTLDATAFILL, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 9}},
+ {COLUMN_PINGCTLFREQUENCY, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 10}},
+ {COLUMN_PINGCTLMAXROWS, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 11}},
+ {COLUMN_PINGCTLSTORAGETYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 12}},
+ {COLUMN_PINGCTLTRAPGENERATION, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 13}},
+ {COLUMN_PINGCTLTRAPPROBEFAILUREFILTER, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 14}},
+ {COLUMN_PINGCTLTRAPTESTFAILUREFILTER, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 15}},
+ {COLUMN_PINGCTLTYPE, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 16}},
+ {COLUMN_PINGCTLDESCR, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 17}},
+ {COLUMN_PINGCTLSOURCEADDRESSTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 18}},
+ {COLUMN_PINGCTLSOURCEADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 19}},
+ {COLUMN_PINGCTLIFINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 20}},
+ {COLUMN_PINGCTLBYPASSROUTETABLE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 21}},
+ {COLUMN_PINGCTLDSFIELD, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 22}},
+ {COLUMN_PINGCTLROWSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_pingCtlTable, 2, {1, 23}}
+};
+
+
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+
+
+struct header_complex_index *pingCtlTableStorage = NULL;
+struct header_complex_index *pingResultsTableStorage = NULL;
+struct header_complex_index *pingProbeHistoryTableStorage = NULL;
+
+void
+init_pingCtlTable(void)
+{
+ DEBUGMSGTL(("pingCtlTable", "initializing... "));
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("pingCtlTable", pingCtlTable_variables, variable2,
+ pingCtlTable_variables_oid);
+
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("pingCtlTable", parse_pingCtlTable,
+ NULL, NULL);
+
+ /*
+ * we need to be called back later to store our data
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_pingCtlTable, NULL);
+
+ DEBUGMSGTL(("pingCtlTable", "done.\n"));
+}
+
+void shutdown_pingCtlTable(void)
+{
+ snmp_unregister_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_pingCtlTable, NULL, 1);
+ snmpd_unregister_config_handler("pingCtlTable");
+ unregister_mib(pingCtlTable_variables_oid, pingCtlTable_variables_oid_len);
+ pingCtlTable_cleaner(pingCtlTableStorage);
+ pingCtlTableStorage = NULL;
+}
+
+struct pingCtlTable_data *
+create_pingCtlTable_data(void)
+{
+ struct pingCtlTable_data *StorageNew = NULL;
+
+ StorageNew = SNMP_MALLOC_STRUCT(pingCtlTable_data);
+ if (StorageNew == NULL)
+ return NULL;
+ StorageNew->pingCtlTargetAddressType = 1;
+ StorageNew->pingCtlTargetAddress = strdup("");
+ StorageNew->pingCtlTargetAddressLen = 0;
+ StorageNew->pingCtlDataSize = 0;
+ StorageNew->pingCtlTimeOut = 3;
+ StorageNew->pingCtlProbeCount = 1;
+ StorageNew->pingCtlAdminStatus = 2;
+ StorageNew->pingCtlDataFill = strdup("00");
+ if (StorageNew->pingCtlDataFill == NULL) {
+ free(StorageNew);
+ return NULL;
+ }
+ StorageNew->pingCtlDataFillLen = strlen(StorageNew->pingCtlDataFill);
+ StorageNew->pingCtlFrequency = 0;
+ StorageNew->pingCtlMaxRows = 50;
+ StorageNew->pingCtlStorageType = 1;
+ StorageNew->pingCtlTrapGeneration = strdup("");
+ StorageNew->pingCtlTrapGenerationLen = 0;
+ StorageNew->pingCtlTrapProbeFailureFilter = 1;
+ StorageNew->pingCtlTrapTestFailureFilter = 1;
+ StorageNew->pingCtlType = calloc(1, sizeof(oid) * sizeof(2)); /* 0.0 */
+ StorageNew->pingCtlTypeLen = 2;
+ StorageNew->pingCtlDescr = strdup("");
+ StorageNew->pingCtlDescrLen = 0;
+ StorageNew->pingCtlSourceAddressType = 1;
+ StorageNew->pingCtlSourceAddress = strdup("");
+ StorageNew->pingCtlSourceAddressLen = 0;
+ StorageNew->pingCtlIfIndex = 0;
+ StorageNew->pingCtlByPassRouteTable = 2;
+ StorageNew->pingCtlDSField = 0;
+ StorageNew->pingResults = NULL;
+ StorageNew->pingProbeHis = NULL;
+
+ StorageNew->storageType = ST_NONVOLATILE;
+ StorageNew->pingProbeHistoryMaxIndex = 0;
+ return StorageNew;
+}
+
+static void free_pingCtlTable_data(struct pingCtlTable_data *StorageDel)
+{
+ netsnmp_assert(StorageDel);
+ free(StorageDel->pingCtlOwnerIndex);
+ free(StorageDel->pingCtlTestName);
+ free(StorageDel->pingCtlTargetAddress);
+ free(StorageDel->pingCtlDataFill);
+ free(StorageDel->pingCtlTrapGeneration);
+ free(StorageDel->pingCtlType);
+ free(StorageDel->pingCtlDescr);
+ free(StorageDel->pingCtlSourceAddress);
+ free(StorageDel);
+}
+
+/*
+ * pingCtlTable_add(): adds a structure node to our data set
+ */
+int
+pingCtlTable_add(struct pingCtlTable_data *thedata)
+{
+ netsnmp_variable_list *vars = NULL;
+
+
+ DEBUGMSGTL(("pingCtlTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlOwnerIndex,
+ thedata->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlTestName,
+ thedata->pingCtlTestNameLen);
+ header_complex_add_data(&pingCtlTableStorage, vars, thedata);
+
+ DEBUGMSGTL(("pingCtlTable", "registered an entry\n"));
+
+ return SNMPERR_SUCCESS;
+}
+
+int
+pingResultsTable_add(struct pingCtlTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list = NULL;
+ struct pingResultsTable_data *p;
+
+ p = thedata->pingResults;
+ if (thedata->pingResults != NULL) {
+
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR,
+ p->pingCtlOwnerIndex,
+ p->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR,
+ p->pingCtlTestName, p->pingCtlTestNameLen);
+
+ /*
+ * XXX: fill in default row values here into StorageNew
+ *
+ */
+
+
+ DEBUGMSGTL(("pingResultsTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ header_complex_add_data(&pingResultsTableStorage, vars_list, p);
+
+ DEBUGMSGTL(("pingResultsTable", "out finished\n"));
+
+ }
+
+ return SNMPERR_SUCCESS;
+}
+
+
+int
+pingProbeHistoryTable_add(struct pingProbeHistoryTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list;
+
+ vars_list = NULL;
+ if (thedata != NULL) {
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlOwnerIndex,
+ thedata->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlTestName,
+ thedata->pingCtlTestNameLen);
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED,
+ &thedata->pingProbeHistoryIndex,
+ sizeof(thedata->pingProbeHistoryIndex));
+
+ /*
+ * XXX: fill in default row values here into StorageNew
+ *
+ */
+
+
+ DEBUGMSGTL(("pingProbeHistoryTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ header_complex_add_data(&pingProbeHistoryTableStorage, vars_list,
+ thedata);
+ DEBUGMSGTL(("pingProbeHistoryTable", "out finished\n"));
+ }
+
+ return SNMPERR_SUCCESS;
+}
+
+int
+pingProbeHistoryTable_addall(struct pingCtlTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list;
+ struct pingProbeHistoryTable_data *p;
+
+ for (p = thedata->pingProbeHis; p; p = p->next) {
+ vars_list = NULL;
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR,
+ p->pingCtlOwnerIndex,
+ p->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR,
+ p->pingCtlTestName,
+ p->pingCtlTestNameLen);
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED,
+ &p->pingProbeHistoryIndex,
+ sizeof(p->pingProbeHistoryIndex));
+ header_complex_add_data(&pingProbeHistoryTableStorage, vars_list, p);
+ }
+
+ return SNMPERR_SUCCESS;
+}
+
+void
+pingCtlTable_cleaner(struct header_complex_index *thestuff)
+{
+ struct header_complex_index *hciptr, *next;
+ struct pingCtlTable_data *StorageDel;
+
+ DEBUGMSGTL(("pingProbeHistoryTable", "cleanerout "));
+ for (hciptr = thestuff; hciptr; hciptr = next) {
+ next = hciptr->next;
+ StorageDel = header_complex_extract_entry(&pingCtlTableStorage, hciptr);
+ free_pingCtlTable_data(StorageDel);
+ DEBUGMSGTL(("pingProbeHistoryTable", "cleaner "));
+ }
+}
+
+/*
+ * parse_mteObjectsTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+void
+parse_pingCtlTable(const char *token, char *line)
+{
+ size_t tmpint;
+ struct pingCtlTable_data *StorageTmp =
+ SNMP_MALLOC_STRUCT(pingCtlTable_data);
+
+ DEBUGMSGTL(("pingCtlTable", "parsing config... "));
+
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingCtlOwnerIndex,
+ &StorageTmp->pingCtlOwnerIndexLen);
+ if (StorageTmp->pingCtlOwnerIndex == NULL) {
+ config_perror("invalid specification for pingCtlOwnerIndex");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingCtlTestName,
+ &StorageTmp->pingCtlTestNameLen);
+ if (StorageTmp->pingCtlTestName == NULL) {
+ config_perror("invalid specification for pingCtlTestName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pingCtlTargetAddressType,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingCtlTargetAddress,
+ &StorageTmp->pingCtlTargetAddressLen);
+ if (StorageTmp->pingCtlTargetAddress == NULL) {
+ config_perror("invalid specification for pingCtlTargetAddress");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingCtlDataSize, &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingCtlTimeOut, &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingCtlProbeCount, &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pingCtlAdminStatus, &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingCtlDataFill,
+ &StorageTmp->pingCtlDataFillLen);
+ if (StorageTmp->pingCtlDataFill == NULL) {
+ config_perror("invalid specification for pingCtlDataFill");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingCtlFrequency, &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingCtlMaxRows, &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pingCtlStorageType, &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingCtlTrapGeneration,
+ &StorageTmp->pingCtlTrapGenerationLen);
+ if (StorageTmp->pingCtlTrapGeneration == NULL) {
+ config_perror("invalid specification for pingCtlTrapGeneration");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingCtlTrapProbeFailureFilter,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingCtlTrapTestFailureFilter,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OBJECT_ID, line,
+ &StorageTmp->pingCtlType,
+ &StorageTmp->pingCtlTypeLen);
+ if (StorageTmp->pingCtlType == NULL) {
+ config_perror("invalid specification for pingCtlType");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingCtlDescr,
+ &StorageTmp->pingCtlDescrLen);
+ if (StorageTmp->pingCtlDescr == NULL) {
+ config_perror("invalid specification for pingCtlTrapDescr");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pingCtlSourceAddressType,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingCtlSourceAddress,
+ &StorageTmp->pingCtlSourceAddressLen);
+ if (StorageTmp->pingCtlSourceAddress == NULL) {
+ config_perror("invalid specification for pingCtlSourceAddress");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pingCtlIfIndex, &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pingCtlByPassRouteTable,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingCtlDSField, &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pingCtlRowStatus, &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingProbeHistoryMaxIndex,
+ &tmpint);
+
+ StorageTmp->storageType = ST_NONVOLATILE;
+ pingCtlTable_add(StorageTmp);
+ /* pingCtlTable_cleaner(pingCtlTableStorage); */
+
+ DEBUGMSGTL(("pingCtlTable", "done.\n"));
+}
+
+
+
+/*
+ * store_pingCtlTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+int
+store_pingCtlTable(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr = NULL;
+ size_t tmpint;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ struct header_complex_index *hcindex = NULL;
+
+
+ DEBUGMSGTL(("pingCtlTable", "storing data... "));
+
+
+ for (hcindex = pingCtlTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct pingCtlTable_data *) hcindex->data;
+
+ if (StorageTmp->storageType != ST_READONLY) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "pingCtlTable ");
+ cptr = line + strlen(line);
+
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pingCtlOwnerIndex,
+ &StorageTmp->pingCtlOwnerIndexLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pingCtlTestName,
+ &StorageTmp->pingCtlTestNameLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ pingCtlTargetAddressType, &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pingCtlTargetAddress,
+ &StorageTmp->
+ pingCtlTargetAddressLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->pingCtlDataSize,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->pingCtlTimeOut,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->pingCtlProbeCount,
+ &tmpint);
+
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pingCtlAdminStatus,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pingCtlDataFill,
+ &StorageTmp->pingCtlDataFillLen);
+
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->pingCtlFrequency,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->pingCtlMaxRows,
+ &tmpint);
+
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pingCtlStorageType,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pingCtlTrapGeneration,
+ &StorageTmp->
+ pingCtlTrapGenerationLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ pingCtlTrapProbeFailureFilter,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ pingCtlTrapTestFailureFilter,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OBJECT_ID, cptr,
+ &StorageTmp->pingCtlType,
+ &StorageTmp->pingCtlTypeLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pingCtlDescr,
+ &StorageTmp->pingCtlDescrLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ pingCtlSourceAddressType, &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pingCtlSourceAddress,
+ &StorageTmp->
+ pingCtlSourceAddressLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pingCtlIfIndex,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ pingCtlByPassRouteTable, &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->pingCtlDSField,
+ &tmpint);
+
+ if (StorageTmp->pingCtlRowStatus == RS_ACTIVE)
+ StorageTmp->pingCtlRowStatus = RS_NOTINSERVICE;
+
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pingCtlRowStatus,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ pingProbeHistoryMaxIndex, &tmpint);
+
+
+
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("pingCtlTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+/*
+ * var_pingCtlTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_mteObjectsTable above.
+ */
+unsigned char *
+var_pingCtlTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact, size_t *var_len, WriteMethod ** write_method)
+{
+
+
+ struct pingCtlTable_data *StorageTmp = NULL;
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL) {
+ if (vp->magic == COLUMN_PINGCTLROWSTATUS)
+ *write_method = write_pingCtlRowStatus;
+ return NULL;
+ }
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+
+
+ case COLUMN_PINGCTLTARGETADDRESSTYPE:
+ *write_method = write_pingCtlTargetAddressType;
+ *var_len = sizeof(StorageTmp->pingCtlTargetAddressType);
+ return (u_char *) & StorageTmp->pingCtlTargetAddressType;
+
+ case COLUMN_PINGCTLTARGETADDRESS:
+ *write_method = write_pingCtlTargetAddress;
+ *var_len = (StorageTmp->pingCtlTargetAddressLen);
+
+ return (u_char *) StorageTmp->pingCtlTargetAddress;
+
+ case COLUMN_PINGCTLDATASIZE:
+ *write_method = write_pingCtlDataSize;
+ *var_len = sizeof(StorageTmp->pingCtlDataSize);
+
+ return (u_char *) & StorageTmp->pingCtlDataSize;
+
+ case COLUMN_PINGCTLTIMEOUT:
+ *write_method = write_pingCtlTimeOut;
+ *var_len = sizeof(StorageTmp->pingCtlTimeOut);
+
+ return (u_char *) & StorageTmp->pingCtlTimeOut;
+
+ case COLUMN_PINGCTLPROBECOUNT:
+ *write_method = write_pingCtlProbeCount;
+ *var_len = sizeof(StorageTmp->pingCtlProbeCount);
+
+ return (u_char *) & StorageTmp->pingCtlProbeCount;
+
+ case COLUMN_PINGCTLADMINSTATUS:
+ *write_method = write_pingCtlAdminStatus;
+ *var_len = sizeof(StorageTmp->pingCtlAdminStatus);
+
+ return (u_char *) & StorageTmp->pingCtlAdminStatus;
+
+ case COLUMN_PINGCTLDATAFILL:
+ *write_method = write_pingCtlDataFill;
+ *var_len = (StorageTmp->pingCtlDataFillLen);
+
+ return (u_char *) StorageTmp->pingCtlDataFill;
+
+ case COLUMN_PINGCTLFREQUENCY:
+ *write_method = write_pingCtlFrequency;
+ *var_len = sizeof(StorageTmp->pingCtlFrequency);
+
+ return (u_char *) & StorageTmp->pingCtlFrequency;
+
+ case COLUMN_PINGCTLMAXROWS:
+ *write_method = write_pingCtlMaxRows;
+ *var_len = sizeof(StorageTmp->pingCtlMaxRows);
+
+ return (u_char *) & StorageTmp->pingCtlMaxRows;
+
+ case COLUMN_PINGCTLSTORAGETYPE:
+ *write_method = write_pingCtlStorageType;
+ *var_len = sizeof(StorageTmp->pingCtlStorageType);
+
+ return (u_char *) & StorageTmp->pingCtlStorageType;
+
+ case COLUMN_PINGCTLTRAPGENERATION:
+ *write_method = write_pingCtlTrapGeneration;
+ *var_len = (StorageTmp->pingCtlTrapGenerationLen);
+
+ return (u_char *) StorageTmp->pingCtlTrapGeneration;
+
+ case COLUMN_PINGCTLTRAPPROBEFAILUREFILTER:
+ *write_method = write_pingCtlTrapProbeFailureFilter;
+ *var_len = sizeof(StorageTmp->pingCtlTrapProbeFailureFilter);
+
+ return (u_char *) & StorageTmp->pingCtlTrapProbeFailureFilter;
+
+ case COLUMN_PINGCTLTRAPTESTFAILUREFILTER:
+ *write_method = write_pingCtlTrapTestFailureFilter;
+ *var_len = sizeof(StorageTmp->pingCtlTrapTestFailureFilter);
+
+ return (u_char *) & StorageTmp->pingCtlTrapTestFailureFilter;
+
+ case COLUMN_PINGCTLTYPE:
+ *write_method = write_pingCtlType;
+ *var_len = (StorageTmp->pingCtlTypeLen) * sizeof(oid);
+
+ return (u_char *) StorageTmp->pingCtlType;
+
+ case COLUMN_PINGCTLDESCR:
+ *write_method = write_pingCtlDescr;
+ *var_len = (StorageTmp->pingCtlDescrLen);
+
+ return (u_char *) StorageTmp->pingCtlDescr;
+
+ case COLUMN_PINGCTLSOURCEADDRESSTYPE:
+ *write_method = write_pingCtlSourceAddressType;
+ *var_len = sizeof(StorageTmp->pingCtlSourceAddressType);
+
+ return (u_char *) & StorageTmp->pingCtlSourceAddressType;
+
+ case COLUMN_PINGCTLSOURCEADDRESS:
+ *write_method = write_pingCtlSourceAddress;
+ *var_len = (StorageTmp->pingCtlSourceAddressLen);
+
+ return (u_char *) StorageTmp->pingCtlSourceAddress;
+
+ case COLUMN_PINGCTLIFINDEX:
+ *write_method = write_pingCtlIfIndex;
+ *var_len = sizeof(StorageTmp->pingCtlIfIndex);
+
+ return (u_char *) & StorageTmp->pingCtlIfIndex;
+
+ case COLUMN_PINGCTLBYPASSROUTETABLE:
+ *write_method = write_pingCtlByPassRouteTable;
+ *var_len = sizeof(StorageTmp->pingCtlByPassRouteTable);
+
+ return (u_char *) & StorageTmp->pingCtlByPassRouteTable;
+
+ case COLUMN_PINGCTLDSFIELD:
+ *write_method = write_pingCtlDSField;
+ *var_len = sizeof(StorageTmp->pingCtlDSField);
+
+ return (u_char *) & StorageTmp->pingCtlDSField;
+
+
+
+ case COLUMN_PINGCTLROWSTATUS:
+ *write_method = write_pingCtlRowStatus;
+ *var_len = sizeof(StorageTmp->pingCtlRowStatus);
+
+ return (u_char *) & StorageTmp->pingCtlRowStatus;
+
+ default:
+ ERROR_MSG("");
+ }
+ return NULL;
+}
+
+
+unsigned long
+pingProbeHistoryTable_count(struct pingCtlTable_data *thedata)
+{
+ struct header_complex_index *hciptr2 = NULL;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len;
+ unsigned long count = 0;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlOwnerIndex,
+ thedata->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlTestName,
+ thedata->pingCtlTestNameLen);
+
+ header_complex_generate_oid(newoid, &newoid_len, NULL, 0, vars);
+ snmp_free_varbind(vars);
+
+ for (hciptr2 = pingProbeHistoryTableStorage; hciptr2 != NULL;
+ hciptr2 = hciptr2->next) {
+ if (snmp_oid_compare(newoid, newoid_len, hciptr2->name, newoid_len)
+ == 0) {
+ count = count + 1;
+ }
+ }
+ return count;
+}
+
+
+void
+pingProbeHistoryTable_delLast(struct pingCtlTable_data *thedata)
+{
+ struct header_complex_index *hciptr2 = NULL;
+ struct header_complex_index *hcilast = NULL;
+ struct pingProbeHistoryTable_data *StorageTmp, *StorageDel;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len;
+ time_t last_time = 2147483647;
+ time_t tp;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlOwnerIndex,
+ thedata->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlTestName,
+ thedata->pingCtlTestNameLen);
+ header_complex_generate_oid(newoid, &newoid_len, NULL, 0, vars);
+ snmp_free_varbind(vars);
+
+ for (hcilast = hciptr2 = pingProbeHistoryTableStorage; hciptr2 != NULL;
+ hciptr2 = hciptr2->next) {
+ if (snmp_oid_compare(newoid, newoid_len, hciptr2->name, newoid_len)
+ == 0) {
+
+ StorageTmp =
+ header_complex_get_from_oid(pingProbeHistoryTableStorage,
+ hciptr2->name,
+ hciptr2->namelen);
+ tp = StorageTmp->pingProbeHistoryTime_time;
+
+ if (last_time > tp) {
+ last_time = tp;
+ hcilast = hciptr2;
+ }
+
+ }
+ }
+ StorageDel =
+ header_complex_extract_entry(&pingProbeHistoryTableStorage, hcilast);
+ for (hciptr2 = pingCtlTableStorage; hciptr2; hciptr2 = hciptr2->next) {
+ struct pingCtlTable_data *tmp;
+
+ tmp = hciptr2->data;
+ if (tmp->pingProbeHis == StorageDel) {
+ tmp->pingProbeHis = tmp->pingProbeHis->next;
+ DEBUGMSGTL(("pingProbeHistoryTable",
+ "deleting the last one succeeded!\n"));
+ break;
+ }
+ }
+ if (StorageDel) {
+ free(StorageDel->pingProbeHistoryTime);
+ free(StorageDel->pingCtlTestName);
+ free(StorageDel->pingCtlOwnerIndex);
+ free(StorageDel);
+ }
+ DEBUGMSGTL(("pingProbeHistoryTable",
+ "delete the last one success!\n"));
+}
+
+
+char *
+sock_ntop_host(const struct sockaddr *sa, socklen_t salen)
+{
+ static char str[128]; /* Unix domain is largest */
+
+ switch (sa->sa_family) {
+ case AF_INET:{
+ const struct sockaddr_in *sin = (const struct sockaddr_in *) sa;
+
+ if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) ==
+ NULL)
+ return (NULL);
+ return (str);
+ }
+
+#ifdef IPV6
+ case AF_INET6:{
+ const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *) sa;
+
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) ==
+ NULL)
+ return (NULL);
+ return (str);
+ }
+#endif
+
+#ifdef AF_UNIX
+ case AF_UNIX:{
+ const struct sockaddr_un *unp = (const struct sockaddr_un *) sa;
+
+ /*
+ * OK to have no pathname bound to the socket: happens on
+ * every connect() unless client calls bind() first.
+ */
+ if (unp->sun_path[0] == 0)
+ strcpy(str, "(no pathname bound)");
+ else
+ snprintf(str, sizeof(str), "%s", unp->sun_path);
+ return (str);
+ }
+#endif
+
+#ifdef HAVE_SOCKADDR_DL_STRUCT
+ case AF_LINK:{
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *) sa;
+
+ if (sdl->sdl_nlen > 0)
+ snprintf(str, sizeof(str), "%*s",
+ sdl->sdl_nlen, &sdl->sdl_data[0]);
+ else
+ snprintf(str, sizeof(str), "AF_LINK, index=%d",
+ sdl->sdl_index);
+ return (str);
+ }
+#endif
+ default:
+ snprintf(str, sizeof(str),
+ "sock_ntop_host: unknown AF_xxx: %d, len %d",
+ sa->sa_family, salen);
+ return (str);
+ }
+ return (NULL);
+}
+
+
+char *
+Sock_ntop_host(const struct sockaddr *sa, socklen_t salen)
+{
+ char *ptr;
+
+ if ((ptr = sock_ntop_host(sa, salen)) == NULL) {
+ /* inet_ntop() sets errno */
+ snmp_log_perror("pingCtlTable: sock_ntop_host()");
+ }
+ return (ptr);
+}
+
+
+
+unsigned short
+in_cksum(unsigned short *addr, int len)
+{
+ int nleft = len;
+ int sum = 0;
+ unsigned short *w = addr;
+ unsigned short answer = 0;
+
+ /*
+ * Our algorithm is simple, using a 32 bit accumulator (sum), we add
+ * sequential 16 bit words to it, and at the end, fold back all the
+ * carry bits from the top 16 bits into the lower 16 bits.
+ */
+ while (nleft > 1) {
+ sum += *w++;
+ nleft -= 2;
+ }
+
+ /*
+ * 4mop up an odd byte, if necessary
+ */
+ if (nleft == 1) {
+ *(unsigned char *) (&answer) = *(unsigned char *) w;
+ sum += answer;
+ }
+
+ /*
+ * 4add back carry outs from top 16 bits to low 16 bits
+ */
+ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
+ sum += (sum >> 16); /* add carry */
+ answer = ~sum; /* truncate to 16 bits */
+ return (answer);
+}
+
+
+struct addrinfo *
+host_serv(const char *host, const char *serv, int family, int socktype)
+{
+ int n;
+ struct addrinfo hints, *res;
+
+ memset(&hints, '\0', sizeof(struct addrinfo));
+ hints.ai_flags = AI_CANONNAME; /* always return canonical name */
+ hints.ai_family = family; /* AF_UNSPEC, AF_INET, AF_INET6, etc. */
+ hints.ai_socktype = socktype; /* 0, SOCK_STREAM, SOCK_DGRAM, etc. */
+
+ if ((n = netsnmp_getaddrinfo(host, serv, &hints, &res)) != 0)
+ return (NULL);
+
+ return (res); /* return pointer to first on linked list */
+}
+
+/*
+ * end host_serv
+ */
+
+/*
+ * There is no easy way to pass back the integer return code from
+ * getaddrinfo() in the function above, short of adding another argument
+ * that is a pointer, so the easiest way to provide the wrapper function
+ * is just to duplicate the simple function as we do here.
+ */
+
+struct addrinfo *
+Host_serv(const char *host, const char *serv, int family, int socktype)
+{
+ int n;
+ struct addrinfo hints, *res;
+
+ memset(&hints, '\0', sizeof(struct addrinfo));
+ hints.ai_flags = AI_CANONNAME; /* always return canonical name */
+ hints.ai_family = family; /* 0, AF_INET, AF_INET6, etc. */
+ hints.ai_socktype = socktype; /* 0, SOCK_STREAM, SOCK_DGRAM, etc. */
+
+ if ((n = netsnmp_getaddrinfo(host, serv, &hints, &res)) != 0) {
+#if HAVE_GAI_STRERROR
+ snmp_log(LOG_ERR, "host_serv error for %s, %s: %s",
+ (host == NULL) ? "(no hostname)" : host,
+ (serv == NULL) ? "(no service name)" : serv,
+ gai_strerror(n));
+#else
+ snmp_log(LOG_ERR, "host_serv error for %s, %s",
+ (host == NULL) ? "(no hostname)" : host,
+ (serv == NULL) ? "(no service name)" : serv);
+#endif
+ }
+
+ return (res); /* return pointer to first on linked list */
+}
+
+int
+readable_timeo(int fd, int sec)
+{
+ fd_set rset;
+ struct timeval tv;
+ FD_ZERO(&rset);
+ FD_SET(fd, &rset);
+ tv.tv_sec = sec;
+ tv.tv_usec = 0;
+ return (select(fd + 1, &rset, NULL, NULL, &tv));
+
+}
+
+/*
+ * send trap
+ */
+void
+send_ping_trap(struct pingCtlTable_data *item,
+ oid * trap_oid, size_t trap_oid_len)
+{
+ static oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; /* snmpTrapIOD.0 */
+ struct pingResultsTable_data *StorageTmp = NULL;
+ netsnmp_variable_list *var_list = NULL, *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len;
+
+ oid pingCtlTargetAddress[] =
+ { 1, 3, 6, 1, 2, 1, 80, 1, 2, 1, 4 };
+ oid pingResultsMinRtt[] =
+ { 1, 3, 6, 1, 2, 1, 80, 1, 3, 1, 4 };
+ oid pingResultsMaxRtt[] =
+ { 1, 3, 6, 1, 2, 1, 80, 1, 3, 1, 5 };
+ oid pingResultsAverageRtt[] =
+ { 1, 3, 6, 1, 2, 1, 80, 1, 3, 1, 6 };
+ oid pingResultsProbeResponses[] =
+ { 1, 3, 6, 1, 2, 1, 80, 1, 3, 1, 7 };
+ oid pingResultsSendProbes[] =
+ { 1, 3, 6, 1, 2, 1, 80, 1, 3, 1, 8 };
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlTestName,
+ item->pingCtlTestNameLen);
+ StorageTmp = header_complex_get(pingResultsTableStorage, vars);
+ snmp_free_varbind(vars);
+ if (!StorageTmp)
+ return;
+
+ /*
+ * snmpTrap oid
+ */
+ snmp_varlist_add_variable(&var_list, objid_snmptrap,
+ sizeof(objid_snmptrap) / sizeof(oid),
+ ASN_OBJECT_ID, (u_char *) trap_oid,
+ trap_oid_len * sizeof(oid));
+ /*
+ * pingCtlTargetAddress
+ */
+ memset(newoid, '\0', MAX_OID_LEN * sizeof(oid));
+ header_complex_generate_oid(newoid, &newoid_len, pingCtlTargetAddress,
+ sizeof(pingCtlTargetAddress) / sizeof(oid),
+ vars);
+
+ snmp_varlist_add_variable(&var_list, newoid,
+ newoid_len,
+ ASN_OCTET_STR,
+ (u_char *) item->pingCtlTargetAddress,
+ item->pingCtlTargetAddressLen);
+
+ /*
+ * pingResultsMinRtt
+ */
+ memset(newoid, '\0', newoid_len);
+ header_complex_generate_oid(newoid, &newoid_len, pingResultsMinRtt,
+ sizeof(pingResultsMinRtt) / sizeof(oid),
+ vars);
+
+ snmp_varlist_add_variable(&var_list, newoid,
+ newoid_len,
+ ASN_UNSIGNED,
+ (u_char *) & (StorageTmp->pingResultsMinRtt),
+ sizeof(StorageTmp->pingResultsMinRtt));
+ /*
+ * pingResultsMaxRtt
+ */
+ memset(newoid, '\0', newoid_len);
+ header_complex_generate_oid(newoid, &newoid_len, pingResultsMaxRtt,
+ sizeof(pingResultsMaxRtt) / sizeof(oid),
+ vars);
+
+ snmp_varlist_add_variable(&var_list, newoid,
+ newoid_len,
+ ASN_UNSIGNED,
+ (u_char *) & (StorageTmp->pingResultsMaxRtt),
+ sizeof(StorageTmp->pingResultsMaxRtt));
+
+ /*
+ * pingResultsAverageRtt
+ */
+ memset(newoid, '\0', newoid_len);
+ header_complex_generate_oid(newoid, &newoid_len, pingResultsAverageRtt,
+ sizeof(pingResultsAverageRtt) /
+ sizeof(oid), vars);
+
+ snmp_varlist_add_variable(&var_list, newoid,
+ newoid_len,
+ ASN_UNSIGNED,
+ (u_char *) & (StorageTmp->
+ pingResultsAverageRtt),
+ sizeof(StorageTmp->pingResultsAverageRtt));
+
+ /*
+ * pingResultsProbeResponses
+ */
+ memset(newoid, '\0', newoid_len);
+ header_complex_generate_oid(newoid, &newoid_len,
+ pingResultsProbeResponses,
+ sizeof(pingResultsProbeResponses) /
+ sizeof(oid), vars);
+
+ snmp_varlist_add_variable(&var_list, newoid,
+ newoid_len,
+ ASN_UNSIGNED,
+ (u_char *) & (StorageTmp->
+ pingResultsProbeResponses),
+ sizeof(StorageTmp->
+ pingResultsProbeResponses));
+ /*
+ * pingResultsSendProbes
+ */
+ memset(newoid, '\0', newoid_len);
+ header_complex_generate_oid(newoid, &newoid_len, pingResultsSendProbes,
+ sizeof(pingResultsSendProbes) /
+ sizeof(oid), vars);
+
+ snmp_varlist_add_variable(&var_list, newoid,
+ newoid_len,
+ ASN_UNSIGNED,
+ (u_char *) & (StorageTmp->
+ pingResultsSendProbes),
+ sizeof(StorageTmp->pingResultsSendProbes));
+
+ /*
+ * XXX: stuff based on event table
+ */
+
+ DEBUGMSG(("pingTest:send_ping_trap", "success!\n"));
+
+ send_v2trap(var_list);
+ snmp_free_varbind(vars);
+ vars = NULL;
+ snmp_free_varbind(var_list);
+ vars = NULL;
+}
+
+
+
+void
+readloop(struct pingCtlTable_data *item, struct addrinfo *ai, int datalen,
+ unsigned long *minrtt, unsigned long *maxrtt,
+ unsigned long *averagertt, pid_t pid)
+{
+ char recvbuf[BUFSIZE];
+ char sendbuf[BUFSIZE];
+ int nsent = 1;
+ socklen_t len;
+ ssize_t n;
+ struct timeval tval;
+ /* static int loop_num; */
+ /* struct pingProbeHistoryTable_data * current=NULL; */
+ struct pingProbeHistoryTable_data current_var;
+ int sockfd;
+ int select_result;
+ int current_probe_temp;
+ int success_probe = 0;
+ int fail_probe = 0;
+ int flag;
+ unsigned long sumrtt;
+ struct timeval tv;
+
+ memset(sendbuf, 0, sizeof(sendbuf));
+
+ sockfd = socket(pr->sasend->sa_family, SOCK_RAW, pr->icmpproto);
+ if (sockfd < 0) {
+ snmp_log_perror("pingCtlTable: failed to create socket");
+ return;
+ }
+ setuid(getuid()); /* don't need special permissions any more */
+
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+
+ for (current_probe_temp = 1;
+ current_probe_temp <= item->pingCtlProbeCount;
+ current_probe_temp++) {
+ time_t timep;
+ (*pr->fsend) (datalen, pid, nsent, sockfd, sendbuf);
+ nsent++;
+ len = pr->salen;
+ select_result = readable_timeo(sockfd, item->pingCtlTimeOut);
+ do {
+ if (select_result == 0) {
+ DEBUGMSGTL(("pingCtlTable", "socket timeout\n"));
+ n = -1;
+ fail_probe = fail_probe + 1;
+ flag = 1;
+ } else {
+ n = recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, pr->sarecv,
+ &len);
+ success_probe = success_probe + 1;
+ flag = 0;
+ }
+
+ netsnmp_get_monotonic_clock(&tval);
+
+ time(&timep);
+
+ (*pr->fproc) (recvbuf, n, &tval, timep, item, ai, datalen, minrtt,
+ maxrtt, &sumrtt, averagertt, current_probe_temp,
+ success_probe, fail_probe, flag, &current_var, pid);
+ select_result = readable_timeo(sockfd, 0);
+ } while (select_result > 0);
+ }
+ close(sockfd);
+}
+
+unsigned long
+round_double(double number)
+{
+ unsigned long ret_num = 0;
+ if (number - (unsigned long) number < 0.5)
+ ret_num = (unsigned long) number;
+ else
+ ret_num = (unsigned long) number + 1;
+ return ret_num;
+}
+
+int
+proc_v4(char *ptr, ssize_t len, struct timeval *tvrecv, time_t timep,
+ struct pingCtlTable_data *item, struct addrinfo *ai, int datalen,
+ unsigned long *minrtt, unsigned long *maxrtt,
+ unsigned long *sumrtt, unsigned long *averagertt,
+ unsigned long current_probe, int success_probe, int fail_probe,
+ int flag, struct pingProbeHistoryTable_data *current_temp,
+ pid_t pid)
+{
+ int hlen1 = 0, icmplen = 0;
+ unsigned long rtt = 0;
+
+ struct ip *ip = NULL;
+ struct icmp *icmp = NULL;
+ struct timeval *tvsend = NULL;
+ struct pingProbeHistoryTable_data *temp = NULL;
+ static int probeFailed = 0;
+ static int testFailed = 0;
+ static int series = 0;
+ netsnmp_variable_list *vars = NULL;
+ struct pingResultsTable_data *StorageNew = NULL;
+
+ DEBUGMSGTL(("pingCtlTable", "proc_v4(flag = %d)\n", flag));
+
+ if (flag == 0) {
+ series = 0;
+ ip = (struct ip *) ptr; /* start of IP header */
+ hlen1 = ip->ip_hl << 2; /* length of IP header */
+
+ icmp = (struct icmp *) (ptr + hlen1); /* start of ICMP header */
+ if ((icmplen = len - hlen1) < 8)
+ DEBUGMSGTL(("pingCtlTable", "icmplen (%d) < 8", icmplen));
+
+ DEBUGMSGTL(("pingCtlTable", "ICMP type = %d (%sa reply)\n",
+ icmp->icmp_type,
+ icmp->icmp_type == ICMP_ECHOREPLY ? "" : "not a "));
+
+ if (icmp->icmp_type == ICMP_ECHOREPLY) {
+ if (icmp->icmp_id != pid) {
+ DEBUGMSGTL(("pingCtlTable", "not a response to our ECHO_REQUEST\n"));
+ return SNMP_ERR_NOERROR;
+ }
+
+ if (icmplen < 16)
+ DEBUGMSGTL(("pingCtlTable", "icmplen (%d) < 16", icmplen));
+
+ tvsend = (struct timeval *) icmp->icmp_data;
+
+ rtt =
+ round_double((1000000 * (tvrecv->tv_sec - tvsend->tv_sec) +
+ tvrecv->tv_usec - tvsend->tv_usec) / 1000);
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlTestName,
+ item->pingCtlTestNameLen);
+
+ StorageNew = header_complex_get(pingResultsTableStorage, vars);
+ snmp_free_varbind(vars);
+ if (!StorageNew) {
+ DEBUGMSGTL(("pingCtlTable", "StorageNew == NULL\n"));
+ return SNMP_ERR_NOSUCHNAME;
+ }
+
+ if (current_probe == 1) {
+ *averagertt = rtt;
+ *minrtt = rtt;
+ *maxrtt = rtt;
+ *sumrtt = rtt;
+ } else {
+ if (rtt < *minrtt)
+ *minrtt = rtt;
+ if (rtt > *maxrtt)
+ *maxrtt = rtt;
+ *sumrtt = (*sumrtt) + rtt;
+ *averagertt =
+ round_double((*sumrtt) /
+ (StorageNew->pingResultsProbeResponses +
+ 1));
+ }
+
+
+ StorageNew->pingResultsMinRtt = *minrtt;
+ StorageNew->pingResultsMaxRtt = *maxrtt;
+ StorageNew->pingResultsAverageRtt = *averagertt;
+ StorageNew->pingResultsProbeResponses =
+ StorageNew->pingResultsProbeResponses + 1;
+ StorageNew->pingResultsSendProbes =
+ StorageNew->pingResultsSendProbes + 1;
+ StorageNew->pingResultsRttSumOfSquares =
+ StorageNew->pingResultsRttSumOfSquares + rtt * rtt;
+
+ StorageNew->pingResultsLastGoodProbe_time = timep;
+ free(StorageNew->pingResultsLastGoodProbe);
+ memdup(&StorageNew->pingResultsLastGoodProbe,
+ date_n_time(&timep,
+ &StorageNew->pingResultsLastGoodProbeLen), 11);
+
+ temp = SNMP_MALLOC_STRUCT(pingProbeHistoryTable_data);
+
+ temp->pingCtlOwnerIndex =
+ (char *) malloc(item->pingCtlOwnerIndexLen + 1);
+ memcpy(temp->pingCtlOwnerIndex, item->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndexLen + 1);
+ temp->pingCtlOwnerIndex[item->pingCtlOwnerIndexLen] = '\0';
+ temp->pingCtlOwnerIndexLen = item->pingCtlOwnerIndexLen;
+
+ temp->pingCtlTestName =
+ (char *) malloc(item->pingCtlTestNameLen + 1);
+ memcpy(temp->pingCtlTestName, item->pingCtlTestName,
+ item->pingCtlTestNameLen + 1);
+ temp->pingCtlTestName[item->pingCtlTestNameLen] = '\0';
+ temp->pingCtlTestNameLen = item->pingCtlTestNameLen;
+
+ /* add lock to protect */
+ pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&counter_mutex);
+ if (item->pingProbeHistoryMaxIndex >=
+ (unsigned long) (2147483647))
+ item->pingProbeHistoryMaxIndex = 0;
+ temp->pingProbeHistoryIndex =
+ ++(item->pingProbeHistoryMaxIndex);
+ pthread_mutex_unlock(&counter_mutex);
+
+
+ temp->pingProbeHistoryResponse = rtt;
+ temp->pingProbeHistoryStatus = 1;
+ temp->pingProbeHistoryLastRC = 0;
+
+ temp->pingProbeHistoryTime_time = timep;
+ memdup(&temp->pingProbeHistoryTime,
+ date_n_time(&timep, &temp->pingProbeHistoryTimeLen), 11);
+
+ if (StorageNew->pingResultsSendProbes == 1)
+ item->pingProbeHis = temp;
+ else
+ (current_temp)->next = temp;
+
+ current_temp = temp;
+
+ if (StorageNew->pingResultsSendProbes >= item->pingCtlProbeCount)
+ current_temp->next = NULL;
+
+ if (item->pingProbeHis != NULL) {
+ if (pingProbeHistoryTable_count(item) >= item->pingCtlMaxRows)
+ pingProbeHistoryTable_delLast(item);
+ if (pingProbeHistoryTable_add(current_temp) != SNMPERR_SUCCESS)
+ DEBUGMSGTL(("pingProbeHistoryTable",
+ "failed to add a row\n"));
+ }
+ }
+ } else if (flag == 1) {
+ if (series == 0)
+ probeFailed = 1;
+ else
+ probeFailed = probeFailed + 1;
+ series = 1;
+ testFailed = testFailed + 1;
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlTestName,
+ item->pingCtlTestNameLen);
+
+ StorageNew = header_complex_get(pingResultsTableStorage, vars);
+ snmp_free_varbind(vars);
+ if (!StorageNew)
+ return SNMP_ERR_NOSUCHNAME;
+
+ if (current_probe == 1) {
+ *averagertt = rtt;
+ *minrtt = rtt;
+ *maxrtt = rtt;
+ *sumrtt = rtt;
+ }
+ StorageNew->pingResultsSendProbes =
+ StorageNew->pingResultsSendProbes + 1;
+
+
+
+ temp = SNMP_MALLOC_STRUCT(pingProbeHistoryTable_data);
+
+ temp->pingCtlOwnerIndex =
+ (char *) malloc(item->pingCtlOwnerIndexLen + 1);
+ memcpy(temp->pingCtlOwnerIndex, item->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndexLen + 1);
+ temp->pingCtlOwnerIndex[item->pingCtlOwnerIndexLen] = '\0';
+ temp->pingCtlOwnerIndexLen = item->pingCtlOwnerIndexLen;
+
+ temp->pingCtlTestName =
+ (char *) malloc(item->pingCtlTestNameLen + 1);
+ memcpy(temp->pingCtlTestName, item->pingCtlTestName,
+ item->pingCtlTestNameLen + 1);
+ temp->pingCtlTestName[item->pingCtlTestNameLen] = '\0';
+ temp->pingCtlTestNameLen = item->pingCtlTestNameLen;
+
+ /* add lock to protect */
+ pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&counter_mutex);
+ temp->pingProbeHistoryIndex = ++(item->pingProbeHistoryMaxIndex);
+ pthread_mutex_unlock(&counter_mutex);
+ /* end */
+
+ temp->pingProbeHistoryResponse = item->pingCtlTimeOut * 1000;
+ temp->pingProbeHistoryStatus = 4;
+ temp->pingProbeHistoryLastRC = 1;
+
+ temp->pingProbeHistoryTime_time = timep;
+ memdup(&temp->pingProbeHistoryTime,
+ date_n_time(&timep, &temp->pingProbeHistoryTimeLen), 11);
+
+ if (StorageNew->pingResultsSendProbes == 1)
+ item->pingProbeHis = temp;
+ else {
+ (current_temp)->next = temp;
+ }
+
+ current_temp = temp;
+
+ if (StorageNew->pingResultsSendProbes >= item->pingCtlProbeCount) {
+ current_temp->next = NULL;
+ }
+
+ if (item->pingProbeHis != NULL) {
+ if (pingProbeHistoryTable_count(item) < item->pingCtlMaxRows) {
+ if (pingProbeHistoryTable_add(current_temp) !=
+ SNMPERR_SUCCESS)
+ DEBUGMSGTL(("pingProbeHistoryTable",
+ "registered an entry error\n"));
+ } else {
+
+ pingProbeHistoryTable_delLast(item);
+ if (pingProbeHistoryTable_add(current_temp) !=
+ SNMPERR_SUCCESS)
+ DEBUGMSGTL(("pingProbeHistoryTable",
+ "registered an entry error\n"));
+
+ }
+ }
+
+ if ((item->
+ pingCtlTrapGeneration[0] & PINGTRAPGENERATION_PROBEFAILED) !=
+ 0) {
+ if (probeFailed >= item->pingCtlTrapProbeFailureFilter)
+ send_ping_trap(item, pingProbeFailed,
+ sizeof(pingProbeFailed) / sizeof(oid));
+ }
+
+
+ }
+
+ if (current_probe == item->pingCtlProbeCount) {
+ if ((item->
+ pingCtlTrapGeneration[0] & PINGTRAPGENERATION_TESTCOMPLETED)
+ != 0) {
+ send_ping_trap(item, pingTestCompleted,
+ sizeof(pingTestCompleted) / sizeof(oid));
+ } else
+ if ((item->
+ pingCtlTrapGeneration[0] & PINGTRAPGENERATION_TESTFAILED)
+ != 0) {
+
+ if (testFailed >= item->pingCtlTrapTestFailureFilter)
+ send_ping_trap(item, pingTestFailed,
+ sizeof(pingTestFailed) / sizeof(oid));
+ }
+
+ else if ((item->
+ pingCtlTrapGeneration[0] &
+ PINGTRAPGENERATION_PROBEFAILED) != 0) {;
+ } else {
+ ;
+ }
+
+ series = 0;
+ probeFailed = 0;
+ testFailed = 0;
+
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+void
+send_v4(int datalen, pid_t pid, int nsent, int sockfd, char *sendbuf)
+{
+ int len;
+ struct icmp *icmp = NULL;
+
+ icmp = (struct icmp *) sendbuf;
+ icmp->icmp_type = ICMP_ECHO;
+ icmp->icmp_code = 0;
+ icmp->icmp_id = pid;
+ icmp->icmp_seq = nsent;
+ netsnmp_get_monotonic_clock((struct timeval *) icmp->icmp_data);
+
+ len = 8 + datalen; /* checksum ICMP header and data */
+ icmp->icmp_cksum = 0;
+ icmp->icmp_cksum = in_cksum((u_short *) icmp, len);
+
+ sendto(sockfd, sendbuf, len, 0, pr->sasend, pr->salen);
+}
+
+
+void
+run_ping(unsigned int clientreg, void *clientarg)
+/* run_ping(struct pingCtlTable_data *item) */
+{
+ struct pingCtlTable_data *item = clientarg;
+ netsnmp_variable_list *vars = NULL;
+ struct pingResultsTable_data *StorageNew = NULL;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlTestName, item->pingCtlTestNameLen);
+
+ StorageNew = header_complex_get(pingResultsTableStorage, vars);
+ snmp_free_varbind(vars);
+ if (!StorageNew)
+ return;
+
+ StorageNew->pingResultsSendProbes = 0;
+ StorageNew->pingResultsProbeResponses = 0;
+
+ if (item->pingCtlTargetAddressType == 1
+ || item->pingCtlTargetAddressType == 16) {
+ struct proto proto_v4 =
+ { proc_v4, send_v4, NULL, NULL, 0, IPPROTO_ICMP };
+ char *host = NULL;
+ pid_t pid; /* our PID */
+
+ int datalen;
+ unsigned long *minrtt = NULL;
+ unsigned long *maxrtt = NULL;
+ unsigned long *averagertt = NULL;
+
+ datalen = 56; /* data that goes with ICMP echo request */
+ struct addrinfo *ai = NULL;
+ minrtt = malloc(sizeof(unsigned long));
+ maxrtt = malloc(sizeof(unsigned long));
+ averagertt = malloc(sizeof(unsigned long));
+ host = item->pingCtlTargetAddress;
+ pid = getpid();
+
+ ai = host_serv(host, NULL, 0, 0);
+
+ if (ai) {
+ DEBUGMSGTL(("pingCtlTable", "PING %s (%s): %d data bytes\n",
+ ai->ai_canonname,
+ sock_ntop_host(ai->ai_addr, ai->ai_addrlen), datalen));
+
+ /*
+ * 4initialize according to protocol
+ */
+ if (ai->ai_family == AF_INET) {
+ pr = &proto_v4;
+#ifdef IPV6
+ } else if (ai->ai_family == AF_INET6) {
+ pr = &proto_v6;
+
+ if (IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6 *)
+ ai->ai_addr)->sin6_addr)))
+ snmp_log(LOG_ERR, "cannot ping IPv4-mapped IPv6 address");
+#endif
+ } else {
+ snmp_log(LOG_ERR, "unknown address family %d", ai->ai_family);
+ }
+
+ pr->sasend = ai->ai_addr;
+ pr->sarecv = calloc(1, ai->ai_addrlen);
+ pr->salen = ai->ai_addrlen;
+ readloop(item, ai, datalen, minrtt, maxrtt, averagertt, pid);
+ free(pr->sarecv);
+ } else {
+ snmp_log(LOG_ERR, "PING: name resolution for %s failed.\n", host);
+ }
+
+ SNMP_FREE(minrtt);
+ SNMP_FREE(maxrtt);
+ SNMP_FREE(averagertt);
+ freeaddrinfo(ai);
+ }
+
+ else if (item->pingCtlTargetAddressType == 2) {
+
+ int hold = 0, packlen = 0;
+ u_char *packet = NULL;
+ char *target = NULL;
+ struct sockaddr_in6 firsthop;
+ int socket_errno = 0;
+ struct icmp6_filter filter;
+ int err = 0, csum_offset = 0, sz_opt = 0;
+
+ static int icmp_sock = 0;
+ int uid = 0;
+ struct sockaddr_in6 source;
+ int preload = 0;
+ static unsigned char cmsgbuf[4096];
+ static int cmsglen = 0;
+ struct sockaddr_in6 whereto; /* who to ping */
+ int options = 0;
+ char *hostname = NULL;
+ char *device = NULL;
+ int interval = 1000; /* interval between packets (msec) */
+ int pmtudisc = -1;
+ int datalen = DEFDATALEN;
+ int timing = 0; /* flag to do timing */
+ int working_recverr = 0;
+ __u32 flowlabel = 0;
+
+ int ident = 0; /* process id to identify our packets */
+ u_char outpack[MAX_PACKET];
+ struct timeval start_time;
+ static int screen_width = INT_MAX;
+ int deadline = 0; /* time to die */
+ int timeout = 0;
+
+ timeout = item->pingCtlTimeOut;
+ memset(&source, 0, sizeof(source));
+ icmp_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ socket_errno = errno;
+
+ uid = getuid();
+ setuid(uid);
+
+ source.sin6_family = AF_INET6;
+ memset(&firsthop, 0, sizeof(firsthop));
+ firsthop.sin6_family = AF_INET6;
+ preload = 1;
+
+ target = item->pingCtlTargetAddress;
+
+ memset(&whereto, 0, sizeof(struct sockaddr_in6));
+ whereto.sin6_family = AF_INET6;
+ whereto.sin6_port = htons(IPPROTO_ICMPV6);
+
+ if (inet_pton(AF_INET6, target, &whereto.sin6_addr) <= 0) {
+ struct hostent *hp = NULL;
+
+ hp = gethostbyname2(target, AF_INET6);
+
+ if (hp == NULL) {
+ fprintf(stderr, "unknown host\n");
+ return;
+ }
+
+ memcpy(&whereto.sin6_addr, hp->h_addr_list[0], 16);
+ } else {
+ options |= F_NUMERIC;
+ }
+ if (ipv6_addr_any(&firsthop.sin6_addr))
+ memcpy(&firsthop.sin6_addr, &whereto.sin6_addr, 16);
+
+ hostname = target;
+
+ if (ipv6_addr_any(&source.sin6_addr)) {
+ socklen_t alen;
+ int probe_fd = socket(AF_INET6, SOCK_DGRAM, 0);
+
+ if (probe_fd < 0) {
+ snmp_log_perror("pingCtlTable: IPv6 datagram socket creation");
+ return;
+ }
+ if (device) {
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, device, IFNAMSIZ);
+ if (setsockopt
+ (probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device,
+ strlen(device) + 1) == -1) {
+#ifdef HAVE_SIN6_SCOPEID
+ if ((firsthop.sin6_addr.
+ s6_addr16[0] & htons(0xffc0)) == htons(0xfe80)
+ || (firsthop.sin6_addr.
+ s6_addr16[0] & htons(0xffff)) ==
+ htons(0xff02)) {
+ if (ioctl(probe_fd, SIOCGIFINDEX, &ifr) < 0) {
+ fprintf(stderr, "ping: unknown iface %s\n",
+ device);
+ close(probe_fd);
+ return;
+ }
+ firsthop.sin6_scope_id = ifr.ifr_ifindex;
+ }
+#endif
+ }
+ }
+ firsthop.sin6_port = htons(1025);
+ if (connect
+ (probe_fd, (struct sockaddr *) &firsthop,
+ sizeof(firsthop)) == -1) {
+ perror("connect");
+ close(probe_fd);
+ return;
+ }
+ alen = sizeof(source);
+ if (getsockname(probe_fd, (struct sockaddr *) &source, &alen)
+ == -1) {
+ perror("getsockname");
+ close(probe_fd);
+ return;
+ }
+ source.sin6_port = 0;
+ close(probe_fd);
+ }
+
+ if (icmp_sock < 0) {
+ errno = socket_errno;
+ perror("ping: icmp open socket");
+ return;
+ }
+
+ if ((whereto.sin6_addr.s6_addr16[0] & htons(0xff00)) ==
+ htons(0xff00)) {
+ if (uid) {
+ if (interval < 1000) {
+ fprintf(stderr,
+ "ping: multicast ping with too short interval.\n");
+ return;
+ }
+ if (pmtudisc >= 0 && pmtudisc != IPV6_PMTUDISC_DO) {
+ fprintf(stderr,
+ "ping: multicast ping does not fragment.\n");
+ return;
+ }
+ }
+ if (pmtudisc < 0)
+ pmtudisc = IPV6_PMTUDISC_DO;
+ }
+
+ if (pmtudisc >= 0) {
+ if (setsockopt
+ (icmp_sock, SOL_IPV6, IPV6_MTU_DISCOVER, &pmtudisc,
+ sizeof(pmtudisc)) == -1) {
+ perror("ping: IPV6_MTU_DISCOVER");
+ return;
+ }
+ }
+ if (bind(icmp_sock, (struct sockaddr *) &source, sizeof(source)) ==
+ -1) {
+ perror("ping: bind icmp socket");
+ return;
+ }
+ if (datalen >= sizeof(struct timeval)) /* can we time transfer */
+ timing = 1;
+ packlen = datalen + 8 + 4096 + 40 + 8; /* 4096 for rthdr */
+ if (!(packet = (u_char *) malloc((u_int) packlen))) {
+ fprintf(stderr, "ping: out of memory.\n");
+ return;
+ }
+
+ working_recverr = 1;
+ hold = 1;
+ if (setsockopt
+ (icmp_sock, SOL_IPV6, IPV6_RECVERR, (char *) &hold,
+ sizeof(hold))) {
+ fprintf(stderr,
+ "WARNING: your kernel is veeery old. No problems.\n");
+ working_recverr = 0;
+ }
+
+ /*
+ * Estimate memory eaten by single packet. It is rough estimate.
+ * * Actually, for small datalen's it depends on kernel side a lot.
+ */
+ hold = datalen + 8;
+ hold += ((hold + 511) / 512) * (40 + 16 + 64 + 160);
+ sock_setbufs(icmp_sock, hold, preload);
+
+ csum_offset = 2;
+ sz_opt = sizeof(int);
+
+ err =
+ setsockopt(icmp_sock, SOL_RAW, IPV6_CHECKSUM, &csum_offset,
+ sz_opt);
+ if (err < 0) {
+ perror("setsockopt(RAW_CHECKSUM)");
+ return;
+ }
+
+ /*
+ * select icmp echo reply as icmp type to receive
+ */
+
+ ICMPV6_FILTER_SETBLOCKALL(&filter);
+
+ if (!working_recverr) {
+ ICMPV6_FILTER_SETPASS(ICMP6_DST_UNREACH, &filter);
+ ICMPV6_FILTER_SETPASS(ICMP6_PACKET_TOO_BIG, &filter);
+ ICMPV6_FILTER_SETPASS(ICMP6_TIME_EXCEEDED, &filter);
+ ICMPV6_FILTER_SETPASS(ICMP6_PARAM_PROB, &filter);
+ }
+
+ ICMPV6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filter);
+
+ err = setsockopt(icmp_sock, SOL_ICMPV6, ICMP6_FILTER, &filter,
+ sizeof(struct icmp6_filter));
+
+ if (err < 0) {
+ perror("setsockopt(ICMP6_FILTER)");
+ return;
+ }
+
+ if (1) {
+ int on = 1;
+ if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_HOPLIMIT,
+ &on, sizeof(on)) == -1) {
+ perror("can't receive hop limit");
+ return;
+ }
+ }
+
+ DEBUGMSGTL(("pingCtlTable", "PING %s(%s) ", hostname,
+ pr_addr(&whereto.sin6_addr, options)));
+ if (flowlabel)
+ DEBUGMSGTL(("pingCtlTable", ", flow 0x%05x, ",
+ (unsigned) ntohl(flowlabel)));
+ if (device || (options & F_NUMERIC)) {
+ DEBUGMSGTL(("pingCtlTable", "from %s %s: ",
+ pr_addr_n(&source.sin6_addr), device ? : ""));
+ }
+ DEBUGMSGTL(("pingCtlTable", "%d data bytes\n", datalen));
+
+ setup(icmp_sock, options, uid, timeout, preload, interval, datalen,
+ (char *) outpack, &ident, &start_time, &screen_width,
+ &deadline);
+
+ main_loop(item, icmp_sock, preload, packet, packlen, cmsglen,
+ (char *) cmsgbuf, &whereto, options, uid, hostname,
+ interval, datalen, timing, working_recverr,
+ (char *) outpack, &ident, &start_time, &screen_width,
+ &deadline);
+
+ close(icmp_sock);
+ }
+ return;
+}
+
+void
+init_resultsTable(struct pingCtlTable_data *item)
+{
+ struct pingResultsTable_data *StorageTmp = NULL;
+ struct pingResultsTable_data *StorageNew = NULL;
+ struct addrinfo *ai = NULL;
+ char *host = NULL;
+ netsnmp_variable_list *vars = NULL;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlTestName, item->pingCtlTestNameLen);
+
+ StorageNew = header_complex_get(pingResultsTableStorage, vars);
+ snmp_free_varbind(vars);
+ if (StorageNew) {
+ StorageNew->pingResultsSendProbes = 0;
+ StorageNew->pingResultsProbeResponses = 0;
+ return;
+ }
+
+ host = item->pingCtlTargetAddress;
+ ai = host_serv(host, NULL, 0, 0);
+ StorageTmp = SNMP_MALLOC_STRUCT(pingResultsTable_data);
+
+ StorageTmp->pingCtlOwnerIndex =
+ (char *) malloc(item->pingCtlOwnerIndexLen + 1);
+ memcpy(StorageTmp->pingCtlOwnerIndex, item->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndexLen + 1);
+ StorageTmp->pingCtlOwnerIndex[item->pingCtlOwnerIndexLen] = '\0';
+ StorageTmp->pingCtlOwnerIndexLen = item->pingCtlOwnerIndexLen;
+
+ StorageTmp->pingCtlTestName =
+ (char *) malloc(item->pingCtlTestNameLen + 1);
+ memcpy(StorageTmp->pingCtlTestName, item->pingCtlTestName,
+ item->pingCtlTestNameLen + 1);
+ StorageTmp->pingCtlTestName[item->pingCtlTestNameLen] = '\0';
+ StorageTmp->pingCtlTestNameLen = item->pingCtlTestNameLen;
+
+ StorageTmp->pingResultsOperStatus = 1;
+
+ if (item->pingCtlTargetAddressType == 1
+ || item->pingCtlTargetAddressType == 16) {
+ const char* str;
+
+ StorageTmp->pingResultsIpTargetAddressType = ai ? 1 : 0;
+ str = ai ? sock_ntop_host(ai->ai_addr, ai->ai_addrlen) : NULL;
+ if (!str)
+ str = "";
+ StorageTmp->pingResultsIpTargetAddress = strdup(str);
+ StorageTmp->pingResultsIpTargetAddressLen = strlen(str);
+ }
+ if (item->pingCtlTargetAddressType == 2) {
+
+ struct sockaddr_in6 whereto; /* Who to try to reach */
+ register struct sockaddr_in6 *to =
+ (struct sockaddr_in6 *) &whereto;
+ struct hostent *hp = NULL;
+ char pa[64];
+
+ to->sin6_family = AF_INET6;
+ to->sin6_port = htons(33434);
+
+ if (inet_pton(AF_INET6, host, &to->sin6_addr) > 0) {
+ StorageTmp->pingResultsIpTargetAddressType = 2;
+ StorageTmp->pingResultsIpTargetAddress = strdup(host);
+ StorageTmp->pingResultsIpTargetAddressLen = strlen(host);
+ } else {
+ hp = gethostbyname2(host, AF_INET6);
+ if (hp != NULL) {
+ const char *hostname = NULL;
+ memmove((caddr_t) & to->sin6_addr, hp->h_addr, 16);
+ hostname = inet_ntop(AF_INET6, &to->sin6_addr, pa, 64);
+ StorageTmp->pingResultsIpTargetAddressType = 2;
+ StorageTmp->pingResultsIpTargetAddress = strdup(hostname);
+ StorageTmp->pingResultsIpTargetAddressLen = strlen(hostname);
+ } else {
+ (void) fprintf(stderr,
+ "traceroute: unknown host %s\n", host);
+ StorageTmp->pingResultsIpTargetAddressType = 0;
+ StorageTmp->pingResultsIpTargetAddress = strdup("");
+ StorageTmp->pingResultsIpTargetAddressLen = 0;
+ }
+ }
+ }
+
+
+ StorageTmp->pingResultsMinRtt = 0;
+ StorageTmp->pingResultsMaxRtt = 0;
+ StorageTmp->pingResultsAverageRtt = 0;
+ StorageTmp->pingResultsProbeResponses = 0;
+ StorageTmp->pingResultsSendProbes = 0;
+ StorageTmp->pingResultsRttSumOfSquares = 0;
+
+ StorageTmp->pingResultsLastGoodProbeLen = 0;
+
+ item->pingResults = StorageTmp;
+ if (item->pingProbeHistoryMaxIndex == 0) {
+ if (item->pingResults != NULL) {
+ if (pingResultsTable_add(item) != SNMPERR_SUCCESS) {
+ DEBUGMSGTL(("pingResultsTable", "init an entry error\n"));
+ }
+ }
+ }
+ freeaddrinfo(ai);
+}
+
+
+int
+modify_ResultsOper(struct pingCtlTable_data *thedata, long val)
+{
+ netsnmp_variable_list *vars = NULL;
+ struct pingResultsTable_data *StorageTmp = NULL;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlOwnerIndex,
+ thedata->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlTestName,
+ thedata->pingCtlTestNameLen);
+
+ StorageTmp = header_complex_get(pingResultsTableStorage, vars);
+ snmp_free_varbind(vars);
+ if (!StorageTmp)
+ return SNMP_ERR_NOSUCHNAME;
+ StorageTmp->pingResultsOperStatus = val;
+
+ DEBUGMSGTL(("pingResultsOperStatus", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+int
+pingResultsTable_del(struct pingCtlTable_data *thedata)
+{
+ struct header_complex_index *hciptr2, *next;
+ struct pingResultsTable_data *StorageDel = NULL;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlOwnerIndex,
+ thedata->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlTestName,
+ thedata->pingCtlTestNameLen);
+ header_complex_generate_oid(newoid, &newoid_len, NULL, 0, vars);
+ snmp_free_varbind(vars);
+
+ for (hciptr2 = pingResultsTableStorage; hciptr2; hciptr2 = next) {
+ next = hciptr2->next;
+ if (snmp_oid_compare(newoid, newoid_len, hciptr2->name, newoid_len)
+ == 0) {
+ StorageDel =
+ header_complex_extract_entry(&pingResultsTableStorage,
+ hciptr2);
+ if (StorageDel != NULL) {
+ SNMP_FREE(StorageDel->pingCtlOwnerIndex);
+ SNMP_FREE(StorageDel->pingCtlTestName);
+ SNMP_FREE(StorageDel->pingResultsIpTargetAddress);
+ SNMP_FREE(StorageDel->pingResultsLastGoodProbe);
+ SNMP_FREE(StorageDel);
+ }
+ DEBUGMSGTL(("pingResultsTable", "delete success!\n"));
+
+ }
+ }
+ return SNMPERR_SUCCESS;
+}
+
+
+int
+pingProbeHistoryTable_del(struct pingCtlTable_data *thedata)
+{
+ struct header_complex_index *hciptr2, *next;
+ struct pingProbeHistoryTable_data *StorageDel = NULL;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlOwnerIndex,
+ thedata->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ thedata->pingCtlTestName,
+ thedata->pingCtlTestNameLen);
+ header_complex_generate_oid(newoid, &newoid_len, NULL, 0, vars);
+ snmp_free_varbind(vars);
+
+ for (hciptr2 = pingProbeHistoryTableStorage; hciptr2; hciptr2 = next) {
+ next = hciptr2->next;
+ if (snmp_oid_compare(newoid, newoid_len, hciptr2->name, newoid_len)
+ == 0) {
+ StorageDel =
+ header_complex_extract_entry(&pingProbeHistoryTableStorage,
+ hciptr2);
+ if (StorageDel != NULL) {
+ SNMP_FREE(StorageDel->pingCtlOwnerIndex);
+ SNMP_FREE(StorageDel->pingCtlTestName);
+ SNMP_FREE(StorageDel->pingProbeHistoryTime);
+ SNMP_FREE(StorageDel);
+ }
+ DEBUGMSGTL(("pingProbeHistoryTable", "delete success!\n"));
+
+ }
+ }
+ return SNMPERR_SUCCESS;
+}
+
+
+int
+write_pingCtlTargetAddressType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "write_pingCtlTargetAddressType entering action=%d... \n",
+ action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlTargetAddressType not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlTargetAddressType;
+ StorageTmp->pingCtlTargetAddressType = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlTargetAddressType = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_pingCtlTargetAddress(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ static size_t tmplen;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlTargetAddress not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlTargetAddress;
+ tmplen = StorageTmp->pingCtlTargetAddressLen;
+
+ StorageTmp->pingCtlTargetAddress =
+ (char *) malloc(var_val_len + 1);
+ if (StorageTmp->pingCtlTargetAddress == NULL) {
+ exit(1);
+ }
+ memcpy(StorageTmp->pingCtlTargetAddress, var_val, var_val_len);
+ StorageTmp->pingCtlTargetAddress[var_val_len] = '\0';
+ StorageTmp->pingCtlTargetAddressLen = var_val_len;
+
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->pingCtlTargetAddress);
+ StorageTmp->pingCtlTargetAddress = tmpvar;
+ StorageTmp->pingCtlTargetAddressLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_pingCtlDataSize(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlDataSize entering action=%d... \n", action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlDataSize not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlDataSize;
+ if ((*((long *) var_val)) >= 0 && (*((long *) var_val)) <= 65507)
+ StorageTmp->pingCtlDataSize = *((long *) var_val);
+ else
+ StorageTmp->pingCtlDataSize = 56;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlDataSize = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_pingCtlTimeOut(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlTimeOut entering action=%d... \n", action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlDataSize not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlTimeOut;
+ if ((*((long *) var_val)) >= 1 && (*((long *) var_val)) <= 60)
+ StorageTmp->pingCtlTimeOut = *((long *) var_val);
+ else
+ StorageTmp->pingCtlTimeOut = 3;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlTimeOut = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+
+int
+write_pingCtlProbeCount(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlProbeCount entering action=%d... \n", action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlDataSize not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlProbeCount;
+
+ if ((*((long *) var_val)) >= 1 && (*((long *) var_val)) <= 15)
+ StorageTmp->pingCtlProbeCount = *((long *) var_val);
+ else
+ StorageTmp->pingCtlProbeCount = 15;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlProbeCount = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_pingCtlAdminStatus(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlAdminStatus entering action=%d... \n", action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlTargetAddressType not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlAdminStatus;
+ StorageTmp->pingCtlAdminStatus = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlAdminStatus = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ if (StorageTmp->pingCtlAdminStatus == 1
+ && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ StorageTmp->pingResults->pingResultsOperStatus = 1;
+ modify_ResultsOper(StorageTmp, 1);
+ if (StorageTmp->pingCtlFrequency != 0)
+ StorageTmp->timer_id =
+ snmp_alarm_register(StorageTmp->pingCtlFrequency,
+ SA_REPEAT, run_ping, StorageTmp);
+ else
+ StorageTmp->timer_id = snmp_alarm_register(1, 0, run_ping,
+ StorageTmp);
+
+ } else if (StorageTmp->pingCtlAdminStatus == 2
+ && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ snmp_alarm_unregister(StorageTmp->timer_id);
+ StorageTmp->pingResults->pingResultsOperStatus = 2;
+ modify_ResultsOper(StorageTmp, 2);
+ }
+
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_pingCtlDataFill(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ static size_t tmplen;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlTargetAddress not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlDataFill;
+ tmplen = StorageTmp->pingCtlDataFillLen;
+ StorageTmp->pingCtlDataFill = (char *) malloc(var_val_len + 1);
+ if (StorageTmp->pingCtlDataFill == NULL) {
+ exit(1);
+ }
+ memcpy(StorageTmp->pingCtlDataFill, var_val, var_val_len);
+ StorageTmp->pingCtlDataFill[var_val_len] = '\0';
+ StorageTmp->pingCtlDataFillLen = var_val_len;
+
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->pingCtlDataFill);
+ StorageTmp->pingCtlDataFill = tmpvar;
+ StorageTmp->pingCtlDataFillLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+int
+write_pingCtlFrequency(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlFrequency entering action=%d... \n", action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlDataSize not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlFrequency;
+ StorageTmp->pingCtlFrequency = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlFrequency = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+int
+write_pingCtlMaxRows(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlMaxRows entering action=%d... \n", action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlMaxRows not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlMaxRows;
+ StorageTmp->pingCtlMaxRows = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlMaxRows = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_pingCtlStorageType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlStorageType entering action=%d... \n", action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlStorageType not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlStorageType;
+ StorageTmp->pingCtlStorageType = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlStorageType = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_pingCtlTrapGeneration(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ static size_t tmplen;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlTargetAddress not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlTrapGeneration;
+ tmplen = StorageTmp->pingCtlTrapGenerationLen;
+
+ StorageTmp->pingCtlTrapGeneration =
+ (char *) malloc(var_val_len + 1);
+ if (StorageTmp->pingCtlTrapGeneration == NULL) {
+ exit(1);
+ }
+ memcpy(StorageTmp->pingCtlTrapGeneration, var_val, var_val_len);
+ StorageTmp->pingCtlTrapGeneration[var_val_len] = '\0';
+ StorageTmp->pingCtlTrapGenerationLen = var_val_len;
+
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->pingCtlTrapGeneration);
+ StorageTmp->pingCtlTrapGeneration = tmpvar;
+ StorageTmp->pingCtlTrapGenerationLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+int
+write_pingCtlTrapProbeFailureFilter(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlTrapProbeFailureFilter entering action=%d... \n",
+ action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlTrapProbeFailureFilter not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlTrapProbeFailureFilter;
+
+ if ((*((long *) var_val)) >= 0 && (*((long *) var_val)) <= 15)
+ StorageTmp->pingCtlTrapProbeFailureFilter =
+ *((long *) var_val);
+ else
+ StorageTmp->pingCtlTrapProbeFailureFilter = 1;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlTrapProbeFailureFilter = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+int
+write_pingCtlTrapTestFailureFilter(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlTrapTestFailureFilter entering action=%d... \n",
+ action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlTrapTestFailureFilter not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlTrapTestFailureFilter;
+
+ if ((*((long *) var_val)) >= 0 && (*((long *) var_val)) <= 15)
+ StorageTmp->pingCtlTrapTestFailureFilter = *((long *) var_val);
+ else
+ StorageTmp->pingCtlTrapTestFailureFilter = 1;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlTrapTestFailureFilter = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+
+int
+write_pingCtlType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static oid *tmpvar;
+ static size_t tmplen;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OBJECT_ID) {
+ snmp_log(LOG_ERR, "write to pingCtlType not ASN_OBJECT_ID\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlType;
+ tmplen = StorageTmp->pingCtlTypeLen;
+
+ StorageTmp->pingCtlType = (oid *) malloc(var_val_len);
+ if (StorageTmp->pingCtlType == NULL) {
+ exit(1);
+ }
+ memcpy(StorageTmp->pingCtlType, var_val, var_val_len);
+
+ StorageTmp->pingCtlTypeLen = var_val_len / sizeof(oid);
+
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->pingCtlType);
+ StorageTmp->pingCtlType = tmpvar;
+ StorageTmp->pingCtlTypeLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_pingCtlDescr(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ static size_t tmplen;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR, "write to pingCtlDescr not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlDescr;
+ tmplen = StorageTmp->pingCtlDescrLen;
+
+ StorageTmp->pingCtlDescr = (char *) malloc(var_val_len + 1);
+ if (StorageTmp->pingCtlDescr == NULL) {
+ exit(1);
+ }
+ memcpy(StorageTmp->pingCtlDescr, var_val, var_val_len);
+ StorageTmp->pingCtlDescr[var_val_len] = '\0';
+ StorageTmp->pingCtlDescrLen = var_val_len;
+
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->pingCtlDescr);
+ StorageTmp->pingCtlDescr = tmpvar;
+ StorageTmp->pingCtlDescrLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+int
+write_pingCtlSourceAddressType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlSourceAddressType entering action=%d... \n",
+ action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlSourceAddressType not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlSourceAddressType;
+ StorageTmp->pingCtlSourceAddressType = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlSourceAddressType = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_pingCtlSourceAddress(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ static size_t tmplen;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlSourceAddress not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlSourceAddress;
+ tmplen = StorageTmp->pingCtlSourceAddressLen;
+
+ StorageTmp->pingCtlSourceAddress =
+ (char *) malloc(var_val_len + 1);
+ if (StorageTmp->pingCtlSourceAddress == NULL) {
+ exit(1);
+ }
+ memcpy(StorageTmp->pingCtlSourceAddress, var_val, var_val_len);
+ StorageTmp->pingCtlSourceAddress[var_val_len] = '\0';
+ StorageTmp->pingCtlSourceAddressLen = var_val_len;
+
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->pingCtlSourceAddress);
+ StorageTmp->pingCtlSourceAddress = tmpvar;
+ StorageTmp->pingCtlSourceAddressLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_pingCtlIfIndex(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlIfIndex entering action=%d... \n", action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR, "write to pingCtlIfIndex not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlIfIndex;
+ StorageTmp->pingCtlIfIndex = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlIfIndex = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_pingCtlByPassRouteTable(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlByPassRouteTable entering action=%d... \n",
+ action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlByPassRouteTable not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlByPassRouteTable;
+ StorageTmp->pingCtlByPassRouteTable = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlByPassRouteTable = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+
+int
+write_pingCtlDSField(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct pingCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+
+
+ DEBUGMSGTL(("pingCtlTable",
+ "pingCtlDSField entering action=%d... \n", action));
+
+ if ((StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to pingCtlDSField not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->pingCtlDSField;
+ StorageTmp->pingCtlDSField = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->pingCtlDSField = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+int
+write_pingCtlRowStatus(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ struct pingCtlTable_data *StorageTmp;
+ static struct pingCtlTable_data *StorageNew, *StorageDel;
+ size_t newlen =
+ name_len - (sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 3 - 1);
+ static int old_value;
+ int set_value;
+ struct header_complex_index *hciptr = NULL;
+
+ DEBUGMSGTL(("pingCtlTable",
+ "var_pingCtlTable: Entering... action=%ul\n", action));
+ StorageTmp =
+ header_complex(pingCtlTableStorage, NULL,
+ &name[sizeof(pingCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL, NULL);
+
+ if (var_val_type != ASN_INTEGER || var_val == NULL) {
+ snmp_log(LOG_ERR, "write to pingCtlRowStatus not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ set_value = *((long *) var_val);
+
+
+ /*
+ * check legal range, and notReady is reserved for us, not a user
+ */
+ if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY)
+ return SNMP_ERR_INCONSISTENTVALUE;
+
+
+ switch (action) {
+ case RESERVE1:
+ /*
+ * stage one: test validity
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * create the row now?
+ */
+
+
+ /*
+ * ditch illegal values now
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
+
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+
+ /*
+ * destroying a non-existent row is actually legal
+ */
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+
+
+ /*
+ * illegal creation values
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ } else {
+ /*
+ * row exists. Check for a valid state change
+ */
+ if (set_value == RS_CREATEANDGO
+ || set_value == RS_CREATEANDWAIT) {
+ /*
+ * can't create a row that exists
+ */
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+
+ /*
+ * XXX: interaction with row storage type needed
+ */
+
+ if (StorageTmp->pingCtlRowStatus == RS_ACTIVE &&
+ set_value != RS_DESTROY) {
+ /*
+ * "Once made active an entry may not be modified except to
+ * delete it." XXX: doesn't this in fact apply to ALL
+ * columns of the table and not just this one?
+ */
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE)
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ break;
+
+
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ if (StorageTmp == NULL) {
+ netsnmp_variable_list *vars, *vp;
+
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+ /*
+ * creation
+ */
+ vars = NULL;
+
+ /*
+ * ½«nameΪ¿ÕµÄÈý¸öË÷Òý×ֶμӵ½var±äÁ¿ÁбíµÄĩβ
+ */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* pingCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* pingCtlTestName */
+
+ if (header_complex_parse_oid
+ (&
+ (name
+ [sizeof(pingCtlTable_variables_oid) / sizeof(oid) +
+ 2]), newlen, vars) != SNMPERR_SUCCESS) {
+ snmp_free_varbind(vars);
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+ vp = vars;
+
+ StorageNew = create_pingCtlTable_data();
+ if (!StorageNew)
+ return SNMP_ERR_GENERR;
+ if (vp->val_len <= 32) {
+ StorageNew->pingCtlOwnerIndex = malloc(vp->val_len + 1);
+ memcpy(StorageNew->pingCtlOwnerIndex, vp->val.string,
+ vp->val_len);
+ StorageNew->pingCtlOwnerIndex[vp->val_len] = '\0';
+ StorageNew->pingCtlOwnerIndexLen = vp->val_len;
+ } else {
+ StorageNew->pingCtlOwnerIndex = malloc(33);
+ memcpy(StorageNew->pingCtlOwnerIndex, vp->val.string, 32);
+ StorageNew->pingCtlOwnerIndex[32] = '\0';
+ StorageNew->pingCtlOwnerIndexLen = 32;
+ }
+
+ vp = vp->next_variable;
+
+ if (vp->val_len <= 32) {
+ StorageNew->pingCtlTestName = malloc(vp->val_len + 1);
+ memcpy(StorageNew->pingCtlTestName, vp->val.string,
+ vp->val_len);
+ StorageNew->pingCtlTestName[vp->val_len] = '\0';
+ StorageNew->pingCtlTestNameLen = vp->val_len;
+ } else {
+ StorageNew->pingCtlTestName = malloc(33);
+ memcpy(StorageNew->pingCtlTestName, vp->val.string, 32);
+ StorageNew->pingCtlTestName[32] = '\0';
+ StorageNew->pingCtlTestNameLen = 32;
+ }
+ vp = vp->next_variable;
+
+ /*
+ * XXX: fill in default row values here into StorageNew
+ */
+
+ StorageNew->pingCtlRowStatus = set_value;
+
+
+ snmp_free_varbind(vars);
+ }
+
+
+ break;
+
+
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+
+ if (set_value == RS_DESTROY && StorageNew)
+ free_pingCtlTable_data(StorageNew);
+ StorageNew = NULL;
+
+ if (StorageDel) {
+ free_pingCtlTable_data(StorageDel);
+ StorageDel = NULL;
+ }
+ break;
+
+
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in set_value for you to
+ * use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in
+ * the UNDO case
+ */
+
+ if (StorageTmp == NULL) {
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+ /*
+ * row creation, so add it
+ */
+ if (StorageNew != NULL)
+#if 1
+ DEBUGMSGTL(("pingCtlTable",
+ "write_pingCtlRowStatus entering new=%d... \n",
+ action));
+#endif
+ pingCtlTable_add(StorageNew);
+ /*
+ * XXX: ack, and if it is NULL?
+ */
+ } else if (set_value != RS_DESTROY) {
+ /*
+ * set the flag?
+ */
+ old_value = StorageTmp->pingCtlRowStatus;
+ StorageTmp->pingCtlRowStatus = *((long *) var_val);
+ } else {
+ /*
+ * destroy... extract it for now
+ */
+
+ hciptr =
+ header_complex_find_entry(pingCtlTableStorage, StorageTmp);
+ StorageDel =
+ header_complex_extract_entry(&pingCtlTableStorage, hciptr);
+ snmp_alarm_unregister(StorageDel->timer_id);
+
+ pingResultsTable_del(StorageTmp);
+ pingProbeHistoryTable_del(StorageTmp);
+ }
+ break;
+
+
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ if (StorageTmp == NULL) {
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+ /*
+ * row creation, so remove it again
+ */
+ hciptr =
+ header_complex_find_entry(pingCtlTableStorage, StorageNew);
+ StorageDel =
+ header_complex_extract_entry(&pingCtlTableStorage, hciptr);
+ free_pingCtlTable_data(StorageDel);
+ StorageDel = NULL;
+ } else if (StorageDel != NULL) {
+ /*
+ * row deletion, so add it again
+ */
+ pingCtlTable_add(StorageDel);
+ pingResultsTable_add(StorageDel);
+ pingProbeHistoryTable_addall(StorageDel);
+ StorageDel = NULL;
+ } else {
+ StorageTmp->pingCtlRowStatus = old_value;
+ }
+ break;
+
+
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ if (StorageTmp == NULL) {
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+ }
+
+ if (StorageDel != NULL) {
+ free_pingCtlTable_data(StorageDel);
+ StorageDel = NULL;
+ } else {
+ if (StorageTmp
+ && StorageTmp->pingCtlRowStatus == RS_CREATEANDGO) {
+ StorageTmp->pingCtlRowStatus = RS_ACTIVE;
+ } else if (StorageTmp &&
+ StorageTmp->pingCtlRowStatus == RS_CREATEANDWAIT) {
+ DEBUGMSGTL(("pingCtlTable",
+ "write_pingCtlRowStatus entering pingCtlRowStatus=%ld... \n",
+ StorageTmp->pingCtlRowStatus));
+
+ StorageTmp->pingCtlRowStatus = RS_NOTINSERVICE;
+ }
+ }
+ if (StorageTmp && StorageTmp->pingCtlRowStatus == RS_ACTIVE) {
+#if 1
+ DEBUGMSGTL(("pingCtlTable",
+ "write_pingCtlRowStatus entering runbefore \n"));
+
+#endif
+
+ if (StorageTmp->pingCtlAdminStatus == 1) {
+ init_resultsTable(StorageTmp);
+ if (StorageTmp->pingCtlFrequency != 0)
+ StorageTmp->timer_id =
+ snmp_alarm_register(StorageTmp->pingCtlFrequency,
+ SA_REPEAT, run_ping,
+ StorageTmp);
+ else
+ StorageTmp->timer_id =
+ snmp_alarm_register(1, 0, run_ping, StorageTmp);
+
+ }
+
+ }
+ snmp_store_needed(NULL);
+
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+static inline void
+tvsub(struct timeval *out, struct timeval *in)
+{
+ if ((out->tv_usec -= in->tv_usec) < 0) {
+ --out->tv_sec;
+ out->tv_usec += 1000000;
+ }
+ out->tv_sec -= in->tv_sec;
+}
+
+
+static inline int
+schedule_exit(int next, int *deadline, long *npackets, long *nreceived,
+ long *ntransmitted, long *tmax)
+{
+ if ((*npackets) && (*ntransmitted) >= (*npackets) && !(*deadline))
+ next = __schedule_exit(next, nreceived, tmax);
+ return next;
+}
+
+static inline int
+in_flight(__u16 * acked, long *nreceived, long *ntransmitted,
+ long *nerrors)
+{
+ __u16 diff = (__u16) (*ntransmitted) - (*acked);
+ return (diff <=
+ 0x7FFF) ? diff : (*ntransmitted) - (*nreceived) - (*nerrors);
+}
+
+static inline void
+acknowledge(__u16 seq, __u16 * acked, long *ntransmitted, int *pipesize)
+{
+ __u16 diff = (__u16) (*ntransmitted) - seq;
+ if (diff <= 0x7FFF) {
+ if ((int) diff + 1 > (*pipesize))
+ (*pipesize) = (int) diff + 1;
+ if ((__s16) (seq - (*acked)) > 0 ||
+ (__u16) (*ntransmitted) - (*acked) > 0x7FFF)
+ *acked = seq;
+ }
+}
+
+static inline void
+advance_ntransmitted(__u16 * acked, long *ntransmitted)
+{
+ (*ntransmitted)++;
+ /*
+ * Invalidate acked, if 16 bit seq overflows.
+ */
+ if ((__u16) (*ntransmitted) - (*acked) > 0x7FFF)
+ *acked = (__u16) (*ntransmitted) + 1;
+}
+
+
+static inline void
+update_interval(int uid, int interval, int *rtt_addend, int *rtt)
+{
+ int est = (*rtt) ? (*rtt) / 8 : interval * 1000;
+
+ interval = (est + (*rtt_addend) + 500) / 1000;
+ if (uid && interval < MINUSERINTERVAL)
+ interval = MINUSERINTERVAL;
+}
+
+
+
+int
+__schedule_exit(int next, long *nreceived, long *tmax)
+{
+ unsigned long waittime;
+#if 0
+ struct itimerval it;
+#endif
+
+ if (*nreceived) {
+ waittime = 2 * (*tmax);
+ if (waittime < 1000000)
+ waittime = 1000000;
+ } else
+ waittime = MAXWAIT * 1000000;
+
+ if (next < 0 || next < waittime / 1000)
+ next = waittime / 1000;
+
+#if 0
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+ it.it_value.tv_sec = waittime / 1000000;
+ it.it_value.tv_usec = waittime % 1000000;
+ setitimer(ITIMER_REAL, &it, NULL);
+#endif
+ return next;
+}
+
+
+/*
+ * pinger --
+ * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
+ * will be added on by the kernel. The ID field is our UNIX process ID,
+ * and the sequence number is an ascending integer. The first 8 bytes
+ * of the data portion are used to hold a UNIX "timeval" struct in VAX
+ * byte-order, to compute the round-trip time.
+ */
+
+int
+pinger(int icmp_sock, int preload, int cmsglen, char *cmsgbuf,
+ struct sockaddr_in6 *whereto, int *rtt_addend, int options, int uid,
+ int interval, int datalen, int timing, char *outpack, int *rtt,
+ int *ident, int *screen_width, int *deadline, __u16 * acked,
+ long *npackets, long *nreceived, long *ntransmitted, long *nerrors,
+ int *confirm_flag, int *confirm, int *pipesize,
+ struct timeval *cur_time)
+{
+ static int tokens;
+ int i;
+
+ /*
+ * Have we already sent enough? If we have, return an arbitrary positive value.
+ */
+
+ if (exiting
+ || ((*npackets) && (*ntransmitted) >= (*npackets)
+ && !(*deadline))) {
+
+ return 1000;
+ }
+ /*
+ * Check that packets < rate*time + preload
+ */
+ if ((*cur_time).tv_sec == 0) {
+ netsnmp_get_monotonic_clock(cur_time);
+ tokens = interval * (preload - 1);
+ } else {
+ long ntokens;
+ struct timeval tv;
+
+ netsnmp_get_monotonic_clock(&tv);
+ ntokens = (tv.tv_sec - (*cur_time).tv_sec) * 1000 +
+ (tv.tv_usec - (*cur_time).tv_usec) / 1000;
+ if (!interval) {
+ /*
+ * Case of unlimited flood is special;
+ * * if we see no reply, they are limited to 100pps
+ */
+ if (ntokens < MININTERVAL
+ && in_flight(acked, nreceived, ntransmitted,
+ nerrors) >= preload)
+ return MININTERVAL - ntokens;
+ }
+ ntokens += tokens;
+
+ if (ntokens > interval * preload)
+ ntokens = interval * preload;
+
+ if (ntokens < interval) {
+ return interval - ntokens;
+ }
+ *cur_time = tv;
+ tokens = ntokens - interval;
+ }
+
+ resend:
+ i = send_v6(icmp_sock, cmsglen, cmsgbuf, whereto, datalen, timing,
+ outpack, ident, ntransmitted, confirm);
+
+ if (i == 0) {
+ advance_ntransmitted(acked, ntransmitted);
+ if (!(options & F_QUIET) && (options & F_FLOOD)) {
+ /*
+ * Very silly, but without this output with
+ * * high preload or pipe size is very confusing.
+ */
+ if ((preload < (*screen_width)
+ && (*pipesize) < (*screen_width))
+ || in_flight(acked, nreceived, ntransmitted,
+ nerrors) < (*screen_width))
+ write(STDOUT_FILENO, ".", 1);
+ }
+
+ return interval - tokens;
+ }
+
+ /*
+ * And handle various errors...
+ */
+ if (i > 0) {
+ /*
+ * Apparently, it is some fatal bug.
+ */
+ abort();
+ } else if (errno == ENOBUFS || errno == ENOMEM) {
+ /*
+ * Device queue overflow or OOM. Packet is not sent.
+ */
+ tokens = 0;
+ /*
+ * Slowdown. This works only in adaptive mode (option -A)
+ */
+ (*rtt_addend) += ((*rtt) < 8 * 50000 ? (*rtt) / 8 : 50000);
+ if (options & F_ADAPTIVE)
+ update_interval(uid, interval, rtt_addend, rtt);
+
+ return SCHINT(interval);
+ } else if (errno == EAGAIN) {
+ /*
+ * Socket buffer is full.
+ */
+ tokens += interval;
+
+ return MININTERVAL;
+ } else {
+ if ((i =
+ receive_error_msg(icmp_sock, whereto, options, ident,
+ nerrors)) > 0) {
+ /*
+ * An ICMP error arrived.
+ */
+ tokens += interval;
+
+ return MININTERVAL;
+ }
+ /*
+ * Compatibility with old linuces.
+ */
+ if (i == 0 && (*confirm_flag) && errno == EINVAL) {
+ *confirm_flag = 0;
+ errno = 0;
+ }
+ if (!errno)
+ goto resend;
+
+ /*
+ * Hard local error. Pretend we sent packet.
+ */
+ advance_ntransmitted(acked, ntransmitted);
+
+ if (i == 0 && !(options & F_QUIET)) {
+ if (options & F_FLOOD)
+ write(STDOUT_FILENO, "E", 1);
+ else
+ perror("ping: sendmsg");
+ }
+ tokens = 0;
+
+ return SCHINT(interval);
+ }
+}
+
+/*
+ * Set socket buffers, "alloc" is an esimate of memory taken by single packet.
+ */
+
+void
+sock_setbufs(int icmp_sock, int alloc, int preload)
+{
+ int rcvbuf, hold;
+ socklen_t tmplen = sizeof(hold);
+ int sndbuf;
+
+ if (!sndbuf)
+ sndbuf = alloc;
+ setsockopt(icmp_sock, SOL_SOCKET, SO_SNDBUF, (char *) &sndbuf,
+ sizeof(sndbuf));
+
+ rcvbuf = hold = alloc * preload;
+ if (hold < 65536)
+ hold = 65536;
+ setsockopt(icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *) &hold,
+ sizeof(hold));
+ if (getsockopt
+ (icmp_sock, SOL_SOCKET, SO_RCVBUF, (char *) &hold, &tmplen) == 0) {
+ if (hold < rcvbuf)
+ fprintf(stderr,
+ "WARNING: probably, rcvbuf is not enough to hold preload.\n");
+ }
+}
+
+/*
+ * Protocol independent setup and parameter checks.
+ */
+
+void
+setup(int icmp_sock, int options, int uid, int timeout, int preload,
+ int interval, int datalen, char *outpack, int *ident,
+ struct timeval *start_time, int *screen_width, int *deadline)
+{
+ int hold;
+ struct timeval tv;
+
+ if ((options & F_FLOOD) && !(options & F_INTERVAL))
+ interval = 0;
+
+ if (uid && interval < MINUSERINTERVAL) {
+ fprintf(stderr,
+ "ping: cannot flood; minimal interval, allowed for user, is %dms\n",
+ MINUSERINTERVAL);
+ return;
+ }
+
+ if (interval >= INT_MAX / preload) {
+ fprintf(stderr, "ping: illegal preload and/or interval\n");
+ return;
+ }
+
+ hold = 1;
+ if (options & F_SO_DEBUG)
+ setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG, (char *) &hold,
+ sizeof(hold));
+ if (options & F_SO_DONTROUTE)
+ setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE, (char *) &hold,
+ sizeof(hold));
+
+#ifdef SO_TIMESTAMP
+ if (!(options & F_LATENCY)) {
+ int on = 1;
+ if (setsockopt
+ (icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
+ fprintf(stderr,
+ "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP\n");
+ }
+#endif
+
+ /*
+ * Set some SNDTIMEO to prevent blocking forever
+ * * on sends, when device is too slow or stalls. Just put limit
+ * * of one second, or "interval", if it is less.
+ */
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ if (interval < 1000) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000 * SCHINT(interval);
+ }
+ setsockopt(icmp_sock, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv,
+ sizeof(tv));
+
+ /*
+ * Set RCVTIMEO to "interval". Note, it is just an optimization
+ * * allowing to avoid redundant poll().
+ */
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ if (setsockopt
+ (icmp_sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(tv)))
+ options |= F_FLOOD_POLL;
+
+ if (!(options & F_PINGFILLED)) {
+ int i;
+ char *p = outpack + 8;
+
+ /*
+ * Do not forget about case of small datalen,
+ * * fill timestamp area too!
+ */
+ for (i = 0; i < datalen; ++i)
+ *p++ = i;
+ }
+
+ *ident = getpid() & 0xFFFF;
+
+ netsnmp_get_monotonic_clock(start_time);
+
+#if 0
+ if (*deadline) {
+ struct itimerval it;
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+ it.it_value.tv_sec = (*deadline);
+ it.it_value.tv_usec = 0;
+ }
+#endif
+
+ if (isatty(STDOUT_FILENO)) {
+ struct winsize w;
+
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
+ if (w.ws_col > 0)
+ *screen_width = w.ws_col;
+ }
+ }
+}
+
+void
+main_loop(struct pingCtlTable_data *item, int icmp_sock, int preload,
+ __u8 * packet, int packlen, int cmsglen, char *cmsgbuf,
+ struct sockaddr_in6 *whereto, int options, int uid,
+ char *hostname, int interval, int datalen, int timing,
+ int working_recverr, char *outpack, int *ident,
+ struct timeval *start_time, int *screen_width, int *deadline)
+{
+ char addrbuf[128];
+ char ans_data[4096];
+ struct iovec iov;
+ struct msghdr msg;
+ struct cmsghdr *c;
+ int cc = 0;
+ int next = 0;
+ int polling = 0;
+ int rtt = 0;
+ int rtt_addend = 0;
+
+ __u16 acked = 0;
+ /*
+ * counters
+ */
+ long npackets = 0; /* max packets to transmit */
+ long nreceived = 0; /* # of packets we got back */
+ long nrepeats = 0; /* number of duplicates */
+ long ntransmitted = 0; /* sequence # for outbound packets = #sent */
+ long nchecksum = 0; /* replies with bad checksum */
+ long nerrors = 0; /* icmp errors */
+
+ /*
+ * timing
+ */
+ long tmin = LONG_MAX; /* minimum round trip time */
+ long tmax = 0; /* maximum round trip time */
+ long long tsum = 0; /* sum of all times, for doing average */
+ long long tsum2 = 0;
+
+ int confirm_flag = MSG_CONFIRM;
+ int confirm = 0;
+
+ int pipesize = -1;
+ struct timeval cur_time;
+ cur_time.tv_sec = 0;
+ cur_time.tv_usec = 0;
+
+ struct pingProbeHistoryTable_data current_temp;
+ static int probeFailed = 0;
+ static int testFailed = 0;
+ static int series = 0;
+
+ iov.iov_base = (char *) packet;
+ npackets = item->pingCtlProbeCount;
+ for (;;) {
+ /*
+ * Check exit conditions.
+ */
+ if (exiting) {
+ break;
+ }
+ if (npackets && nreceived >= npackets) {
+ DEBUGMSGTL(("pingCtlTable", "npackets,nreceived=%ld\n", nreceived));
+ break;
+ }
+ if (deadline && nerrors) {
+ DEBUGMSGTL(("pingCtlTable", "deadline\n"));
+ break;
+ }
+
+ /*
+ * Check for and do special actions.
+ */
+ if (status_snapshot)
+ status(timing, &rtt, &nreceived, &nrepeats, &ntransmitted,
+ &tmin, &tmax, &tsum, &tsum2);
+
+ /*
+ * Send probes scheduled to this time.
+ */
+ do {
+ DEBUGMSGTL(("pingCtlTable", "pinger\n"));
+ next =
+ pinger(icmp_sock, preload, cmsglen, cmsgbuf, whereto,
+ &rtt_addend, uid, options, interval, datalen,
+ timing, outpack, &rtt, ident, screen_width,
+ deadline, &acked, &npackets, &nreceived,
+ &ntransmitted, &nerrors, &confirm_flag, &confirm,
+ &pipesize, &cur_time);
+ DEBUGMSGTL(("pingCtlTable", "1:next=%d\n", next));
+ next =
+ schedule_exit(next, deadline, &npackets, &nreceived,
+ &ntransmitted, &tmax);
+ DEBUGMSGTL(("pingCtlTable", "2:next=%d\n", next));
+ } while (next <= 0);
+
+ /*
+ * "next" is time to send next probe, if positive.
+ * * If next<=0 send now or as soon as possible.
+ */
+
+ /*
+ * Technical part. Looks wicked. Could be dropped,
+ * * if everyone used the newest kernel. :-)
+ * * Its purpose is:
+ * * 1. Provide intervals less than resolution of scheduler.
+ * * Solution: spinning.
+ * * 2. Avoid use of poll(), when recvmsg() can provide
+ * * timed waiting (SO_RCVTIMEO).
+ */
+ polling = 0;
+ if ((options & (F_ADAPTIVE | F_FLOOD_POLL))
+ || next < SCHINT(interval)) {
+ int recv_expected =
+ in_flight(&acked, &nreceived, &ntransmitted, &nerrors);
+
+ /*
+ * If we are here, recvmsg() is unable to wait for
+ * * required timeout.
+ */
+ if (1000 * next <= 1000000 / (int) HZ) {
+ /*
+ * Very short timeout... So, if we wait for
+ * * something, we sleep for MININTERVAL.
+ * * Otherwise, spin!
+ */
+ if (recv_expected) {
+ next = MININTERVAL;
+ } else {
+ next = 0;
+ /*
+ * When spinning, no reasons to poll.
+ * * Use nonblocking recvmsg() instead.
+ */
+ polling = MSG_DONTWAIT;
+ /*
+ * But yield yet.
+ */
+ sched_yield();
+ }
+ }
+
+ if (!polling &&
+ ((options & (F_ADAPTIVE | F_FLOOD_POLL)) || interval)) {
+ struct pollfd pset;
+ pset.fd = icmp_sock;
+ pset.events = POLLIN | POLLERR;
+ pset.revents = 0;
+ if (poll(&pset, 1, next) < 1 ||
+ !(pset.revents & (POLLIN | POLLERR)))
+ continue;
+ polling = MSG_DONTWAIT;
+ }
+ }
+
+ for (;;) {
+ struct timeval *recv_timep = NULL;
+ struct timeval recv_time;
+ int not_ours = 0; /* Raw socket can receive messages
+ * destined to other running pings. */
+
+ iov.iov_len = packlen;
+ msg.msg_name = addrbuf;
+ msg.msg_namelen = sizeof(addrbuf);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ans_data;
+ msg.msg_controllen = sizeof(ans_data);
+
+ cc = recvmsg(icmp_sock, &msg, polling);
+ time_t timep;
+ time(&timep);
+ polling = MSG_DONTWAIT;
+
+ if (cc < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ break;
+ if (errno == EWOULDBLOCK) {
+ struct pingResultsTable_data *StorageNew = NULL;
+ struct pingProbeHistoryTable_data *temp = NULL;
+ netsnmp_variable_list *vars = NULL;
+
+ if (series == 0)
+ probeFailed = 1;
+ else
+ probeFailed = probeFailed + 1;
+ series = 1;
+ testFailed = testFailed + 1;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlTestName,
+ item->pingCtlTestNameLen);
+
+ StorageNew = header_complex_get(pingResultsTableStorage,
+ vars);
+ snmp_free_varbind(vars);
+ if (!StorageNew)
+ return;
+
+ StorageNew->pingResultsSendProbes =
+ StorageNew->pingResultsSendProbes + 1;
+
+ temp = SNMP_MALLOC_STRUCT(pingProbeHistoryTable_data);
+
+ temp->pingCtlOwnerIndex =
+ (char *) malloc(item->pingCtlOwnerIndexLen + 1);
+ memcpy(temp->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndexLen + 1);
+ temp->pingCtlOwnerIndex[item->pingCtlOwnerIndexLen] =
+ '\0';
+ temp->pingCtlOwnerIndexLen =
+ item->pingCtlOwnerIndexLen;
+
+ temp->pingCtlTestName =
+ (char *) malloc(item->pingCtlTestNameLen + 1);
+ memcpy(temp->pingCtlTestName, item->pingCtlTestName,
+ item->pingCtlTestNameLen + 1);
+ temp->pingCtlTestName[item->pingCtlTestNameLen] = '\0';
+ temp->pingCtlTestNameLen = item->pingCtlTestNameLen;
+
+ /* add lock to protect */
+ pthread_mutex_t counter_mutex =
+ PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&counter_mutex);
+ temp->pingProbeHistoryIndex =
+ ++(item->pingProbeHistoryMaxIndex);
+ pthread_mutex_unlock(&counter_mutex);
+ /* end */
+
+ temp->pingProbeHistoryResponse =
+ item->pingCtlTimeOut * 1000;
+ temp->pingProbeHistoryStatus = 4;
+ temp->pingProbeHistoryLastRC = 1;
+
+ temp->pingProbeHistoryTime_time = timep;
+ memdup(&temp->pingProbeHistoryTime,
+ date_n_time(&timep, &temp->pingProbeHistoryTimeLen), 11);
+
+ if (StorageNew->pingResultsSendProbes == 1)
+ item->pingProbeHis = temp;
+ else {
+ (current_temp).next = temp;
+ }
+
+ current_temp = (*temp);
+
+ if (StorageNew->pingResultsSendProbes >=
+ item->pingCtlProbeCount) {
+ current_temp.next = NULL;
+ }
+
+ if (item->pingProbeHis != NULL) {
+ if (pingProbeHistoryTable_count(item) <
+ item->pingCtlMaxRows) {
+ if (pingProbeHistoryTable_add(&current_temp) !=
+ SNMPERR_SUCCESS)
+ DEBUGMSGTL(("pingProbeHistoryTable",
+ "registered an entry error\n"));
+ } else {
+ pingProbeHistoryTable_delLast(item);
+ if (pingProbeHistoryTable_add(&current_temp) !=
+ SNMPERR_SUCCESS)
+ DEBUGMSGTL(("pingProbeHistoryTable",
+ "registered an entry error\n"));
+
+ }
+ }
+ if ((item->
+ pingCtlTrapGeneration[0] &
+ PINGTRAPGENERATION_PROBEFAILED) != 0) {
+ if (probeFailed >=
+ item->pingCtlTrapProbeFailureFilter)
+ send_ping_trap(item, pingProbeFailed,
+ sizeof(pingProbeFailed) /
+ sizeof(oid));
+ }
+ break;
+ }
+ /* timeout finish */
+ if (!receive_error_msg
+ (icmp_sock, whereto, options, ident, &nerrors)) {
+ if (errno) {
+ perror("ping: recvmsg");
+ break;
+ }
+ not_ours = 1;
+ }
+ } else {
+ DEBUGMSGTL(("pingCtlTable", "cc>=0,else\n"));
+#ifdef SO_TIMESTAMP
+ for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
+ if (c->cmsg_level != SOL_SOCKET ||
+ c->cmsg_type != SO_TIMESTAMP)
+ continue;
+ if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
+ continue;
+ recv_timep = (struct timeval *) CMSG_DATA(c);
+ }
+#endif
+
+ if ((options & F_LATENCY) || recv_timep == NULL) {
+ if ((options & F_LATENCY) ||
+ ioctl(icmp_sock, SIOCGSTAMP, &recv_time))
+ netsnmp_get_monotonic_clock(&recv_time);
+ recv_timep = &recv_time;
+ }
+
+ not_ours =
+ parse_reply(&series, item, &msg, cc, addrbuf,
+ recv_timep, timep, uid, whereto,
+ &rtt_addend, options, interval, datalen,
+ timing, working_recverr, outpack, &rtt,
+ ident, &acked, &nreceived, &nrepeats,
+ &ntransmitted, &nchecksum, &nerrors, &tmin,
+ &tmax, &tsum, &tsum2, &confirm_flag,
+ &confirm, &pipesize, &current_temp);
+ }
+
+ /*
+ * See? ... someone runs another ping on this host.
+ */
+ if (not_ours)
+ install_filter(icmp_sock, ident);
+
+ /*
+ * If nothing is in flight, "break" returns us to pinger.
+ */
+ if (in_flight(&acked, &nreceived, &ntransmitted, &nerrors) ==
+ 0)
+ break;
+
+ /*
+ * Otherwise, try to recvmsg() again. recvmsg()
+ * * is nonblocking after the first iteration, so that
+ * * if nothing is queued, it will receive EAGAIN
+ * * and return to pinger.
+ */
+ }
+ }
+
+ if (ntransmitted == item->pingCtlProbeCount) {
+
+ if ((item->
+ pingCtlTrapGeneration[0] & PINGTRAPGENERATION_TESTCOMPLETED)
+ != 0) {
+ send_ping_trap(item, pingTestCompleted,
+ sizeof(pingTestCompleted) / sizeof(oid));
+ } else
+ if ((item->
+ pingCtlTrapGeneration[0] & PINGTRAPGENERATION_TESTFAILED)
+ != 0) {
+
+ if (testFailed >= item->pingCtlTrapTestFailureFilter)
+ send_ping_trap(item, pingTestFailed,
+ sizeof(pingTestFailed) / sizeof(oid));
+ }
+
+ else if ((item->
+ pingCtlTrapGeneration[0] &
+ PINGTRAPGENERATION_PROBEFAILED) != 0) {;
+ } else {
+ ;
+ }
+
+ series = 0;
+ probeFailed = 0;
+ testFailed = 0;
+
+ }
+
+ finish(options, hostname, interval, timing, &rtt, start_time, deadline,
+ &npackets, &nreceived, &nrepeats, &ntransmitted, &nchecksum,
+ &nerrors, &tmin, &tmax, &tsum, &tsum2, &pipesize, &cur_time);
+}
+
+int
+gather_statistics(int *series, struct pingCtlTable_data *item, __u8 * ptr,
+ int cc, __u16 seq, int hops, int csfailed,
+ struct timeval *tv, time_t timep, int *rtt_addend,
+ int uid, int options, char *from, int interval,
+ int datalen, int timing, char *outpack, int *rtt,
+ __u16 * acked, long *nreceived, long *nrepeats,
+ long *ntransmitted, long *nchecksum, long *tmin,
+ long *tmax, long long *tsum, long long *tsum2,
+ int *confirm_flag, int *confirm, int *pipesize,
+ struct pingProbeHistoryTable_data *current_temp)
+{
+ int dupflag = 0;
+ long triptime = 0;
+ int mx_dup_ck = MAX_DUP_CHK;
+
+ netsnmp_variable_list *vars = NULL;
+ struct pingResultsTable_data *StorageNew = NULL;
+ struct pingProbeHistoryTable_data *temp = NULL;
+ ++(*nreceived);
+ *series = 0;
+ if (!csfailed)
+ acknowledge(seq, acked, ntransmitted, pipesize);
+
+ if (timing && cc >= 8 + sizeof(struct timeval)) {
+ struct timeval tmp_tv;
+ memcpy(&tmp_tv, ptr, sizeof(tmp_tv));
+
+ tvsub(tv, &tmp_tv);
+ triptime = tv->tv_sec * 1000000 + tv->tv_usec;
+ if (triptime < 0) {
+ snmp_log(LOG_INFO,
+ "Warning: invalid timestamp in ICMP response.\n");
+ triptime = 0;
+ if (!(options & F_LATENCY))
+ options |= F_LATENCY;
+ }
+ if (!csfailed) {
+ (*tsum) += triptime;
+ (*tsum2) += (long long) triptime *(long long) triptime;
+ if (triptime < (*tmin))
+ (*tmin) = triptime;
+ if (triptime > (*tmax))
+ (*tmax) = triptime;
+ if (!(*rtt))
+ *rtt = triptime * 8;
+ else
+ *rtt += triptime - (*rtt) / 8;
+ if (options & F_ADAPTIVE)
+ update_interval(uid, interval, rtt_addend, rtt);
+ }
+ }
+
+ if (csfailed) {
+ ++(*nchecksum);
+ --(*nreceived);
+ } else if (TST(seq % mx_dup_ck)) {
+ ++(*nrepeats);
+ --(*nreceived);
+ dupflag = 1;
+ } else {
+ SET(seq % mx_dup_ck);
+ dupflag = 0;
+ }
+ *confirm = *confirm_flag;
+
+ if (options & F_QUIET)
+ return 1;
+
+ if (options & F_FLOOD) {
+ if (!csfailed)
+ write(STDOUT_FILENO, "\b \b", 3);
+ else
+ write(STDOUT_FILENO, "\bC", 1);
+ } else {
+ int i;
+ __u8 *cp, *dp;
+
+ DEBUGMSGTL(("pingCtlTable", "%d bytes from %s: icmp_seq=%u", cc, from,
+ seq));
+
+ if (hops >= 0)
+ DEBUGMSGTL(("pingCtlTable", " ttl=%d", hops));
+
+ if (cc < datalen + 8) {
+ DEBUGMSGTL(("pingCtlTable", " (truncated)\n"));
+ return 1;
+ }
+ if (timing) {
+ if (triptime >= 100000)
+ DEBUGMSGTL(("pingCtlTable", " time=%ld ms", triptime / 1000));
+ else if (triptime >= 10000)
+ DEBUGMSGTL(("pingCtlTable", " time=%ld.%01ld ms",
+ triptime / 1000, (triptime % 1000) / 100));
+ else if (triptime >= 1000)
+ DEBUGMSGTL(("pingCtlTable", " time=%ld.%02ld ms",
+ triptime / 1000, (triptime % 1000) / 10));
+ else
+ DEBUGMSGTL(("pingCtlTable", " time=%ld.%03ld ms",
+ triptime / 1000, triptime % 1000));
+ }
+ if (dupflag)
+ DEBUGMSGTL(("pingCtlTable", " (DUP!)"));
+ if (csfailed)
+ DEBUGMSGTL(("pingCtlTable", " (BAD CHECKSUM!)"));
+
+ /*
+ * check the data
+ */
+ cp = ((u_char *) ptr) + sizeof(struct timeval);
+ dp = (u_char *)&outpack[8 + sizeof(struct timeval)];
+ for (i = sizeof(struct timeval); i < datalen; ++i, ++cp, ++dp) {
+ if (*cp != *dp) {
+ DEBUGMSGTL(("pingCtlTable",
+ "\nwrong data byte #%d should be 0x%x but was 0x%x",
+ i, *dp, *cp));
+ cp = (u_char *) ptr + sizeof(struct timeval);
+ for (i = sizeof(struct timeval); i < datalen; ++i, ++cp) {
+ if ((i % 32) == sizeof(struct timeval))
+ DEBUGMSGTL(("pingCtlTable", "\n#%d\t", i));
+ DEBUGMSGTL(("pingCtlTable", "%x ", *cp));
+ }
+ break;
+ }
+ }
+ }
+
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndexLen);
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR,
+ item->pingCtlTestName,
+ item->pingCtlTestNameLen);
+
+ StorageNew = header_complex_get(pingResultsTableStorage, vars);
+ snmp_free_varbind(vars);
+ if (!StorageNew)
+ return SNMP_ERR_NOSUCHNAME;
+
+
+ StorageNew->pingResultsMinRtt = *tmin;
+ StorageNew->pingResultsMaxRtt = *tmax;
+ StorageNew->pingResultsAverageRtt =
+ (*tsum) / (StorageNew->pingResultsProbeResponses + 1);
+ StorageNew->pingResultsProbeResponses =
+ StorageNew->pingResultsProbeResponses + 1;
+ StorageNew->pingResultsSendProbes =
+ StorageNew->pingResultsSendProbes + 1;
+ StorageNew->pingResultsRttSumOfSquares = *tsum2;
+
+ StorageNew->pingResultsLastGoodProbe_time = timep;
+ free(StorageNew->pingResultsLastGoodProbe);
+ memdup(&StorageNew->pingResultsLastGoodProbe,
+ date_n_time(&timep, &StorageNew->pingResultsLastGoodProbeLen), 11);
+
+ /* ProbeHistory */
+ if (item->pingCtlMaxRows != 0) {
+ temp = SNMP_MALLOC_STRUCT(pingProbeHistoryTable_data);
+
+ temp->pingCtlOwnerIndex =
+ (char *) malloc(item->pingCtlOwnerIndexLen + 1);
+ memcpy(temp->pingCtlOwnerIndex, item->pingCtlOwnerIndex,
+ item->pingCtlOwnerIndexLen + 1);
+ temp->pingCtlOwnerIndex[item->pingCtlOwnerIndexLen] = '\0';
+ temp->pingCtlOwnerIndexLen = item->pingCtlOwnerIndexLen;
+
+ temp->pingCtlTestName =
+ (char *) malloc(item->pingCtlTestNameLen + 1);
+ memcpy(temp->pingCtlTestName, item->pingCtlTestName,
+ item->pingCtlTestNameLen + 1);
+ temp->pingCtlTestName[item->pingCtlTestNameLen] = '\0';
+ temp->pingCtlTestNameLen = item->pingCtlTestNameLen;
+
+ /* add lock to protect */
+ pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&counter_mutex);
+ if (item->pingProbeHistoryMaxIndex >= (unsigned long) (2147483647))
+ item->pingProbeHistoryMaxIndex = 0;
+ temp->pingProbeHistoryIndex = ++(item->pingProbeHistoryMaxIndex);
+ pthread_mutex_unlock(&counter_mutex);
+ /* end */
+
+
+ temp->pingProbeHistoryResponse = triptime;
+ temp->pingProbeHistoryStatus = 1;
+ temp->pingProbeHistoryLastRC = 0;
+
+ temp->pingProbeHistoryTime_time = timep;
+ memdup(&temp->pingProbeHistoryTime,
+ date_n_time(&timep, &temp->pingProbeHistoryTimeLen), 11);
+
+ if (StorageNew->pingResultsSendProbes == 1)
+ item->pingProbeHis = temp;
+ else {
+ (current_temp)->next = temp;
+ }
+
+ current_temp = temp;
+
+ if (StorageNew->pingResultsSendProbes >= item->pingCtlProbeCount) {
+ current_temp->next = NULL;
+ }
+
+ if (item->pingProbeHis != NULL) {
+
+ if (pingProbeHistoryTable_count(item) < item->pingCtlMaxRows) {
+ if (pingProbeHistoryTable_add(current_temp) !=
+ SNMPERR_SUCCESS)
+ DEBUGMSGTL(("pingProbeHistoryTable",
+ "registered an entry error\n"));
+ } else {
+ pingProbeHistoryTable_delLast(item);
+
+ if (pingProbeHistoryTable_add(current_temp) !=
+ SNMPERR_SUCCESS)
+ DEBUGMSGTL(("pingProbeHistoryTable",
+ "registered an entry error\n"));
+
+ }
+
+ }
+ }
+ return 0;
+}
+
+static long
+llsqrt(long long a)
+{
+ long long prev = ~((long long) 1 << 63);
+ long long x = a;
+
+ if (x > 0) {
+ while (x < prev) {
+ prev = x;
+ x = (x + (a / x)) / 2;
+ }
+ }
+
+ return (long) x;
+}
+
+/*
+ * finish --
+ * Print out statistics, and give up.
+ */
+void
+finish(int options, char *hostname, int interval, int timing, int *rtt,
+ struct timeval *start_time, int *deadline, long *npackets,
+ long *nreceived, long *nrepeats, long *ntransmitted,
+ long *nchecksum, long *nerrors, long *tmin, long *tmax,
+ long long *tsum, long long *tsum2, int *pipesize,
+ struct timeval *cur_time)
+{
+ struct timeval tv = *cur_time;
+
+ tvsub(&tv, start_time);
+
+ putchar('\n');
+ fflush(stdout);
+ DEBUGMSGTL(("pingCtlTable", "--- %s ping statistics ---\n", hostname));
+
+ if (*nrepeats)
+ DEBUGMSGTL(("pingCtlTable", ", +%ld duplicates", *nrepeats));
+ if (*nchecksum)
+ DEBUGMSGTL(("pingCtlTable", ", +%ld corrupted", *nchecksum));
+ if (*nerrors)
+ DEBUGMSGTL(("pingCtlTable", ", +%ld errors", *nerrors));
+ if (*ntransmitted) {
+ DEBUGMSGTL(("pingCtlTable", ", %d%% loss",
+ (int) ((((long long) ((*ntransmitted) -
+ (*nreceived))) * 100) /
+ (*ntransmitted))));
+ DEBUGMSGTL(("pingCtlTable", ", time %ldms",
+ 1000 * tv.tv_sec + tv.tv_usec / 1000));
+ }
+ putchar('\n');
+
+ if ((*nreceived) && timing) {
+ long tmdev;
+
+ (*tsum) /= (*nreceived) + (*nrepeats);
+ (*tsum2) /= (*nreceived) + (*nrepeats);
+ tmdev = llsqrt((*tsum2) - (*tsum) * (*tsum));
+
+ DEBUGMSGTL(("pingCtlTable", "rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld"
+ "/%ld.%03ld/%ld.%03ld ms",
+ (*tmin) / 1000, (*tmin) % 1000,
+ (unsigned long) ((*tsum) / 1000), (long) ((*tsum) % 1000),
+ (*tmax) / 1000, (*tmax) % 1000, tmdev / 1000,
+ tmdev % 1000));
+ }
+ if ((*pipesize) > 1)
+ DEBUGMSGTL(("pingCtlTable", ", pipe %d", *pipesize));
+ if ((*ntransmitted) > 1
+ && (!interval || (options & (F_FLOOD | F_ADAPTIVE)))) {
+ int ipg =
+ (1000000 * (long long) tv.tv_sec +
+ tv.tv_usec) / ((*ntransmitted) - 1);
+ DEBUGMSGTL(("pingCtlTable", ", ipg/ewma %d.%03d/%d.%03d ms",
+ ipg / 1000, ipg % 1000,
+ (*rtt) / 8000, ((*rtt) / 8) % 1000));
+ }
+ putchar('\n');
+ return;
+ /* return(deadline ? (*nreceived)<(*npackets) : (*nreceived)==0); */
+}
+
+
+void
+status(int timing, int *rtt, long *nreceived, long *nrepeats,
+ long *ntransmitted, long *tmin, long *tmax, long long *tsum,
+ long long *tsum2)
+{
+ int loss = 0;
+ long tavg = 0;
+
+ status_snapshot = 0;
+
+ if (*ntransmitted)
+ loss =
+ (((long long) ((*ntransmitted) -
+ (*nreceived))) * 100) / (*ntransmitted);
+
+ DEBUGMSGTL(("pingCtlTable", "\n%ld/%ld packets, %d%% loss", *ntransmitted,
+ *nreceived, loss));
+
+ if ((*nreceived) && timing) {
+ tavg = (*tsum) / ((*nreceived) + (*nrepeats));
+
+ DEBUGMSGTL(("pingCtlTable", ", min/avg/ewma/max = %ld.%03ld/%lu.%03ld"
+ "/%d.%03d/%ld.%03ld ms",
+ (*tmin) / 1000, (*tmin) % 1000, tavg / 1000, tavg % 1000,
+ (*rtt) / 8000, ((*rtt) / 8) % 1000, (*tmax) / 1000,
+ (*tmax) % 1000));
+ }
+ DEBUGMSGTL(("pingCtlTable", "\n"));
+}
+
+
+static __inline__ int
+ipv6_addr_any(struct in6_addr *addr)
+{
+ static struct in6_addr in6_anyaddr;
+ return (memcmp(addr, &in6_anyaddr, 16) == 0);
+}
+
+int
+receive_error_msg(int icmp_sock, struct sockaddr_in6 *whereto, int options,
+ int *ident, long *nerrors)
+{
+ int res;
+ char cbuf[512];
+ struct iovec iov;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct sock_extended_err *e;
+ struct icmp6_hdr icmph;
+ struct sockaddr_in6 target;
+ int net_errors = 0;
+ int local_errors = 0;
+ int saved_errno = errno;
+
+ iov.iov_base = &icmph;
+ iov.iov_len = sizeof(icmph);
+ msg.msg_name = (void *) &target;
+ msg.msg_namelen = sizeof(target);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+ msg.msg_control = cbuf;
+ msg.msg_controllen = sizeof(cbuf);
+
+ res = recvmsg(icmp_sock, &msg, MSG_ERRQUEUE | MSG_DONTWAIT);
+ if (res < 0)
+ goto out;
+
+ e = NULL;
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_level == SOL_IPV6) {
+ if (cmsg->cmsg_type == IPV6_RECVERR)
+ e = (struct sock_extended_err *) CMSG_DATA(cmsg);
+ }
+ }
+ if (e == NULL)
+ abort();
+
+ if (e->ee_origin == SO_EE_ORIGIN_LOCAL) {
+ local_errors++;
+ if (options & F_QUIET)
+ goto out;
+ if (options & F_FLOOD)
+ write(STDOUT_FILENO, "E", 1);
+ else if (e->ee_errno != EMSGSIZE)
+ snmp_log(LOG_ERR, "ping: local error: %s\n", strerror(e->ee_errno));
+ else
+ snmp_log(LOG_ERR, "ping: local error: Message too long, mtu=%u\n",
+ e->ee_info);
+ (*nerrors)++;
+ } else if (e->ee_origin == SO_EE_ORIGIN_ICMP6) {
+ if (res < sizeof(icmph) ||
+ memcmp(&target.sin6_addr, &(whereto->sin6_addr), 16) ||
+ icmph.icmp6_type != ICMP6_ECHO_REQUEST ||
+ icmph.icmp6_id != *ident) {
+ /*
+ * Not our error, not an error at all. Clear.
+ */
+ saved_errno = 0;
+ goto out;
+ }
+
+ net_errors++;
+ (*nerrors)++;
+ if (options & F_QUIET)
+ goto out;
+ if (options & F_FLOOD) {
+ write(STDOUT_FILENO, "\bE", 2);
+ } else {
+ fflush(stdout);
+ }
+ }
+
+ out:
+ errno = saved_errno;
+ return net_errors ? : -local_errors;
+}
+
+int
+send_v6(int icmp_sock, int cmsglen, char *cmsgbuf,
+ struct sockaddr_in6 *whereto, int datalen, int timing,
+ char *outpack, int *ident, long *ntransmitted, int *confirm)
+{
+ struct icmp6_hdr *icmph;
+ int cc;
+ int i;
+ int mx_dup_ck = MAX_DUP_CHK;
+
+ icmph = (struct icmp6_hdr *) outpack;
+ icmph->icmp6_type = ICMP6_ECHO_REQUEST;
+ icmph->icmp6_code = 0;
+ icmph->icmp6_cksum = 0;
+ icmph->icmp6_seq = (*ntransmitted) + 1;
+ icmph->icmp6_id = *ident;
+
+ CLR(icmph->icmp6_seq % mx_dup_ck);
+
+ if (timing)
+ gettimeofday((struct timeval *) &outpack[8],
+ (struct timezone *) NULL);
+
+ cc = datalen + 8; /* skips ICMP portion */
+
+ if (cmsglen == 0) {
+ i = sendto(icmp_sock, (char *) outpack, cc, *confirm,
+ (struct sockaddr *) whereto,
+ sizeof(struct sockaddr_in6));
+ } else {
+ struct msghdr mhdr;
+ struct iovec iov;
+
+ iov.iov_len = cc;
+ iov.iov_base = outpack;
+
+ mhdr.msg_name = whereto;
+ mhdr.msg_namelen = sizeof(struct sockaddr_in6);
+ mhdr.msg_iov = &iov;
+ mhdr.msg_iovlen = 1;
+ mhdr.msg_control = cmsgbuf;
+ mhdr.msg_controllen = cmsglen;
+
+ i = sendmsg(icmp_sock, &mhdr, *confirm);
+ }
+ *confirm = 0;
+
+ return (cc == i ? 0 : i);
+}
+
+/*
+ * parse_reply --
+ * Print out the packet, if it came from us. This logic is necessary
+ * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
+ * which arrive ('tis only fair). This permits multiple copies of this
+ * program to be run without having intermingled output (or statistics!).
+ */
+int
+parse_reply(int *series, struct pingCtlTable_data *item,
+ struct msghdr *msg, int cc, void *addr, struct timeval *tv,
+ time_t timep, int uid, struct sockaddr_in6 *whereto,
+ int *rtt_addend, int options, int interval, int datalen,
+ int timing, int working_recverr, char *outpack, int *rtt,
+ int *ident, __u16 * acked, long *nreceived, long *nrepeats,
+ long *ntransmitted, long *nchecksum, long *nerrors, long *tmin,
+ long *tmax, long long *tsum, long long *tsum2,
+ int *confirm_flag, int *confirm, int *pipesize,
+ struct pingProbeHistoryTable_data *current_temp)
+{
+ struct sockaddr_in6 *from = addr;
+ __u8 *buf = msg->msg_iov->iov_base;
+ struct cmsghdr *c;
+ struct icmp6_hdr *icmph;
+ int hops = -1;
+
+
+ for (c = CMSG_FIRSTHDR(msg); c; c = CMSG_NXTHDR(msg, c)) {
+ if (c->cmsg_level != SOL_IPV6 || c->cmsg_type != IPV6_HOPLIMIT)
+ continue;
+ if (c->cmsg_len < CMSG_LEN(sizeof(int)))
+ continue;
+ hops = *(int *) CMSG_DATA(c);
+ }
+
+
+ /*
+ * Now the ICMP part
+ */
+
+ icmph = (struct icmp6_hdr *) buf;
+ if (cc < 8) {
+ if (options & F_VERBOSE)
+ snmp_log(LOG_ERR, "ping: packet too short (%d bytes)\n", cc);
+ return 1;
+ }
+ if (icmph->icmp6_type == ICMP6_ECHO_REPLY) {
+ if (icmph->icmp6_id != *ident)
+ return 1;
+ if (gather_statistics(series, item, (__u8 *) (icmph + 1), cc,
+ icmph->icmp6_seq,
+ hops, 0, tv, timep, rtt_addend, uid, options,
+ pr_addr(&from->sin6_addr, options), interval,
+ datalen, timing, outpack, rtt, acked,
+ nreceived, nrepeats, ntransmitted, nchecksum,
+ tmin, tmax, tsum, tsum2, confirm_flag,
+ confirm, pipesize, current_temp))
+ return 0;
+ } else {
+ int nexthdr;
+ struct ip6_hdr *iph1 = (struct ip6_hdr *) (icmph + 1);
+ struct icmp6_hdr *icmph1 = (struct icmp6_hdr *) (iph1 + 1);
+
+ /*
+ * We must not ever fall here. All the messages but
+ * * echo reply are blocked by filter and error are
+ * * received with IPV6_RECVERR. Ugly code is preserved
+ * * however, just to remember what crap we avoided
+ * * using RECVRERR. :-)
+ */
+
+ if (cc < 8 + sizeof(struct ip6_hdr) + 8)
+ return 1;
+
+ if (memcmp(&iph1->ip6_dst, &(whereto->sin6_addr), 16))
+ return 1;
+
+ nexthdr = iph1->ip6_nxt;
+
+ if (nexthdr == 44) {
+ nexthdr = *(__u8 *) icmph1;
+ icmph1++;
+ }
+ if (nexthdr == IPPROTO_ICMPV6) {
+ if (icmph1->icmp6_type != ICMP6_ECHO_REQUEST ||
+ icmph1->icmp6_id != *ident)
+ return 1;
+ acknowledge(icmph1->icmp6_seq, acked, ntransmitted,
+ pipesize);
+ if (working_recverr)
+ return 0;
+ (*nerrors)++;
+ if (options & F_FLOOD) {
+ write(STDOUT_FILENO, "\bE", 2);
+ return 0;
+ }
+ DEBUGMSGTL(("pingCtlTable", "From %s: icmp_seq=%u ",
+ pr_addr(&from->sin6_addr, options),
+ icmph1->icmp6_seq));
+ } else {
+ /*
+ * We've got something other than an ECHOREPLY
+ */
+ if (!(options & F_VERBOSE) || uid)
+ return 1;
+ DEBUGMSGTL(("pingCtlTable", "From %s: ",
+ pr_addr(&from->sin6_addr, options)));
+ }
+ /* pr_icmph(icmph->icmp6_type, icmph->icmp6_code, ntohl(icmph->icmp6_mtu)); */
+ }
+
+ if (!(options & F_FLOOD)) {
+ if (options & F_AUDIBLE)
+ putchar('\a');
+ putchar('\n');
+ fflush(stdout);
+ }
+ return 0;
+}
+
+
+
+#include <linux/filter.h>
+void
+install_filter(int icmp_sock, int *ident)
+{
+ static int once;
+ static struct sock_filter insns[] = {
+ BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 4), /* Load icmp echo ident */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA, 0, 1), /* Ours? */
+ BPF_STMT(BPF_RET | BPF_K, ~0U), /* Yes, it passes. */
+ BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 0), /* Load icmp type */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ICMP6_ECHO_REPLY, 1, 0), /* Echo? */
+ BPF_STMT(BPF_RET | BPF_K, ~0U), /* No. It passes. This must not happen. */
+ BPF_STMT(BPF_RET | BPF_K, 0), /* Echo with wrong ident. Reject. */
+ };
+ static struct sock_fprog filter = {
+ sizeof insns / sizeof(insns[0]),
+ insns
+ };
+ int id;
+
+ if (once)
+ return;
+ once = 1;
+
+ /*
+ * Patch bpflet for current identifier.
+ */
+ id = htons( *ident );
+ insns[1] =
+ (struct sock_filter) BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,
+ id, 0, 1);
+
+ if (setsockopt
+ (icmp_sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)))
+ perror("WARNING: failed to install socket filter\n");
+}
+
+
+/*
+ * pr_addr --
+ * Return an ascii host address as a dotted quad and optionally with
+ * a hostname.
+ */
+static char *
+pr_addr(struct in6_addr *addr, int options)
+{
+ struct hostent *hp = NULL;
+
+ if (!(options & F_NUMERIC))
+ hp = netsnmp_gethostbyaddr((__u8 *) addr, sizeof(struct in6_addr),
+ AF_INET6);
+
+ return hp ? hp->h_name : pr_addr_n(addr);
+}
+
+static char *
+pr_addr_n(struct in6_addr *addr)
+{
+ static char str[64];
+ inet_ntop(AF_INET6, addr, str, sizeof(str));
+ return str;
+}
diff --git a/agent/mibgroup/disman/ping/pingCtlTable.h b/agent/mibgroup/disman/ping/pingCtlTable.h
new file mode 100644
index 0000000..ca69d13
--- /dev/null
+++ b/agent/mibgroup/disman/ping/pingCtlTable.h
@@ -0,0 +1,437 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:pingCtlTable.h
+ *File Description:The head file of pingCtlTable.c
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+
+#ifndef PINGCTLTABLE_H
+#define PINGCTLTABLE_H
+
+#include <sys/types.h> /* basic system data types */
+#include <sys/socket.h> /* basic socket definitions */
+#include <sys/time.h> /* timeval{} for select() */
+#include <time.h> /* timespec{} for pselect() */
+#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
+#include <arpa/inet.h> /* inet(3) functions */
+#include <errno.h>
+#include <fcntl.h> /* for nonblocking */
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h> /* for S_xxx file mode constants */
+#include <sys/uio.h> /* for iovec{} and readv/writev */
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/un.h> /* for Unix domain sockets */
+#include <netdb.h>
+#include <pthread.h>
+
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h> /* for convenience */
+#endif
+
+#ifdef HAVE_POLL_H
+# include <poll.h> /* for convenience */
+#endif
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h> /* for convenience */
+#endif
+
+/*
+ * Three headers are normally needed for socket/file ioctl's:
+ * * <sys/ioctl.h>, <sys/filio.h>, and <sys/sockio.h>.
+ */
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+#ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+#endif
+
+#ifdef HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+
+#ifdef HAVE_SOCKADDR_DL_STRUCT
+# include <net/if_dl.h>
+#endif
+
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#define BUFSIZE 1500
+
+/*
+ * ipv6 include
+ */
+#include <sys/param.h>
+#include <linux/sockios.h>
+#include <sys/file.h>
+#include <sys/signal.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <sys/poll.h>
+#include <linux/types.h>
+#include <ctype.h>
+#include <linux/errqueue.h>
+
+#include <sched.h>
+
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+
+
+/*
+ * ipv4 include
+ */
+
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <netinet/ip_icmp.h>
+#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
+
+
+config_require(header_complex);
+
+struct pingCtlTable_data {
+ char *pingCtlOwnerIndex; /* string */
+ size_t pingCtlOwnerIndexLen;
+
+ char *pingCtlTestName; /* string */
+ size_t pingCtlTestNameLen;
+
+ long pingCtlTargetAddressType; /* integer32 */
+
+ char *pingCtlTargetAddress; /* string */
+ size_t pingCtlTargetAddressLen;
+
+ unsigned long pingCtlDataSize;
+ unsigned long pingCtlTimeOut;
+ unsigned long pingCtlProbeCount;
+ long pingCtlAdminStatus;
+ char *pingCtlDataFill;
+ size_t pingCtlDataFillLen;
+
+ unsigned long pingCtlFrequency;
+ unsigned long pingCtlMaxRows;
+ long pingCtlStorageType;
+
+ char *pingCtlTrapGeneration;
+ size_t pingCtlTrapGenerationLen;
+ unsigned long pingCtlTrapProbeFailureFilter;
+ unsigned long pingCtlTrapTestFailureFilter;
+ oid *pingCtlType;
+ size_t pingCtlTypeLen;
+
+ char *pingCtlDescr;
+ size_t pingCtlDescrLen;
+ long pingCtlSourceAddressType;
+ char *pingCtlSourceAddress;
+ size_t pingCtlSourceAddressLen;
+ long pingCtlIfIndex;
+ long pingCtlByPassRouteTable;
+ unsigned long pingCtlDSField;
+ long pingCtlRowStatus;
+
+ int storageType;
+ u_long timer_id;
+ unsigned long pingProbeHistoryMaxIndex;
+
+ struct pingResultsTable_data *pingResults;
+ struct pingProbeHistoryTable_data *pingProbeHis;
+
+};
+
+struct pingResultsTable_data {
+ char *pingCtlOwnerIndex; /* string */
+ size_t pingCtlOwnerIndexLen;
+ char *pingCtlTestName; /* string */
+ size_t pingCtlTestNameLen;
+
+ long pingResultsOperStatus;
+ long pingResultsIpTargetAddressType;
+ char *pingResultsIpTargetAddress;
+ size_t pingResultsIpTargetAddressLen;
+ unsigned long pingResultsMinRtt;
+ unsigned long pingResultsMaxRtt;
+ unsigned long pingResultsAverageRtt;
+ unsigned long pingResultsProbeResponses;
+ unsigned long pingResultsSendProbes;
+ unsigned long pingResultsRttSumOfSquares;
+ u_char *pingResultsLastGoodProbe;
+ size_t pingResultsLastGoodProbeLen;
+ time_t pingResultsLastGoodProbe_time;
+
+ int storageType;
+
+};
+
+struct pingProbeHistoryTable_data {
+ struct pingProbeHistoryTable_data *next;
+ char *pingCtlOwnerIndex; /* string */
+ size_t pingCtlOwnerIndexLen;
+ char *pingCtlTestName; /* string */
+ size_t pingCtlTestNameLen;
+
+ unsigned long pingProbeHistoryIndex;
+ unsigned long pingProbeHistoryResponse;
+ long pingProbeHistoryStatus;
+ long pingProbeHistoryLastRC;
+ u_char *pingProbeHistoryTime;
+ size_t pingProbeHistoryTimeLen;
+ time_t pingProbeHistoryTime_time;
+
+ int storageType;
+
+};
+
+
+/*
+ * function declarations
+ */
+void init_pingCtlTable(void);
+void shutdown_pingCtlTable(void);
+FindVarMethod var_pingCtlTable;
+void parse_pingCtlTable(const char *, char *);
+SNMPCallback store_pingCtlTable;
+
+
+WriteMethod write_pingCtlTargetAddressType;
+WriteMethod write_pingCtlTargetAddress;
+WriteMethod write_pingCtlDataSize;
+WriteMethod write_pingCtlTimeOut;
+WriteMethod write_pingCtlProbeCount;
+WriteMethod write_pingCtlAdminStatus;
+WriteMethod write_pingCtlDataFill;
+WriteMethod write_pingCtlFrequency;
+WriteMethod write_pingCtlMaxRows;
+WriteMethod write_pingCtlStorageType;
+WriteMethod write_pingCtlTrapGeneration;
+WriteMethod write_pingCtlTrapProbeFailureFilter;
+WriteMethod write_pingCtlTrapTestFailureFilter;
+WriteMethod write_pingCtlType;
+WriteMethod write_pingCtlDescr;
+WriteMethod write_pingCtlSourceAddressType;
+WriteMethod write_pingCtlSourceAddress;
+WriteMethod write_pingCtlIfIndex;
+WriteMethod write_pingCtlByPassRouteTable;
+WriteMethod write_pingCtlDSField;
+
+WriteMethod write_pingCtlRowStatus;
+
+
+
+#define PINGTRAPGENERATION_PROBEFAILED 0x80
+#define PINGTRAPGENERATION_TESTFAILED 0x40
+#define PINGTRAPGENERATION_TESTCOMPLETED 0x20
+#define PINGTRAPGENERATION_NULL 0x00
+
+/*
+ * column number definitions for table pingCtlTable
+ */
+#define COLUMN_PINGCTLOWNERINDEX 1
+#define COLUMN_PINGCTLTESTNAME 2
+#define COLUMN_PINGCTLTARGETADDRESSTYPE 3
+#define COLUMN_PINGCTLTARGETADDRESS 4
+#define COLUMN_PINGCTLDATASIZE 5
+#define COLUMN_PINGCTLTIMEOUT 6
+#define COLUMN_PINGCTLPROBECOUNT 7
+#define COLUMN_PINGCTLADMINSTATUS 8
+#define COLUMN_PINGCTLDATAFILL 9
+#define COLUMN_PINGCTLFREQUENCY 10
+#define COLUMN_PINGCTLMAXROWS 11
+#define COLUMN_PINGCTLSTORAGETYPE 12
+#define COLUMN_PINGCTLTRAPGENERATION 13
+#define COLUMN_PINGCTLTRAPPROBEFAILUREFILTER 14
+#define COLUMN_PINGCTLTRAPTESTFAILUREFILTER 15
+#define COLUMN_PINGCTLTYPE 16
+#define COLUMN_PINGCTLDESCR 17
+#define COLUMN_PINGCTLSOURCEADDRESSTYPE 18
+#define COLUMN_PINGCTLSOURCEADDRESS 19
+#define COLUMN_PINGCTLIFINDEX 20
+#define COLUMN_PINGCTLBYPASSROUTETABLE 21
+#define COLUMN_PINGCTLDSFIELD 22
+#define COLUMN_PINGCTLROWSTATUS 23
+
+
+/*
+ * ipv4 function
+ */
+int proc_v4(char *, ssize_t, struct timeval *, time_t,
+ struct pingCtlTable_data *, struct addrinfo *, int,
+ unsigned long *, unsigned long *, unsigned long *,
+ unsigned long *, unsigned long, int, int, int,
+ struct pingProbeHistoryTable_data *, pid_t);
+void send_v4(int, pid_t, int, int, char *);
+void readloop(struct pingCtlTable_data *, struct addrinfo *,
+ int, unsigned long *, unsigned long *,
+ unsigned long *, pid_t);
+void sig_alrm(int);
+void tv_sub(struct timeval *, struct timeval *);
+unsigned long round_double(double);
+struct proto {
+ int (*fproc) (char *, ssize_t, struct timeval *, time_t,
+ struct pingCtlTable_data *,
+ struct addrinfo *, int, unsigned long *,
+ unsigned long *, unsigned long *,
+ unsigned long *, unsigned long, int, int,
+ int, struct pingProbeHistoryTable_data *,
+ pid_t);
+ void (*fsend) (int, pid_t, int, int, char *);
+ struct sockaddr *sasend; /* sockaddr{} for send, from getaddrinfo */
+ struct sockaddr *sarecv; /* sockaddr{} for receiving */
+ socklen_t salen; /* length of sockaddr{}s */
+ int icmpproto; /* IPPROTO_xxx value for ICMP */
+} *pr;
+
+
+/*
+ * ipv6 function
+ */
+
+#define BIT_CLEAR(nr, addr) do { ((__u32 *)(addr))[(nr) >> 5] &= ~(1U << ((nr) & 31)); } while(0)
+#define BIT_SET(nr, addr) do { ((__u32 *)(addr))[(nr) >> 5] |= (1U << ((nr) & 31)); } while(0)
+#define BIT_TEST(nr, addr) do { (__u32 *)(addr))[(nr) >> 5] & (1U << ((nr) & 31)); } while(0)
+
+#define ICMPV6_FILTER_WILLPASS(type, filterp) \
+ (BIT_TEST((type), filterp) == 0)
+
+#define ICMPV6_FILTER_WILLBLOCK(type, filterp) \
+ BIT_TEST((type), filterp)
+
+#define ICMPV6_FILTER_SETPASS(type, filterp) \
+ BIT_CLEAR((type), filterp)
+
+#define ICMPV6_FILTER_SETBLOCK(type, filterp) \
+ BIT_SET((type), filterp)
+
+#define ICMPV6_FILTER_SETPASSALL(filterp) \
+ memset(filterp, 0, sizeof(struct icmp6_filter));
+
+#define ICMPV6_FILTER_SETBLOCKALL(filterp) \
+ memset(filterp, 0xFF, sizeof(struct icmp6_filter));
+
+
+#define MAX_PACKET 128000 /* max packet size */
+
+#ifdef SO_TIMESTAMP
+#define HAVE_SIN6_SCOPEID 1
+#endif
+
+
+
+#define MAX_DUP_CHK 0x10000
+char rcvd_tbl[MAX_DUP_CHK / 8];
+
+volatile int exiting;
+volatile int status_snapshot;
+
+#ifndef MSG_CONFIRM
+#define MSG_CONFIRM 0
+#endif
+
+#define DEFDATALEN (64 - 8) /* default data length */
+
+#define MAXWAIT 10 /* max seconds to wait for response */
+#define MININTERVAL 10 /* Minimal interpacket gap */
+#define MINUSERINTERVAL 200 /* Minimal allowed interval for non-root */
+
+#define SCHINT(a) (((a) <= MININTERVAL) ? MININTERVAL : (a))
+
+#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */
+#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */
+#define SET(bit) (A(bit) |= B(bit))
+#define CLR(bit) (A(bit) &= (~B(bit)))
+#define TST(bit) (A(bit) & B(bit))
+
+/*
+ * various options
+ */
+#define F_FLOOD 0x001
+#define F_INTERVAL 0x002
+#define F_NUMERIC 0x004
+#define F_PINGFILLED 0x008
+#define F_QUIET 0x010
+#define F_RROUTE 0x020
+#define F_SO_DEBUG 0x040
+#define F_SO_DONTROUTE 0x080
+#define F_VERBOSE 0x100
+#define F_TIMESTAMP 0x200
+#define F_FLOWINFO 0x200
+#define F_SOURCEROUTE 0x400
+#define F_TCLASS 0x400
+#define F_FLOOD_POLL 0x800
+#define F_LATENCY 0x1000
+#define F_AUDIBLE 0x2000
+#define F_ADAPTIVE 0x4000
+
+/*
+ * multicast options
+ */
+#define MULTICAST_NOLOOP 0x001
+#define MULTICAST_TTL 0x002
+#define MULTICAST_IF 0x004
+
+int __schedule_exit(int, long *, long *);
+int pinger(int, int, int, char *, struct sockaddr_in6 *, int *,
+ int, int, int, int, int, char *, int *, int *,
+ int *, int *, __u16 *, long *, long *, long *,
+ long *, int *, int *, int *, struct timeval *);
+void sock_setbufs(int, int, int);
+void setup(int, int, int, int, int, int, int, char *, int *,
+ struct timeval *, int *, int *);
+void main_loop(struct pingCtlTable_data *, int, int, __u8 *,
+ int, int, char *, struct sockaddr_in6 *, int,
+ int, char *, int, int, int, int, char *, int *,
+ struct timeval *, int *, int *);
+int gather_statistics(int *, struct pingCtlTable_data *,
+ __u8 *, int, __u16, int, int,
+ struct timeval *, time_t, int *, int,
+ int, char *, int, int, int, char *,
+ int *, __u16 *, long *, long *, long *,
+ long *, long *, long *, long long *,
+ long long *, int *, int *, int *,
+ struct pingProbeHistoryTable_data *);
+void finish(int, char *, int, int, int *, struct timeval *,
+ int *, long *, long *, long *, long *, long *,
+ long *, long *, long *, long long *, long long *,
+ int *, struct timeval *);
+void status(int, int *, long *, long *, long *, long *, long *,
+ long long *, long long *);
+size_t inet6_srcrt_space(int, int);
+struct cmsghdr *inet6_srcrt_init(void *, int);
+int inet6_srcrt_add(struct cmsghdr *, const struct in6_addr *);
+int receive_error_msg(int, struct sockaddr_in6 *, int, int *,
+ long *);
+int send_v6(int, int, char *, struct sockaddr_in6 *, int, int,
+ char *, int *, long *, int *);
+int parse_reply(int *, struct pingCtlTable_data *,
+ struct msghdr *, int, void *, struct timeval *,
+ time_t, int, struct sockaddr_in6 *, int *, int,
+ int, int, int, int, char *, int *, int *,
+ __u16 *, long *, long *, long *, long *,
+ long *, long *, long *, long long *,
+ long long *, int *, int *, int *,
+ struct pingProbeHistoryTable_data *);
+void install_filter(int, int *);
+
+#endif
+/*
+ * PINGCTLTABLE_H
+ */
diff --git a/agent/mibgroup/disman/ping/pingProbeHistoryTable.c b/agent/mibgroup/disman/ping/pingProbeHistoryTable.c
new file mode 100644
index 0000000..78c75be
--- /dev/null
+++ b/agent/mibgroup/disman/ping/pingProbeHistoryTable.c
@@ -0,0 +1,342 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:pingProbeHistoryTable.c
+ *File Description:Rows of pingProbeHistoryTable MIB read.
+ *
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+
+/*
+ * This should always be included first before anything else
+ */
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+
+
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "pingCtlTable.h"
+#include "pingResultsTable.h"
+#include "pingProbeHistoryTable.h"
+#include "header_complex.h"
+
+
+/*
+ *pingProbeHistoryTable_variables_oid:
+ *
+ */
+
+oid pingProbeHistoryTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 80, 1, 4 };
+
+struct variable2 pingProbeHistoryTable_variables[] = {
+ {COLUMN_PINGPROBEHISTORYRESPONSE, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_pingProbeHistoryTable, 2, {1, 2}},
+ {COLUMN_PINGPROBEHISTORYSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_pingProbeHistoryTable, 2, {1, 3}},
+ {COLUMN_PINGPROBEHISTORYLASTRC, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_pingProbeHistoryTable, 2, {1, 4}},
+ {COLUMN_PINGPROBEHISTORYTIME, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_pingProbeHistoryTable, 2, {1, 5}}
+};
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+
+extern struct header_complex_index *pingCtlTableStorage;
+extern struct header_complex_index *pingProbeHistoryTableStorage;
+int
+pingProbeHistoryTable_inadd(struct pingProbeHistoryTable_data *thedata);
+
+void
+pingProbeHistoryTable_cleaner(struct header_complex_index *thestuff)
+{
+ struct header_complex_index *hciptr = NULL;
+
+ DEBUGMSGTL(("pingProbeHistoryTable", "cleanerout "));
+ for (hciptr = thestuff; hciptr != NULL; hciptr = hciptr->next) {
+ header_complex_extract_entry(&pingProbeHistoryTableStorage, hciptr);
+ DEBUGMSGTL(("pingProbeHistoryTable", "cleaner "));
+ }
+
+}
+void
+init_pingProbeHistoryTable(void)
+{
+
+ DEBUGMSGTL(("pingProbeHistoryTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("pingProbeHistoryTable", pingProbeHistoryTable_variables,
+ variable2, pingProbeHistoryTable_variables_oid);
+
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("pingProbeHistoryTable",
+ parse_pingProbeHistoryTable, NULL, NULL);
+
+ /*
+ * we need to be called back later to store our data
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_pingProbeHistoryTable, NULL);
+
+ DEBUGMSGTL(("pingProbeHistoryTable", "done.\n"));
+}
+
+/*
+ * parse_mteObjectsTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+
+void
+parse_pingProbeHistoryTable(const char *token, char *line)
+{
+ size_t tmpint;
+ struct pingProbeHistoryTable_data *StorageTmp =
+ SNMP_MALLOC_STRUCT(pingProbeHistoryTable_data);
+
+ DEBUGMSGTL(("pingProbeHistoryTable", "parsing config... "));
+
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingCtlOwnerIndex,
+ &StorageTmp->pingCtlOwnerIndexLen);
+ if (StorageTmp->pingCtlOwnerIndex == NULL) {
+ config_perror("invalid specification for pingCtlOwnerIndex");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingCtlTestName,
+ &StorageTmp->pingCtlTestNameLen);
+ if (StorageTmp->pingCtlTestName == NULL) {
+ config_perror("invalid specification for pingCtlTestName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingProbeHistoryIndex, &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingProbeHistoryResponse,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pingProbeHistoryStatus,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pingProbeHistoryLastRC,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingProbeHistoryTime,
+ &StorageTmp->pingProbeHistoryTimeLen);
+ if (StorageTmp->pingProbeHistoryTime == NULL) {
+ config_perror("invalid specification for pingProbeHistoryTime");
+ return;
+ }
+
+
+ pingProbeHistoryTable_inadd(StorageTmp);
+
+ /* pingProbeHistoryTable_cleaner(pingProbeHistoryTableStorage); */
+
+ DEBUGMSGTL(("pingProbeHistoryTable", "done.\n"));
+}
+
+
+
+
+
+/*
+ * store_pingProbeHistoryTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+
+int
+store_pingProbeHistoryTable(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr;
+ size_t tmpint;
+ struct pingProbeHistoryTable_data *StorageTmp;
+ struct header_complex_index *hcindex;
+
+
+ DEBUGMSGTL(("pingProbeHistoryTable", "storing data... "));
+
+
+ for (hcindex = pingProbeHistoryTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct pingProbeHistoryTable_data *) hcindex->data;
+
+ if (StorageTmp->storageType != ST_READONLY) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "pingProbeHistoryTable ");
+ cptr = line + strlen(line);
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pingCtlOwnerIndex,
+ &StorageTmp->pingCtlOwnerIndexLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pingCtlTestName,
+ &StorageTmp->pingCtlTestNameLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->pingProbeHistoryIndex,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ pingProbeHistoryResponse, &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pingProbeHistoryStatus,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pingProbeHistoryLastRC,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pingProbeHistoryTime,
+ &StorageTmp->
+ pingProbeHistoryTimeLen);
+
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("pingProbeHistoryTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+int
+pingProbeHistoryTable_inadd(struct pingProbeHistoryTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list;
+ vars_list = NULL;
+
+
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->pingCtlOwnerIndex, thedata->pingCtlOwnerIndexLen); /* pingCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->pingCtlTestName, thedata->pingCtlTestNameLen); /* pingCtlTestName */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &thedata->pingProbeHistoryIndex, sizeof(thedata->pingProbeHistoryIndex)); /* pingProbeHistoryIndex */
+
+ /*
+ * XXX: fill in default row values here into StorageNew
+ *
+ */
+
+
+ DEBUGMSGTL(("pingProbeHistoryTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ header_complex_add_data(&pingProbeHistoryTableStorage, vars_list,
+ thedata);
+ DEBUGMSGTL(("pingProbeHistoryTable", "registered an entry\n"));
+
+
+ DEBUGMSGTL(("pingProbeHistoryTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+/*
+ * var_pingProbeHistoryTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_pingProbeHistoryTable above.
+ */
+unsigned char *
+var_pingProbeHistoryTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact,
+ size_t *var_len, WriteMethod ** write_method)
+{
+
+
+ struct pingProbeHistoryTable_data *StorageTmp = NULL;
+
+ *write_method = NULL;
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(pingProbeHistoryTableStorage, vp, name, length,
+ exact, var_len, write_method)) == NULL) {
+
+ return NULL;
+ }
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+
+ switch (vp->magic) {
+
+ case COLUMN_PINGPROBEHISTORYRESPONSE:
+ *var_len = sizeof(StorageTmp->pingProbeHistoryResponse);
+ return (u_char *) & StorageTmp->pingProbeHistoryResponse;
+
+ case COLUMN_PINGPROBEHISTORYSTATUS:
+ *var_len = sizeof(StorageTmp->pingProbeHistoryStatus);
+ return (u_char *) & StorageTmp->pingProbeHistoryStatus;
+
+ case COLUMN_PINGPROBEHISTORYLASTRC:
+ *var_len = sizeof(StorageTmp->pingProbeHistoryLastRC);
+ return (u_char *) & StorageTmp->pingProbeHistoryLastRC;
+
+ case COLUMN_PINGPROBEHISTORYTIME:
+ *var_len = (StorageTmp->pingProbeHistoryTimeLen);
+ return (u_char *) StorageTmp->pingProbeHistoryTime;
+
+ default:
+ ERROR_MSG("");
+ }
+
+ return NULL;
+}
diff --git a/agent/mibgroup/disman/ping/pingProbeHistoryTable.h b/agent/mibgroup/disman/ping/pingProbeHistoryTable.h
new file mode 100644
index 0000000..1c3eadb
--- /dev/null
+++ b/agent/mibgroup/disman/ping/pingProbeHistoryTable.h
@@ -0,0 +1,36 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:pingProbeHistoryTable.h
+ *File Description:The head file of pingProbeHistoryTable.c
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+#ifndef PINGPROBEHISTORYTABLE_H
+#define PINGPROBEHISTORYTABLE_H
+
+config_require(header_complex);
+
+/*
+ * function declarations
+ */
+void init_pingProbeHistoryTable(void);
+FindVarMethod var_pingProbeHistoryTable;
+void parse_pingProbeHistoryTable(const char *, char *);
+SNMPCallback store_pingProbeHistoryTable;
+
+
+/*
+ * column number definitions for table pingProbeHistoryTable
+ */
+#define COLUMN_PINGPROBEHISTORYINDEX 1
+#define COLUMN_PINGPROBEHISTORYRESPONSE 2
+#define COLUMN_PINGPROBEHISTORYSTATUS 3
+#define COLUMN_PINGPROBEHISTORYLASTRC 4
+#define COLUMN_PINGPROBEHISTORYTIME 5
+#endif /* PINGPROBEHISTORYTABLE_H */
diff --git a/agent/mibgroup/disman/ping/pingResultsTable.c b/agent/mibgroup/disman/ping/pingResultsTable.c
new file mode 100644
index 0000000..1445d86
--- /dev/null
+++ b/agent/mibgroup/disman/ping/pingResultsTable.c
@@ -0,0 +1,425 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:pingResultsTable.c
+ *File Description:Rows of lookupResultsTable MIB add and delete.
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+
+/*
+ * This should always be included first before anything else
+ */
+
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+
+
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "pingCtlTable.h"
+#include "pingResultsTable.h"
+#include "pingProbeHistoryTable.h"
+#include "header_complex.h"
+
+
+/*
+ *pingResultsTable_variables_oid:
+ *
+ */
+oid pingResultsTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 80, 1, 3 };
+
+struct variable2 pingResultsTable_variables[] = {
+ {COLUMN_PINGRESULTSOPERSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_pingResultsTable, 2, {1, 1}},
+ {COLUMN_PINGRESULTSIPTARGETADDRESSTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_pingResultsTable, 2, {1, 2}},
+ {COLUMN_PINGRESULTSIPTARGETADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_pingResultsTable, 2, {1, 3}},
+ {COLUMN_PINGRESULTSMINRTT, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_pingResultsTable, 2, {1, 4}},
+ {COLUMN_PINGRESULTSMAXRTT, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_pingResultsTable, 2, {1, 5}},
+ {COLUMN_PINGRESULTSAVERAGERTT, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_pingResultsTable, 2, {1, 6}},
+ {COLUMN_PINGRESULTSPROBERESPONSES, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_pingResultsTable, 2, {1, 7}},
+ {COLUMN_PINGRESULTSSENTPROBES, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_pingResultsTable, 2, {1, 8}},
+ {COLUMN_PINGRESULTSRTTSUMOFSQUARES, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_pingResultsTable, 2, {1, 9}},
+ {COLUMN_PINGRESULTSLASTGOODPROBE, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_pingResultsTable, 2, {1, 10}}
+};
+
+
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+
+extern struct header_complex_index *pingCtlTableStorage;
+extern struct header_complex_index *pingResultsTableStorage;
+int
+pingResultsTable_inadd(struct pingResultsTable_data *thedata);
+
+void
+pingResultsTable_cleaner(struct header_complex_index *thestuff)
+{
+ struct header_complex_index *hciptr;
+
+ DEBUGMSGTL(("pingResultsTable", "cleanerout "));
+ for (hciptr = thestuff; hciptr != NULL; hciptr = hciptr->next) {
+ header_complex_extract_entry(&pingResultsTableStorage, hciptr);
+ DEBUGMSGTL(("pingResultsTable", "cleaner "));
+ }
+
+}
+void
+init_pingResultsTable(void)
+{
+
+ DEBUGMSGTL(("pingResultsTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("pingResultsTable", pingResultsTable_variables, variable2,
+ pingResultsTable_variables_oid);
+
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("pingResultsTable",
+ parse_pingResultsTable, NULL, NULL);
+
+ /*
+ * we need to be called back later to store our data
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_pingResultsTable, NULL);
+
+ DEBUGMSGTL(("pingResultsTable", "done.\n"));
+}
+
+/*
+ * parse_mteObjectsTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+
+void
+parse_pingResultsTable(const char *token, char *line)
+{
+ size_t tmpint;
+ struct pingResultsTable_data *StorageTmp =
+ SNMP_MALLOC_STRUCT(pingResultsTable_data);
+
+ DEBUGMSGTL(("pingResultsTable", "parsing config... "));
+
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingCtlOwnerIndex,
+ &StorageTmp->pingCtlOwnerIndexLen);
+ if (StorageTmp->pingCtlOwnerIndex == NULL) {
+ config_perror("invalid specification for pingCtlOwnerIndex");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingCtlTestName,
+ &StorageTmp->pingCtlTestNameLen);
+ if (StorageTmp->pingCtlTestName == NULL) {
+ config_perror("invalid specification for pingCtlTestName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pingResultsOperStatus, &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->pingResultsIpTargetAddressType,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingResultsIpTargetAddress,
+ &StorageTmp->pingResultsIpTargetAddressLen);
+ if (StorageTmp->pingResultsIpTargetAddress == NULL) {
+ config_perror
+ ("invalid specification for pingResultsIpTargetAddress");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingResultsMinRtt, &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingResultsMaxRtt, &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingResultsAverageRtt, &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingResultsProbeResponses,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingResultsSendProbes, &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->pingResultsRttSumOfSquares,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->pingResultsLastGoodProbe,
+ &StorageTmp->pingResultsLastGoodProbeLen);
+ if (StorageTmp->pingResultsLastGoodProbe == NULL) {
+ config_perror
+ ("invalid specification for pingResultsLastGoodProbe!");
+ return;
+ }
+
+ pingResultsTable_inadd(StorageTmp);
+
+ /* pingResultsTable_cleaner(pingResultsTableStorage); */
+
+ DEBUGMSGTL(("pingResultsTable", "done.\n"));
+}
+
+
+
+
+
+/*
+ * store_pingResultsTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+
+int
+store_pingResultsTable(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr;
+ size_t tmpint;
+ struct pingResultsTable_data *StorageTmp;
+ struct header_complex_index *hcindex;
+
+
+ DEBUGMSGTL(("pingResultsTable", "storing data... "));
+
+
+ for (hcindex = pingResultsTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct pingResultsTable_data *) hcindex->data;
+
+ if (StorageTmp->storageType != ST_READONLY) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "pingResultsTable ");
+ cptr = line + strlen(line);
+
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pingCtlOwnerIndex,
+ &StorageTmp->pingCtlOwnerIndexLen);
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->pingCtlTestName,
+ &StorageTmp->pingCtlTestNameLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->pingResultsOperStatus,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ pingResultsIpTargetAddressType,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ pingResultsIpTargetAddress,
+ &StorageTmp->
+ pingResultsIpTargetAddressLen);
+
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->pingResultsMinRtt,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->pingResultsMaxRtt,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->pingResultsAverageRtt,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ pingResultsProbeResponses, &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->pingResultsSendProbes,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ pingResultsRttSumOfSquares,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ pingResultsLastGoodProbe,
+ &StorageTmp->
+ pingResultsLastGoodProbeLen);
+
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("pingResultsTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+int
+pingResultsTable_inadd(struct pingResultsTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list;
+ vars_list = NULL;
+
+
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->pingCtlOwnerIndex, thedata->pingCtlOwnerIndexLen); /* pingCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->pingCtlTestName, thedata->pingCtlTestNameLen); /* pingCtlTestName */
+
+ /*
+ * XXX: fill in default row values here into StorageNew
+ *
+ */
+
+
+ DEBUGMSGTL(("pingResultsTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ header_complex_add_data(&pingResultsTableStorage, vars_list, thedata);
+ DEBUGMSGTL(("pingResultsTable", "registered an entry\n"));
+
+
+ DEBUGMSGTL(("pingResultsTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+/*
+ * var_pingResultsTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_pingResultsTable above.
+ */
+unsigned char *
+var_pingResultsTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact,
+ size_t *var_len, WriteMethod ** write_method)
+{
+
+
+ struct pingResultsTable_data *StorageTmp = NULL;
+
+ *write_method = NULL;
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(pingResultsTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL) {
+
+ return NULL;
+ }
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+
+ switch (vp->magic) {
+
+ case COLUMN_PINGRESULTSOPERSTATUS:
+ *var_len = sizeof(StorageTmp->pingResultsOperStatus);
+ return (u_char *) & StorageTmp->pingResultsOperStatus;
+
+ case COLUMN_PINGRESULTSIPTARGETADDRESSTYPE:
+ *var_len = sizeof(StorageTmp->pingResultsIpTargetAddressType);
+ return (u_char *) & StorageTmp->pingResultsIpTargetAddressType;
+
+ case COLUMN_PINGRESULTSIPTARGETADDRESS:
+ *var_len = (StorageTmp->pingResultsIpTargetAddressLen);
+ return (u_char *) StorageTmp->pingResultsIpTargetAddress;
+
+ case COLUMN_PINGRESULTSMINRTT:
+ *var_len = sizeof(StorageTmp->pingResultsMinRtt);
+ return (u_char *) & StorageTmp->pingResultsMinRtt;
+
+ case COLUMN_PINGRESULTSMAXRTT:
+ *var_len = sizeof(StorageTmp->pingResultsMaxRtt);
+ return (u_char *) & StorageTmp->pingResultsMaxRtt;
+
+ case COLUMN_PINGRESULTSAVERAGERTT:
+ *var_len = sizeof(StorageTmp->pingResultsAverageRtt);
+ return (u_char *) & StorageTmp->pingResultsAverageRtt;
+
+ case COLUMN_PINGRESULTSPROBERESPONSES:
+ *var_len = sizeof(StorageTmp->pingResultsProbeResponses);
+ return (u_char *) & StorageTmp->pingResultsProbeResponses;
+
+ case COLUMN_PINGRESULTSSENTPROBES:
+ *var_len = sizeof(StorageTmp->pingResultsSendProbes);
+ return (u_char *) & StorageTmp->pingResultsSendProbes;
+
+ case COLUMN_PINGRESULTSRTTSUMOFSQUARES:
+ *var_len = sizeof(StorageTmp->pingResultsRttSumOfSquares);
+ return (u_char *) & StorageTmp->pingResultsRttSumOfSquares;
+
+ case COLUMN_PINGRESULTSLASTGOODPROBE:
+ *var_len = (StorageTmp->pingResultsLastGoodProbeLen);
+ return (u_char *) StorageTmp->pingResultsLastGoodProbe;
+
+ default:
+ ERROR_MSG("");
+ }
+
+ return NULL;
+}
diff --git a/agent/mibgroup/disman/ping/pingResultsTable.h b/agent/mibgroup/disman/ping/pingResultsTable.h
new file mode 100644
index 0000000..5cfa339
--- /dev/null
+++ b/agent/mibgroup/disman/ping/pingResultsTable.h
@@ -0,0 +1,42 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:pingResultsTable.h
+ *File Description:The head file of pingResultsTable.c
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+
+#ifndef PINGRESULTSTABLE_H
+#define PINGRESULTSTABLE_H
+
+config_require(header_complex);
+
+/*
+ * function declarations
+ */
+void init_pingResultsTable(void);
+FindVarMethod var_pingResultsTable;
+void parse_pingResultsTable(const char *, char *);
+SNMPCallback store_pingResultsTable;
+
+
+/*
+ * column number definitions for table pingResultsTable
+ */
+#define COLUMN_PINGRESULTSOPERSTATUS 1
+#define COLUMN_PINGRESULTSIPTARGETADDRESSTYPE 2
+#define COLUMN_PINGRESULTSIPTARGETADDRESS 3
+#define COLUMN_PINGRESULTSMINRTT 4
+#define COLUMN_PINGRESULTSMAXRTT 5
+#define COLUMN_PINGRESULTSAVERAGERTT 6
+#define COLUMN_PINGRESULTSPROBERESPONSES 7
+#define COLUMN_PINGRESULTSSENTPROBES 8
+#define COLUMN_PINGRESULTSRTTSUMOFSQUARES 9
+#define COLUMN_PINGRESULTSLASTGOODPROBE 10
+#endif /* PINGRESULTSTABLE_H */
diff --git a/agent/mibgroup/disman/schedule.h b/agent/mibgroup/disman/schedule.h
new file mode 100644
index 0000000..a3351b6
--- /dev/null
+++ b/agent/mibgroup/disman/schedule.h
@@ -0,0 +1,3 @@
+config_require(disman/schedule/schedCore)
+config_require(disman/schedule/schedConf)
+config_require(disman/schedule/schedTable)
diff --git a/agent/mibgroup/disman/schedule/schedConf.c b/agent/mibgroup/disman/schedule/schedConf.c
new file mode 100644
index 0000000..0cbdbc6
--- /dev/null
+++ b/agent/mibgroup/disman/schedule/schedConf.c
@@ -0,0 +1,437 @@
+/*
+ * DisMan Schedule MIB:
+ * Implementation of the schedule MIB config handling
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <ctype.h>
+#include "disman/schedule/schedCore.h"
+#include "disman/schedule/schedConf.h"
+
+netsnmp_feature_require(iquery)
+netsnmp_feature_require(string_time_to_secs)
+
+static int schedEntries;
+
+/** Initializes the schedConf module */
+void
+init_schedConf(void)
+{
+ DEBUGMSGTL(("disman:schedule:init", "Initializing config module\n"));
+ init_schedule_container();
+
+ /*
+ * Register public configuration directives
+ */
+ snmpd_register_config_handler("repeat", parse_sched_periodic, NULL,
+ "repeat period OID = value");
+ snmpd_register_config_handler("cron", parse_sched_timed, NULL,
+ "cron * * * * * OID = value");
+ snmpd_register_config_handler("at", parse_sched_timed, NULL,
+ "at * * * * * OID = value");
+
+ /*
+ * Register internal configuration directive,
+ * and arrange for dynamically configured entries to be saved
+ */
+ snmpd_register_config_handler("_schedTable", parse_schedTable, NULL, NULL);
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_schedTable, NULL);
+ schedEntries = 0;
+}
+
+
+/* =======================================================
+ *
+ * Handlers for user-configured (static) scheduled actions
+ *
+ * ======================================================= */
+
+void
+parse_sched_periodic( const char *token, char *line )
+{
+ netsnmp_tdata_row *row;
+ struct schedTable_entry *entry;
+ char buf[24], tmpbuf[SPRINT_MAX_LEN];
+ long frequency;
+ long value;
+ size_t tmpint;
+ oid variable[ MAX_OID_LEN], *var_ptr = variable;
+ size_t var_len = MAX_OID_LEN;
+
+ schedEntries++;
+ sprintf(buf, "_conf%03d", schedEntries);
+
+ DEBUGMSGTL(( "disman:schedule:conf", "periodic: %s %s\n", token, line));
+ /*
+ * Parse the configure directive line
+ */
+ line = copy_nword(line, tmpbuf, sizeof(tmpbuf));
+ frequency = netsnmp_string_time_to_secs(tmpbuf);
+ if (frequency == -1) {
+ config_perror("Illegal frequency specified");
+ return;
+ }
+
+ line = read_config_read_data(ASN_OBJECT_ID, line, &var_ptr, &var_len);
+ if (var_len == 0) {
+ config_perror("invalid specification for schedVariable");
+ return;
+ }
+ /*
+ * Skip over optional assignment in "var = value"
+ */
+ while (line && isspace((unsigned char)(*line)))
+ line++;
+ if (line && *line == '=' ) {
+ line++;
+ while (line && isspace((unsigned char)(*line))) {
+ line++;
+ }
+ }
+ line = read_config_read_data(ASN_INTEGER, line, &value, &tmpint);
+
+ /*
+ * Create an entry in the schedTable
+ */
+ row = schedTable_createEntry( "snmpd.conf", buf );
+ if (!row || !row->data) {
+ config_perror("create schedule entry failure");
+ return;
+ }
+ entry = (struct schedTable_entry *)row->data;
+
+ entry->schedInterval = frequency;
+ entry->schedValue = value;
+ entry->schedVariable_len = var_len;
+ memcpy(entry->schedVariable, variable, var_len*sizeof(oid));
+
+ entry->schedType = SCHED_TYPE_PERIODIC;
+ entry->schedStorageType = ST_READONLY; /* or PERMANENT */
+ entry->flags = SCHEDULE_FLAG_ENABLED |
+ SCHEDULE_FLAG_ACTIVE |
+ SCHEDULE_FLAG_VALID;
+ entry->session = netsnmp_query_get_default_session();
+ sched_nextTime( entry );
+}
+
+
+/*
+ * Timed-schedule utility:
+ * Convert from a cron-style specification to the equivalent set
+ * of bits. Note that minute, hour and weekday crontab fields are
+ * 0-based, while day and month more naturally start from 1.
+ */
+void
+_sched_convert_bits( char *cron_spec, char *bit_buf,
+ int bit_buf_len, int max_val, int startAt1 ) {
+ char *cp = cron_spec;
+ u_char b[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
+ int val, major, minor;
+ int overshoot;
+
+ if (!cron_spec || !bit_buf)
+ return;
+
+ /*
+ * Wildcard field - set all bits
+ */
+ if ( *cp == '*' ) {
+ memset( bit_buf, 0xff, bit_buf_len );
+
+ /*
+ * An "all-bits" specification may not be an exact multiple of 8.
+ * Work out how far we've overshot things, and tidy up the excess.
+ */
+ overshoot = 8*bit_buf_len-max_val;
+ while ( overshoot > 0 ) {
+ bit_buf[ bit_buf_len-1 ] ^= b[8-overshoot];
+ overshoot--;
+ }
+ return;
+ }
+
+ /*
+ * Otherwise, clear the bit string buffer,
+ * and start calculating which bits to set
+ */
+ memset( bit_buf, 0, bit_buf_len );
+
+ while (1) {
+ sscanf( cp, "%d", &val);
+ /* Handle negative day specification */
+ if ( val < 0 ) {
+ val = max_val - val;
+ }
+ if ( startAt1 )
+ val--;
+ major = val/8;
+ minor = val%8;
+ bit_buf[ major ] |= b[minor];
+
+ /* XXX - ideally we should handle "X-Y" syntax as well */
+ while (*cp && *cp!=',')
+ cp++;
+ if (!*cp)
+ break;
+ cp++;
+ }
+}
+
+void
+parse_sched_timed( const char *token, char *line )
+{
+ netsnmp_tdata_row *row;
+ struct schedTable_entry *entry;
+ char buf[24], *cp;
+
+ char minConf[512]; size_t min_len = sizeof(minConf); char minVal[8];
+ char hourConf[512]; size_t hour_len = sizeof(hourConf); char hourVal[3];
+ char dateConf[512]; size_t date_len = sizeof(dateConf); char dateVal[8];
+ char monConf[512]; size_t mon_len = sizeof(monConf); char monVal[2];
+ char dayConf[512]; size_t day_len = sizeof(dayConf); char dayVal;
+
+ long value;
+ size_t tmpint;
+ oid variable[ MAX_OID_LEN], *var_ptr = variable;
+ size_t var_len = MAX_OID_LEN;
+
+ schedEntries++;
+ sprintf(buf, "_conf%03d", schedEntries);
+
+ DEBUGMSGTL(( "sched", "config: %s %s\n", token, line));
+ /*
+ * Parse the configure directive line
+ */
+ cp = minConf;
+ line = read_config_read_data(ASN_OCTET_STR, line, &cp, &min_len);
+ cp = hourConf;
+ line = read_config_read_data(ASN_OCTET_STR, line, &cp, &hour_len);
+ cp = dateConf;
+ line = read_config_read_data(ASN_OCTET_STR, line, &cp, &date_len);
+ cp = monConf;
+ line = read_config_read_data(ASN_OCTET_STR, line, &cp, &mon_len);
+ cp = dayConf;
+ line = read_config_read_data(ASN_OCTET_STR, line, &cp, &day_len);
+ if (!line) {
+ config_perror("invalid schedule time specification");
+ return;
+ }
+
+ line = read_config_read_data(ASN_OBJECT_ID, line, &var_ptr, &var_len);
+ if (var_len == 0) {
+ config_perror("invalid specification for schedVariable");
+ return;
+ }
+ /*
+ * Skip over optional assignment in "var = value"
+ */
+ while (line && isspace((unsigned char)(*line)))
+ line++;
+ if ( *line == '=' ) {
+ line++;
+ while (line && isspace((unsigned char)(*line))) {
+ line++;
+ }
+ }
+ line = read_config_read_data(ASN_INTEGER, line, &value, &tmpint);
+
+ /*
+ * Convert from cron-style specifications into bits
+ */
+ _sched_convert_bits( minConf, minVal, 8, 60, 0 );
+ _sched_convert_bits( hourConf, hourVal, 3, 24, 0 );
+ memset(dateVal+4, 0, 4); /* Clear the reverse day bits */
+ _sched_convert_bits( dateConf, dateVal, 4, 31, 1 );
+ _sched_convert_bits( monConf, monVal, 2, 12, 1 );
+ _sched_convert_bits( dayConf, &dayVal, 1, 8, 0 );
+ if ( dayVal & 0x01 ) { /* sunday(7) = sunday(0) */
+ dayVal |= 0x80;
+ dayVal &= 0xfe;
+ }
+
+ /*
+ * Create an entry in the schedTable
+ */
+ row = schedTable_createEntry("snmpd.conf", buf);
+ if (!row || !row->data) {
+ config_perror("create schedule entry failure");
+ return;
+ }
+ entry = (struct schedTable_entry *)row->data;
+
+ entry->schedWeekDay = dayVal;
+ memcpy(entry->schedMonth, monVal, 2);
+ memcpy(entry->schedDay, dateVal, 4+4);
+ memcpy(entry->schedHour, hourVal, 3);
+ memcpy(entry->schedMinute, minVal, 8);
+
+ memcpy(entry->schedVariable, variable, var_len*sizeof(oid));
+ entry->schedVariable_len = var_len;
+ entry->schedValue = value;
+
+ if ( !strcmp( token, "at" ))
+ entry->schedType = SCHED_TYPE_ONESHOT;
+ else
+ entry->schedType = SCHED_TYPE_CALENDAR;
+ entry->schedStorageType = ST_READONLY; /* or PERMANENT */
+ entry->flags = SCHEDULE_FLAG_ENABLED |
+ SCHEDULE_FLAG_ACTIVE |
+ SCHEDULE_FLAG_VALID;
+ entry->session = netsnmp_query_get_default_session();
+ sched_nextTime( entry );
+}
+
+
+/* ========================================
+ *
+ * Handlers for persistent schedule entries
+ *
+ * ======================================== */
+
+void
+parse_schedTable( const char *token, char *line )
+{
+ char owner[SCHED_STR1_LEN+1];
+ char name[ SCHED_STR1_LEN+1];
+ char time_bits[22]; /* schedWeekDay..schedMinute */
+ void *vp;
+ size_t len;
+ netsnmp_tdata_row *row;
+ struct schedTable_entry *entry;
+
+ DEBUGMSGTL(("disman:schedule:conf", "Parsing schedTable config... "));
+
+ /*
+ * Read in the index information for this entry
+ * and create a (non-fixed) data structure for it.
+ */
+ memset( owner, 0, sizeof(owner));
+ memset( name, 0, sizeof(name));
+ len = SCHED_STR1_LEN; vp = owner;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = SCHED_STR1_LEN; vp = name;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ row = schedTable_createEntry(owner, name);
+ if (!row || !row->data) {
+ config_perror("create schedule entry failure");
+ return;
+ }
+ entry = (struct schedTable_entry *)row->data;
+ DEBUGMSG(("disman:schedule:conf", "(%s, %s) ", owner, name));
+
+ /*
+ * Read in the column values.
+ */
+ len = SCHED_STR2_LEN; vp = entry->schedDescr;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ line = read_config_read_data(ASN_UNSIGNED, line,
+ &entry->schedInterval, NULL);
+ /* Unpick the various timed bits */
+ len = 22; vp = time_bits;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ entry->schedWeekDay = time_bits[0];
+ entry->schedMonth[0] = time_bits[1];
+ entry->schedMonth[1] = time_bits[2];
+ entry->schedHour[0] = time_bits[11];
+ entry->schedHour[1] = time_bits[12];
+ entry->schedHour[2] = time_bits[13];
+ memcpy(entry->schedDay, time_bits+3, 8);
+ memcpy(entry->schedMinute, time_bits+14, 8);
+
+ len = SCHED_STR1_LEN; vp = entry->schedContextName;
+ line = read_config_read_data(ASN_OCTET_STR, line, &vp, &len);
+ len = MAX_OID_LEN; vp = entry->schedVariable;
+ line = read_config_read_data(ASN_OBJECT_ID, line, &vp, &len);
+ entry->schedVariable_len = len;
+ line = read_config_read_data(ASN_INTEGER, line,
+ &entry->schedValue, NULL);
+ line = read_config_read_data(ASN_UNSIGNED, line,
+ &entry->schedType, NULL);
+ line = read_config_read_data(ASN_UNSIGNED, line, &len, NULL);
+ entry->flags |= (len /* & WHAT ?? */);
+ /* XXX - Will need to read in the 'iquery' access information */
+ entry->flags |= SCHEDULE_FLAG_VALID;
+
+ DEBUGMSG(("disman:schedule:conf", "\n"));
+}
+
+/*
+ * Save dynamically-configured schedTable entries into persistent storage
+ */
+int
+store_schedTable(int majorID, int minorID, void *serverarg, void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char time_bits[22]; /* schedWeekDay..schedMinute */
+ char *cptr, *cp;
+ void *vp;
+ size_t tint;
+ netsnmp_tdata_row *row;
+ struct schedTable_entry *entry;
+
+
+ DEBUGMSGTL(( "disman:schedule:conf", "Storing schedTable:\n"));
+
+ for (row = netsnmp_tdata_row_first( schedule_table );
+ row;
+ row = netsnmp_tdata_row_next( schedule_table, row )) {
+
+ if (!row->data)
+ continue;
+ entry = (struct schedTable_entry *)row->data;
+
+ /*
+ * Only save (dynamically-created) 'nonVolatile' entries
+ * (XXX - what about dynamic 'permanent' entries ??)
+ */
+ if (entry->schedStorageType != ST_NONVOLATILE )
+ continue;
+ DEBUGMSGTL(( "disman:schedule:conf", " Storing (%s, %s)\n",
+ entry->schedOwner, entry->schedName));
+
+ memset(line, 0, sizeof(line));
+ strcpy(line, "_schedTable ");
+ cptr = line + strlen(line);
+
+ cp = entry->schedOwner; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->schedName; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ cp = entry->schedDescr; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ tint = entry->schedInterval;
+ cptr = read_config_store_data(ASN_UNSIGNED, cptr, &tint, NULL );
+
+ /* Combine all the timed bits into a single field */
+ time_bits[0] = entry->schedWeekDay;
+ time_bits[1] = entry->schedMonth[0];
+ time_bits[2] = entry->schedMonth[1];
+ time_bits[11] = entry->schedHour[0];
+ time_bits[12] = entry->schedHour[1];
+ time_bits[13] = entry->schedHour[2];
+ memcpy(time_bits+3, entry->schedDay, 8);
+ memcpy(time_bits+14, entry->schedMinute, 8);
+ vp = time_bits; tint = 22;
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &vp, &tint );
+
+ cp = entry->schedContextName; tint = strlen( cp );
+ cptr = read_config_store_data(ASN_OCTET_STR, cptr, &cp, &tint );
+ vp = entry->schedVariable;
+ tint = entry->schedVariable_len;
+ cptr = read_config_store_data(ASN_OBJECT_ID, cptr, &vp, &tint );
+ tint = entry->schedValue;
+ cptr = read_config_store_data(ASN_INTEGER, cptr, &tint, NULL );
+ tint = entry->schedType;
+ cptr = read_config_store_data(ASN_UNSIGNED, cptr, &tint, NULL );
+ tint = entry->flags /* & WHAT ?? */;
+ cptr = read_config_store_data(ASN_UNSIGNED, cptr, &tint, NULL );
+ /* XXX - Need to store the 'iquery' access information */
+ snmpd_store_config(line);
+ }
+ DEBUGMSGTL(( "disman:schedule:conf", " done.\n"));
+ return SNMPERR_SUCCESS;
+}
diff --git a/agent/mibgroup/disman/schedule/schedConf.h b/agent/mibgroup/disman/schedule/schedConf.h
new file mode 100644
index 0000000..91f4965
--- /dev/null
+++ b/agent/mibgroup/disman/schedule/schedConf.h
@@ -0,0 +1,17 @@
+#ifndef SCHEDCONF_H
+#define SCHEDCONF_H
+
+config_require(disman/schedule/schedCore)
+
+/*
+ * function declarations
+ */
+void init_schedConf(void);
+
+void parse_sched_periodic(const char *, char *);
+void parse_sched_timed( const char *, char *);
+void parse_schedTable( const char *, char *);
+SNMPCallback store_schedTable;
+
+
+#endif /* SCHEDCONF_H */
diff --git a/agent/mibgroup/disman/schedule/schedCore.c b/agent/mibgroup/disman/schedule/schedCore.c
new file mode 100644
index 0000000..c3db34f
--- /dev/null
+++ b/agent/mibgroup/disman/schedule/schedCore.c
@@ -0,0 +1,515 @@
+/*
+ * DisMan Schedule MIB:
+ * Core implementation of the schedule handling behaviour
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "disman/schedule/schedCore.h"
+#include "utilities/iquery.h"
+
+netsnmp_feature_require(iquery)
+
+netsnmp_feature_child_of(sched_nextrowtime, netsnmp_unused)
+
+netsnmp_tdata *schedule_table;
+
+
+#if !defined(HAVE_LOCALTIME_R) && !defined(localtime_r)
+/*
+ * localtime_r() replacement for older MinGW versions.
+ * Note: this implementation is not thread-safe, while it should.
+ */
+struct tm *
+localtime_r(const time_t * timer, struct tm *result)
+{
+ struct tm *result_p;
+
+ result_p = localtime(timer);
+ if (result && result_p)
+ *result = *result_p;
+ return result_p;
+}
+#endif
+
+
+ /*
+ * Initialize the container for the schedule table,
+ * regardless of which initialisation routine is called first.
+ */
+void
+init_schedule_container(void)
+{
+ DEBUGMSGTL(("disman:schedule:init", "init schedule container\n"));
+ if (!schedule_table) {
+ schedule_table = netsnmp_tdata_create_table("schedTable", 0);
+ DEBUGMSGTL(("disman:schedule:init",
+ "create schedule container(%p)\n", schedule_table));
+ }
+}
+
+/** Initializes the schedCore module */
+void
+init_schedCore(void)
+{
+ /*
+ * Create a table structure for the schedule table
+ * This will typically be registered by the schedTable module
+ */
+ DEBUGMSGTL(("disman:schedule:init", "Initializing core module\n"));
+ init_schedule_container();
+}
+
+
+/*
+ * Callback to invoke a scheduled action
+ */
+static void
+_sched_callback( unsigned int reg, void *magic )
+{
+ struct schedTable_entry *entry = (struct schedTable_entry *)magic;
+ int ret;
+ netsnmp_variable_list assign;
+
+ if ( !entry ) {
+ DEBUGMSGTL(("disman:schedule:callback", "missing entry\n"));
+ return;
+ }
+ entry->schedLastRun = time(NULL);
+ entry->schedTriggers++;
+
+ DEBUGMSGTL(( "disman:schedule:callback", "assignment "));
+ DEBUGMSGOID(("disman:schedule:callback", entry->schedVariable,
+ entry->schedVariable_len));
+ DEBUGMSG(( "disman:schedule:callback", " = %ld\n", entry->schedValue));
+
+ memset(&assign, 0, sizeof(netsnmp_variable_list));
+ snmp_set_var_objid(&assign, entry->schedVariable, entry->schedVariable_len);
+ snmp_set_var_typed_value(&assign, ASN_INTEGER,
+ (u_char *)&entry->schedValue,
+ sizeof(entry->schedValue));
+
+ ret = netsnmp_query_set( &assign, entry->session );
+ if ( ret != SNMP_ERR_NOERROR ) {
+ DEBUGMSGTL(( "disman:schedule:callback",
+ "assignment failed (%d)\n", ret));
+ entry->schedFailures++;
+ entry->schedLastFailure = ret;
+ time ( &entry->schedLastFailed );
+ }
+
+ sched_nextTime( entry );
+}
+
+
+ /*
+ * Internal utility routines to help interpret
+ * calendar-based schedule bit strings
+ */
+static u_char _masks[] = { /* 0xff, */ 0x7f, 0x3f, 0x1f,
+ 0x0f, 0x07, 0x03, 0x01, 0x00 };
+static u_char _bits[] = { 0x80, 0x40, 0x20, 0x10,
+ 0x08, 0x04, 0x02, 0x01 };
+
+/*
+ * Are any of the bits set?
+ */
+static int
+_bit_allClear( char *pattern, int len ) {
+ int i;
+
+ for (i=0; i<len; i++) {
+ if ( pattern[i] != 0 )
+ return 0; /* At least one bit set */
+ }
+ return 1; /* All bits clear */
+}
+
+/*
+ * Is a particular bit set?
+ */
+static int
+_bit_set( char *pattern, int bit ) {
+ int major, minor;
+
+ major = bit/8;
+ minor = bit%8;
+ if ( pattern[major] & _bits[minor] ) {
+ return 1; /* Specified bit is set */
+ }
+ return 0; /* Bit not set */
+}
+
+/*
+ * What is the next bit set?
+ * (after a specified point)
+ */
+static int
+_bit_next( char *pattern, int current, size_t len ) {
+ char buf[ 8 ];
+ int major, minor, i, j;
+
+ /* Make a working copy of the bit pattern */
+ memset( buf, 0, 8 );
+ memcpy( buf, pattern, len );
+
+ /*
+ * If we're looking for the first bit after some point,
+ * then clear all earlier bits from the working copy.
+ */
+ if ( current > -1 ) {
+ major = current/8;
+ minor = current%8;
+ for ( i=0; i<major; i++ )
+ buf[i]=0;
+ buf[major] &= _masks[minor];
+ }
+
+ /*
+ * Look for the first bit that's set
+ */
+ for ( i=0; i<(int)len; i++ ) {
+ if ( buf[i] != 0 ) {
+ major = i*8;
+ for ( j=0; j<8; j++ ) {
+ if ( buf[i] & _bits[j] ) {
+ return major+j;
+ }
+ }
+ }
+ }
+ return -1; /* No next bit */
+}
+
+
+static int _daysPerMonth[] = { 31, 28, 31, 30,
+ 31, 30, 31, 31,
+ 30, 31, 30, 31, 29 };
+
+static u_char _truncate[] = { 0xfe, 0xf0, 0xfe, 0xfc,
+ 0xfe, 0xfc, 0xfe, 0xfe,
+ 0xfc, 0xfe, 0xfc, 0xfe, 0xf8 };
+
+/*
+ * What is the next day with a relevant bit set?
+ *
+ * Merge the forward and reverse day bits into a single
+ * pattern relevant for this particular month,
+ * and apply the standard _bit_next() call.
+ * Then check this result against the day of the week bits.
+ */
+static int
+_bit_next_day( char *day_pattern, char weekday_pattern,
+ int day, int month, int year ) {
+ char buf[4];
+ union {
+ char buf2[4];
+ int int_val;
+ } rev;
+ int next_day, i;
+ struct tm tm_val;
+
+ /* Make a working copy of the forward day bits ... */
+ memset( buf, 0, 4 );
+ memcpy( buf, day_pattern, 4 );
+
+ /* ... and another (right-aligned) of the reverse day bits */
+ memset( rev.buf2, 0, 4 );
+ memcpy( rev.buf2, day_pattern+4, 4 );
+ rev.int_val >>= 2;
+ if ( buf[3] & 0x01 )
+ rev.buf2[0] |= 0x40;
+ if ( month == 3 || month == 5 ||
+ month == 8 || month == 10 )
+ rev.int_val >>= 1; /* April, June, September, November */
+ if ( month == 1 )
+ rev.int_val >>= 3; /* February */
+ if ( month == 12 )
+ rev.int_val >>= 2; /* February (leap year) */
+
+ /* Combine the two bit patterns, and truncate to the month end */
+ for ( i=0; i<4; i++ ) {
+ if ( rev.buf2[i] & 0x80 ) buf[3-i] |= 0x01;
+ if ( rev.buf2[i] & 0x40 ) buf[3-i] |= 0x02;
+ if ( rev.buf2[i] & 0x20 ) buf[3-i] |= 0x04;
+ if ( rev.buf2[i] & 0x10 ) buf[3-i] |= 0x08;
+ if ( rev.buf2[i] & 0x08 ) buf[3-i] |= 0x10;
+ if ( rev.buf2[i] & 0x04 ) buf[3-i] |= 0x20;
+ if ( rev.buf2[i] & 0x02 ) buf[3-i] |= 0x40;
+ if ( rev.buf2[i] & 0x01 ) buf[3-i] |= 0x80;
+ }
+
+ buf[3] &= _truncate[ month ];
+
+ next_day = day-1; /* tm_day is 1-based, not 0-based */
+ do {
+ next_day = _bit_next( buf, next_day, 4 );
+ if ( next_day < 0 )
+ return -1;
+
+ /*
+ * Calculate the day of the week, and
+ * check this against the weekday pattern
+ */
+ memset( &tm_val, 0, sizeof(struct tm));
+ tm_val.tm_mday = next_day+1;
+ tm_val.tm_mon = month;
+ tm_val.tm_year = year;
+ mktime( &tm_val );
+ } while ( !_bit_set( &weekday_pattern, tm_val.tm_wday ));
+ return next_day+1; /* Convert back to 1-based list */
+}
+
+
+/*
+ * determine the time for the next scheduled action of a given entry
+ */
+void
+sched_nextTime( struct schedTable_entry *entry )
+{
+ time_t now;
+ struct tm now_tm, next_tm;
+ int rev_day, mon;
+
+ time( &now );
+
+ if ( !entry ) {
+ DEBUGMSGTL(("disman:schedule:time", "missing entry\n"));
+ return;
+ }
+
+ if ( entry->schedCallbackID )
+ snmp_alarm_unregister( entry->schedCallbackID );
+
+ if (!(entry->flags & SCHEDULE_FLAG_ENABLED) ||
+ !(entry->flags & SCHEDULE_FLAG_ACTIVE)) {
+ DEBUGMSGTL(("disman:schedule:time", "inactive entry\n"));
+ return;
+ }
+
+ switch ( entry->schedType ) {
+ case SCHED_TYPE_PERIODIC:
+ if ( !entry->schedInterval ) {
+ DEBUGMSGTL(("disman:schedule:time", "periodic: no interval\n"));
+ return;
+ }
+ if ( entry->schedLastRun ) {
+ entry->schedNextRun = entry->schedLastRun +
+ entry->schedInterval;
+ } else {
+ entry->schedNextRun = now + entry->schedInterval;
+ }
+ DEBUGMSGTL(("disman:schedule:time", "periodic: (%ld) %s",
+ (long) entry->schedNextRun, ctime(&entry->schedNextRun)));
+ break;
+
+ case SCHED_TYPE_ONESHOT:
+ if ( entry->schedLastRun ) {
+ DEBUGMSGTL(("disman:schedule:time", "one-shot: expired (%ld) %s",
+ (long) entry->schedNextRun,
+ ctime(&entry->schedNextRun)));
+ return;
+ }
+ /* Fallthrough */
+ DEBUGMSGTL(("disman:schedule:time", "one-shot: fallthrough\n"));
+ case SCHED_TYPE_CALENDAR:
+ /*
+ * Check for complete time specification
+ * If any of the five fields have no bits set,
+ * the entry can't possibly match any time.
+ */
+ if ( _bit_allClear( entry->schedMinute, 8 ) ||
+ _bit_allClear( entry->schedHour, 3 ) ||
+ _bit_allClear( entry->schedDay, 4+4 ) ||
+ _bit_allClear( entry->schedMonth, 2 ) ||
+ _bit_allClear(&entry->schedWeekDay, 1 )) {
+ DEBUGMSGTL(("disman:schedule:time", "calendar: incomplete spec\n"));
+ return;
+ }
+
+ /*
+ * Calculate the next run time:
+ *
+ * If the current Month, Day & Hour bits are set
+ * calculate the next specified minute
+ * If this fails (or the current Hour bit is not set)
+ * use the first specified minute,
+ * and calculate the next specified hour
+ * If this fails (or the current Day bit is not set)
+ * use the first specified minute and hour
+ * and calculate the next specified day (in this month)
+ * If this fails (or the current Month bit is not set)
+ * use the first specified minute and hour
+ * calculate the next specified month, and
+ * the first specified day (in that month)
+ */
+
+ (void) localtime_r( &now, &now_tm );
+ (void) localtime_r( &now, &next_tm );
+
+ next_tm.tm_mon=-1;
+ next_tm.tm_mday=-1;
+ next_tm.tm_hour=-1;
+ next_tm.tm_min=-1;
+ next_tm.tm_sec=0;
+ if ( _bit_set( entry->schedMonth, now_tm.tm_mon )) {
+ next_tm.tm_mon = now_tm.tm_mon;
+ rev_day = _daysPerMonth[ now_tm.tm_mon ] - now_tm.tm_mday;
+ if ( _bit_set( &entry->schedWeekDay, now_tm.tm_wday ) &&
+ (_bit_set( entry->schedDay, now_tm.tm_mday-1 ) ||
+ _bit_set( entry->schedDay, 31+rev_day ))) {
+ next_tm.tm_mday = now_tm.tm_mday;
+
+ if ( _bit_set( entry->schedHour, now_tm.tm_hour )) {
+ next_tm.tm_hour = now_tm.tm_hour;
+ /* XXX - Check Fall timechange */
+ next_tm.tm_min = _bit_next( entry->schedMinute,
+ now_tm.tm_min, 8 );
+ } else {
+ next_tm.tm_min = -1;
+ }
+
+ if ( next_tm.tm_min == -1 ) {
+ next_tm.tm_min = _bit_next( entry->schedMinute, -1, 8 );
+ next_tm.tm_hour = _bit_next( entry->schedHour,
+ now_tm.tm_hour, 3 );
+ }
+ } else {
+ next_tm.tm_hour = -1;
+ }
+
+ if ( next_tm.tm_hour == -1 ) {
+ next_tm.tm_min = _bit_next( entry->schedMinute, -1, 8 );
+ next_tm.tm_hour = _bit_next( entry->schedHour, -1, 3 );
+ /* Handle leap years */
+ mon = now_tm.tm_mon;
+ if ( mon == 1 && (now_tm.tm_year%4 == 0) )
+ mon = 12;
+ next_tm.tm_mday = _bit_next_day( entry->schedDay,
+ entry->schedWeekDay,
+ now_tm.tm_mday,
+ mon, now_tm.tm_year );
+ }
+ } else {
+ next_tm.tm_min = _bit_next( entry->schedMinute, -1, 2 );
+ next_tm.tm_hour = _bit_next( entry->schedHour, -1, 3 );
+ next_tm.tm_mday = -1;
+ next_tm.tm_mon = now_tm.tm_mon;
+ }
+
+ while ( next_tm.tm_mday == -1 ) {
+ next_tm.tm_mon = _bit_next( entry->schedMonth,
+ next_tm.tm_mon, 2 );
+ if ( next_tm.tm_mon == -1 ) {
+ next_tm.tm_year++;
+ next_tm.tm_mon = _bit_next( entry->schedMonth,
+ -1, 2 );
+ }
+ /* Handle leap years */
+ mon = next_tm.tm_mon;
+ if ( mon == 1 && (next_tm.tm_year%4 == 0) )
+ mon = 12;
+ next_tm.tm_mday = _bit_next_day( entry->schedDay,
+ entry->schedWeekDay,
+ -1, mon, next_tm.tm_year );
+ /* XXX - catch infinite loop */
+ }
+
+ /* XXX - Check for Spring timechange */
+
+ /*
+ * 'next_tm' now contains the time for the next scheduled run
+ */
+ entry->schedNextRun = mktime( &next_tm );
+ DEBUGMSGTL(("disman:schedule:time", "calendar: (%ld) %s",
+ (long) entry->schedNextRun, ctime(&entry->schedNextRun)));
+ return;
+
+ default:
+ DEBUGMSGTL(("disman:schedule:time", "unknown type (%ld)\n",
+ entry->schedType));
+ return;
+ }
+ entry->schedCallbackID = snmp_alarm_register(
+ entry->schedNextRun - now,
+ 0, _sched_callback, entry );
+ return;
+}
+
+#ifndef NETSNMP_FEATURE_REMOVE_SCHED_NEXTROWTIME
+void
+sched_nextRowTime( netsnmp_tdata_row *row )
+{
+ sched_nextTime((struct schedTable_entry *) row->data );
+}
+#endif /* NETSNMP_FEATURE_REMOVE_SCHED_NEXTROWTIME */
+
+/*
+ * create a new row in the table
+ */
+netsnmp_tdata_row *
+schedTable_createEntry(const char *schedOwner, const char *schedName)
+{
+ struct schedTable_entry *entry;
+ netsnmp_tdata_row *row;
+
+ DEBUGMSGTL(("disman:schedule:entry", "creating entry (%s, %s)\n",
+ schedOwner, schedName));
+ entry = SNMP_MALLOC_TYPEDEF(struct schedTable_entry);
+ if (!entry)
+ return NULL;
+
+ row = netsnmp_tdata_create_row();
+ if (!row) {
+ SNMP_FREE(entry);
+ return NULL;
+ }
+ row->data = entry;
+ /*
+ * Set the indexing for this entry, both in the row
+ * data structure, and in the table_data helper.
+ */
+ if (schedOwner) {
+ memcpy(entry->schedOwner, schedOwner, strlen(schedOwner));
+ netsnmp_tdata_row_add_index(row, ASN_OCTET_STR,
+ entry->schedOwner, strlen(schedOwner));
+ }
+ else
+ netsnmp_tdata_row_add_index(row, ASN_OCTET_STR, "", 0 );
+
+ memcpy( entry->schedName, schedName, strlen(schedName));
+ netsnmp_tdata_row_add_index(row, ASN_OCTET_STR,
+ entry->schedName, strlen(schedName));
+ /*
+ * Set the (non-zero) default values in the row data structure.
+ */
+ entry->schedType = SCHED_TYPE_PERIODIC;
+ entry->schedVariable_len = 2; /* .0.0 */
+
+ netsnmp_tdata_add_row(schedule_table, row);
+ return row;
+}
+
+
+/*
+ * remove a row from the table
+ */
+void
+schedTable_removeEntry(netsnmp_tdata_row *row)
+{
+ struct schedTable_entry *entry;
+
+ if (!row || !row->data) {
+ DEBUGMSGTL(("disman:schedule:entry", "remove: missing entry\n"));
+ return; /* Nothing to remove */
+ }
+ entry = (struct schedTable_entry *)
+ netsnmp_tdata_remove_and_delete_row(schedule_table, row);
+ if (entry) {
+ DEBUGMSGTL(("disman:schedule:entry", "remove entry (%s, %s)\n",
+ entry->schedOwner, entry->schedName));
+ SNMP_FREE(entry);
+ }
+}
diff --git a/agent/mibgroup/disman/schedule/schedCore.h b/agent/mibgroup/disman/schedule/schedCore.h
new file mode 100644
index 0000000..35866d7
--- /dev/null
+++ b/agent/mibgroup/disman/schedule/schedCore.h
@@ -0,0 +1,85 @@
+#ifndef SCHEDCORE_H
+#define SCHEDCORE_H
+
+config_require(utilities/iquery)
+
+ /*
+ * Values for schedType field
+ */
+#define SCHED_TYPE_PERIODIC 1
+#define SCHED_TYPE_CALENDAR 2
+#define SCHED_TYPE_ONESHOT 3
+
+ /*
+ * Schedule flags
+ */
+#define SCHEDULE_FLAG_ENABLED 0x01 /* for schedAdminStatus */
+#define SCHEDULE_FLAG_ACTIVE 0x02 /* for schedRowStatus */
+#define SCHEDULE_FLAG_VALID 0x04 /* for row creation/undo */
+
+ /*
+ * All Schedule-MIB OCTET STRING objects are either short (32-char)
+ * tags, or SnmpAdminString values (i.e. 255 characters)
+ */
+#define SCHED_STR1_LEN 32
+#define SCHED_STR2_LEN 255
+
+ /*
+ * Data structure for a schedTable row entry
+ */
+struct schedTable_entry {
+ /*
+ * Index values
+ */
+ char schedOwner[SCHED_STR1_LEN+1];
+ char schedName[ SCHED_STR1_LEN+1];
+
+ /*
+ * Column values - schedule actions
+ */
+ char schedDescr[SCHED_STR2_LEN+1];
+ u_long schedInterval;
+ char schedWeekDay;
+ char schedMonth[2];
+ char schedDay[4+4];
+ char schedHour[3];
+ char schedMinute[8];
+ char schedContextName[SCHED_STR1_LEN+1];
+ oid schedVariable[ MAX_OID_LEN ];
+ size_t schedVariable_len;
+ long schedValue;
+
+ /*
+ * Column values - schedule control
+ */
+ long schedType;
+ u_long schedFailures;
+ long schedLastFailure;
+ time_t schedLastFailed;
+ long schedStorageType;
+ u_long schedTriggers;
+
+ /*
+ * Supporting values
+ */
+ time_t schedLastRun;
+ time_t schedNextRun;
+ unsigned int schedCallbackID;
+ netsnmp_session *session;
+ long flags;
+};
+
+/*
+ * function declarations
+ */
+extern netsnmp_tdata *schedule_table;
+void init_schedule_container(void);
+void init_schedCore(void);
+
+netsnmp_tdata_row *
+ schedTable_createEntry(const char *schedOwner, const char *schedName);
+void schedTable_removeEntry(netsnmp_tdata_row *row);
+void sched_nextTime( struct schedTable_entry *entry );
+void sched_nextRowTime( netsnmp_tdata_row *row );
+
+#endif /* SCHEDCORE_H */
diff --git a/agent/mibgroup/disman/schedule/schedTable.c b/agent/mibgroup/disman/schedule/schedTable.c
new file mode 100644
index 0000000..bba48fd
--- /dev/null
+++ b/agent/mibgroup/disman/schedule/schedTable.c
@@ -0,0 +1,540 @@
+/*
+ * DisMan Schedule MIB:
+ * Core implementation of the schedTable MIB interface.
+ * See 'schedCore.c' for active behaviour of this table.
+ *
+ * (based on mib2c.table_data.conf output)
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include "utilities/iquery.h"
+#include "disman/schedule/schedCore.h"
+#include "disman/schedule/schedTable.h"
+
+netsnmp_feature_require(iquery)
+netsnmp_feature_require(iquery_pdu_session)
+netsnmp_feature_require(table_tdata)
+netsnmp_feature_require(date_n_time)
+netsnmp_feature_require(check_vb_uint)
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(check_vb_type_and_max_size)
+netsnmp_feature_require(check_vb_oid)
+netsnmp_feature_require(check_vb_truthvalue)
+netsnmp_feature_require(table_tdata_insert_row)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+static netsnmp_table_registration_info *table_info;
+
+/** Initializes the schedTable module */
+void
+init_schedTable(void)
+{
+ static oid schedTable_oid[] = { 1, 3, 6, 1, 2, 1, 63, 1, 2 };
+ size_t schedTable_oid_len = OID_LENGTH(schedTable_oid);
+ netsnmp_handler_registration *reg;
+
+ DEBUGMSGTL(("disman:schedule:init", "Initializing table\n"));
+ /*
+ * Ensure the schedule table container is available...
+ */
+ init_schedule_container();
+
+ /*
+ * ... then set up the MIB interface.
+ */
+ reg = netsnmp_create_handler_registration("schedTable",
+ schedTable_handler,
+ schedTable_oid,
+ schedTable_oid_len,
+ HANDLER_CAN_RWRITE);
+
+ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
+ netsnmp_table_helper_add_indexes(table_info,
+ ASN_OCTET_STR, /* index: schedOwner */
+ ASN_OCTET_STR, /* index: schedName */
+ 0);
+ table_info->min_column = COLUMN_SCHEDDESCR;
+ table_info->max_column = COLUMN_SCHEDTRIGGERS;
+
+ netsnmp_tdata_register(reg, schedule_table, table_info);
+}
+
+void
+shutdown_schedTable(void)
+{
+ if (table_info) {
+ netsnmp_table_registration_info_free(table_info);
+ table_info = NULL;
+ }
+}
+
+/** handles requests for the schedTable table */
+int
+schedTable_handler(netsnmp_mib_handler *handler,
+ netsnmp_handler_registration *reginfo,
+ netsnmp_agent_request_info *reqinfo,
+ netsnmp_request_info *requests)
+{
+
+ netsnmp_request_info *request;
+ netsnmp_table_request_info *tinfo;
+ netsnmp_tdata_row *row;
+ struct schedTable_entry *entry;
+ int recalculate = 0;
+ size_t len;
+ char *cp;
+ char owner[SCHED_STR1_LEN+1];
+ char name[ SCHED_STR1_LEN+1];
+ int ret;
+
+ DEBUGMSGTL(("disman:schedule:mib", "Schedule handler (%d)\n",
+ reqinfo->mode));
+ switch (reqinfo->mode) {
+ /*
+ * Read-support (also covers GetNext requests)
+ */
+ case MODE_GET:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct schedTable_entry *)
+ netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info( request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_SCHEDDESCR:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ entry->schedDescr,
+ strlen(entry->schedDescr));
+ break;
+ case COLUMN_SCHEDINTERVAL:
+ snmp_set_var_typed_integer(request->requestvb, ASN_UNSIGNED,
+ entry->schedInterval);
+ break;
+ case COLUMN_SCHEDWEEKDAY:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ &entry->schedWeekDay,
+ sizeof(entry->schedWeekDay));
+ break;
+ case COLUMN_SCHEDMONTH:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ entry->schedMonth,
+ sizeof(entry->schedMonth));
+ break;
+ case COLUMN_SCHEDDAY:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ entry->schedDay,
+ sizeof(entry->schedDay));
+ break;
+ case COLUMN_SCHEDHOUR:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ entry->schedHour,
+ sizeof(entry->schedHour));
+ break;
+ case COLUMN_SCHEDMINUTE:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ entry->schedMinute,
+ sizeof(entry->schedMinute));
+ break;
+ case COLUMN_SCHEDCONTEXTNAME:
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ entry->schedContextName,
+ strlen(entry->schedContextName));
+ break;
+ case COLUMN_SCHEDVARIABLE:
+ snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
+ (u_char *)entry->schedVariable,
+ entry->schedVariable_len*sizeof(oid));
+ break;
+ case COLUMN_SCHEDVALUE:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->schedValue);
+ break;
+ case COLUMN_SCHEDTYPE:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->schedType);
+ break;
+ case COLUMN_SCHEDADMINSTATUS:
+ ret = (entry->flags & SCHEDULE_FLAG_ENABLED ) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_SCHEDOPERSTATUS:
+ ret = (entry->flags & SCHEDULE_FLAG_ENABLED ) ?
+ TV_TRUE : TV_FALSE;
+ /*
+ * Check for one-shot entries that have already fired
+ */
+ if ((entry->schedType == SCHED_TYPE_ONESHOT) &&
+ (entry->schedLastRun != 0 ))
+ ret = 3; /* finished(3) */
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_SCHEDFAILURES:
+ snmp_set_var_typed_integer(request->requestvb, ASN_COUNTER,
+ entry->schedFailures);
+ break;
+ case COLUMN_SCHEDLASTFAILURE:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->schedLastFailure);
+ break;
+ case COLUMN_SCHEDLASTFAILED:
+ /*
+ * Convert 'schedLastFailed' timestamp
+ * into DateAndTime string
+ */
+ cp = (char *) date_n_time( &entry->schedLastFailed, &len );
+ snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
+ cp, len);
+ break;
+ case COLUMN_SCHEDSTORAGETYPE:
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
+ entry->schedStorageType);
+ break;
+ case COLUMN_SCHEDROWSTATUS:
+ ret = (entry->flags & SCHEDULE_FLAG_ACTIVE ) ?
+ TV_TRUE : TV_FALSE;
+ snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, ret);
+ break;
+ case COLUMN_SCHEDTRIGGERS:
+ snmp_set_var_typed_integer(request->requestvb, ASN_COUNTER,
+ entry->schedTriggers);
+ break;
+ }
+ }
+ break;
+
+ /*
+ * Write-support
+ */
+ case MODE_SET_RESERVE1:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct schedTable_entry *)
+ netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info( request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_SCHEDDESCR:
+ ret = netsnmp_check_vb_type_and_max_size(
+ request->requestvb, ASN_OCTET_STR, SCHED_STR2_LEN);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDINTERVAL:
+ ret = netsnmp_check_vb_uint( request->requestvb );
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDWEEKDAY:
+ ret = netsnmp_check_vb_type_and_size(
+ request->requestvb, ASN_OCTET_STR, 1);
+ /* XXX - check for bit(7) set */
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDMONTH:
+ ret = netsnmp_check_vb_type_and_size( /* max_size ?? */
+ request->requestvb, ASN_OCTET_STR, 2);
+ /* XXX - check for bit(12)-bit(15) set */
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDDAY:
+ ret = netsnmp_check_vb_type_and_size( /* max_size ?? */
+ request->requestvb, ASN_OCTET_STR, 4+4);
+ /* XXX - check for bit(62) or bit(63) set */
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDHOUR:
+ ret = netsnmp_check_vb_type_and_size( /* max_size ?? */
+ request->requestvb, ASN_OCTET_STR, 3);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDMINUTE:
+ ret = netsnmp_check_vb_type_and_size( /* max_size ?? */
+ request->requestvb, ASN_OCTET_STR, 8);
+ /* XXX - check for bit(60)-bit(63) set */
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDCONTEXTNAME:
+ ret = netsnmp_check_vb_type_and_max_size(
+ request->requestvb, ASN_OCTET_STR, SCHED_STR1_LEN);
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDVARIABLE:
+ ret = netsnmp_check_vb_oid( request->requestvb );
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDVALUE:
+ ret = netsnmp_check_vb_int( request->requestvb );
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDTYPE:
+ ret = netsnmp_check_vb_int_range( request->requestvb,
+ SCHED_TYPE_PERIODIC, SCHED_TYPE_ONESHOT );
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDADMINSTATUS:
+ ret = netsnmp_check_vb_truthvalue( request->requestvb );
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_WRONGTYPE);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDSTORAGETYPE:
+ ret = netsnmp_check_vb_int_range( request->requestvb,
+ ST_NONE, ST_READONLY );
+ /* XXX - check valid/consistent assignments */
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ case COLUMN_SCHEDROWSTATUS:
+ ret = netsnmp_check_vb_rowstatus( request->requestvb,
+ (entry ? RS_ACTIVE: RS_NONEXISTENT));
+ /* XXX - check consistency assignments */
+ if (ret != SNMP_ERR_NOERROR) {
+ netsnmp_set_request_error(reqinfo, request, ret);
+ return SNMP_ERR_NOERROR;
+ }
+ break;
+ default:
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOTWRITABLE);
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_RESERVE2:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_SCHEDROWSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_CREATEANDGO:
+ case RS_CREATEANDWAIT:
+ /*
+ * Create an (empty) new row structure
+ */
+ memset(owner, 0, SCHED_STR1_LEN+1);
+ memset(name, 0, SCHED_STR1_LEN+1);
+ memcpy(owner, tinfo->indexes->val.string,
+ tinfo->indexes->val_len);
+ memcpy(name, tinfo->indexes->next_variable->val.string,
+ tinfo->indexes->next_variable->val_len);
+ row = schedTable_createEntry(owner, name);
+ if (!row) {
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_RESOURCEUNAVAILABLE);
+ return SNMP_ERR_NOERROR;
+ }
+ netsnmp_insert_tdata_row(request, row);
+ }
+ }
+ }
+ break;
+
+ case MODE_SET_FREE:
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ tinfo = netsnmp_extract_table_info(request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_SCHEDROWSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_CREATEANDGO:
+ case RS_CREATEANDWAIT:
+ /*
+ * Tidy up after a failed row creation request
+ */
+ entry = (struct schedTable_entry *)
+ netsnmp_tdata_extract_entry(request);
+ if (entry &&
+ !(entry->flags & SCHEDULE_FLAG_VALID)) {
+ row = (netsnmp_tdata_row *)
+ netsnmp_tdata_extract_row(request);
+ schedTable_removeEntry(row);
+ }
+ }
+ }
+ }
+ break;
+
+ case MODE_SET_ACTION:
+ for (request = requests; request; request = request->next) {
+ entry = (struct schedTable_entry *)
+ netsnmp_tdata_extract_entry(request);
+ if (!entry) {
+ /*
+ * New rows must be created via the RowStatus column
+ */
+ netsnmp_set_request_error(reqinfo, request,
+ SNMP_ERR_NOCREATION);
+ /* or inconsistentName? */
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ break;
+
+ case MODE_SET_UNDO:
+ break;
+
+ case MODE_SET_COMMIT:
+ /*
+ * All these assignments are "unfailable", so it's
+ * (reasonably) safe to apply them in the Commit phase
+ */
+ entry = NULL;
+ for (request = requests; request; request = request->next) {
+ if (request->processed)
+ continue;
+
+ entry = (struct schedTable_entry *)
+ netsnmp_tdata_extract_entry(request);
+ tinfo = netsnmp_extract_table_info( request);
+
+ switch (tinfo->colnum) {
+ case COLUMN_SCHEDDESCR:
+ memset(entry->schedDescr, 0, sizeof(entry->schedDescr));
+ memcpy(entry->schedDescr, request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_SCHEDINTERVAL:
+ entry->schedInterval = *request->requestvb->val.integer;
+ recalculate = 1;
+ break;
+ case COLUMN_SCHEDWEEKDAY:
+ entry->schedWeekDay = request->requestvb->val.string[0];
+ recalculate = 1;
+ break;
+ case COLUMN_SCHEDMONTH:
+ entry->schedMonth[0] = request->requestvb->val.string[0];
+ entry->schedMonth[1] = request->requestvb->val.string[1];
+ recalculate = 1;
+ break;
+ case COLUMN_SCHEDDAY:
+ memset(entry->schedDay, 0, sizeof(entry->schedDay));
+ memcpy(entry->schedDay, request->requestvb->val.string,
+ request->requestvb->val_len);
+ recalculate = 1;
+ break;
+ case COLUMN_SCHEDHOUR:
+ entry->schedHour[0] = request->requestvb->val.string[0];
+ entry->schedHour[1] = request->requestvb->val.string[1];
+ entry->schedHour[2] = request->requestvb->val.string[2];
+ recalculate = 1;
+ break;
+ case COLUMN_SCHEDMINUTE:
+ memset(entry->schedMinute, 0, sizeof(entry->schedMinute));
+ memcpy(entry->schedMinute, request->requestvb->val.string,
+ request->requestvb->val_len);
+ recalculate = 1;
+ break;
+ case COLUMN_SCHEDCONTEXTNAME:
+ memset(entry->schedContextName, 0, sizeof(entry->schedContextName));
+ memcpy(entry->schedContextName,
+ request->requestvb->val.string,
+ request->requestvb->val_len);
+ break;
+ case COLUMN_SCHEDVARIABLE:
+ memset(entry->schedVariable, 0, sizeof(entry->schedVariable));
+ memcpy(entry->schedVariable,
+ request->requestvb->val.string,
+ request->requestvb->val_len);
+ entry->schedVariable_len =
+ request->requestvb->val_len/sizeof(oid);
+ break;
+ case COLUMN_SCHEDVALUE:
+ entry->schedValue = *request->requestvb->val.integer;
+ break;
+ case COLUMN_SCHEDTYPE:
+ entry->schedType = *request->requestvb->val.integer;
+ break;
+ case COLUMN_SCHEDADMINSTATUS:
+ if (*request->requestvb->val.integer == TV_TRUE)
+ entry->flags |= SCHEDULE_FLAG_ENABLED;
+ else
+ entry->flags &= ~SCHEDULE_FLAG_ENABLED;
+ break;
+ case COLUMN_SCHEDSTORAGETYPE:
+ entry->schedStorageType = *request->requestvb->val.integer;
+ break;
+ case COLUMN_SCHEDROWSTATUS:
+ switch (*request->requestvb->val.integer) {
+ case RS_ACTIVE:
+ entry->flags |= SCHEDULE_FLAG_ACTIVE;
+ break;
+ case RS_CREATEANDGO:
+ entry->flags |= SCHEDULE_FLAG_ACTIVE;
+ entry->flags |= SCHEDULE_FLAG_VALID;
+ entry->session =
+ netsnmp_iquery_pdu_session(reqinfo->asp->pdu);
+ break;
+ case RS_CREATEANDWAIT:
+ entry->flags |= SCHEDULE_FLAG_VALID;
+ entry->session =
+ netsnmp_iquery_pdu_session(reqinfo->asp->pdu);
+ break;
+
+ case RS_DESTROY:
+ row = (netsnmp_tdata_row *)
+ netsnmp_tdata_extract_row(request);
+ schedTable_removeEntry(row);
+ }
+ recalculate = 1;
+ break;
+ }
+ }
+ if (recalculate) {
+ netsnmp_assert(entry);
+ sched_nextTime(entry);
+ }
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
diff --git a/agent/mibgroup/disman/schedule/schedTable.h b/agent/mibgroup/disman/schedule/schedTable.h
new file mode 100644
index 0000000..52033ba
--- /dev/null
+++ b/agent/mibgroup/disman/schedule/schedTable.h
@@ -0,0 +1,39 @@
+#ifndef SCHEDTABLE_H
+#define SCHEDTABLE_H
+
+config_require(disman/schedule/schedCore)
+config_add_mib(DISMAN-SCHEDULE-MIB)
+
+/*
+ * function declarations
+ */
+void init_schedTable(void);
+void shutdown_schedTable(void);
+Netsnmp_Node_Handler schedTable_handler;
+
+/*
+ * column number definitions for table schedTable
+ */
+#define COLUMN_SCHEDOWNER 1
+#define COLUMN_SCHEDNAME 2
+#define COLUMN_SCHEDDESCR 3
+#define COLUMN_SCHEDINTERVAL 4
+#define COLUMN_SCHEDWEEKDAY 5
+#define COLUMN_SCHEDMONTH 6
+#define COLUMN_SCHEDDAY 7
+#define COLUMN_SCHEDHOUR 8
+#define COLUMN_SCHEDMINUTE 9
+#define COLUMN_SCHEDCONTEXTNAME 10
+#define COLUMN_SCHEDVARIABLE 11
+#define COLUMN_SCHEDVALUE 12
+#define COLUMN_SCHEDTYPE 13
+#define COLUMN_SCHEDADMINSTATUS 14
+#define COLUMN_SCHEDOPERSTATUS 15
+#define COLUMN_SCHEDFAILURES 16
+#define COLUMN_SCHEDLASTFAILURE 17
+#define COLUMN_SCHEDLASTFAILED 18
+#define COLUMN_SCHEDSTORAGETYPE 19
+#define COLUMN_SCHEDROWSTATUS 20
+#define COLUMN_SCHEDTRIGGERS 21
+
+#endif /* SCHEDTABLE_H */
diff --git a/agent/mibgroup/disman/traceroute-mib.h b/agent/mibgroup/disman/traceroute-mib.h
new file mode 100644
index 0000000..b33d69e
--- /dev/null
+++ b/agent/mibgroup/disman/traceroute-mib.h
@@ -0,0 +1,21 @@
+/*
+*Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+*
+*All right reserved
+*
+*File Name:traceroute-mib.h
+*File Description:Add DISMAN-TRACEROUTE-MIB.
+*
+*Current Version:1.0
+*Author:ChenJing
+*Date:2004.8.20
+*/
+
+/*
+ * wrapper for the disman traceroute mib code files
+ */
+config_require(disman/traceroute/traceRouteCtlTable)
+config_require(disman/traceroute/traceRouteResultsTable)
+config_require(disman/traceroute/traceRouteProbeHistoryTable)
+config_require(disman/traceroute/traceRouteHopsTable)
+config_add_mib(DISMAN-TRACEROUTE-MIB)
diff --git a/agent/mibgroup/disman/traceroute/traceRouteCtlTable.c b/agent/mibgroup/disman/traceroute/traceRouteCtlTable.c
new file mode 100644
index 0000000..04143eb
--- /dev/null
+++ b/agent/mibgroup/disman/traceroute/traceRouteCtlTable.c
@@ -0,0 +1,6198 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:traceRouteCtlTable.c
+ *File Description:Rows of traceRouteCtlTable MIB add delete ans read.
+ * Rows of traceRouteResultsTable MIB add and delete.
+ * Rows of traceRouteProbeHistoryTable MIB add and delete.
+ * Rows of traceRouteHopsTable MIB add and delete.
+ * The main function is also here.
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/net-snmp-features.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <pthread.h>
+#include <math.h>
+
+#ifndef NETSNMP_NO_WRITE_SUPPORT
+netsnmp_feature_require(header_complex_find_entry)
+#endif /* NETSNMP_NO_WRITE_SUPPORT */
+
+#include "traceRouteCtlTable.h"
+#include "traceRouteResultsTable.h"
+#include "traceRouteProbeHistoryTable.h"
+#include "traceRouteHopsTable.h"
+#include "header_complex.h"
+
+oid traceRouteCtlTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 81, 1, 2 };
+
+/* trap */
+oid traceRoutePathChange[] = { 1, 3, 6, 1, 2, 1, 81, 0, 1 };
+oid traceRouteTestFailed[] = { 1, 3, 6, 1, 2, 1, 81, 0, 2 };
+oid traceRouteTestCompleted[] = { 1, 3, 6, 1, 2, 1, 81, 0, 3 };
+
+struct variable2 traceRouteCtlTable_variables[] = {
+ /*
+ * magic number , variable type , ro/rw , callback fn , L, oidsuffix
+ */
+
+ {COLUMN_TRACEROUTECTLTARGETADDRESSTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 3}},
+ {COLUMN_TRACEROUTECTLTARGETADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 4}},
+ {COLUMN_TRACEROUTECTLBYPASSROUTETABLE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 5}},
+ {COLUMN_TRACEROUTECTLDATASIZE, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 6}},
+ {COLUMN_TRACEROUTECTLTIMEOUT, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 7}},
+ {COLUMN_TRACEROUTECTLPROBESPERHOP, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 8}},
+ {COLUMN_TRACEROUTECTLPORT, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 9}},
+ {COLUMN_TRACEROUTECTLMAXTTL, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 10}},
+ {COLUMN_TRACEROUTECTLDSFIELD, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 11}},
+ {COLUMN_TRACEROUTECTLSOURCEADDRESSTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 12}},
+ {COLUMN_TRACEROUTECTLSOURCEADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 13}},
+ {COLUMN_TRACEROUTECTLIFINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 14}},
+ {COLUMN_TRACEROUTECTLMISCOPTIONS, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 15}},
+ {COLUMN_TRACEROUTECTLMAXFAILURES, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 16}},
+ {COLUMN_TRACEROUTECTLDONTFRAGMENT, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 17}},
+ {COLUMN_TRACEROUTECTLINITIALTTL, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 18}},
+ {COLUMN_TRACEROUTECTLFREQUENCY, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 19}},
+ {COLUMN_TRACEROUTECTLSTORAGETYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 20}},
+ {COLUMN_TRACEROUTECTLADMINSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 21}},
+ {COLUMN_TRACEROUTECTLDESCR, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 22}},
+ {COLUMN_TRACEROUTECTLMAXROWS, ASN_UNSIGNED, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 23}},
+ {COLUMN_TRACEROUTECTLTRAPGENERATION, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 24}},
+ {COLUMN_TRACEROUTECTLCREATEHOPSENTRIES, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 25}},
+ {COLUMN_TRACEROUTECTLTYPE, ASN_OBJECT_ID, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 26}},
+ {COLUMN_TRACEROUTECTLROWSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
+ var_traceRouteCtlTable, 2, {1, 27}}
+
+};
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+
+struct header_complex_index *traceRouteCtlTableStorage = NULL;
+struct header_complex_index *traceRouteResultsTableStorage = NULL;
+struct header_complex_index *traceRouteProbeHistoryTableStorage = NULL;
+struct header_complex_index *traceRouteHopsTableStorage = NULL;
+
+int
+traceRouteResultsTable_add(struct traceRouteCtlTable_data *thedata);
+int
+traceRouteResultsTable_del(struct traceRouteCtlTable_data *thedata);
+
+void
+init_traceRouteCtlTable(void)
+{
+ DEBUGMSGTL(("traceRouteCtlTable", "initializing... "));
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("traceRouteCtlTable", traceRouteCtlTable_variables,
+ variable2, traceRouteCtlTable_variables_oid);
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("traceRouteCtlTable",
+ parse_traceRouteCtlTable, NULL, NULL);
+
+ /*
+ * we need to be called back later to store our data
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_traceRouteCtlTable, NULL);
+
+ DEBUGMSGTL(("traceRouteCtlTable", "done.\n"));
+}
+
+
+void
+init_trResultsTable(struct traceRouteCtlTable_data *item)
+{
+ struct traceRouteResultsTable_data *StorageTmp = NULL;
+ netsnmp_variable_list *vars = NULL;
+ char *host = NULL;
+
+ host =
+ (char *) malloc(sizeof(char) *
+ (item->traceRouteCtlTargetAddressLen + 1));
+
+ if (host == NULL) {
+ DEBUGMSGTL(("traceRouteCtlTable", "host calloc %s\n",
+ strerror(errno)));
+ exit(1);
+ }
+
+ memset(host, '\0',
+ sizeof(char) * (item->traceRouteCtlTargetAddressLen + 1));
+ strcpy(host, item->traceRouteCtlTargetAddress);
+ host[item->traceRouteCtlTargetAddressLen] = '\0';
+
+ StorageTmp = SNMP_MALLOC_STRUCT(traceRouteResultsTable_data);
+ if (StorageTmp == NULL) {
+ DEBUGMSGTL(("traceRouteCtlTable", "StorageTmp malloc %s\n",
+ strerror(errno)));
+ exit(1);
+ }
+
+ StorageTmp->traceRouteCtlOwnerIndex =
+ (char *) malloc(sizeof(char) *
+ (item->traceRouteCtlOwnerIndexLen + 1));
+ if (StorageTmp->traceRouteCtlOwnerIndex == NULL) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "traceRouteCtlOwnerIndex malloc %s\n",
+ strerror(errno)));
+ exit(1);
+ }
+
+ memcpy(StorageTmp->traceRouteCtlOwnerIndex,
+ item->traceRouteCtlOwnerIndex,
+ item->traceRouteCtlOwnerIndexLen + 1);
+ StorageTmp->traceRouteCtlOwnerIndex[item->traceRouteCtlOwnerIndexLen] =
+ '\0';
+ StorageTmp->traceRouteCtlOwnerIndexLen =
+ item->traceRouteCtlOwnerIndexLen;
+
+ StorageTmp->traceRouteCtlTestName =
+ (char *) malloc(sizeof(char) *
+ (item->traceRouteCtlTestNameLen + 1));
+ if (StorageTmp->traceRouteCtlTestName == NULL) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "traceRouteCtlTestName malloc %s\n", strerror(errno)));
+ exit(1);
+ }
+
+ memcpy(StorageTmp->traceRouteCtlTestName, item->traceRouteCtlTestName,
+ item->traceRouteCtlTestNameLen + 1);
+ StorageTmp->traceRouteCtlTestName[item->traceRouteCtlTestNameLen] =
+ '\0';
+ StorageTmp->traceRouteCtlTestNameLen = item->traceRouteCtlTestNameLen;
+
+ StorageTmp->traceRouteResultsOperStatus = 1;
+
+ if (item->traceRouteCtlTargetAddressType == 1
+ || item->traceRouteCtlTargetAddressType == 16) {
+ struct sockaddr whereto; /* Who to try to reach */
+ register struct sockaddr_in *to = (struct sockaddr_in *) &whereto;
+ register struct hostinfo *hi = NULL;
+ hi = gethostinfo(host);
+ if (hi == NULL) {
+ DEBUGMSGTL(("traceRouteCtlTable", "hi calloc %s\n",
+ strerror(errno)));
+ exit(1);
+ }
+
+ setsin(to, hi->addrs[0]);
+ if (inet_ntoa(to->sin_addr) == NULL) {
+ StorageTmp->traceRouteResultsIpTgtAddrType = 0;
+ StorageTmp->traceRouteResultsIpTgtAddr = strdup("");
+ StorageTmp->traceRouteResultsIpTgtAddrLen = 0;
+ } else {
+ StorageTmp->traceRouteResultsIpTgtAddrType = 1;
+ StorageTmp->traceRouteResultsIpTgtAddr =
+ (char *) malloc(sizeof(char) *
+ (strlen(inet_ntoa(to->sin_addr)) + 1));
+ if (StorageTmp->traceRouteResultsIpTgtAddr == NULL) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "traceRouteResultsIpTgtAddr malloc %s\n",
+ strerror(errno)));
+ exit(1);
+ }
+
+ memcpy(StorageTmp->traceRouteResultsIpTgtAddr,
+ inet_ntoa(to->sin_addr),
+ strlen(inet_ntoa(to->sin_addr)) + 1);
+ StorageTmp->
+ traceRouteResultsIpTgtAddr[strlen(inet_ntoa(to->sin_addr))]
+ = '\0';
+ StorageTmp->traceRouteResultsIpTgtAddrLen =
+ strlen(inet_ntoa(to->sin_addr));
+ }
+ }
+ if (item->traceRouteCtlTargetAddressType == 2) {
+
+ struct sockaddr_in6 whereto; /* Who to try to reach */
+ register struct sockaddr_in6 *to =
+ (struct sockaddr_in6 *) &whereto;
+ struct hostent *hp = NULL;
+ /* struct hostenv hp; */
+ char pa[64];
+ memset(pa, '\0', 64);
+
+ to->sin6_family = AF_INET6;
+ to->sin6_port = htons(33434);
+
+ if (inet_pton(AF_INET6, host, &to->sin6_addr) > 0) {
+ StorageTmp->traceRouteResultsIpTgtAddrType = 2;
+ StorageTmp->traceRouteResultsIpTgtAddr =
+ (char *) malloc(sizeof(char) * (strlen(host) + 1));
+ if (StorageTmp->traceRouteResultsIpTgtAddr == NULL) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "traceRouteResultsIpTgtAddr malloc %s\n",
+ strerror(errno)));
+ exit(1);
+ }
+ memset(StorageTmp->traceRouteResultsIpTgtAddr, '\0',
+ sizeof(char) * (strlen(host) + 1));
+ memcpy(StorageTmp->traceRouteResultsIpTgtAddr, host,
+ strlen(host) + 1);
+ StorageTmp->traceRouteResultsIpTgtAddr[strlen(host)] = '\0';
+ StorageTmp->traceRouteResultsIpTgtAddrLen = strlen(host);
+ } else {
+ hp = gethostbyname2(host, AF_INET6);
+ if (hp != NULL) {
+ const char *hostname;
+ memmove((caddr_t) & to->sin6_addr, hp->h_addr, 16);
+ hostname = inet_ntop(AF_INET6, &to->sin6_addr, pa, 64);
+ StorageTmp->traceRouteResultsIpTgtAddrType = 2;
+ StorageTmp->traceRouteResultsIpTgtAddr =
+ (char *) malloc(sizeof(char) * (strlen(hostname) + 1));
+ if (StorageTmp->traceRouteResultsIpTgtAddr == NULL) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "traceRouteResultsIpTgtAddr malloc %s\n",
+ strerror(errno)));
+ exit(1);
+ }
+ memset(StorageTmp->traceRouteResultsIpTgtAddr, '\0',
+ sizeof(char) * (strlen(host) + 1));
+ memcpy(StorageTmp->traceRouteResultsIpTgtAddr, hostname,
+ strlen(hostname) + 1);
+ StorageTmp->traceRouteResultsIpTgtAddr[strlen(hostname)] =
+ '\0';
+ StorageTmp->traceRouteResultsIpTgtAddrLen =
+ strlen(hostname);
+ } else {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "traceroute: unknown host %s\n", host));
+
+ StorageTmp->traceRouteResultsIpTgtAddrType = 0;
+ StorageTmp->traceRouteResultsIpTgtAddr = strdup("");
+ StorageTmp->traceRouteResultsIpTgtAddrLen = 0;
+ }
+ }
+ }
+
+ StorageTmp->traceRouteResultsCurHopCount = 0;
+ StorageTmp->traceRouteResultsCurProbeCount = 0;
+ StorageTmp->traceRouteResultsTestAttempts = 0;
+ StorageTmp->traceRouteResultsTestSuccesses = 0;
+
+ StorageTmp->traceRouteResultsLastGoodPathLen = 0;
+
+ item->traceRouteResults = StorageTmp;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlOwnerIndex, item->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlTestName, item->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ if ((header_complex_get(traceRouteResultsTableStorage, vars)) != NULL) {
+ traceRouteResultsTable_del(item);
+ }
+ snmp_free_varbind(vars);
+ vars = NULL;
+ if (item->traceRouteResults != NULL) {
+ if (traceRouteResultsTable_add(item) != SNMPERR_SUCCESS) {
+ DEBUGMSGTL(("traceRouteResultsTable",
+ "init an entry error\n"));
+ }
+ }
+
+}
+
+
+
+int
+modify_trResultsOper(struct traceRouteCtlTable_data *thedata, long val)
+{
+ netsnmp_variable_list *vars = NULL;
+ struct traceRouteResultsTable_data *StorageTmp = NULL;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+
+ if ((StorageTmp =
+ header_complex_get(traceRouteResultsTableStorage,
+ vars)) == NULL) {
+ snmp_free_varbind(vars);
+ vars = NULL;
+ return SNMP_ERR_NOSUCHNAME;
+ } else {
+ StorageTmp->traceRouteResultsOperStatus = val;
+ DEBUGMSGTL(("traceRouteResultsOperStatus", "done.\n"));
+ snmp_free_varbind(vars);
+ vars = NULL;
+ return SNMPERR_SUCCESS;
+ }
+}
+
+
+struct traceRouteCtlTable_data *
+create_traceRouteCtlTable_data(void)
+{
+ struct traceRouteCtlTable_data *StorageNew = NULL;
+ StorageNew = SNMP_MALLOC_STRUCT(traceRouteCtlTable_data);
+ if (StorageNew == NULL) {
+ exit(1);
+ }
+ StorageNew->traceRouteCtlTargetAddressType = 1;
+ StorageNew->traceRouteCtlTargetAddress = strdup("");
+ StorageNew->traceRouteCtlTargetAddressLen = 0;
+ StorageNew->traceRouteCtlByPassRouteTable = 2;
+ StorageNew->traceRouteCtlDataSize = 0;
+ StorageNew->traceRouteCtlTimeOut = 3;
+ StorageNew->traceRouteCtlProbesPerHop = 3;
+ StorageNew->traceRouteCtlPort = 33434;
+ StorageNew->traceRouteCtlMaxTtl = 30;
+ StorageNew->traceRouteCtlDSField = 0;
+ StorageNew->traceRouteCtlSourceAddressType = 0;
+ StorageNew->traceRouteCtlSourceAddress = strdup("");
+ StorageNew->traceRouteCtlSourceAddressLen = 0;
+ StorageNew->traceRouteCtlIfIndex = 0;
+ StorageNew->traceRouteCtlMiscOptions = strdup("");
+ StorageNew->traceRouteCtlMiscOptionsLen = 0;
+ StorageNew->traceRouteCtlMaxFailures = 5;
+ StorageNew->traceRouteCtlDontFragment = 2;
+ StorageNew->traceRouteCtlInitialTtl = 1;
+ StorageNew->traceRouteCtlFrequency = 0;
+ StorageNew->traceRouteCtlStorageType = ST_NONVOLATILE;
+ StorageNew->traceRouteCtlAdminStatus = 2;
+ StorageNew->traceRouteCtlDescr = (char *) malloc(strlen("00") + 1);
+ if (StorageNew->traceRouteCtlDescr == NULL) {
+ exit(1);
+ }
+ memcpy(StorageNew->traceRouteCtlDescr, "00", strlen("00") + 1);
+ StorageNew->traceRouteCtlDescr[strlen("00")] = '\0';
+ StorageNew->traceRouteCtlDescrLen =
+ strlen(StorageNew->traceRouteCtlDescr);
+
+ StorageNew->traceRouteCtlMaxRows = 50;
+ StorageNew->traceRouteCtlTrapGeneration = strdup("");
+ StorageNew->traceRouteCtlTrapGenerationLen = 0;
+ StorageNew->traceRouteCtlCreateHopsEntries = 2;
+
+ StorageNew->traceRouteCtlType = calloc(1, sizeof(oid) * sizeof(2)); /* 0.0 */
+ StorageNew->traceRouteCtlTypeLen = 2;
+
+ StorageNew->traceRouteResults = NULL;
+ StorageNew->traceRouteProbeHis = NULL;
+ StorageNew->traceRouteHops = NULL;
+
+ StorageNew->storageType = ST_NONVOLATILE;
+ /* StorageNew->traceRouteProbeHistoryMaxIndex=0; */
+ return StorageNew;
+}
+
+
+/*
+ * traceRouteCtlTable_add(): adds a structure node to our data set
+ */
+int
+traceRouteCtlTable_add(struct traceRouteCtlTable_data *thedata)
+{
+ netsnmp_variable_list *vars = NULL;
+
+
+ DEBUGMSGTL(("traceRouteCtlTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlOperationName */
+
+ if (header_complex_add_data(&traceRouteCtlTableStorage, vars, thedata)
+ == NULL) {
+ vars = NULL;
+ return SNMPERR_GENERR;
+ } else {
+
+ DEBUGMSGTL(("traceRouteCtlTable", "registered an entry\n"));
+
+
+ DEBUGMSGTL(("traceRouteCtlTable", "done.\n"));
+ vars = NULL;
+ return SNMPERR_SUCCESS;
+ }
+}
+
+int
+traceRouteResultsTable_add(struct traceRouteCtlTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list = NULL;
+ struct traceRouteResultsTable_data *p = NULL;
+ p = thedata->traceRouteResults;
+ if (thedata->traceRouteResults != NULL) {
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) p->traceRouteCtlOwnerIndex, p->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) p->traceRouteCtlTestName, p->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ DEBUGMSGTL(("traceRouteResultsTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ header_complex_add_data(&traceRouteResultsTableStorage, vars_list,
+ p);
+ DEBUGMSGTL(("traceRouteResultsTable", "out finished\n"));
+ vars_list = NULL;
+ DEBUGMSGTL(("traceRouteResultsTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+ } else {
+ vars_list = NULL;
+ DEBUGMSGTL(("traceRouteResultsTable", "error.\n"));
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+}
+
+
+int
+traceRouteProbeHistoryTable_add(struct traceRouteProbeHistoryTable_data
+ *thedata)
+{
+ netsnmp_variable_list *vars_list = NULL;
+ if (thedata != NULL) {
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &thedata->traceRouteProbeHistoryIndex, sizeof(thedata->traceRouteProbeHistoryIndex)); /* traceRouteProbeHistoryIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &thedata->traceRouteProbeHistoryHopIndex, sizeof(thedata->traceRouteProbeHistoryHopIndex)); /* traceRouteProbeHistoryHopIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &thedata->traceRouteProbeHistoryProbeIndex, sizeof(thedata->traceRouteProbeHistoryProbeIndex)); /* traceRouteProbeHistoryProbeIndex */
+
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ if (header_complex_add_data
+ (&traceRouteProbeHistoryTableStorage, vars_list,
+ thedata) == NULL) {
+ vars_list = NULL;
+ return SNMP_ERR_INCONSISTENTNAME;
+ } else {
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "out finished\n"));
+
+ vars_list = NULL;
+
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+ }
+ } else {
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+}
+
+int
+traceRouteProbeHistoryTable_addall(struct traceRouteCtlTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list = NULL;
+ struct traceRouteProbeHistoryTable_data *p = NULL;
+ p = thedata->traceRouteProbeHis;
+ if (thedata->traceRouteProbeHis != NULL)
+ do {
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) p->traceRouteCtlOwnerIndex, p->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) p->traceRouteCtlTestName, p->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &p->traceRouteProbeHistoryIndex, sizeof(p->traceRouteProbeHistoryIndex)); /* traceRouteProbeHistoryIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &p->traceRouteProbeHistoryHopIndex, sizeof(p->traceRouteProbeHistoryHopIndex)); /* traceRouteProbeHistoryHopIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &p->traceRouteProbeHistoryProbeIndex, sizeof(p->traceRouteProbeHistoryProbeIndex)); /* traceRouteProbeHistoryProbeIndex */
+
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ if (header_complex_add_data
+ (&traceRouteProbeHistoryTableStorage, vars_list,
+ p) == NULL) {
+ vars_list = NULL;
+ return SNMP_ERR_INCONSISTENTNAME;
+ } else {
+
+ struct header_complex_index *temp = NULL;
+ temp = traceRouteProbeHistoryTableStorage;
+ if (traceRouteProbeHistoryTableStorage != NULL)
+ do {
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "adding data,vars_oid="));
+ DEBUGMSGOID(("traceRouteProbeHistoryTable",
+ temp->name, temp->namelen));
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "\n "));
+ temp = temp->next;
+ } while (temp != NULL);
+
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "out finished\n"));
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "done.\n"));
+ vars_list = NULL;
+ return SNMPERR_SUCCESS;
+ }
+
+ p = p->next;
+ } while (p != NULL);
+ else {
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+
+}
+
+
+
+int
+traceRouteHopsTable_add(struct traceRouteHopsTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list = NULL;
+
+ if (thedata != NULL) {
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &thedata->traceRouteHopsHopIndex, sizeof(thedata->traceRouteHopsHopIndex)); /* traceRouteHopsHopIndex */
+
+ DEBUGMSGTL(("traceRouteHopsTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ if (header_complex_add_data
+ (&traceRouteHopsTableStorage, vars_list, thedata) == NULL) {
+ vars_list = NULL;
+ return SNMP_ERR_INCONSISTENTNAME;
+ } else {
+ DEBUGMSGTL(("traceRouteHopsTable", "out finished\n"));
+ DEBUGMSGTL(("traceRouteHopsTable", "done.\n"));
+ vars_list = NULL;
+ return SNMPERR_SUCCESS;
+ }
+ }
+ return SNMPERR_GENERR;
+}
+
+int
+traceRouteHopsTable_addall(struct traceRouteCtlTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list = NULL;
+ struct traceRouteHopsTable_data *p = NULL;
+ vars_list = NULL;
+ p = thedata->traceRouteHops;
+ if (thedata->traceRouteHops != NULL) {
+ do {
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) p->traceRouteCtlOwnerIndex, p->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) p->traceRouteCtlTestName, p->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &p->traceRouteHopsHopIndex, sizeof(p->traceRouteHopsHopIndex)); /* traceRouteHopsHopIndex */
+
+ DEBUGMSGTL(("traceRouteHopsTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ if (header_complex_add_data
+ (&traceRouteHopsTableStorage, vars_list, p) == NULL) {
+ vars_list = NULL;
+ return SNMP_ERR_INCONSISTENTNAME;
+ } else {
+
+ struct header_complex_index *temp = NULL;
+ temp = traceRouteHopsTableStorage;
+ if (traceRouteHopsTableStorage != NULL)
+ do {
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "adding data,vars_oid="));
+ DEBUGMSGOID(("traceRouteProbeHistoryTable",
+ temp->name, temp->namelen));
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "\n "));
+ temp = temp->next;
+ } while (temp != NULL);
+ DEBUGMSGTL(("traceRouteHopsTable", "out finished\n"));
+
+ vars_list = NULL;
+ }
+ p = p->next;
+ } while (p != NULL);
+ DEBUGMSGTL(("traceRouteHopsTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+ } else {
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+
+}
+
+
+unsigned long
+traceRouteProbeHistoryTable_count(struct traceRouteCtlTable_data *thedata)
+{
+ struct header_complex_index *hciptr2 = NULL;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len;
+ unsigned long count = 0;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+
+ header_complex_generate_oid(newoid, &newoid_len, NULL, 0, vars);
+
+ vars = NULL;
+ for (hciptr2 = traceRouteProbeHistoryTableStorage; hciptr2 != NULL;
+ hciptr2 = hciptr2->next) {
+ if (snmp_oid_compare(newoid, newoid_len, hciptr2->name, newoid_len)
+ == 0) {
+ count = count + 1;
+ }
+ }
+ return count;
+}
+
+
+
+unsigned long
+traceRouteHopsTable_count(struct traceRouteCtlTable_data *thedata)
+{
+ struct header_complex_index *hciptr2 = NULL;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len;
+ unsigned long count = 0;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlOperationName */
+
+ header_complex_generate_oid(newoid, &newoid_len, NULL, 0, vars);
+
+ vars = NULL;
+ for (hciptr2 = traceRouteHopsTableStorage; hciptr2 != NULL;
+ hciptr2 = hciptr2->next) {
+ if (snmp_oid_compare(newoid, newoid_len, hciptr2->name, newoid_len)
+ == 0) {
+ count = count + 1;
+ }
+ }
+ return count;
+}
+
+
+
+void
+traceRouteProbeHistoryTable_delLast(struct traceRouteCtlTable_data
+ *thedata)
+{
+ struct header_complex_index *hciptr2 = NULL;
+ struct header_complex_index *hcilast = NULL;
+ struct traceRouteProbeHistoryTable_data *StorageTmp = NULL;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len = 0;
+ time_t last_time = 2147483647;
+ time_t tp;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlOperationName */
+
+ memset(newoid, '\0', sizeof(oid) * MAX_OID_LEN);
+ header_complex_generate_oid(newoid, &newoid_len, NULL, 0, vars);
+
+ for (hcilast = hciptr2 = traceRouteProbeHistoryTableStorage;
+ hciptr2 != NULL; hciptr2 = hciptr2->next) {
+ if (snmp_oid_compare(newoid, newoid_len, hciptr2->name, newoid_len)
+ == 0) {
+
+ StorageTmp =
+ header_complex_get_from_oid
+ (traceRouteProbeHistoryTableStorage, hciptr2->name,
+ hciptr2->namelen);
+ tp = StorageTmp->traceRouteProbeHistoryTime_time;
+
+ if (last_time > tp) {
+ last_time = tp;
+ hcilast = hciptr2;
+ }
+
+ }
+ }
+ header_complex_extract_entry(&traceRouteProbeHistoryTableStorage, hcilast);
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "delete the last one success!\n"));
+ vars = NULL;
+}
+
+
+
+void
+traceRouteCtlTable_cleaner(struct header_complex_index *thestuff)
+{
+ struct header_complex_index *hciptr = NULL;
+ struct traceRouteCtlTable_data *StorageDel = NULL;
+ DEBUGMSGTL(("traceRouteCtlTable", "cleanerout "));
+ for (hciptr = thestuff; hciptr != NULL; hciptr = hciptr->next) {
+ StorageDel =
+ header_complex_extract_entry(&traceRouteCtlTableStorage,
+ hciptr);
+ if (StorageDel != NULL) {
+ free(StorageDel->traceRouteCtlOwnerIndex);
+ StorageDel->traceRouteCtlOwnerIndex = NULL;
+ free(StorageDel->traceRouteCtlTestName);
+ StorageDel->traceRouteCtlTestName = NULL;
+ free(StorageDel->traceRouteCtlTargetAddress);
+ StorageDel->traceRouteCtlTargetAddress = NULL;
+ free(StorageDel->traceRouteCtlSourceAddress);
+ StorageDel->traceRouteCtlSourceAddress = NULL;
+ free(StorageDel->traceRouteCtlMiscOptions);
+ StorageDel->traceRouteCtlMiscOptions = NULL;
+ free(StorageDel->traceRouteCtlDescr);
+ StorageDel->traceRouteCtlDescr = NULL;
+ free(StorageDel->traceRouteCtlTrapGeneration);
+ StorageDel->traceRouteCtlTrapGeneration = NULL;
+ free(StorageDel->traceRouteCtlType);
+ StorageDel->traceRouteCtlType = NULL;
+ free(StorageDel);
+ StorageDel = NULL;
+
+ }
+ DEBUGMSGTL(("traceRouteCtlTable", "cleaner "));
+ }
+}
+
+
+/*
+ * parse_mteObjectsTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+void
+parse_traceRouteCtlTable(const char *token, char *line)
+{
+ size_t tmpint;
+ struct traceRouteCtlTable_data *StorageTmp =
+ SNMP_MALLOC_STRUCT(traceRouteCtlTable_data);
+
+ DEBUGMSGTL(("traceRouteCtlTable", "parsing config... "));
+
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlOwnerIndex,
+ &StorageTmp->traceRouteCtlOwnerIndexLen);
+ if (StorageTmp->traceRouteCtlOwnerIndex == NULL) {
+ config_perror("invalid specification for traceRouteCtlOwnerIndex");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlTestName,
+ &StorageTmp->traceRouteCtlTestNameLen);
+ if (StorageTmp->traceRouteCtlTestName == NULL) {
+ config_perror("invalid specification for traceRouteCtlTestName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteCtlTargetAddressType,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlTargetAddress,
+ &StorageTmp->traceRouteCtlTargetAddressLen);
+ if (StorageTmp->traceRouteCtlTargetAddress == NULL) {
+ config_perror
+ ("invalid specification for traceRouteCtlTargetAddress");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteCtlByPassRouteTable,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteCtlDataSize, &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteCtlTimeOut, &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteCtlProbesPerHop,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteCtlPort, &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteCtlMaxTtl, &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteCtlDSField, &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteCtlSourceAddressType,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlSourceAddress,
+ &StorageTmp->traceRouteCtlSourceAddressLen);
+ if (StorageTmp->traceRouteCtlSourceAddress == NULL) {
+ config_perror
+ ("invalid specification for traceRouteCtlSourceAddress");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteCtlIfIndex, &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlMiscOptions,
+ &StorageTmp->traceRouteCtlMiscOptionsLen);
+ if (StorageTmp->traceRouteCtlMiscOptions == NULL) {
+ config_perror
+ ("invalid specification for traceRouteCtlMiscOptions");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteCtlMaxFailures,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteCtlDontFragment,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteCtlInitialTtl,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteCtlFrequency,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteCtlStorageType,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteCtlAdminStatus,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlDescr,
+ &StorageTmp->traceRouteCtlDescrLen);
+ if (StorageTmp->traceRouteCtlDescr == NULL) {
+ config_perror("invalid specification for traceRouteCtlTrapDescr");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteCtlMaxRows, &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlTrapGeneration,
+ &StorageTmp->traceRouteCtlTrapGenerationLen);
+ if (StorageTmp->traceRouteCtlTrapGeneration == NULL) {
+ config_perror
+ ("invalid specification for traceRouteCtlTrapGeneration");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteCtlCreateHopsEntries,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OBJECT_ID, line,
+ &StorageTmp->traceRouteCtlType,
+ &StorageTmp->traceRouteCtlTypeLen);
+ if (StorageTmp->traceRouteCtlType == NULL) {
+ config_perror("invalid specification for traceRouteCtlType");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteCtlRowStatus,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteProbeHistoryMaxIndex,
+ &tmpint);
+
+ StorageTmp->storageType = ST_NONVOLATILE;
+ traceRouteCtlTable_add(StorageTmp);
+ /* traceRouteCtlTable_cleaner(traceRouteCtlTableStorage); */
+
+ DEBUGMSGTL(("traceRouteCtlTable", "done.\n"));
+}
+
+
+
+/*
+ * store_traceRouteCtlTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+int
+store_traceRouteCtlTable(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr = NULL;
+ size_t tmpint;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ struct header_complex_index *hcindex = NULL;
+
+
+ DEBUGMSGTL(("traceRouteCtlTable", "storing data... "));
+
+
+ for (hcindex = traceRouteCtlTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct traceRouteCtlTable_data *) hcindex->data;
+
+ if (StorageTmp->storageType != ST_READONLY) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "traceRouteCtlTable ");
+ cptr = line + strlen(line);
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteCtlOwnerIndex,
+ &StorageTmp->
+ traceRouteCtlOwnerIndexLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->traceRouteCtlTestName,
+ &StorageTmp->
+ traceRouteCtlTestNameLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteCtlTargetAddressType,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteCtlTargetAddress,
+ &StorageTmp->
+ traceRouteCtlTargetAddressLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteCtlByPassRouteTable,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->traceRouteCtlDataSize,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->traceRouteCtlTimeOut,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteCtlProbesPerHop, &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->traceRouteCtlPort,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->traceRouteCtlMaxTtl,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->traceRouteCtlDSField,
+ &tmpint);
+
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteCtlSourceAddressType,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteCtlSourceAddress,
+ &StorageTmp->
+ traceRouteCtlSourceAddressLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->traceRouteCtlIfIndex,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteCtlMiscOptions,
+ &StorageTmp->
+ traceRouteCtlMiscOptionsLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteCtlMaxFailures, &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteCtlDontFragment, &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteCtlInitialTtl, &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->traceRouteCtlFrequency,
+ &tmpint);
+
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteCtlStorageType, &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteCtlAdminStatus, &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->traceRouteCtlDescr,
+ &StorageTmp->traceRouteCtlDescrLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->traceRouteCtlMaxRows,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteCtlTrapGeneration,
+ &StorageTmp->
+ traceRouteCtlTrapGenerationLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteCtlCreateHopsEntries,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OBJECT_ID, cptr,
+ &StorageTmp->traceRouteCtlType,
+ &StorageTmp->traceRouteCtlTypeLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->traceRouteCtlRowStatus,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteProbeHistoryMaxIndex,
+ &tmpint);
+
+
+
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("traceRouteCtlTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+
+
+/*
+ * var_traceRouteCtlTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_mteObjectsTable above.
+ */
+unsigned char *
+var_traceRouteCtlTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact,
+ size_t *var_len, WriteMethod ** write_method)
+{
+
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, vp, name, length, exact,
+ var_len, write_method)) == NULL) {
+ if (vp->magic == COLUMN_TRACEROUTECTLROWSTATUS)
+ *write_method = write_traceRouteCtlRowStatus;
+
+ return NULL;
+ }
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+ switch (vp->magic) {
+
+
+ case COLUMN_TRACEROUTECTLTARGETADDRESSTYPE:
+ *write_method = write_traceRouteCtlTargetAddressType;
+ *var_len = sizeof(StorageTmp->traceRouteCtlTargetAddressType);
+
+ return (u_char *) & StorageTmp->traceRouteCtlTargetAddressType;
+
+ case COLUMN_TRACEROUTECTLTARGETADDRESS:
+ *write_method = write_traceRouteCtlTargetAddress;
+ *var_len = (StorageTmp->traceRouteCtlTargetAddressLen);
+
+ return (u_char *) StorageTmp->traceRouteCtlTargetAddress;
+
+ case COLUMN_TRACEROUTECTLBYPASSROUTETABLE:
+ *write_method = write_traceRouteCtlByPassRouteTable;
+ *var_len = sizeof(StorageTmp->traceRouteCtlByPassRouteTable);
+
+ return (u_char *) & StorageTmp->traceRouteCtlByPassRouteTable;
+
+ case COLUMN_TRACEROUTECTLDATASIZE:
+ *write_method = write_traceRouteCtlDataSize;
+ *var_len = sizeof(StorageTmp->traceRouteCtlDataSize);
+
+ return (u_char *) & StorageTmp->traceRouteCtlDataSize;
+
+ case COLUMN_TRACEROUTECTLTIMEOUT:
+ *write_method = write_traceRouteCtlTimeOut;
+ *var_len = sizeof(StorageTmp->traceRouteCtlTimeOut);
+
+ return (u_char *) & StorageTmp->traceRouteCtlTimeOut;
+
+ case COLUMN_TRACEROUTECTLPROBESPERHOP:
+ *write_method = write_traceRouteCtlProbesPerHop;
+ *var_len = sizeof(StorageTmp->traceRouteCtlProbesPerHop);
+
+ return (u_char *) & StorageTmp->traceRouteCtlProbesPerHop;
+
+ case COLUMN_TRACEROUTECTLPORT:
+ *write_method = write_traceRouteCtlPort;
+ *var_len = sizeof(StorageTmp->traceRouteCtlPort);
+
+ return (u_char *) & StorageTmp->traceRouteCtlPort;
+
+ case COLUMN_TRACEROUTECTLMAXTTL:
+ *write_method = write_traceRouteCtlMaxTtl;
+ *var_len = sizeof(StorageTmp->traceRouteCtlMaxTtl);
+
+ return (u_char *) & StorageTmp->traceRouteCtlMaxTtl;
+
+ case COLUMN_TRACEROUTECTLDSFIELD:
+ *write_method = write_traceRouteCtlDSField;
+ *var_len = sizeof(StorageTmp->traceRouteCtlDSField);
+
+ return (u_char *) & StorageTmp->traceRouteCtlDSField;
+
+ case COLUMN_TRACEROUTECTLSOURCEADDRESSTYPE:
+ *write_method = write_traceRouteCtlSourceAddressType;
+ *var_len = sizeof(StorageTmp->traceRouteCtlSourceAddressType);
+
+ return (u_char *) & StorageTmp->traceRouteCtlSourceAddressType;
+
+ case COLUMN_TRACEROUTECTLSOURCEADDRESS:
+ *write_method = write_traceRouteCtlSourceAddress;
+ *var_len = (StorageTmp->traceRouteCtlSourceAddressLen);
+
+ return (u_char *) StorageTmp->traceRouteCtlSourceAddress;
+
+ case COLUMN_TRACEROUTECTLIFINDEX:
+ *write_method = write_traceRouteCtlIfIndex;
+ *var_len = sizeof(StorageTmp->traceRouteCtlIfIndex);
+
+ return (u_char *) & StorageTmp->traceRouteCtlIfIndex;
+
+ case COLUMN_TRACEROUTECTLMISCOPTIONS:
+ *write_method = write_traceRouteCtlMiscOptions;
+ *var_len = (StorageTmp->traceRouteCtlMiscOptionsLen);
+
+ return (u_char *) StorageTmp->traceRouteCtlMiscOptions;
+
+ case COLUMN_TRACEROUTECTLMAXFAILURES:
+ *write_method = write_traceRouteCtlMaxFailures;
+ *var_len = sizeof(StorageTmp->traceRouteCtlMaxFailures);
+
+ return (u_char *) & StorageTmp->traceRouteCtlMaxFailures;
+
+ case COLUMN_TRACEROUTECTLDONTFRAGMENT:
+ *write_method = write_traceRouteCtlDontFragment;
+ *var_len = sizeof(StorageTmp->traceRouteCtlDontFragment);
+
+ return (u_char *) & StorageTmp->traceRouteCtlDontFragment;
+
+ case COLUMN_TRACEROUTECTLINITIALTTL:
+ *write_method = write_traceRouteCtlInitialTtl;
+ *var_len = sizeof(StorageTmp->traceRouteCtlInitialTtl);
+
+ return (u_char *) & StorageTmp->traceRouteCtlInitialTtl;
+
+ case COLUMN_TRACEROUTECTLFREQUENCY:
+ *write_method = write_traceRouteCtlFrequency;
+ *var_len = sizeof(StorageTmp->traceRouteCtlFrequency);
+
+ return (u_char *) & StorageTmp->traceRouteCtlFrequency;
+
+ case COLUMN_TRACEROUTECTLSTORAGETYPE:
+ *write_method = write_traceRouteCtlStorageType;
+ *var_len = sizeof(StorageTmp->traceRouteCtlStorageType);
+
+ return (u_char *) & StorageTmp->traceRouteCtlStorageType;
+
+ case COLUMN_TRACEROUTECTLADMINSTATUS:
+ *write_method = write_traceRouteCtlAdminStatus;
+ *var_len = sizeof(StorageTmp->traceRouteCtlAdminStatus);
+
+ return (u_char *) & StorageTmp->traceRouteCtlAdminStatus;
+
+ case COLUMN_TRACEROUTECTLDESCR:
+ *write_method = write_traceRouteCtlDescr;
+ *var_len = (StorageTmp->traceRouteCtlDescrLen);
+
+ return (u_char *) StorageTmp->traceRouteCtlDescr;
+
+ case COLUMN_TRACEROUTECTLMAXROWS:
+ *write_method = write_traceRouteCtlMaxRows;
+ *var_len = sizeof(StorageTmp->traceRouteCtlMaxRows);
+
+ return (u_char *) & StorageTmp->traceRouteCtlMaxRows;
+
+ case COLUMN_TRACEROUTECTLTRAPGENERATION:
+ *write_method = write_traceRouteCtlTrapGeneration;
+ *var_len = (StorageTmp->traceRouteCtlTrapGenerationLen);
+
+ return (u_char *) StorageTmp->traceRouteCtlTrapGeneration;
+
+ case COLUMN_TRACEROUTECTLCREATEHOPSENTRIES:
+ *write_method = write_traceRouteCtlCreateHopsEntries;
+ *var_len = sizeof(StorageTmp->traceRouteCtlCreateHopsEntries);
+
+ return (u_char *) & StorageTmp->traceRouteCtlCreateHopsEntries;
+
+ case COLUMN_TRACEROUTECTLTYPE:
+ *write_method = write_traceRouteCtlType;
+ *var_len = (StorageTmp->traceRouteCtlTypeLen) * sizeof(oid);
+
+ return (u_char *) StorageTmp->traceRouteCtlType;
+
+ case COLUMN_TRACEROUTECTLROWSTATUS:
+ *write_method = write_traceRouteCtlRowStatus;
+ *var_len = sizeof(StorageTmp->traceRouteCtlRowStatus);
+
+ return (u_char *) & StorageTmp->traceRouteCtlRowStatus;
+
+ default:
+ ERROR_MSG("");
+ }
+ return NULL;
+}
+
+
+
+int
+traceRouteResultsTable_del(struct traceRouteCtlTable_data *thedata)
+{
+ struct header_complex_index *hciptr2 = NULL;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len = 0;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+
+ memset(newoid, '\0', sizeof(oid) * MAX_OID_LEN);
+ header_complex_generate_oid(newoid, &newoid_len, NULL, 0, vars);
+
+ for (hciptr2 = traceRouteResultsTableStorage; hciptr2 != NULL;
+ hciptr2 = hciptr2->next) {
+ if (snmp_oid_compare(newoid, newoid_len, hciptr2->name, newoid_len)
+ == 0) {
+ header_complex_extract_entry(&traceRouteResultsTableStorage,
+ hciptr2);
+ DEBUGMSGTL(("traceRouteResultsTable", "delete success!\n"));
+
+ }
+ }
+ vars = NULL;
+ return SNMPERR_SUCCESS;
+}
+
+
+
+
+int
+traceRouteProbeHistoryTable_del(struct traceRouteCtlTable_data *thedata)
+{
+ struct header_complex_index *hciptr2 = NULL;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len = 0;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlOperationName */
+
+ memset(newoid, '\0', sizeof(oid) * MAX_OID_LEN);
+
+ header_complex_generate_oid(newoid, &newoid_len, NULL, 0, vars);
+
+ for (hciptr2 = traceRouteProbeHistoryTableStorage; hciptr2 != NULL;
+ hciptr2 = hciptr2->next) {
+ if (snmp_oid_compare(newoid, newoid_len, hciptr2->name, newoid_len)
+ == 0) {
+ header_complex_extract_entry(&traceRouteProbeHistoryTableStorage,
+ hciptr2);
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "delete success!\n"));
+
+ }
+ }
+ vars = NULL;
+ return SNMPERR_SUCCESS;
+}
+
+
+int
+traceRouteHopsTable_del(struct traceRouteCtlTable_data *thedata)
+{
+ struct header_complex_index *hciptr2 = NULL;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len = 0;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+
+ memset(newoid, '\0', sizeof(oid) * MAX_OID_LEN);
+
+ header_complex_generate_oid(newoid, &newoid_len, NULL, 0, vars);
+
+ for (hciptr2 = traceRouteHopsTableStorage; hciptr2 != NULL;
+ hciptr2 = hciptr2->next) {
+ if (snmp_oid_compare(newoid, newoid_len, hciptr2->name, newoid_len)
+ == 0) {
+ header_complex_extract_entry(&traceRouteHopsTableStorage, hciptr2);
+ DEBUGMSGTL(("traceRouteHopsTable", "delete success!\n"));
+
+ }
+ }
+ vars = NULL;
+ return SNMPERR_SUCCESS;
+}
+
+/*
+ * send trap
+ */
+
+void
+send_traceRoute_trap(struct traceRouteCtlTable_data *item,
+ oid * trap_oid, size_t trap_oid_len)
+{
+ static oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; /* snmpTrapIOD.0 */
+ struct traceRouteHopsTable_data *StorageHops = NULL;
+ netsnmp_variable_list *var_list = NULL;
+ netsnmp_variable_list *vars = NULL;
+ netsnmp_variable_list *var_hops = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len = 0;
+
+ oid indexoid[MAX_OID_LEN];
+ size_t indexoid_len = 0;
+
+ struct header_complex_index *hciptr;
+ oid tempoid[MAX_OID_LEN];
+ size_t tempoid_len = 0;
+
+ oid traceRouteCtlTargetAddress[] =
+ { 1, 3, 6, 1, 2, 1, 81, 1, 2, 1, 4 };
+ oid traceRouteHopsIpTgAddress[] =
+ { 1, 3, 6, 1, 2, 1, 81, 1, 5, 1, 3 };
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlOwnerIndex, item->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlTestName, item->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+
+ /*
+ * snmpTrap oid
+ */
+ snmp_varlist_add_variable(&var_list, objid_snmptrap,
+ sizeof(objid_snmptrap) / sizeof(oid),
+ ASN_OBJECT_ID, (u_char *) trap_oid,
+ trap_oid_len * sizeof(oid));
+
+ /*
+ * traceRouteCtlTargetAddress
+ */
+ memset(newoid, '\0', MAX_OID_LEN * sizeof(oid));
+ header_complex_generate_oid(newoid, &newoid_len,
+ traceRouteCtlTargetAddress,
+ sizeof(traceRouteCtlTargetAddress) /
+ sizeof(oid), vars);
+
+ snmp_varlist_add_variable(&var_list, newoid,
+ newoid_len,
+ ASN_OCTET_STR,
+ (u_char *) item->traceRouteCtlTargetAddress,
+ item->traceRouteCtlTargetAddressLen);
+
+ for (hciptr = traceRouteHopsTableStorage; hciptr != NULL;
+ hciptr = hciptr->next) {
+ memset(indexoid, '\0', MAX_OID_LEN * sizeof(oid));
+ header_complex_generate_oid(indexoid, &indexoid_len, NULL, 0,
+ vars);
+ if (snmp_oid_compare
+ (indexoid, indexoid_len, hciptr->name, indexoid_len) == 0) {
+ StorageHops =
+ (struct traceRouteHopsTable_data *)
+ header_complex_get_from_oid(traceRouteHopsTableStorage,
+ hciptr->name, hciptr->namelen);
+ memset(tempoid, '\0', MAX_OID_LEN * sizeof(oid));
+ header_complex_generate_oid(tempoid, &tempoid_len,
+ traceRouteHopsIpTgAddress,
+ sizeof(traceRouteHopsIpTgAddress) /
+ sizeof(oid), vars);
+ snmp_varlist_add_variable(&var_hops, NULL, 0, ASN_UNSIGNED, (char *) &StorageHops->traceRouteHopsHopIndex, sizeof(StorageHops->traceRouteHopsHopIndex)); /* traceRouteCtlTestName */
+ memset(newoid, '\0', MAX_OID_LEN * sizeof(oid));
+ header_complex_generate_oid(newoid, &newoid_len, tempoid,
+ tempoid_len, var_hops);
+ snmp_varlist_add_variable(&var_list, newoid, newoid_len,
+ ASN_OCTET_STR,
+ (u_char *) StorageHops->
+ traceRouteHopsIpTgtAddress,
+ StorageHops->
+ traceRouteHopsIpTgtAddressLen);
+
+ var_hops = NULL;
+ }
+ }
+
+ /*
+ * XXX: stuff based on event table
+ */
+
+ DEBUGMSG(("pingTest:send_traceRoute_trap", "success!\n"));
+
+ send_v2trap(var_list);
+ snmp_free_varbind(vars);
+ vars = NULL;
+ snmp_free_varbind(var_list);
+ var_list = NULL;
+}
+
+
+int
+write_traceRouteCtlTargetAddressType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlTargetAddressType not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlTargetAddressType;
+ StorageTmp->traceRouteCtlTargetAddressType = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlTargetAddressType = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_traceRouteCtlTargetAddress(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static char *tmpvar;
+ static size_t tmplen;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlTargetAddress not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlTargetAddress;
+ tmplen = StorageTmp->traceRouteCtlTargetAddressLen;
+
+ StorageTmp->traceRouteCtlTargetAddress =
+ (char *) malloc(var_val_len + 1);
+ if (StorageTmp->traceRouteCtlTargetAddress == NULL) {
+ exit(1);
+ }
+ memcpy(StorageTmp->traceRouteCtlTargetAddress, var_val,
+ var_val_len);
+ StorageTmp->traceRouteCtlTargetAddress[var_val_len] = '\0';
+ StorageTmp->traceRouteCtlTargetAddressLen = var_val_len;
+
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->traceRouteCtlTargetAddress);
+ StorageTmp->traceRouteCtlTargetAddress = tmpvar;
+ StorageTmp->traceRouteCtlTargetAddressLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+int
+write_traceRouteCtlByPassRouteTable(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlTargetAddressType not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlByPassRouteTable;
+ StorageTmp->traceRouteCtlByPassRouteTable = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlByPassRouteTable = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+
+}
+
+int
+write_traceRouteCtlDataSize(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlDataSize not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlDataSize;
+ if ((*((long *) var_val)) >= 0 && (*((long *) var_val)) <= 65507)
+ StorageTmp->traceRouteCtlDataSize = *((long *) var_val);
+ else
+ StorageTmp->traceRouteCtlDataSize = 56;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlDataSize = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_traceRouteCtlTimeOut(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlDataSize not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlTimeOut;
+
+ if ((*((long *) var_val)) >= 1 && (*((long *) var_val)) <= 60)
+ StorageTmp->traceRouteCtlTimeOut = *((long *) var_val);
+ else
+ StorageTmp->traceRouteCtlTimeOut = 3;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlTimeOut = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+
+int
+write_traceRouteCtlProbesPerHop(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlDataSize not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlProbesPerHop;
+
+ if ((*((long *) var_val)) >= 1 && (*((long *) var_val)) <= 10)
+ StorageTmp->traceRouteCtlProbesPerHop = *((long *) var_val);
+ else
+ StorageTmp->traceRouteCtlProbesPerHop = 3;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlProbesPerHop = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_traceRouteCtlPort(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlTargetAddressType not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlPort;
+ StorageTmp->traceRouteCtlPort = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlPort = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_traceRouteCtlMaxTtl(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlDataSize not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlMaxTtl;
+ if ((*((long *) var_val)) >= 1 && (*((long *) var_val)) <= 255)
+ StorageTmp->traceRouteCtlMaxTtl = *((long *) var_val);
+ else
+ StorageTmp->traceRouteCtlMaxTtl = 30;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlMaxTtl = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+int
+write_traceRouteCtlDSField(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlDataSize not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlDSField;
+ StorageTmp->traceRouteCtlDSField = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlDSField = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+int
+write_traceRouteCtlSourceAddressType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlMaxRows not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlSourceAddressType;
+ StorageTmp->traceRouteCtlSourceAddressType = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlSourceAddressType = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+int
+write_traceRouteCtlSourceAddress(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static char *tmpvar;
+ static size_t tmplen;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlTargetAddress not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlSourceAddress;
+ tmplen = StorageTmp->traceRouteCtlSourceAddressLen;
+ StorageTmp->traceRouteCtlSourceAddress =
+ (char *) malloc(var_val_len + 1);
+ if (StorageTmp->traceRouteCtlSourceAddress == NULL) {
+ exit(1);
+ }
+ memcpy(StorageTmp->traceRouteCtlSourceAddress, var_val,
+ var_val_len + 1);
+ StorageTmp->traceRouteCtlSourceAddress[var_val_len] = '\0';
+ StorageTmp->traceRouteCtlSourceAddressLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->traceRouteCtlSourceAddress);
+ StorageTmp->traceRouteCtlSourceAddress = tmpvar;
+ StorageTmp->traceRouteCtlSourceAddressLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_traceRouteCtlIfIndex(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlMaxRows not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlIfIndex;
+ StorageTmp->traceRouteCtlIfIndex = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlIfIndex = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_traceRouteCtlMiscOptions(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ static size_t tmplen;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlTargetAddress not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlMiscOptions;
+ tmplen = StorageTmp->traceRouteCtlMiscOptionsLen;
+ StorageTmp->traceRouteCtlMiscOptions =
+ (char *) malloc(var_val_len + 1);
+ if (StorageTmp->traceRouteCtlMiscOptions == NULL) {
+ exit(1);
+ }
+ memcpy(StorageTmp->traceRouteCtlMiscOptions, var_val,
+ var_val_len + 1);
+ StorageTmp->traceRouteCtlMiscOptions[var_val_len] = '\0';
+ StorageTmp->traceRouteCtlMiscOptionsLen = var_val_len;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->traceRouteCtlMiscOptions);
+ StorageTmp->traceRouteCtlMiscOptions = tmpvar;
+ StorageTmp->traceRouteCtlMiscOptionsLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+int
+write_traceRouteCtlMaxFailures(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlTrapTestFailureFilter not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlMaxFailures;
+ if ((*((long *) var_val)) >= 0 && (*((long *) var_val)) <= 15)
+ StorageTmp->traceRouteCtlMaxFailures = *((long *) var_val);
+ else
+ StorageTmp->traceRouteCtlMaxFailures = 1;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlMaxFailures = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+
+int
+write_traceRouteCtlDontFragment(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlMaxRows not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlDontFragment;
+ StorageTmp->traceRouteCtlDontFragment = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlDontFragment = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_traceRouteCtlInitialTtl(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlTrapTestFailureFilter not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlInitialTtl;
+ if ((*((long *) var_val)) >= 0 && (*((long *) var_val)) <= 255)
+ StorageTmp->traceRouteCtlInitialTtl = *((long *) var_val);
+ else
+ StorageTmp->traceRouteCtlInitialTtl = 1;
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlInitialTtl = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+int
+write_traceRouteCtlFrequency(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlSourceAddressType not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlFrequency;
+ StorageTmp->traceRouteCtlFrequency = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlFrequency = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_traceRouteCtlStorageType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ int set_value;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+
+ set_value = *((long *) var_val);
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlMaxRows not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+
+ if ((StorageTmp->traceRouteCtlStorageType == 2
+ || StorageTmp->traceRouteCtlStorageType == 3)
+ && (set_value == 4 || set_value == 5)) {
+ return SNMP_ERR_WRONGVALUE;
+ }
+ break;
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlStorageType;
+ StorageTmp->traceRouteCtlStorageType = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlStorageType = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+int
+write_traceRouteCtlAdminStatus(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ netsnmp_variable_list *vars = NULL;
+ struct traceRouteResultsTable_data *StorageNew = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlIfIndex not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlAdminStatus;
+ StorageTmp->traceRouteCtlAdminStatus = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlAdminStatus = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) StorageTmp->traceRouteCtlOwnerIndex, StorageTmp->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) StorageTmp->traceRouteCtlTestName, StorageTmp->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ StorageNew =
+ header_complex_get(traceRouteResultsTableStorage, vars);
+
+ if (StorageTmp->traceRouteCtlAdminStatus == 1
+ && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ if (StorageNew == NULL)
+ init_trResultsTable(StorageTmp);
+ else {
+ StorageTmp->traceRouteResults->
+ traceRouteResultsOperStatus = 1;
+ modify_trResultsOper(StorageTmp, 1);
+ }
+ if (StorageTmp->traceRouteCtlFrequency != 0)
+ StorageTmp->timer_id =
+ snmp_alarm_register(StorageTmp->traceRouteCtlFrequency,
+ SA_REPEAT, run_traceRoute,
+ StorageTmp);
+ else
+ StorageTmp->timer_id = snmp_alarm_register(1, 0, run_traceRoute,
+ StorageTmp);
+
+ } else if (StorageTmp->traceRouteCtlAdminStatus == 2
+ && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ snmp_alarm_unregister(StorageTmp->timer_id);
+ if (StorageNew == NULL)
+ init_trResultsTable(StorageTmp);
+ else {
+ StorageTmp->traceRouteResults->
+ traceRouteResultsOperStatus = 2;
+ modify_trResultsOper(StorageTmp, 2);
+ }
+ }
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+int
+write_traceRouteCtlDescr(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static char *tmpvar;
+ static size_t tmplen;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlTargetAddress not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlDescr;
+ tmplen = StorageTmp->traceRouteCtlDescrLen;
+
+ StorageTmp->traceRouteCtlDescr = (char *) malloc(var_val_len + 1);
+ if (StorageTmp->traceRouteCtlDescr == NULL) {
+ exit(1);
+ }
+ memcpy(StorageTmp->traceRouteCtlDescr, var_val, var_val_len + 1);
+ StorageTmp->traceRouteCtlDescr[var_val_len] = '\0';
+ StorageTmp->traceRouteCtlDescrLen = var_val_len;
+
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->traceRouteCtlDescr);
+ StorageTmp->traceRouteCtlDescr = tmpvar;
+ StorageTmp->traceRouteCtlDescrLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+
+
+
+int
+write_traceRouteCtlMaxRows(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_UNSIGNED) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlDSField not ASN_UNSIGNED\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlMaxRows;
+ StorageTmp->traceRouteCtlMaxRows = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlMaxRows = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+int
+write_traceRouteCtlTrapGeneration(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static char *tmpvar;
+ static size_t tmplen;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OCTET_STR) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlTargetAddress not ASN_OCTET_STR\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlTrapGeneration;
+ tmplen = StorageTmp->traceRouteCtlTrapGenerationLen;
+ StorageTmp->traceRouteCtlTrapGeneration =
+ (char *) malloc(var_val_len + 1);
+ if (StorageTmp->traceRouteCtlTrapGeneration == NULL) {
+ exit(1);
+ }
+
+ memcpy(StorageTmp->traceRouteCtlTrapGeneration, var_val,
+ var_val_len + 1);
+ StorageTmp->traceRouteCtlTrapGeneration[var_val_len] = '\0';
+ StorageTmp->traceRouteCtlTrapGenerationLen = var_val_len;
+
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->traceRouteCtlTrapGeneration);
+ StorageTmp->traceRouteCtlTrapGeneration = tmpvar;
+ StorageTmp->traceRouteCtlTrapGenerationLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+int
+write_traceRouteCtlCreateHopsEntries(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name,
+ size_t name_len)
+{
+ static size_t tmpvar;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_INTEGER) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlDSField not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in objid for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlCreateHopsEntries;
+ StorageTmp->traceRouteCtlCreateHopsEntries = *((long *) var_val);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ StorageTmp->traceRouteCtlCreateHopsEntries = tmpvar;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+int
+write_traceRouteCtlType(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ static oid *tmpvar;
+ static size_t tmplen;
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+
+ if ((StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL,
+ NULL)) == NULL)
+ return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
+
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ switch (action) {
+ case RESERVE1:
+ if (var_val_type != ASN_OBJECT_ID) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlType not ASN_OBJECT_ID\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ break;
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ break;
+
+
+ case FREE:
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+
+ case ACTION:
+ /*
+ * The variable has been stored in long_ret for
+ * you to use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in the UNDO case
+ */
+ tmpvar = StorageTmp->traceRouteCtlType;
+ tmplen = StorageTmp->traceRouteCtlTypeLen;
+
+ StorageTmp->traceRouteCtlType = (oid *) malloc(var_val_len);
+ if (StorageTmp->traceRouteCtlType == NULL) {
+ exit(1);
+ }
+ memcpy(StorageTmp->traceRouteCtlType, var_val, var_val_len);
+ StorageTmp->traceRouteCtlTypeLen = var_val_len / sizeof(oid);
+ break;
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ SNMP_FREE(StorageTmp->traceRouteCtlType);
+ StorageTmp->traceRouteCtlType = tmpvar;
+ StorageTmp->traceRouteCtlTypeLen = tmplen;
+ break;
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ SNMP_FREE(tmpvar);
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+int
+write_traceRouteCtlRowStatus(int action,
+ u_char * var_val,
+ u_char var_val_type,
+ size_t var_val_len,
+ u_char * statP, oid * name, size_t name_len)
+{
+ struct traceRouteCtlTable_data *StorageTmp = NULL;
+ static struct traceRouteCtlTable_data *StorageNew = NULL;
+ static struct traceRouteCtlTable_data *StorageDel = NULL;
+ size_t newlen =
+ name_len -
+ (sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) + 3 - 1);
+ static int old_value;
+ int set_value;
+ static netsnmp_variable_list *vars = NULL;
+ struct header_complex_index *hciptr = NULL;
+
+ StorageTmp =
+ header_complex(traceRouteCtlTableStorage, NULL,
+ &name[sizeof(traceRouteCtlTable_variables_oid) /
+ sizeof(oid) + 3 - 1], &newlen, 1, NULL, NULL);
+
+ if (var_val_type != ASN_INTEGER || var_val == NULL) {
+ snmp_log(LOG_ERR,
+ "write to traceRouteCtlRowStatus not ASN_INTEGER\n");
+ return SNMP_ERR_WRONGTYPE;
+ }
+ if (StorageTmp && StorageTmp->storageType == ST_READONLY) {
+ return SNMP_ERR_NOTWRITABLE;
+ }
+
+ set_value = *((long *) var_val);
+
+
+ /*
+ * check legal range, and notReady is reserved for us, not a user
+ */
+ if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY)
+ return SNMP_ERR_INCONSISTENTVALUE;
+
+
+ switch (action) {
+ case RESERVE1:
+ /*
+ * stage one: test validity
+ */
+ if (StorageTmp == NULL) {
+ /*
+ * create the row now?
+ */
+
+ /*
+ * ditch illegal values now
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
+
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+
+ /*
+ * destroying a non-existent row is actually legal
+ */
+ if (set_value == RS_DESTROY) {
+
+ return SNMP_ERR_NOERROR;
+ }
+
+
+ /*
+ * illegal creation values
+ */
+ if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ } else {
+ /*
+ * row exists. Check for a valid state change
+ */
+ if (set_value == RS_CREATEANDGO
+ || set_value == RS_CREATEANDWAIT) {
+ /*
+ * can't create a row that exists
+ */
+
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+
+ /*
+ * XXX: interaction with row storage type needed
+ */
+
+ if (StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE &&
+ set_value != RS_DESTROY) {
+ /*
+ * "Once made active an entry may not be modified except to
+ * delete it." XXX: doesn't this in fact apply to ALL
+ * columns of the table and not just this one?
+ */
+
+ return SNMP_ERR_INCONSISTENTVALUE;
+ }
+ if (StorageTmp->storageType != ST_NONVOLATILE) {
+
+ return SNMP_ERR_NOTWRITABLE;
+ }
+ }
+
+ break;
+
+
+
+
+ case RESERVE2:
+ /*
+ * memory reseveration, final preparation...
+ */
+ if (StorageTmp == NULL) {
+
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+ /*
+ * creation
+ */
+
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0); /* traceRouteCtlTestName */
+
+ if (header_complex_parse_oid
+ (&
+ (name
+ [sizeof(traceRouteCtlTable_variables_oid) / sizeof(oid) +
+ 2]), newlen, vars) != SNMPERR_SUCCESS) {
+ /*
+ * XXX: free, zero vars
+ */
+ return SNMP_ERR_INCONSISTENTNAME;
+ }
+
+
+ StorageNew = create_traceRouteCtlTable_data();
+ if (vars->val_len <= 32) {
+ StorageNew->traceRouteCtlOwnerIndex =
+ malloc(vars->val_len + 1);
+ memcpy(StorageNew->traceRouteCtlOwnerIndex,
+ vars->val.string, vars->val_len);
+ StorageNew->traceRouteCtlOwnerIndex[vars->val_len] = '\0';
+ StorageNew->traceRouteCtlOwnerIndexLen = vars->val_len;
+ } else {
+ StorageNew->traceRouteCtlOwnerIndex = malloc(33);
+ memcpy(StorageNew->traceRouteCtlOwnerIndex,
+ vars->val.string, 32);
+ StorageNew->traceRouteCtlOwnerIndex[32] = '\0';
+ StorageNew->traceRouteCtlOwnerIndexLen = 32;
+ }
+
+ vars = vars->next_variable;
+
+ if (vars->val_len <= 32) {
+ StorageNew->traceRouteCtlTestName =
+ malloc(vars->val_len + 1);
+ memcpy(StorageNew->traceRouteCtlTestName, vars->val.string,
+ vars->val_len);
+ StorageNew->traceRouteCtlTestName[vars->val_len] = '\0';
+ StorageNew->traceRouteCtlTestNameLen = vars->val_len;
+ } else {
+ StorageNew->traceRouteCtlTestName = malloc(33);
+ memcpy(StorageNew->traceRouteCtlTestName, vars->val.string,
+ 32);
+ StorageNew->traceRouteCtlTestName[32] = '\0';
+ StorageNew->traceRouteCtlTestNameLen = 32;
+ }
+ vars = vars->next_variable;
+
+ /*
+ * XXX: fill in default row values here into StorageNew
+ */
+
+ StorageNew->traceRouteCtlRowStatus = set_value;
+
+
+ /*
+ * XXX: free, zero vars, no longer needed?
+ */
+ }
+ snmp_free_varbind(vars);
+ vars = NULL;
+ break;
+
+ case FREE:
+ /*
+ * XXX: free, zero vars
+ */
+ snmp_free_varbind(vars);
+ vars = NULL;
+ /*
+ * Release any resources that have been allocated
+ */
+ break;
+
+ case ACTION:
+ /*
+ * The variable has been stored in set_value for you to
+ * use, and you have just been asked to do something with
+ * it. Note that anything done here must be reversable in
+ * the UNDO case
+ */
+
+ if (StorageTmp == NULL) {
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+ /*
+ * row creation, so add it
+ */
+ if (StorageNew != NULL) {
+#if 1
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "write_traceRouteCtlRowStatus entering new=%d... \n",
+ action));
+#endif
+ traceRouteCtlTable_add(StorageNew);
+ }
+
+ /*
+ * XXX: ack, and if it is NULL?
+ */
+ } else if (set_value != RS_DESTROY) {
+ /*
+ * set the flag?
+ */
+ old_value = StorageTmp->traceRouteCtlRowStatus;
+ StorageTmp->traceRouteCtlRowStatus = *((long *) var_val);
+ } else {
+ /*
+ * destroy... extract it for now
+ */
+
+ hciptr =
+ header_complex_find_entry(traceRouteCtlTableStorage,
+ StorageTmp);
+ StorageDel =
+ header_complex_extract_entry(&traceRouteCtlTableStorage,
+ hciptr);
+ snmp_alarm_unregister(StorageDel->timer_id);
+
+ traceRouteResultsTable_del(StorageTmp);
+ traceRouteProbeHistoryTable_del(StorageTmp);
+ traceRouteHopsTable_del(StorageTmp);
+ }
+ break;
+
+
+
+
+ case UNDO:
+ /*
+ * Back out any changes made in the ACTION case
+ */
+ if (StorageTmp == NULL) {
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+ /*
+ * row creation, so remove it again
+ */
+ hciptr =
+ header_complex_find_entry(traceRouteCtlTableStorage,
+ StorageTmp);
+ StorageDel =
+ header_complex_extract_entry(&traceRouteCtlTableStorage,
+ hciptr);
+ /*
+ * XXX: free it
+ */
+ } else if (StorageDel != NULL) {
+ /*
+ * row deletion, so add it again
+ */
+ traceRouteCtlTable_add(StorageDel);
+ traceRouteResultsTable_add(StorageDel);
+ traceRouteProbeHistoryTable_addall(StorageDel);
+ traceRouteHopsTable_addall(StorageDel);
+ } else {
+ StorageTmp->traceRouteCtlRowStatus = old_value;
+ }
+ break;
+
+
+
+
+ case COMMIT:
+ /*
+ * Things are working well, so it's now safe to make the change
+ * permanently. Make sure that anything done here can't fail!
+ */
+ if (StorageTmp == NULL) {
+ if (set_value == RS_DESTROY) {
+ return SNMP_ERR_NOERROR;
+ }
+ }
+ if (StorageDel != NULL) {
+ free(StorageDel->traceRouteCtlOwnerIndex);
+ StorageDel->traceRouteCtlOwnerIndex = NULL;
+ free(StorageDel->traceRouteCtlTestName);
+ StorageDel->traceRouteCtlTestName = NULL;
+ free(StorageDel->traceRouteCtlTargetAddress);
+ StorageDel->traceRouteCtlTargetAddress = NULL;
+ free(StorageDel->traceRouteCtlSourceAddress);
+ StorageDel->traceRouteCtlSourceAddress = NULL;
+ free(StorageDel->traceRouteCtlMiscOptions);
+ StorageDel->traceRouteCtlMiscOptions = NULL;
+ free(StorageDel->traceRouteCtlDescr);
+ StorageDel->traceRouteCtlDescr = NULL;
+ free(StorageDel->traceRouteCtlTrapGeneration);
+ StorageDel->traceRouteCtlTrapGeneration = NULL;
+ free(StorageDel->traceRouteCtlType);
+ StorageDel->traceRouteCtlType = NULL;
+ free(StorageDel);
+ StorageDel = NULL;
+
+ /*
+ * XXX: free it, its dead
+ */
+ } else {
+ if (StorageTmp
+ && StorageTmp->traceRouteCtlRowStatus == RS_CREATEANDGO) {
+ StorageTmp->traceRouteCtlRowStatus = RS_ACTIVE;
+ } else if (StorageTmp &&
+ StorageTmp->traceRouteCtlRowStatus ==
+ RS_CREATEANDWAIT) {
+
+ StorageTmp->traceRouteCtlRowStatus = RS_NOTINSERVICE;
+ }
+ }
+ if (StorageTmp && StorageTmp->traceRouteCtlRowStatus == RS_ACTIVE) {
+#if 1
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "write_traceRouteCtlRowStatus entering runbefore=%ld... \n",
+ StorageTmp->traceRouteCtlTargetAddressType));
+
+#endif
+ if (StorageTmp->traceRouteCtlAdminStatus == 1) {
+ init_trResultsTable(StorageTmp);
+ if (StorageTmp->traceRouteCtlFrequency != 0)
+ StorageTmp->timer_id =
+ snmp_alarm_register(StorageTmp->
+ traceRouteCtlFrequency,
+ SA_REPEAT, run_traceRoute,
+ StorageTmp);
+ else
+ StorageTmp->timer_id =
+ snmp_alarm_register(1, 0, run_traceRoute, StorageTmp);
+
+ }
+
+ }
+ snmp_store_needed(NULL);
+ break;
+ }
+ return SNMP_ERR_NOERROR;
+}
+
+
+void
+run_traceRoute(unsigned int clientreg, void *clientarg)
+{
+ struct traceRouteCtlTable_data *item = clientarg;
+ u_short port = item->traceRouteCtlPort; /* start udp dest port # for probe packets Ï൱ÓÚctlport */
+ int waittime = item->traceRouteCtlTimeOut; /* time to wait for response (in seconds) ÏàµÈÓÚctltimeout */
+ int nprobes = item->traceRouteCtlProbesPerHop;
+
+ if (item->traceRouteCtlInitialTtl > item->traceRouteCtlMaxTtl) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "first ttl (%lu) may not be greater than max ttl (%lu)\n",
+ item->traceRouteCtlInitialTtl,
+ item->traceRouteCtlMaxTtl));
+ return;
+ }
+
+ char *old_HopsAddress[255];
+ int count = 0;
+ int flag = 0;
+
+ if (item->traceRouteCtlTargetAddressType == 1
+ || item->traceRouteCtlTargetAddressType == 16) {
+ register int code, n;
+ const char *cp;
+ register const char *err;
+ register u_char *outp;
+ register u_int32_t *ap;
+ struct sockaddr whereto; /* Who to try to reach */
+ struct sockaddr wherefrom; /* Who we are */
+
+ register struct sockaddr_in *from =
+ (struct sockaddr_in *) &wherefrom;
+ register struct sockaddr_in *to = (struct sockaddr_in *) &whereto;
+ register struct hostinfo *hi;
+ int on = 1;
+ register struct protoent *pe;
+ register int ttl, probe, i;
+ register int seq = 0;
+ int tos = 0, settos = 0;
+ register int lsrr = 0;
+ register u_short off = 0;
+ struct ifaddrlist *al;
+ char errbuf[132];
+ int minpacket = 0; /* min ip packet size */
+
+
+ struct ip *outip; /* last output (udp) packet */
+ struct udphdr *outudp; /* last output (udp) packet */
+ int packlen = 0; /* total length of packet */
+ int optlen = 0; /* length of ip options */
+ int options = 0; /* socket options */
+ int s; /* receive (icmp) socket file descriptor */
+ int sndsock; /* send (udp/icmp) socket file descriptor */
+
+ u_short ident;
+ /*
+ * loose source route gateway list (including room for final destination)
+ */
+ u_int32_t gwlist[NGATEWAYS + 1];
+ static const char devnull[] = "/dev/null";
+ char *device = NULL;
+ char *source = NULL;
+ char *hostname;
+ u_int pausemsecs = 0;
+ u_char packet[512]; /* last inbound (icmp) packet */
+
+ int pmtu = 0; /* Path MTU Discovery (RFC1191) */
+
+ struct outdata *outdata; /* last output (udp) packet */
+
+ minpacket = sizeof(*outip) + sizeof(*outdata) + optlen;
+ minpacket += sizeof(*outudp);
+ packlen = minpacket; /* minimum sized packet */
+
+ hostname =
+ (char *) malloc(item->traceRouteCtlTargetAddressLen + 1);
+ if (hostname == NULL)
+ return;
+ memcpy(hostname, item->traceRouteCtlTargetAddress,
+ item->traceRouteCtlTargetAddressLen + 1);
+ hostname[item->traceRouteCtlTargetAddressLen] = '\0';
+
+ hi = gethostinfo(hostname);
+ setsin(to, hi->addrs[0]);
+ if (hi->n > 1)
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "Warning: %s has multiple addresses; using %s\n",
+ hostname, inet_ntoa(to->sin_addr)));
+ hostname = hi->name;
+ hi->name = NULL;
+ freehostinfo(hi);
+
+
+ netsnmp_set_line_buffering(stdout);
+
+ outip = (struct ip *) malloc(packlen);
+ if (outip == NULL) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "malloc: %s\n", strerror(errno)));
+ exit(1);
+ }
+ memset((char *) outip, 0, packlen);
+
+ outip->ip_v = IPVERSION;
+ if (settos)
+ outip->ip_tos = tos;
+#ifdef BYTESWAP_IP_HDR
+ outip->ip_len = htons(packlen);
+ outip->ip_off = htons(off);
+#else
+ outip->ip_len = packlen;
+ outip->ip_off = off;
+#endif
+ outp = (u_char *) (outip + 1);
+#ifdef HAVE_RAW_OPTIONS
+ if (lsrr > 0) {
+ register u_char *optlist;
+
+ optlist = outp;
+ outp += optlen;
+
+ /*
+ * final hop
+ */
+ gwlist[lsrr] = to->sin_addr.s_addr;
+
+ outip->ip_dst.s_addr = gwlist[0];
+
+ /*
+ * force 4 byte alignment
+ */
+ optlist[0] = IPOPT_NOP;
+ /*
+ * loose source route option
+ */
+ optlist[1] = IPOPT_LSRR;
+ i = lsrr * sizeof(gwlist[0]);
+ optlist[2] = i + 3;
+ /*
+ * Pointer to LSRR addresses
+ */
+ optlist[3] = IPOPT_MINOFF;
+ memcpy(optlist + 4, gwlist + 1, i);
+ } else
+#endif
+ outip->ip_dst = to->sin_addr;
+ outip->ip_hl = (outp - (u_char *) outip) >> 2;
+ ident = (getpid() & 0xffff) | 0x8000;
+
+ outip->ip_p = IPPROTO_UDP;
+
+ outudp = (struct udphdr *) outp;
+ outudp->source = htons(ident);
+ outudp->len =
+ htons((u_short) (packlen - (sizeof(*outip) + optlen)));
+ outdata = (struct outdata *) (outudp + 1);
+
+ cp = "icmp";
+ if ((pe = getprotobyname(cp)) == NULL) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "unknown protocol %s\n", cp));
+ exit(1);
+ }
+
+ /*
+ * Insure the socket fds won't be 0, 1 or 2
+ */
+ if (open(devnull, O_RDONLY) < 0 ||
+ open(devnull, O_RDONLY) < 0 || open(devnull, O_RDONLY) < 0) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "open \"%s\": %s\n", devnull, strerror(errno)));
+ exit(1);
+ }
+ if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "icmp socket: %s\n", strerror(errno)));
+ exit(1);
+ }
+ if (options & SO_DEBUG)
+ (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *) &on,
+ sizeof(on));
+ if (options & SO_DONTROUTE)
+ (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *) &on,
+ sizeof(on));
+#ifndef __hpux
+ printf("raw\n");
+ sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+#else
+ printf("udp\n");
+ sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
+#endif
+ if (sndsock < 0) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "raw socket: %s\n", strerror(errno)));
+ exit(1);
+ }
+#if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
+ if (lsrr > 0) {
+ u_char optlist[MAX_IPOPTLEN];
+
+ cp = "ip";
+ if ((pe = getprotobyname(cp)) == NULL) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "unknown protocol %s\n", cp));
+ exit(1);
+ }
+ /*
+ * final hop
+ */
+ gwlist[lsrr] = to->sin_addr.s_addr;
+ ++lsrr;
+
+ /*
+ * force 4 byte alignment
+ */
+ optlist[0] = IPOPT_NOP;
+ /*
+ * loose source route option
+ */
+ optlist[1] = IPOPT_LSRR;
+ i = lsrr * sizeof(gwlist[0]);
+ optlist[2] = i + 3;
+ /*
+ * Pointer to LSRR addresses
+ */
+ optlist[3] = IPOPT_MINOFF;
+ memcpy(optlist + 4, gwlist, i);
+
+ if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS,
+ (char *) optlist,
+ i + sizeof(gwlist[0]))) < 0) {
+ DEBUGMSGTL(("traceRouteCtlTable", "IP_OPTIONS: %s\n",
+ strerror(errno)));
+ exit(1);
+ }
+ }
+#endif
+#ifdef SO_SNDBUF
+ if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *) &packlen,
+ sizeof(packlen)) < 0) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "SO_SNDBUF: %s\n", strerror(errno)));
+ exit(1);
+ }
+#endif
+#ifdef IP_HDRINCL
+ if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *) &on,
+ sizeof(on)) < 0) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "IP_HDRINCL: %s\n", strerror(errno)));
+ exit(1);
+ }
+#else
+#ifdef IP_TOS
+ if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
+ (char *) &tos, sizeof(tos)) < 0) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ "setsockopt tos %d: %s\n", strerror(errno)));
+ exit(1);
+ }
+#endif
+#endif
+ if (options & SO_DEBUG)
+ (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *) &on,
+ sizeof(on));
+ if (options & SO_DONTROUTE)
+ (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
+ (char *) &on, sizeof(on));
+ /*
+ * Get the interface address list
+ */
+ n = ifaddrlist(&al, errbuf);
+ if (n < 0) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ " ifaddrlist: %s\n", errbuf));
+ exit(1);
+ }
+ if (n == 0) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ " Can't find any network interfaces\n"));
+
+ exit(1);
+ }
+
+ /*
+ * Look for a specific device
+ */
+ if (device != NULL) {
+ for (i = n; i > 0; --i, ++al)
+ if (strcmp(device, al->device) == 0)
+ break;
+ if (i <= 0) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ " Can't find interface %.32s\n", device));
+
+ exit(1);
+ }
+ }
+ /*
+ * Determine our source address
+ */
+ if (source == NULL) {
+ /*
+ * If a device was specified, use the interface address.
+ * Otherwise, try to determine our source address.
+ */
+ if (device != NULL)
+ setsin(from, al->addr);
+ else if ((err = findsaddr(to, from)) != NULL) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ " findsaddr: %s\n", err));
+ exit(1);
+ }
+
+ } else {
+ hi = gethostinfo(source);
+ source = hi->name;
+ hi->name = NULL;
+ /*
+ * If the device was specified make sure it
+ * corresponds to the source address specified.
+ * Otherwise, use the first address (and warn if
+ * there are more than one).
+ */
+ if (device != NULL) {
+ for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
+ if (*ap == al->addr)
+ break;
+ if (i <= 0) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ " %s is not on interface %.32s\n",
+ source, device));
+
+ exit(1);
+ }
+ setsin(from, *ap);
+ } else {
+ setsin(from, hi->addrs[0]);
+ if (hi->n > 1)
+ DEBUGMSGTL(("traceRouteCtlTable",
+ " Warning: %s has multiple addresses; using %s\n",
+ source, inet_ntoa(from->sin_addr)));
+
+ }
+ freehostinfo(hi);
+ }
+ /*
+ * Revert to non-privileged user after opening sockets
+ */
+ setgid(getgid());
+ setuid(getuid());
+
+ outip->ip_src = from->sin_addr;
+#ifndef IP_HDRINCL
+ if (bind(sndsock, (struct sockaddr *) from, sizeof(*from)) < 0) {
+ DEBUGMSGTL(("traceRouteCtlTable",
+ " bind: %s\n", strerror(errno)));
+ exit(1);
+ }
+#endif
+ DEBUGMSGTL(("traceRouteCtlTable",
+ " to %s (%s)", hostname, inet_ntoa(to->sin_addr)));
+
+ if (source)
+ DEBUGMSGTL(("traceRouteCtlTable", " from %s", source));
+
+ DEBUGMSGTL(("traceRouteCtlTable",
+ ", %lu hops max, %d byte packets\n",
+ item->traceRouteCtlMaxTtl, packlen));
+ (void) fflush(stderr);
+
+ struct traceRouteResultsTable_data *StorageResults = NULL;
+ netsnmp_variable_list *vars_results = NULL;
+
+ struct traceRouteHopsTable_data *temp = NULL;
+ struct traceRouteHopsTable_data *current_temp = NULL;
+ struct traceRouteHopsTable_data *current = NULL;
+
+ unsigned long index = 0;
+
+ struct traceRouteProbeHistoryTable_data *temp_his = NULL;
+ struct traceRouteProbeHistoryTable_data *current_temp_his = NULL;
+
+ snmp_varlist_add_variable(&vars_results, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlOwnerIndex, item->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_results, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlTestName, item->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ if ((StorageResults =
+ header_complex_get(traceRouteResultsTableStorage,
+ vars_results)) == NULL)
+ return;
+ snmp_free_varbind(vars_results);
+ vars_results = NULL;
+
+
+ for (ttl = item->traceRouteCtlInitialTtl;
+ ttl <= item->traceRouteCtlMaxTtl; ++ttl) {
+
+ u_int32_t lastaddr = 0;
+ int gotlastaddr = 0;
+ int got_there = 0;
+ int unreachable = 0;
+ int sentfirst = 0;
+ time_t timep = 0;
+
+ StorageResults->traceRouteResultsCurHopCount = ttl;
+ if (item->traceRouteCtlCreateHopsEntries == 1) {
+ if (ttl == item->traceRouteCtlInitialTtl) {
+ int k = 0;
+ count = traceRouteHopsTable_count(item);
+
+
+ struct traceRouteHopsTable_data *StorageTmp = NULL;
+ struct header_complex_index *hciptr2 = NULL;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlOwnerIndex, item->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlTestName, item->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+
+ header_complex_generate_oid(newoid, &newoid_len, NULL,
+ 0, vars);
+
+ for (hciptr2 = traceRouteHopsTableStorage;
+ hciptr2 != NULL; hciptr2 = hciptr2->next) {
+ if (snmp_oid_compare
+ (newoid, newoid_len, hciptr2->name,
+ newoid_len) == 0) {
+ StorageTmp =
+ header_complex_extract_entry
+ (&traceRouteHopsTableStorage, hciptr2);
+
+ old_HopsAddress[k] =
+ (char *) malloc(StorageTmp->
+ traceRouteHopsIpTgtAddressLen
+ + 1);
+ if (old_HopsAddress[k] == NULL) {
+ exit(1);
+ }
+ memdup((u_char **) & old_HopsAddress[k],
+ StorageTmp->traceRouteHopsIpTgtAddress,
+ StorageTmp->
+ traceRouteHopsIpTgtAddressLen + 1);
+ old_HopsAddress[k][StorageTmp->
+ traceRouteHopsIpTgtAddressLen]
+ = '\0';
+
+ k++;
+ StorageTmp = NULL;
+ }
+ }
+ traceRouteHopsTable_del(item);
+ index = 0;
+ }
+
+ temp = SNMP_MALLOC_STRUCT(traceRouteHopsTable_data);
+ temp->traceRouteCtlOwnerIndex =
+ (char *) malloc(item->traceRouteCtlOwnerIndexLen + 1);
+ memcpy(temp->traceRouteCtlOwnerIndex,
+ item->traceRouteCtlOwnerIndex,
+ item->traceRouteCtlOwnerIndexLen + 1);
+ temp->traceRouteCtlOwnerIndex[item->
+ traceRouteCtlOwnerIndexLen] =
+ '\0';
+ temp->traceRouteCtlOwnerIndexLen =
+ item->traceRouteCtlOwnerIndexLen;
+
+ temp->traceRouteCtlTestName =
+ (char *) malloc(item->traceRouteCtlTestNameLen + 1);
+ memcpy(temp->traceRouteCtlTestName,
+ item->traceRouteCtlTestName,
+ item->traceRouteCtlTestNameLen + 1);
+ temp->traceRouteCtlTestName[item->
+ traceRouteCtlTestNameLen] =
+ '\0';
+ temp->traceRouteCtlTestNameLen =
+ item->traceRouteCtlTestNameLen;
+
+ /* add lock to protect */
+ pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&counter_mutex);
+ temp->traceRouteHopsHopIndex = ++index;
+ pthread_mutex_unlock(&counter_mutex);
+ /* endsadsadsad */
+
+
+ temp->traceRouteHopsIpTgtAddressType = 0;
+ temp->traceRouteHopsIpTgtAddress = strdup("");
+ temp->traceRouteHopsIpTgtAddressLen = 0;
+ temp->traceRouteHopsMinRtt = 0;
+ temp->traceRouteHopsMaxRtt = 0;
+ temp->traceRouteHopsAverageRtt = 0;
+ temp->traceRouteHopsRttSumOfSquares = 0;
+ temp->traceRouteHopsSentProbes = 0;
+ temp->traceRouteHopsProbeResponses = 0;
+
+ temp->traceRouteHopsLastGoodProbeLen = 0;
+ if (index == 1)
+ item->traceRouteHops = temp;
+ else {
+ (current_temp)->next = temp;
+ }
+
+ current_temp = temp;
+
+ if (index + 1 >= item->traceRouteCtlMaxTtl) {
+ current_temp->next = NULL;
+ }
+
+ if (item->traceRouteHops != NULL)
+
+ if (traceRouteHopsTable_add(current_temp) !=
+ SNMPERR_SUCCESS)
+ DEBUGMSGTL(("traceRouteHopsTable",
+ "registered an entry error\n"));
+
+ }
+ register unsigned long maxRtt = 0;
+ register unsigned long minRtt = 0;
+ register unsigned long averageRtt = 0;
+ register unsigned long sumRtt = 0;
+ register unsigned long responseProbe = 0;
+ register unsigned long sumOfSquare = 0;
+ for (probe = 0; probe < nprobes; ++probe) {
+ register int cc;
+ struct timeval t1, t2;
+ struct timezone tz;
+ register struct ip *ip = NULL;
+ register unsigned long Rtt = 0;
+
+ if (sentfirst && pausemsecs > 0)
+ usleep(pausemsecs * 1000);
+ (void) gettimeofday(&t1, &tz);
+ send_probe(to, ++seq, ttl, &t1, outip, outudp, packlen,
+ optlen, hostname, ident, sndsock, port,
+ outdata);
+ ++sentfirst;
+ while ((cc =
+ wait_for_reply(s, from, &t1, packet,
+ waittime)) != 0) {
+ (void) gettimeofday(&t2, &tz);
+ timep = 0;
+ time(&timep);
+ i = packet_ok(packet, cc, from, seq, ident, pmtu,
+ port);
+ /*
+ * Skip short packet
+ */
+ if (i == 0)
+ continue;
+ if (!gotlastaddr || from->sin_addr.s_addr != lastaddr) {
+ register struct ip *ip;
+ register int hlen;
+ ip = (struct ip *) packet;
+ hlen = ip->ip_hl << 2;
+ cc -= hlen;
+ DEBUGMSGTL(("traceRouteCtlTable",
+ " %s", inet_ntoa(from->sin_addr)));
+
+
+ lastaddr = from->sin_addr.s_addr;
+ ++gotlastaddr;
+ }
+ Rtt = deltaT(&t1, &t2);
+ responseProbe = responseProbe + 1;
+ if (probe == 0) {
+ minRtt = Rtt;
+ maxRtt = Rtt;
+ averageRtt = Rtt;
+ sumRtt = Rtt;
+ sumOfSquare = Rtt * Rtt;
+ } else {
+ if (Rtt < minRtt)
+ minRtt = Rtt;
+ if (Rtt > maxRtt)
+ maxRtt = Rtt;
+ sumRtt = (sumRtt) + Rtt;
+ averageRtt =
+ round((double) (sumRtt) /
+ (double) responseProbe);
+ sumOfSquare = sumOfSquare + Rtt * Rtt;
+ }
+
+ StorageResults->traceRouteResultsCurProbeCount =
+ probe + 1;
+ if (i == -2) {
+#ifndef ARCHAIC
+ ip = (struct ip *) packet;
+ if (ip->ip_ttl <= 1)
+ Printf(" !");
+#endif
+ ++got_there;
+ break;
+ }
+ /*
+ * time exceeded in transit
+ */
+ if (i == -1)
+ break;
+ code = i - 1;
+ switch (code) {
+
+ case ICMP_UNREACH_PORT:
+#ifndef ARCHAIC
+ ip = (struct ip *) packet;
+ if (ip->ip_ttl <= 1)
+ Printf(" !");
+#endif
+ ++got_there;
+ break;
+
+ case ICMP_UNREACH_NET:
+ ++unreachable;
+ Printf(" !N");
+ break;
+
+ case ICMP_UNREACH_HOST:
+ ++unreachable;
+ Printf(" !H");
+ break;
+
+ case ICMP_UNREACH_PROTOCOL:
+ ++got_there;
+ Printf(" !P");
+ break;
+
+ case ICMP_UNREACH_NEEDFRAG:
+ ++unreachable;
+ Printf(" !F-%d", pmtu);
+ break;
+
+ case ICMP_UNREACH_SRCFAIL:
+ ++unreachable;
+ Printf(" !S");
+ break;
+
+ case ICMP_UNREACH_FILTER_PROHIB:
+ ++unreachable;
+ Printf(" !X");
+ break;
+
+ case ICMP_UNREACH_HOST_PRECEDENCE:
+ ++unreachable;
+ Printf(" !V");
+ break;
+
+ case ICMP_UNREACH_PRECEDENCE_CUTOFF:
+ ++unreachable;
+ Printf(" !C");
+ break;
+
+ default:
+ ++unreachable;
+ Printf(" !<%d>", code);
+ break;
+ }
+ break;
+ }
+ if (cc == 0) {
+ timep = 0;
+ time(&timep);
+ Printf(" *");
+ Rtt = (item->traceRouteCtlTimeOut) * 1000;
+ }
+ if (item->traceRouteCtlMaxRows != 0) {
+
+ temp_his =
+ SNMP_MALLOC_STRUCT
+ (traceRouteProbeHistoryTable_data);
+ temp_his->traceRouteCtlOwnerIndex =
+ (char *) malloc(item->traceRouteCtlOwnerIndexLen +
+ 1);
+ memcpy(temp_his->traceRouteCtlOwnerIndex,
+ item->traceRouteCtlOwnerIndex,
+ item->traceRouteCtlOwnerIndexLen + 1);
+ temp_his->traceRouteCtlOwnerIndex[item->
+ traceRouteCtlOwnerIndexLen]
+ = '\0';
+ temp_his->traceRouteCtlOwnerIndexLen =
+ item->traceRouteCtlOwnerIndexLen;
+
+ temp_his->traceRouteCtlTestName =
+ (char *) malloc(item->traceRouteCtlTestNameLen +
+ 1);
+ memcpy(temp_his->traceRouteCtlTestName,
+ item->traceRouteCtlTestName,
+ item->traceRouteCtlTestNameLen + 1);
+ temp_his->traceRouteCtlTestName[item->
+ traceRouteCtlTestNameLen]
+ = '\0';
+ temp_his->traceRouteCtlTestNameLen =
+ item->traceRouteCtlTestNameLen;
+
+ /* add lock to protect */
+ pthread_mutex_t counter_mutex =
+ PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&counter_mutex);
+ if (item->traceRouteProbeHistoryMaxIndex >=
+ (unsigned long) (2147483647))
+ item->traceRouteProbeHistoryMaxIndex = 0;
+ temp_his->traceRouteProbeHistoryIndex =
+ ++(item->traceRouteProbeHistoryMaxIndex);
+ pthread_mutex_unlock(&counter_mutex);
+ /* endsadsadsad */
+ temp_his->traceRouteProbeHistoryHopIndex = ttl;
+ temp_his->traceRouteProbeHistoryProbeIndex = probe + 1;
+
+ temp_his->traceRouteProbeHistoryHAddrType = 1;
+ temp_his->traceRouteProbeHistoryHAddr =
+ (char *) malloc(strlen(inet_ntoa(from->sin_addr)) +
+ 1);
+ strcpy(temp_his->traceRouteProbeHistoryHAddr,
+ (inet_ntoa(from->sin_addr)));
+ temp_his->
+ traceRouteProbeHistoryHAddr[strlen
+ (inet_ntoa
+ (from->sin_addr))] =
+ '\0';
+ temp_his->traceRouteProbeHistoryHAddrLen =
+ strlen(inet_ntoa(from->sin_addr));
+
+ temp_his->traceRouteProbeHistoryResponse = Rtt;
+ temp_his->traceRouteProbeHistoryStatus = 1;
+ temp_his->traceRouteProbeHistoryLastRC = 0;
+
+ temp_his->traceRouteProbeHistoryTime_time = timep;
+ memdup(&temp_his->traceRouteProbeHistoryTime,
+ date_n_time(&timep,
+ &temp_his->traceRouteProbeHistoryTimeLen), 11);
+ if (probe == 0)
+ item->traceRouteProbeHis = temp_his;
+ else {
+ (current_temp_his)->next = temp_his;
+ }
+
+ current_temp_his = temp_his;
+
+ if (probe + 1 >= nprobes) {
+ current_temp_his->next = NULL;
+
+ }
+
+ if (item->traceRouteProbeHis != NULL) {
+ if (traceRouteProbeHistoryTable_count(item) <
+ item->traceRouteCtlMaxRows) {
+ if (traceRouteProbeHistoryTable_add
+ (current_temp_his) != SNMPERR_SUCCESS)
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "registered an entry error\n"));
+ } else {
+ traceRouteProbeHistoryTable_delLast(item);
+ if (traceRouteProbeHistoryTable_add
+ (current_temp_his) != SNMPERR_SUCCESS)
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "registered an entry error\n"));
+
+ }
+ }
+
+ }
+
+ if (item->traceRouteCtlCreateHopsEntries == 1) {
+ netsnmp_variable_list *vars_hops = NULL;
+ snmp_varlist_add_variable(&vars_hops, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlOwnerIndex, item->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_hops, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlTestName, item->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ snmp_varlist_add_variable(&vars_hops, NULL, 0, ASN_UNSIGNED, (char *) &index, sizeof(index)); /* traceRouteHopsIndex */
+ if ((current =
+ header_complex_get(traceRouteHopsTableStorage,
+ vars_hops)) == NULL)
+ return;
+ snmp_free_varbind(vars_hops);
+ vars_hops = NULL;
+
+ current->traceRouteHopsIpTgtAddressType = 1;
+ current->traceRouteHopsIpTgtAddress =
+ (char *) malloc(strlen(inet_ntoa(from->sin_addr)) +
+ 1);
+ current->traceRouteHopsIpTgtAddress =
+ strdup(inet_ntoa(from->sin_addr));
+ current->
+ traceRouteHopsIpTgtAddress[strlen
+ (inet_ntoa
+ (from->sin_addr))] =
+ '\0';
+ current->traceRouteHopsIpTgtAddressLen =
+ strlen(inet_ntoa(from->sin_addr));
+ if (count != 0) {
+ if (strcmp
+ (old_HopsAddress[index - 1],
+ current->traceRouteHopsIpTgtAddress) != 0)
+ flag = 1;
+ }
+
+ current->traceRouteHopsIpTgtAddressLen =
+ strlen(inet_ntoa(from->sin_addr));
+ current->traceRouteHopsMinRtt = minRtt;
+ current->traceRouteHopsMaxRtt = maxRtt;
+ current->traceRouteHopsAverageRtt = averageRtt;
+ current->traceRouteHopsRttSumOfSquares = sumOfSquare;
+ current->traceRouteHopsSentProbes = probe + 1;
+ current->traceRouteHopsProbeResponses = responseProbe;
+ current->traceRouteHopsLastGoodProbe_time = timep;
+ memdup(&current->traceRouteHopsLastGoodProbe,
+ date_n_time(&timep,
+ &current->traceRouteHopsLastGoodProbeLen), 11);
+ }
+
+ (void) fflush(stdout);
+ }
+ putchar('\n');
+
+
+ if (got_there
+ || (unreachable > 0 && unreachable >= nprobes - 1)) {
+
+ if (got_there != 0) {
+ StorageResults->traceRouteResultsTestAttempts =
+ StorageResults->traceRouteResultsTestAttempts + 1;
+
+ StorageResults->traceRouteResultsTestSuccesses =
+ StorageResults->traceRouteResultsTestSuccesses + 1;
+
+ StorageResults->traceRouteResultsLastGoodPath_time = timep;
+ memdup(&StorageResults->traceRouteResultsLastGoodPath,
+ date_n_time(&timep,
+ &StorageResults->traceRouteResultsLastGoodPathLen), 11);
+ if ((item->
+ traceRouteCtlTrapGeneration[0] &
+ TRACEROUTETRAPGENERATION_TESTCOMPLETED) != 0) {
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "TEST completed!\n"));
+ send_traceRoute_trap(item, traceRouteTestCompleted,
+ sizeof
+ (traceRouteTestCompleted) /
+ sizeof(oid));
+ }
+ }
+
+ else {
+ StorageResults->traceRouteResultsTestAttempts =
+ StorageResults->traceRouteResultsTestAttempts + 1;
+ if ((item->
+ traceRouteCtlTrapGeneration[0] &
+ TRACEROUTETRAPGENERATION_TESTFAILED) != 0) {
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "test Failed!\n"));
+ send_traceRoute_trap(item, traceRouteTestFailed,
+ sizeof(traceRouteTestFailed) /
+ sizeof(oid));
+ }
+ }
+ break;
+
+ } else if (ttl == item->traceRouteCtlMaxTtl
+ && (probe + 1) == nprobes) {
+ StorageResults->traceRouteResultsTestAttempts =
+ StorageResults->traceRouteResultsTestAttempts + 1;
+
+ if ((item->
+ traceRouteCtlTrapGeneration[0] &
+ TRACEROUTETRAPGENERATION_TESTFAILED) != 0) {
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "test Failed!\n"));
+ send_traceRoute_trap(item, traceRouteTestFailed,
+ sizeof(traceRouteTestFailed) /
+ sizeof(oid));
+ }
+ }
+
+ }
+
+ close(sndsock);
+
+ if (flag == 1) {
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "path changed!\n"));
+ send_traceRoute_trap(item, traceRoutePathChange,
+ sizeof(traceRoutePathChange) /
+ sizeof(oid));
+ }
+
+ int k = 0;
+ for (k = 0; k < count; k++) {
+ free(old_HopsAddress[k]);
+ old_HopsAddress[k] = NULL;
+ }
+ }
+ if (item->traceRouteCtlTargetAddressType == 2) {
+ int icmp_sock = 0; /* receive (icmp) socket file descriptor */
+ int sndsock = 0; /* send (udp) socket file descriptor */
+
+ struct sockaddr_in6 whereto; /* Who to try to reach */
+
+ struct sockaddr_in6 saddr;
+ struct sockaddr_in6 firsthop;
+ char *source = NULL;
+ char *device = NULL;
+ char *hostname = NULL;
+
+ pid_t ident = 0;
+ u_short port = 32768 + 666; /* start udp dest port # for probe packets */
+ int options = 0; /* socket options */
+ int waittime = 5; /* time to wait for response (in seconds) */
+
+ char *sendbuff = NULL;
+ int datalen = sizeof(struct pkt_format);
+
+ u_char packet[512]; /* last inbound (icmp) packet */
+
+ char pa[64];
+ struct hostent *hp = NULL;
+ struct sockaddr_in6 from, *to = NULL;
+ int i = 0, on = 0, probe = 0, seq = 0, tos =
+ 0, ttl = 0;
+ int socket_errno = 0;
+
+ icmp_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ socket_errno = errno;
+
+ setuid(getuid());
+
+ on = 1;
+ seq = tos = 0;
+ to = (struct sockaddr_in6 *) &whereto;
+
+ hostname =
+ (char *) malloc(item->traceRouteCtlTargetAddressLen + 1);
+ memcpy(hostname, item->traceRouteCtlTargetAddress,
+ item->traceRouteCtlTargetAddressLen + 1);
+ hostname[item->traceRouteCtlTargetAddressLen] = '\0';
+
+ setlinebuf(stdout);
+
+ memset(&whereto, '\0', sizeof(struct sockaddr_in6));
+
+ to->sin6_family = AF_INET6;
+ to->sin6_port = htons(port);
+
+ if (inet_pton(AF_INET6, hostname, &to->sin6_addr) <= 0) {
+ hp = gethostbyname2(hostname, AF_INET6);
+ if (hp != NULL) {
+ memmove((caddr_t) & to->sin6_addr, hp->h_addr, 16);
+ hostname = (char *) hp->h_name;
+ } else {
+ (void) fprintf(stderr,
+ "traceroute: unknown host %s\n", hostname);
+ return;
+ }
+ }
+ firsthop = *to;
+
+ datalen = item->traceRouteCtlDataSize;
+ if (datalen < (int) sizeof(struct pkt_format)
+ || datalen >= MAXPACKET) {
+ Fprintf(stderr,
+ "traceroute: packet size must be %d <= s < %d.\n",
+ (int) sizeof(struct pkt_format), MAXPACKET);
+ datalen = 16;
+ }
+
+ ident = getpid();
+
+ sendbuff = malloc(datalen);
+ if (sendbuff == NULL) {
+ fprintf(stderr, "malloc failed\n");
+ return;
+ }
+
+ if (icmp_sock < 0) {
+ errno = socket_errno;
+ perror("traceroute6: icmp socket");
+ return;
+ }
+
+ if (options & SO_DEBUG)
+ setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG,
+ (char *) &on, sizeof(on));
+ if (options & SO_DONTROUTE)
+ setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE,
+ (char *) &on, sizeof(on));
+
+ if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ perror("traceroute: UDP socket");
+ return;
+ }
+#ifdef SO_SNDBUF
+ if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *) &datalen,
+ sizeof(datalen)) < 0) {
+ perror("traceroute: SO_SNDBUF");
+ return;
+ }
+#endif /* SO_SNDBUF */
+
+ if (options & SO_DEBUG)
+ (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
+ (char *) &on, sizeof(on));
+ if (options & SO_DONTROUTE)
+ (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
+ (char *) &on, sizeof(on));
+
+ if (source == NULL) {
+ socklen_t alen;
+ int probe_fd = socket(AF_INET6, SOCK_DGRAM, 0);
+
+ if (probe_fd < 0) {
+ perror("socket");
+ return;
+ }
+ if (device) {
+ if (setsockopt
+ (probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device,
+ strlen(device) + 1) == -1)
+ perror("WARNING: interface is ignored");
+ }
+ firsthop.sin6_port = htons(1025);
+ if (connect
+ (probe_fd, (struct sockaddr *) &firsthop,
+ sizeof(firsthop)) == -1) {
+ perror("connect");
+ return;
+ }
+ alen = sizeof(saddr);
+ if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) ==
+ -1) {
+ perror("getsockname");
+ return;
+ }
+ saddr.sin6_port = 0;
+ close(probe_fd);
+ } else {
+ memset(&saddr, '\0', sizeof(struct sockaddr_in6));
+ saddr.sin6_family = AF_INET6;
+ if (inet_pton(AF_INET6, source, &saddr.sin6_addr) < 0) {
+ Printf("traceroute: unknown addr %s\n", source);
+ return;
+ }
+ }
+
+ if (bind(sndsock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
+ perror("traceroute: bind sending socket");
+ return;
+ }
+ if (bind(icmp_sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
+ perror("traceroute: bind icmp6 socket");
+ return;
+ }
+
+ Fprintf(stderr, "traceroute to %s (%s)", hostname,
+ inet_ntop(AF_INET6, &to->sin6_addr, pa, 64));
+
+ Fprintf(stderr, " from %s",
+ inet_ntop(AF_INET6, &saddr.sin6_addr, pa, 64));
+ Fprintf(stderr, ", %lu hops max, %d byte packets\n",
+ item->traceRouteCtlMaxTtl, datalen);
+ (void) fflush(stderr);
+
+
+ struct traceRouteResultsTable_data *StorageResults = NULL;
+ netsnmp_variable_list *vars_results = NULL;
+
+ struct traceRouteHopsTable_data *temp = NULL;
+ struct traceRouteHopsTable_data *current_temp = NULL;
+ struct traceRouteHopsTable_data *current = NULL;
+
+ unsigned long index = 0;
+
+ struct traceRouteProbeHistoryTable_data *temp_his = NULL;
+ struct traceRouteProbeHistoryTable_data *current_temp_his = NULL;
+
+ snmp_varlist_add_variable(&vars_results, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlOwnerIndex, item->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_results, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlTestName, item->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ if ((StorageResults =
+ header_complex_get(traceRouteResultsTableStorage,
+ vars_results)) == NULL)
+ return;
+ snmp_free_varbind(vars_results);
+ vars_results = NULL;
+
+ for (ttl = item->traceRouteCtlInitialTtl;
+ ttl <= item->traceRouteCtlMaxTtl; ++ttl) {
+ struct in6_addr lastaddr = { {{0,}} };
+ int got_there = 0;
+ int unreachable = 0;
+ time_t timep = 0;
+ Printf("%2d ", ttl);
+
+
+ StorageResults->traceRouteResultsCurHopCount = ttl;
+ if (item->traceRouteCtlCreateHopsEntries == 1) {
+ if (ttl == item->traceRouteCtlInitialTtl) {
+
+ int k = 0;
+ count = traceRouteHopsTable_count(item);
+ struct traceRouteHopsTable_data *StorageTmp = NULL;
+ struct header_complex_index *hciptr2 = NULL;
+ netsnmp_variable_list *vars = NULL;
+ oid newoid[MAX_OID_LEN];
+ size_t newoid_len;
+
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlOwnerIndex, item->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlTestName, item->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+
+ header_complex_generate_oid(newoid, &newoid_len, NULL,
+ 0, vars);
+
+ snmp_free_varbind(vars);
+ vars = NULL;
+
+ for (hciptr2 = traceRouteHopsTableStorage;
+ hciptr2 != NULL; hciptr2 = hciptr2->next) {
+ if (snmp_oid_compare
+ (newoid, newoid_len, hciptr2->name,
+ newoid_len) == 0) {
+ StorageTmp =
+ header_complex_extract_entry
+ (&traceRouteHopsTableStorage, hciptr2);
+
+ old_HopsAddress[k] =
+ (char *) malloc(StorageTmp->
+ traceRouteHopsIpTgtAddressLen
+ + 1);
+ if (old_HopsAddress[k] == NULL) {
+ exit(1);
+ }
+ memdup((u_char **) & old_HopsAddress[k],
+ StorageTmp->traceRouteHopsIpTgtAddress,
+ StorageTmp->
+ traceRouteHopsIpTgtAddressLen + 1);
+ old_HopsAddress[k][StorageTmp->
+ traceRouteHopsIpTgtAddressLen]
+ = '\0';
+
+ k++;
+ }
+ }
+ traceRouteHopsTable_del(item);
+ index = 0;
+ }
+
+ temp = SNMP_MALLOC_STRUCT(traceRouteHopsTable_data);
+ temp->traceRouteCtlOwnerIndex =
+ (char *) malloc(item->traceRouteCtlOwnerIndexLen + 1);
+ memcpy(temp->traceRouteCtlOwnerIndex,
+ item->traceRouteCtlOwnerIndex,
+ item->traceRouteCtlOwnerIndexLen + 1);
+ temp->traceRouteCtlOwnerIndex[item->
+ traceRouteCtlOwnerIndexLen] =
+ '\0';
+ temp->traceRouteCtlOwnerIndexLen =
+ item->traceRouteCtlOwnerIndexLen;
+
+ temp->traceRouteCtlTestName =
+ (char *) malloc(item->traceRouteCtlTestNameLen + 1);
+ memcpy(temp->traceRouteCtlTestName,
+ item->traceRouteCtlTestName,
+ item->traceRouteCtlTestNameLen + 1);
+ temp->traceRouteCtlTestName[item->
+ traceRouteCtlTestNameLen] =
+ '\0';
+ temp->traceRouteCtlTestNameLen =
+ item->traceRouteCtlTestNameLen;
+
+ /* add lock to protect */
+ pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&counter_mutex);
+ temp->traceRouteHopsHopIndex = ++index;
+ pthread_mutex_unlock(&counter_mutex);
+ /* endsadsadsad */
+
+
+ temp->traceRouteHopsIpTgtAddressType = 0;
+ temp->traceRouteHopsIpTgtAddress = strdup("");
+ temp->traceRouteHopsIpTgtAddressLen = 0;
+ temp->traceRouteHopsMinRtt = 0;
+ temp->traceRouteHopsMaxRtt = 0;
+ temp->traceRouteHopsAverageRtt = 0;
+ temp->traceRouteHopsRttSumOfSquares = 0;
+ temp->traceRouteHopsSentProbes = 0;
+ temp->traceRouteHopsProbeResponses = 0;
+
+ temp->traceRouteHopsLastGoodProbeLen = 0;
+ if (index == 1)
+ item->traceRouteHops = temp;
+ else {
+ (current_temp)->next = temp;
+ }
+
+ current_temp = temp;
+
+ if (index >= item->traceRouteCtlMaxTtl) {
+ current_temp->next = NULL;
+ }
+
+ if (item->traceRouteHops != NULL)
+
+ if (traceRouteHopsTable_add(current_temp) !=
+ SNMPERR_SUCCESS)
+ DEBUGMSGTL(("traceRouteHopsTable",
+ "registered an entry error\n"));
+
+ }
+
+ register unsigned long maxRtt = 0;
+ register unsigned long minRtt = 0;
+ register unsigned long averageRtt = 0;
+ register unsigned long sumRtt = 0;
+ register unsigned long responseProbe = 0;
+ register unsigned long sumOfSquare = 0;
+ for (probe = 0; probe < nprobes; ++probe) {
+ int cc = 0, reset_timer = 0;
+ struct timeval t1, t2;
+ struct timezone tz;
+ register unsigned long Rtt = 0;
+
+ gettimeofday(&t1, &tz);
+
+ send_probe_v6(++seq, ttl, sendbuff, ident, &tz, sndsock,
+ datalen, &whereto, hostname);
+ reset_timer = 1;
+
+ while ((cc =
+ wait_for_reply_v6(icmp_sock, &from, reset_timer,
+ waittime, icmp_sock,
+ packet)) != 0) {
+ gettimeofday(&t2, &tz);
+ timep = 0;
+ time(&timep);
+ if ((i =
+ packet_ok_v6(packet, cc, &from, seq, &t1,
+ ident))) {
+ reset_timer = 1;
+ if (memcmp
+ (&from.sin6_addr, &lastaddr,
+ sizeof(struct in6_addr))) {
+
+ memcpy(&lastaddr,
+ &from.sin6_addr,
+ sizeof(struct in6_addr));
+ }
+
+ Rtt = deltaT(&t1, &t2);
+ responseProbe = responseProbe + 1;
+ if (probe == 0) {
+ minRtt = Rtt;
+ maxRtt = Rtt;
+ averageRtt = Rtt;
+ sumRtt = Rtt;
+ sumOfSquare = Rtt * Rtt;
+ } else {
+ if (Rtt < minRtt)
+ minRtt = Rtt;
+ if (Rtt > maxRtt)
+ maxRtt = Rtt;
+ sumRtt = (sumRtt) + Rtt;
+ averageRtt =
+ round((double) (sumRtt) /
+ (double) responseProbe);
+ sumOfSquare = sumOfSquare + Rtt * Rtt;
+ }
+
+ StorageResults->traceRouteResultsCurProbeCount =
+ probe + 1;
+
+
+ switch (i - 1) {
+ case ICMP6_DST_UNREACH_NOPORT:
+ ++got_there;
+ break;
+
+ case ICMP6_DST_UNREACH_NOROUTE:
+ ++unreachable;
+ Printf(" !N");
+ break;
+ case ICMP6_DST_UNREACH_ADDR:
+ ++unreachable;
+ Printf(" !H");
+ break;
+
+ case ICMP6_DST_UNREACH_ADMIN:
+ ++unreachable;
+ Printf(" !S");
+ break;
+ }
+ break;
+ } else
+ reset_timer = 0;
+ }
+ if (cc == 0) {
+ timep = 0;
+ time(&timep);
+ Printf(" *");
+ Rtt = (item->traceRouteCtlTimeOut) * 1000;
+ }
+
+ if (item->traceRouteCtlMaxRows != 0) {
+
+ temp_his =
+ SNMP_MALLOC_STRUCT
+ (traceRouteProbeHistoryTable_data);
+ temp_his->traceRouteCtlOwnerIndex =
+ (char *) malloc(item->traceRouteCtlOwnerIndexLen +
+ 1);
+ memcpy(temp_his->traceRouteCtlOwnerIndex,
+ item->traceRouteCtlOwnerIndex,
+ item->traceRouteCtlOwnerIndexLen + 1);
+ temp_his->traceRouteCtlOwnerIndex[item->
+ traceRouteCtlOwnerIndexLen]
+ = '\0';
+ temp_his->traceRouteCtlOwnerIndexLen =
+ item->traceRouteCtlOwnerIndexLen;
+
+ temp_his->traceRouteCtlTestName =
+ (char *) malloc(item->traceRouteCtlTestNameLen +
+ 1);
+ memcpy(temp_his->traceRouteCtlTestName,
+ item->traceRouteCtlTestName,
+ item->traceRouteCtlTestNameLen + 1);
+ temp_his->traceRouteCtlTestName[item->
+ traceRouteCtlTestNameLen]
+ = '\0';
+ temp_his->traceRouteCtlTestNameLen =
+ item->traceRouteCtlTestNameLen;
+
+ /* add lock to protect */
+ pthread_mutex_t counter_mutex =
+ PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&counter_mutex);
+ if (item->traceRouteProbeHistoryMaxIndex >=
+ (unsigned long) (2147483647))
+ item->traceRouteProbeHistoryMaxIndex = 0;
+ temp_his->traceRouteProbeHistoryIndex =
+ ++(item->traceRouteProbeHistoryMaxIndex);
+ pthread_mutex_unlock(&counter_mutex);
+ /* endsadsadsad */
+ temp_his->traceRouteProbeHistoryHopIndex = ttl;
+ temp_his->traceRouteProbeHistoryProbeIndex = probe + 1;
+
+ temp_his->traceRouteProbeHistoryHAddrType = 2;
+ temp_his->traceRouteProbeHistoryHAddr =
+ (char *)
+ malloc(strlen
+ (inet_ntop
+ (AF_INET6, &from.sin6_addr, pa, 64)) + 1);
+ temp_his->traceRouteProbeHistoryHAddr =
+ strdup(inet_ntop
+ (AF_INET6, &from.sin6_addr, pa, 64));
+ temp_his->
+ traceRouteProbeHistoryHAddr[strlen
+ (inet_ntop
+ (AF_INET6,
+ &from.sin6_addr, pa,
+ 64))] = '\0';
+ temp_his->traceRouteProbeHistoryHAddrLen =
+ strlen(inet_ntop
+ (AF_INET6, &from.sin6_addr, pa, 64));
+
+ temp_his->traceRouteProbeHistoryResponse = Rtt;
+ temp_his->traceRouteProbeHistoryStatus = 1;
+ temp_his->traceRouteProbeHistoryLastRC = 0;
+
+ temp_his->traceRouteProbeHistoryTime_time = timep;
+ memdup(&temp_his->traceRouteProbeHistoryTime,
+ date_n_time(&timep,
+ &temp_his->traceRouteProbeHistoryTimeLen), 11);
+
+ if (probe == 0)
+ item->traceRouteProbeHis = temp_his;
+ else {
+ (current_temp_his)->next = temp_his;
+ }
+
+ current_temp_his = temp_his;
+
+ if (probe + 1 >= nprobes) {
+ current_temp_his->next = NULL;
+ }
+
+ if (item->traceRouteProbeHis != NULL) {
+ if (traceRouteProbeHistoryTable_count(item) <
+ item->traceRouteCtlMaxRows) {
+ if (traceRouteProbeHistoryTable_add
+ (current_temp_his) != SNMPERR_SUCCESS)
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "registered an entry error\n"));
+ } else {
+ traceRouteProbeHistoryTable_delLast(item);
+ if (traceRouteProbeHistoryTable_add
+ (current_temp_his) != SNMPERR_SUCCESS)
+ DEBUGMSGTL(("traceRouteProbeHistoryTable",
+ "registered an entry error\n"));
+
+ }
+ }
+
+ }
+ if (item->traceRouteCtlCreateHopsEntries == 1) {
+ netsnmp_variable_list *vars_hops = NULL;
+ snmp_varlist_add_variable(&vars_hops, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlOwnerIndex, item->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_hops, NULL, 0, ASN_OCTET_STR, (char *) item->traceRouteCtlTestName, item->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ snmp_varlist_add_variable(&vars_hops, NULL, 0, ASN_UNSIGNED, (char *) &index, sizeof(index)); /* traceRouteHopsIndex */
+ if ((current =
+ header_complex_get(traceRouteHopsTableStorage,
+ vars_hops)) == NULL)
+ return;
+ current->traceRouteHopsIpTgtAddressType = 2;
+ current->traceRouteHopsIpTgtAddress =
+ (char *)
+ malloc(strlen
+ (inet_ntop
+ (AF_INET6, &from.sin6_addr, pa, 64)) + 1);
+ current->traceRouteHopsIpTgtAddress =
+ strdup(inet_ntop
+ (AF_INET6, &from.sin6_addr, pa, 64));
+ current->
+ traceRouteHopsIpTgtAddress[strlen
+ (inet_ntop
+ (AF_INET6,
+ &from.sin6_addr, pa,
+ 64))] = '\0';
+
+ if (count != 0) {
+ if (strcmp
+ (old_HopsAddress[index - 1],
+ current->traceRouteHopsIpTgtAddress) != 0)
+ flag = 1;
+ }
+
+ current->traceRouteHopsIpTgtAddressLen =
+ strlen(inet_ntop
+ (AF_INET6, &from.sin6_addr, pa, 64));
+ current->traceRouteHopsMinRtt = minRtt;
+ current->traceRouteHopsMaxRtt = maxRtt;
+ current->traceRouteHopsAverageRtt = averageRtt;
+ current->traceRouteHopsRttSumOfSquares = sumOfSquare;
+ current->traceRouteHopsSentProbes = probe + 1;
+ current->traceRouteHopsProbeResponses = responseProbe;
+ current->traceRouteHopsLastGoodProbe_time = timep;
+ memdup(&current->traceRouteHopsLastGoodProbe,
+ date_n_time(&timep,
+ &current->traceRouteHopsLastGoodProbeLen), 11);
+
+ snmp_free_varbind(vars_hops);
+ vars_hops = NULL;
+ }
+
+
+ (void) fflush(stdout);
+ }
+ putchar('\n');
+
+
+ if (got_there || unreachable >= nprobes - 1) {
+
+
+ if (got_there != 0) {
+ StorageResults->traceRouteResultsTestAttempts =
+ StorageResults->traceRouteResultsTestAttempts + 1;
+
+ StorageResults->traceRouteResultsTestSuccesses =
+ StorageResults->traceRouteResultsTestSuccesses + 1;
+ StorageResults->traceRouteResultsLastGoodPath_time = timep;
+ memdup(&StorageResults->traceRouteResultsLastGoodPath,
+ date_n_time(&timep,
+ &StorageResults->traceRouteResultsLastGoodPathLen), 11);
+ if ((item->
+ traceRouteCtlTrapGeneration[0] &
+ TRACEROUTETRAPGENERATION_TESTCOMPLETED) != 0) {
+ printf("TEST completed!\n");
+ send_traceRoute_trap(item, traceRouteTestCompleted,
+ sizeof
+ (traceRouteTestCompleted) /
+ sizeof(oid));
+ }
+ }
+
+ else {
+ StorageResults->traceRouteResultsTestAttempts =
+ StorageResults->traceRouteResultsTestAttempts + 1;
+ if ((item->
+ traceRouteCtlTrapGeneration[0] &
+ TRACEROUTETRAPGENERATION_TESTFAILED) != 0) {
+ printf("test Failed!\n");
+ send_traceRoute_trap(item, traceRouteTestFailed,
+ sizeof(traceRouteTestFailed) /
+ sizeof(oid));
+ }
+ }
+ break;
+
+ } else if (ttl == item->traceRouteCtlMaxTtl
+ && (probe + 1) == nprobes) {
+ StorageResults->traceRouteResultsTestAttempts =
+ StorageResults->traceRouteResultsTestAttempts + 1;
+
+ if ((item->
+ traceRouteCtlTrapGeneration[0] &
+ TRACEROUTETRAPGENERATION_TESTFAILED) != 0) {
+ printf("test Failed!\n");
+ send_traceRoute_trap(item, traceRouteTestFailed,
+ sizeof(traceRouteTestFailed) /
+ sizeof(oid));
+ }
+ }
+
+ }
+
+ close(sndsock);
+
+ if (flag == 1) {
+ printf("path changed!\n");
+ send_traceRoute_trap(item, traceRoutePathChange,
+ sizeof(traceRoutePathChange) /
+ sizeof(oid));
+ }
+
+ int k = 0;
+ for (k = 0; k < count; k++) {
+ free(old_HopsAddress[k]);
+ old_HopsAddress[k] = NULL;
+ }
+
+ }
+ return;
+}
+
+
+int
+wait_for_reply(register int sock, register struct sockaddr_in *fromp,
+ register const struct timeval *tp, u_char * packet,
+ int waittime)
+{
+ fd_set fds;
+ struct timeval now, wait;
+ struct timezone tz;
+ register int cc = 0;
+ socklen_t fromlen = sizeof(*fromp);
+
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ wait.tv_sec = tp->tv_sec + waittime;
+ wait.tv_usec = tp->tv_usec;
+ (void) gettimeofday(&now, &tz);
+ tvsub(&wait, &now);
+ if (select(sock + 1, &fds, NULL, NULL, &wait) > 0)
+ cc = recvfrom(sock, (char *) packet, 512, 0,
+ (struct sockaddr *) fromp, &fromlen);
+ return (cc);
+}
+
+
+int
+wait_for_reply_v6(int sock, struct sockaddr_in6 *from, int reset_timer,
+ int waittime, int icmp_sock, u_char * packet)
+{
+ fd_set fds;
+ static struct timeval wait;
+ int cc = 0;
+ socklen_t fromlen = sizeof(*from);
+
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ if (reset_timer) {
+ /*
+ * traceroute could hang if someone else has a ping
+ * running and our ICMP reply gets dropped but we don't
+ * realize it because we keep waking up to handle those
+ * other ICMP packets that keep coming in. To fix this,
+ * "reset_timer" will only be true if the last packet that
+ * came in was for us or if this is the first time we're
+ * waiting for a reply since sending out a probe. Note
+ * that this takes advantage of the select() feature on
+ * Linux where the remaining timeout is written to the
+ * struct timeval area.
+ */
+ wait.tv_sec = waittime;
+ wait.tv_usec = 0;
+ }
+
+ if (select(sock + 1, &fds, (fd_set *) 0, (fd_set *) 0, &wait) > 0) {
+ cc = recvfrom(icmp_sock, (char *) packet, 512, 0,
+ (struct sockaddr *) from, &fromlen);
+ }
+
+ return (cc);
+}
+
+/*
+ * send_probe() uses the BSD-ish udpiphdr.
+ * Define something that looks enough like it to work.
+ */
+struct udpiphdr {
+ struct iphdr ui_i;
+ struct udphdr ui_u;
+};
+#define ui_src ui_i.saddr
+#define ui_dst ui_i.daddr
+#define ui_pr ui_i.protocol
+#define ui_len ui_i.tot_len
+
+void
+send_probe(struct sockaddr_in *whereto, register int seq, int ttl,
+ register struct timeval *tp, register struct ip *outip,
+ register struct udphdr *outudp, int packlen, int optlen,
+ char *hostname, u_short ident, int sndsock, u_short port,
+ struct outdata *outdata)
+{
+ register int cc = 0;
+ register struct udpiphdr *ui = NULL, *oui = NULL;
+ struct ip tip;
+
+ outip->ip_ttl = ttl;
+#ifndef __hpux
+ outip->ip_id = htons(ident + seq);
+#endif
+
+ /*
+ * In most cases, the kernel will recalculate the ip checksum.
+ * But we must do it anyway so that the udp checksum comes out
+ * right.
+ */
+
+ outip->ip_sum =
+ in_checksum((u_short *) outip, sizeof(*outip) + optlen);
+ if (outip->ip_sum == 0)
+ outip->ip_sum = 0xffff;
+
+
+ /*
+ * Payload
+ */
+ outdata->seq = seq;
+ outdata->ttl = ttl;
+ outdata->tv = *tp;
+
+
+ outudp->dest = htons(port + seq);
+
+
+ /*
+ * Checksum (we must save and restore ip header)
+ */
+ tip = *outip;
+ ui = (struct udpiphdr *) outip;
+ oui = (struct udpiphdr *) &tip;
+ /*
+ * Easier to zero and put back things that are ok
+ */
+ memset((char *) ui, 0, sizeof(ui->ui_i));
+ ui->ui_src = oui->ui_src;
+ ui->ui_dst = oui->ui_dst;
+ ui->ui_pr = oui->ui_pr;
+ ui->ui_len = outudp->len;
+ outudp->check = 0;
+ outudp->check = in_checksum((u_short *) ui, packlen);
+ if (outudp->check == 0)
+ outudp->check = 0xffff;
+ *outip = tip;
+
+
+ /*
+ * XXX undocumented debugging hack
+ */
+
+
+#if !defined(IP_HDRINCL) && defined(IP_TTL)
+ printf("ttl\n");
+ if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
+ (char *) &ttl, sizeof(ttl)) < 0) {
+ Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
+ "traceroute", ttl, strerror(errno));
+ exit(1);
+ }
+#endif
+
+#ifdef __hpux
+
+ Printf("whereto=%s\n",
+ inet_ntoa(((struct sockaddr_in *) whereto)->sin_addr));
+ cc = sendto(sndsock, (char *) outudp,
+ packlen - (sizeof(*outip) + optlen), 0, whereto,
+ sizeof(*whereto));
+ if (cc > 0)
+ cc += sizeof(*outip) + optlen;
+#else
+
+ cc = sendto(sndsock, (char *) outip,
+ packlen, 0, whereto, sizeof(*whereto));
+#endif
+ if (cc < 0 || cc != packlen) {
+ if (cc < 0)
+ Fprintf(stderr, "%s: sendto: %s\n", "traceroute", strerror(errno));
+ Printf("%s: wrote %s %d chars, ret=%d\n",
+ "traceroute", hostname, packlen, cc);
+ (void) fflush(stdout);
+ }
+}
+
+
+
+void
+send_probe_v6(int seq, int ttl, char *sendbuff, pid_t ident,
+ struct timezone *tz, int sndsock, int datalen,
+ struct sockaddr_in6 *whereto, char *hostname)
+{
+ struct pkt_format *pkt = (struct pkt_format *) sendbuff;
+ int i = 0;
+
+ pkt->ident = htonl(ident);
+ pkt->seq = htonl(seq);
+ gettimeofday(&pkt->tv, tz);
+
+ i = setsockopt(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl,
+ sizeof(int));
+ if (i < 0) {
+ perror("setsockopt");
+ exit(1);
+ }
+
+ do {
+ i = sendto(sndsock, sendbuff, datalen, 0,
+ (struct sockaddr *) whereto,
+ sizeof(struct sockaddr_in6));
+ } while (i < 0 && errno == ECONNREFUSED);
+
+ if (i < 0 || i != datalen) {
+ if (i < 0)
+ perror("sendto");
+ Printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
+ datalen, i);
+ (void) fflush(stdout);
+ }
+}
+
+
+unsigned long
+deltaT(struct timeval *t1p, struct timeval *t2p)
+{
+ register unsigned long dt;
+
+ dt = (unsigned long) ((long) (t2p->tv_sec - t1p->tv_sec) * 1000 +
+ (long) (t2p->tv_usec - t1p->tv_usec) / 1000);
+ return (dt);
+}
+
+
+int
+packet_ok(register u_char * buf, int cc, register struct sockaddr_in *from,
+ register int seq, u_short ident, int pmtu, u_short port)
+{
+ register struct icmp *icp = NULL;
+ register u_char type, code;
+ register int hlen = 0;
+#ifndef ARCHAIC
+ register struct ip *ip = NULL;
+
+ ip = (struct ip *) buf;
+ hlen = ip->ip_hl << 2;
+ if (cc < hlen + ICMP_MINLEN) {
+
+ return (0);
+ }
+ cc -= hlen;
+ icp = (struct icmp *) (buf + hlen);
+#else
+ icp = (struct icmp *) buf;
+#endif
+ type = icp->icmp_type;
+ code = icp->icmp_code;
+ /*
+ * Path MTU Discovery (RFC1191)
+ */
+ if (code != ICMP_UNREACH_NEEDFRAG)
+ pmtu = 0;
+ else {
+#ifdef HAVE_ICMP_NEXTMTU
+ pmtu = ntohs(icp->icmp_nextmtu);
+#else
+ pmtu = ntohs(((struct my_pmtu *) &icp->icmp_void)->ipm_nextmtu);
+#endif
+ }
+ if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
+ type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
+ register struct ip *hip;
+ register struct udphdr *up;
+
+ hip = &icp->icmp_ip;
+ hlen = hip->ip_hl << 2;
+ up = (struct udphdr *) ((u_char *) hip + hlen);
+ /*
+ * XXX 8 is a magic number
+ */
+ if (hlen + 12 <= cc &&
+ hip->ip_p == IPPROTO_UDP &&
+ up->source == htons(ident) && up->dest == htons(port + seq))
+ return (type == ICMP_TIMXCEED ? -1 : code + 1);
+ }
+
+
+ return (0);
+}
+
+
+
+
+int
+packet_ok_v6(u_char * buf, int cc, struct sockaddr_in6 *from, int seq,
+ struct timeval *tv, pid_t ident)
+{
+ struct icmp6_hdr *icp = NULL;
+ u_char type, code;
+
+ icp = (struct icmp6_hdr *) buf;
+
+ type = icp->icmp6_type;
+ code = icp->icmp6_code;
+
+ if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) ||
+ type == ICMP6_DST_UNREACH) {
+ struct ip6_hdr *hip = NULL;
+ struct udphdr *up = NULL;
+ int nexthdr = 0;
+
+ hip = (struct ip6_hdr *) (icp + 1);
+ up = (struct udphdr *) (hip + 1);
+ nexthdr = hip->ip6_nxt;
+
+ if (nexthdr == 44) {
+ nexthdr = *(unsigned char *) up;
+ up++;
+ }
+ if (nexthdr == IPPROTO_UDP) {
+ struct pkt_format *pkt;
+
+ pkt = (struct pkt_format *) (up + 1);
+
+ if (ntohl(pkt->ident) == ident && ntohl(pkt->seq) == seq) {
+ *tv = pkt->tv;
+ return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1);
+ }
+ }
+
+ }
+
+ return (0);
+}
+
+
+/*
+ * Checksum routine for Internet Protocol family headers (C Version)
+ */
+
+u_short
+in_checksum(register u_short * addr, register int len)
+{
+ register int nleft = len;
+ register u_short *w = addr;
+ register u_short answer;
+ register int sum = 0;
+
+ /*
+ * Our algorithm is simple, using a 32 bit accumulator (sum),
+ * we add sequential 16 bit words to it, and at the end, fold
+ * back all the carry bits from the top 16 bits into the lower
+ * 16 bits.
+ */
+ while (nleft > 1) {
+ sum += *w++;
+ nleft -= 2;
+ }
+
+ /*
+ * mop up an odd byte, if necessary
+ */
+ if (nleft == 1)
+ sum += *(u_char *) w;
+
+ /*
+ * add back carry outs from top 16 bits to low 16 bits
+ */
+ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
+ sum += (sum >> 16); /* add carry */
+ answer = ~sum; /* truncate to 16 bits */
+ return (answer);
+}
+
+/*
+ * Subtract 2 timeval structs: out = out - in.
+ * Out is assumed to be >= in.
+ */
+void
+tvsub(register struct timeval *out, register struct timeval *in)
+{
+
+ if ((out->tv_usec -= in->tv_usec) < 0) {
+ --out->tv_sec;
+ out->tv_usec += 1000000;
+ }
+ out->tv_sec -= in->tv_sec;
+}
+
+
+struct hostinfo *
+gethostinfo(register char *hostname)
+{
+ register int n;
+ register struct hostent *hp = NULL;
+ register struct hostinfo *hi = NULL;
+ register char **p = NULL;
+ register u_int32_t addr, *ap = NULL;
+
+ if (strlen(hostname) > 64) {
+ Fprintf(stderr, "%s: hostname \"%.32s...\" is too long\n",
+ "traceroute", hostname);
+ exit(1);
+ }
+ hi = calloc(1, sizeof(*hi));
+ if (hi == NULL) {
+ Fprintf(stderr, "%s: calloc %s\n", "traceroute", strerror(errno));
+ exit(1);
+ }
+ addr = inet_addr(hostname);
+ if ((int32_t) addr != -1) {
+ hi->name = strdup(hostname);
+ hi->n = 1;
+ hi->addrs = calloc(1, sizeof(hi->addrs[0]));
+ if (hi->addrs == NULL) {
+ Fprintf(stderr, "%s: calloc %s\n", "traceroute", strerror(errno));
+ exit(1);
+ }
+ hi->addrs[0] = addr;
+ return (hi);
+ }
+
+ hp = netsnmp_gethostbyname(hostname);
+ if (hp == NULL) {
+ Fprintf(stderr, "%s: unknown host %s\n", "traceroute", hostname);
+ printf("hp=NULL\n");
+ exit(1);
+ }
+ if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
+ Fprintf(stderr, "%s: bad host %s\n", "traceroute", hostname);
+ exit(1);
+ }
+ hi->name = strdup(hp->h_name);
+ for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
+ continue;
+ hi->n = n;
+ hi->addrs = calloc(n, sizeof(hi->addrs[0]));
+ if (hi->addrs == NULL) {
+ Fprintf(stderr, "%s: calloc %s\n", "traceroute", strerror(errno));
+ exit(1);
+ }
+ for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
+ memcpy(ap, *p, sizeof(*ap));
+ return (hi);
+}
+
+void
+freehostinfo(register struct hostinfo *hi)
+{
+ if (hi->name != NULL) {
+ free(hi->name);
+ hi->name = NULL;
+ }
+ free((char *) hi->addrs);
+ free((char *) hi);
+}
+
+void
+setsin(register struct sockaddr_in *sin, register u_int32_t addr)
+{
+
+ memset(sin, 0, sizeof(*sin));
+#ifdef HAVE_SOCKADDR_SA_LEN
+ sin->sin_len = sizeof(*sin);
+#endif
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = addr;
+}
+
+
+/*
+ * Return the source address for the given destination address
+ */
+const char *
+findsaddr(register const struct sockaddr_in *to,
+ register struct sockaddr_in *from)
+{
+ register int i, n;
+ register FILE *f;
+ register u_int32_t mask;
+ u_int32_t dest, tmask;
+ struct ifaddrlist *al;
+ char buf[256], tdevice[256], device[256];
+ static char errbuf[132];
+ static const char route[] = "/proc/net/route";
+
+ if ((f = fopen(route, "r")) == NULL) {
+ sprintf(errbuf, "open %s: %.128s", route, strerror(errno));
+ return (errbuf);
+ }
+
+ /*
+ * Find the appropriate interface
+ */
+ n = 0;
+ mask = 0;
+ device[0] = '\0';
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ ++n;
+ if (n == 1 && strncmp(buf, "Iface", 5) == 0)
+ continue;
+ if ((i = sscanf(buf, "%s %x %*s %*s %*s %*s %*s %x",
+ tdevice, &dest, &tmask)) != 3)
+ return ("junk in buffer");
+ if ((to->sin_addr.s_addr & tmask) == dest &&
+ (tmask > mask || mask == 0)) {
+ mask = tmask;
+ strcpy(device, tdevice);
+ }
+ }
+ fclose(f);
+
+ if (device[0] == '\0')
+ return ("Can't find interface");
+
+ /*
+ * Get the interface address list
+ */
+ if ((n = ifaddrlist(&al, errbuf)) < 0)
+ return (errbuf);
+
+ if (n == 0)
+ return ("Can't find any network interfaces");
+
+ /*
+ * Find our appropriate source address
+ */
+ for (i = n; i > 0; --i, ++al)
+ if (strcmp(device, al->device) == 0)
+ break;
+ if (i <= 0) {
+ sprintf(errbuf, "Can't find interface \"%.32s\"", device);
+ return (errbuf);
+ }
+
+ setsin(from, al->addr);
+ return (NULL);
+}
+
+int
+ifaddrlist(register struct ifaddrlist **ipaddrp, register char *errbuf)
+{
+ register int fd, nipaddr;
+#ifdef HAVE_SOCKADDR_SA_LEN
+ register int n;
+#endif
+ register struct ifreq *ifrp, *ifend, *ifnext;
+ register struct sockaddr_in *sin;
+ register struct ifaddrlist *al;
+ struct ifconf ifc;
+ struct ifreq ibuf[(32 * 1024) / sizeof(struct ifreq)], ifr;
+#define MAX_IPADDR (sizeof(ibuf) / sizeof(ibuf[0]))
+ static struct ifaddrlist ifaddrlist[MAX_IPADDR];
+ char device[sizeof(ifr.ifr_name) + 1];
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ (void) sprintf(errbuf, "socket: %s", strerror(errno));
+ return (-1);
+ }
+ ifc.ifc_len = sizeof(ibuf);
+ ifc.ifc_buf = (caddr_t) ibuf;
+
+ if (ioctl(fd, SIOCGIFCONF, (char *) &ifc) < 0 ||
+ ifc.ifc_len < sizeof(struct ifreq)) {
+ if (errno == EINVAL)
+ (void) sprintf(errbuf,
+ "SIOCGIFCONF: ifreq struct too small (%d bytes)",
+ (int)sizeof(ibuf));
+ else
+ (void) sprintf(errbuf, "SIOCGIFCONF: %s", strerror(errno));
+ (void) close(fd);
+ return (-1);
+ }
+ ifrp = ibuf;
+ ifend = (struct ifreq *) ((char *) ibuf + ifc.ifc_len);
+
+ al = ifaddrlist;
+ nipaddr = 0;
+ for (; ifrp < ifend; ifrp = ifnext) {
+#ifdef HAVE_SOCKADDR_SA_LEN
+ n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
+ if (n < sizeof(*ifrp))
+ ifnext = ifrp + 1;
+ else
+ ifnext = (struct ifreq *) ((char *) ifrp + n);
+ if (ifrp->ifr_addr.sa_family != AF_INET)
+ continue;
+#else
+ ifnext = ifrp + 1;
+#endif
+ /*
+ * Need a template to preserve address info that is
+ * used below to locate the next entry. (Otherwise,
+ * SIOCGIFFLAGS stomps over it because the requests
+ * are returned in a union.)
+ */
+ strlcpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFFLAGS, (char *) &ifr) < 0) {
+ if (errno == ENXIO)
+ continue;
+ (void) sprintf(errbuf, "SIOCGIFFLAGS: %.*s: %s",
+ (int) sizeof(ifr.ifr_name), ifr.ifr_name,
+ strerror(errno));
+ (void) close(fd);
+ return (-1);
+ }
+
+ /*
+ * Must be up
+ */
+ if ((ifr.ifr_flags & IFF_UP) == 0)
+ continue;
+
+ sprintf(device, "%.*s", (int) sizeof(ifr.ifr_name), ifr.ifr_name);
+#ifdef sun
+ /*
+ * Ignore sun virtual interfaces
+ */
+ if (strchr(device, ':') != NULL)
+ continue;
+#endif
+ if (ioctl(fd, SIOCGIFADDR, (char *) &ifr) < 0) {
+ (void) sprintf(errbuf, "SIOCGIFADDR: %s: %s",
+ device, strerror(errno));
+ (void) close(fd);
+ return (-1);
+ }
+
+ if (nipaddr >= MAX_IPADDR) {
+ (void) sprintf(errbuf, "Too many interfaces (%d)", nipaddr);
+ (void) close(fd);
+ return (-1);
+ }
+ sin = (struct sockaddr_in *) &ifr.ifr_addr;
+ al->addr = sin->sin_addr.s_addr;
+ al->device = strdup(device);
+ ++al;
+ ++nipaddr;
+ }
+ (void) close(fd);
+
+ *ipaddrp = ifaddrlist;
+ return (nipaddr);
+}
diff --git a/agent/mibgroup/disman/traceroute/traceRouteCtlTable.h b/agent/mibgroup/disman/traceroute/traceRouteCtlTable.h
new file mode 100644
index 0000000..0711978
--- /dev/null
+++ b/agent/mibgroup/disman/traceroute/traceRouteCtlTable.h
@@ -0,0 +1,613 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:traceRouteCtlTable.h
+ *File Description:The head file of traceRouteCtlTable.c
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.create-dataset.conf,v 5.3 2002/12/05 00:29:45 hardaker Exp $
+ */
+#ifndef TRACEROUTECTLTABLE_H
+#define TRACEROUTECTLTABLE_H
+
+
+config_require(header_complex);
+
+struct traceRouteCtlTable_data {
+ char *traceRouteCtlOwnerIndex; /* string */
+ size_t traceRouteCtlOwnerIndexLen;
+
+ char *traceRouteCtlTestName; /* string */
+ size_t traceRouteCtlTestNameLen;
+
+
+ long traceRouteCtlTargetAddressType;
+
+ char *traceRouteCtlTargetAddress;
+ size_t traceRouteCtlTargetAddressLen;
+
+ long traceRouteCtlByPassRouteTable;
+
+ unsigned long traceRouteCtlDataSize;
+
+ unsigned long traceRouteCtlTimeOut;
+
+ unsigned long traceRouteCtlProbesPerHop;
+
+ unsigned long traceRouteCtlPort;
+
+ unsigned long traceRouteCtlMaxTtl;
+
+ unsigned long traceRouteCtlDSField;
+
+ long traceRouteCtlSourceAddressType;
+
+ char *traceRouteCtlSourceAddress;
+ size_t traceRouteCtlSourceAddressLen;
+
+ long traceRouteCtlIfIndex;
+
+ char *traceRouteCtlMiscOptions;
+ size_t traceRouteCtlMiscOptionsLen;
+
+ unsigned long traceRouteCtlMaxFailures;
+
+ long traceRouteCtlDontFragment;
+
+ unsigned long traceRouteCtlInitialTtl;
+
+ unsigned long traceRouteCtlFrequency;
+
+ long traceRouteCtlStorageType;
+
+ long traceRouteCtlAdminStatus;
+
+ char *traceRouteCtlDescr;
+ size_t traceRouteCtlDescrLen;
+
+ unsigned long traceRouteCtlMaxRows;
+
+ char *traceRouteCtlTrapGeneration;
+ size_t traceRouteCtlTrapGenerationLen;
+
+ long traceRouteCtlCreateHopsEntries;
+
+ oid *traceRouteCtlType;
+ size_t traceRouteCtlTypeLen;
+
+ long traceRouteCtlRowStatus;
+
+
+ int storageType;
+ u_long timer_id;
+ unsigned long traceRouteProbeHistoryMaxIndex;
+
+ struct traceRouteResultsTable_data *traceRouteResults;
+ struct traceRouteProbeHistoryTable_data *traceRouteProbeHis;
+ struct traceRouteHopsTable_data *traceRouteHops;
+
+};
+
+struct traceRouteResultsTable_data {
+ /* struct pingResultsTable_data *next; */
+ char *traceRouteCtlOwnerIndex; /* string */
+ size_t traceRouteCtlOwnerIndexLen;
+
+ char *traceRouteCtlTestName; /* string */
+ size_t traceRouteCtlTestNameLen;
+
+ long traceRouteResultsOperStatus;
+ unsigned long traceRouteResultsCurHopCount;
+ unsigned long traceRouteResultsCurProbeCount;
+ long traceRouteResultsIpTgtAddrType;
+ char *traceRouteResultsIpTgtAddr;
+ size_t traceRouteResultsIpTgtAddrLen;
+ unsigned long traceRouteResultsTestAttempts;
+ unsigned long traceRouteResultsTestSuccesses;
+ u_char *traceRouteResultsLastGoodPath;
+ size_t traceRouteResultsLastGoodPathLen;
+ time_t traceRouteResultsLastGoodPath_time;
+
+ int storageType;
+
+};
+
+struct traceRouteProbeHistoryTable_data {
+ struct traceRouteProbeHistoryTable_data *next;
+ /* index */
+ char *traceRouteCtlOwnerIndex; /* string */
+ size_t traceRouteCtlOwnerIndexLen;
+
+ char *traceRouteCtlTestName; /* string */
+ size_t traceRouteCtlTestNameLen;
+ unsigned long traceRouteProbeHistoryIndex;
+ unsigned long traceRouteProbeHistoryHopIndex;
+ unsigned long traceRouteProbeHistoryProbeIndex;
+ /* index */
+ long traceRouteProbeHistoryHAddrType;
+ char *traceRouteProbeHistoryHAddr;
+ size_t traceRouteProbeHistoryHAddrLen;
+ unsigned long traceRouteProbeHistoryResponse;
+ long traceRouteProbeHistoryStatus;
+ long traceRouteProbeHistoryLastRC;
+ u_char *traceRouteProbeHistoryTime;
+ size_t traceRouteProbeHistoryTimeLen;
+ time_t traceRouteProbeHistoryTime_time;
+
+ int storageType;
+
+};
+
+struct traceRouteHopsTable_data {
+ struct traceRouteHopsTable_data *next;
+
+ char *traceRouteCtlOwnerIndex; /* string */
+ size_t traceRouteCtlOwnerIndexLen;
+
+ char *traceRouteCtlTestName; /* string */
+ size_t traceRouteCtlTestNameLen;
+
+ unsigned long traceRouteHopsHopIndex;
+ long traceRouteHopsIpTgtAddressType;
+ char *traceRouteHopsIpTgtAddress;
+ size_t traceRouteHopsIpTgtAddressLen;
+
+ unsigned long traceRouteHopsMinRtt;
+ unsigned long traceRouteHopsMaxRtt;
+ unsigned long traceRouteHopsAverageRtt;
+ unsigned long traceRouteHopsRttSumOfSquares;
+ unsigned long traceRouteHopsSentProbes;
+ unsigned long traceRouteHopsProbeResponses;
+ u_char *traceRouteHopsLastGoodProbe;
+ size_t traceRouteHopsLastGoodProbeLen;
+ time_t traceRouteHopsLastGoodProbe_time;
+
+ int storageType;
+};
+/*
+ * function declarations
+ */
+void init_traceRouteCtlTable(void);
+FindVarMethod var_traceRouteCtlTable;
+void parse_traceRouteCtlTable(const char *, char *);
+SNMPCallback store_traceRouteCtlTable;
+void init_trResultsTable(struct traceRouteCtlTable_data *);
+
+WriteMethod write_traceRouteCtlTargetAddressType;
+WriteMethod write_traceRouteCtlTargetAddress;
+WriteMethod write_traceRouteCtlByPassRouteTable;
+WriteMethod write_traceRouteCtlDataSize;
+WriteMethod write_traceRouteCtlTimeOut;
+WriteMethod write_traceRouteCtlProbesPerHop;
+WriteMethod write_traceRouteCtlPort;
+WriteMethod write_traceRouteCtlMaxTtl;
+WriteMethod write_traceRouteCtlDSField;
+WriteMethod write_traceRouteCtlSourceAddressType;
+WriteMethod write_traceRouteCtlSourceAddress;
+WriteMethod write_traceRouteCtlIfIndex;
+WriteMethod write_traceRouteCtlMiscOptions;
+WriteMethod write_traceRouteCtlMaxFailures;
+WriteMethod write_traceRouteCtlDontFragment;
+WriteMethod write_traceRouteCtlInitialTtl;
+WriteMethod write_traceRouteCtlFrequency;
+WriteMethod write_traceRouteCtlStorageType;
+WriteMethod write_traceRouteCtlAdminStatus;
+WriteMethod write_traceRouteCtlDescr;
+WriteMethod write_traceRouteCtlMaxRows;
+WriteMethod write_traceRouteCtlTrapGeneration;
+WriteMethod write_traceRouteCtlCreateHopsEntries;
+WriteMethod write_traceRouteCtlType;
+
+WriteMethod write_traceRouteCtlRowStatus;
+
+
+
+#define TRACEROUTETRAPGENERATION_PATHCHANGE 0x80
+#define TRACEROUTETRAPGENERATION_TESTFAILED 0x40
+#define TRACEROUTETRAPGENERATION_TESTCOMPLETED 0x20
+#define TRACEROUTETRAPGENERATION_NULL 0x00
+
+
+/*
+ * column number definitions for table traceRouteCtlTable
+ */
+#define COLUMN_TRACEROUTECTLOWNERINDEX 1
+#define COLUMN_TRACEROUTECTLTESTNAME 2
+#define COLUMN_TRACEROUTECTLTARGETADDRESSTYPE 3
+#define COLUMN_TRACEROUTECTLTARGETADDRESS 4
+#define COLUMN_TRACEROUTECTLBYPASSROUTETABLE 5
+#define COLUMN_TRACEROUTECTLDATASIZE 6
+#define COLUMN_TRACEROUTECTLTIMEOUT 7
+#define COLUMN_TRACEROUTECTLPROBESPERHOP 8
+#define COLUMN_TRACEROUTECTLPORT 9
+#define COLUMN_TRACEROUTECTLMAXTTL 10
+#define COLUMN_TRACEROUTECTLDSFIELD 11
+#define COLUMN_TRACEROUTECTLSOURCEADDRESSTYPE 12
+#define COLUMN_TRACEROUTECTLSOURCEADDRESS 13
+#define COLUMN_TRACEROUTECTLIFINDEX 14
+#define COLUMN_TRACEROUTECTLMISCOPTIONS 15
+#define COLUMN_TRACEROUTECTLMAXFAILURES 16
+#define COLUMN_TRACEROUTECTLDONTFRAGMENT 17
+#define COLUMN_TRACEROUTECTLINITIALTTL 18
+#define COLUMN_TRACEROUTECTLFREQUENCY 19
+#define COLUMN_TRACEROUTECTLSTORAGETYPE 20
+#define COLUMN_TRACEROUTECTLADMINSTATUS 21
+#define COLUMN_TRACEROUTECTLDESCR 22
+#define COLUMN_TRACEROUTECTLMAXROWS 23
+#define COLUMN_TRACEROUTECTLTRAPGENERATION 24
+#define COLUMN_TRACEROUTECTLCREATEHOPSENTRIES 25
+#define COLUMN_TRACEROUTECTLTYPE 26
+#define COLUMN_TRACEROUTECTLROWSTATUS 27
+#endif /* TRACEROUTECTLTABLE_H */
+
+/*
+ * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+ "@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000\n\
+The Regents of the University of California. All rights reserved.\n";
+static const char rcsid[] =
+ "@(#)$Id$ (LBL)";
+#endif
+
+/*
+ * traceroute host - trace the route ip packets follow going to "host".
+ *
+ * Attempt to trace the route an ip packet would follow to some
+ * internet host. We find out intermediate hops by launching probe
+ * packets with a small ttl (time to live) then listening for an
+ * icmp "time exceeded" reply from a gateway. We start our probes
+ * with a ttl of one and increase by one until we get an icmp "port
+ * unreachable" (which means we got to "host") or hit a max (which
+ * defaults to 30 hops & can be changed with the -m flag). Three
+ * probes (change with -q flag) are sent at each ttl setting and a
+ * line is printed showing the ttl, address of the gateway and
+ * round trip time of each probe. If the probe answers come from
+ * different gateways, the address of each responding system will
+ * be printed. If there is no response within a 5 sec. timeout
+ * interval (changed with the -w flag), a "*" is printed for that
+ * probe.
+ *
+ * Probe packets are UDP format. We don't want the destination
+ * host to process them so the destination port is set to an
+ * unlikely value (if some clod on the destination is using that
+ * value, it can be changed with the -p flag).
+ *
+ * A sample use might be:
+ *
+ * [yak 71]% traceroute nis.nsf.net.
+ * traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
+ * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
+ * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
+ * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
+ * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
+ * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
+ * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
+ * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
+ * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
+ * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
+ * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
+ * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
+ *
+ * Note that lines 2 & 3 are the same. This is due to a buggy
+ * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
+ * packets with a zero ttl.
+ *
+ * A more interesting example is:
+ *
+ * [yak 72]% traceroute allspice.lcs.mit.edu.
+ * traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
+ * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
+ * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
+ * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
+ * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
+ * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
+ * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
+ * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
+ * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
+ * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
+ * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
+ * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
+ * 12 * * *
+ * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
+ * 14 * * *
+ * 15 * * *
+ * 16 * * *
+ * 17 * * *
+ * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
+ *
+ * (I start to see why I'm having so much trouble with mail to
+ * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
+ * either don't send ICMP "time exceeded" messages or send them
+ * with a ttl too small to reach us. 14 - 17 are running the
+ * MIT C Gateway code that doesn't send "time exceeded"s. God
+ * only knows what's going on with 12.
+ *
+ * The silent gateway 12 in the above may be the result of a bug in
+ * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
+ * sends an unreachable message using whatever ttl remains in the
+ * original datagram. Since, for gateways, the remaining ttl is
+ * zero, the icmp "time exceeded" is guaranteed to not make it back
+ * to us. The behavior of this bug is slightly more interesting
+ * when it appears on the destination system:
+ *
+ * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
+ * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
+ * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
+ * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
+ * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
+ * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
+ * 7 * * *
+ * 8 * * *
+ * 9 * * *
+ * 10 * * *
+ * 11 * * *
+ * 12 * * *
+ * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
+ *
+ * Notice that there are 12 "gateways" (13 is the final
+ * destination) and exactly the last half of them are "missing".
+ * What's really happening is that rip (a Sun-3 running Sun OS3.5)
+ * is using the ttl from our arriving datagram as the ttl in its
+ * icmp reply. So, the reply will time out on the return path
+ * (with no notice sent to anyone since icmp's aren't sent for
+ * icmp's) until we probe with a ttl that's at least twice the path
+ * length. I.e., rip is really only 7 hops away. A reply that
+ * returns with a ttl of 1 is a clue this problem exists.
+ * Traceroute prints a "!" after the time if the ttl is <= 1.
+ * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
+ * non-standard (HPUX) software, expect to see this problem
+ * frequently and/or take care picking the target host of your
+ * probes.
+ *
+ * Other possible annotations after the time are !H, !N, !P (got a host,
+ * network or protocol unreachable, respectively), !S or !F (source
+ * route failed or fragmentation needed -- neither of these should
+ * ever occur and the associated gateway is busted if you see one). If
+ * almost all the probes result in some kind of unreachable, traceroute
+ * will give up and exit.
+ *
+ * Notes
+ * -----
+ * This program must be run by root or be setuid. (I suggest that
+ * you *don't* make it setuid -- casual use could result in a lot
+ * of unnecessary traffic on our poor, congested nets.)
+ *
+ * This program requires a kernel mod that does not appear in any
+ * system available from Berkeley: A raw ip socket using proto
+ * IPPROTO_RAW must interpret the data sent as an ip datagram (as
+ * opposed to data to be wrapped in a ip datagram). See the README
+ * file that came with the source to this program for a description
+ * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
+ * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
+ * MODIFIED TO RUN THIS PROGRAM.
+ *
+ * The udp port usage may appear bizarre (well, ok, it is bizarre).
+ * The problem is that an icmp message only contains 8 bytes of
+ * data from the original datagram. 8 bytes is the size of a udp
+ * header so, if we want to associate replies with the original
+ * datagram, the necessary information must be encoded into the
+ * udp header (the ip id could be used but there's no way to
+ * interlock with the kernel's assignment of ip id's and, anyway,
+ * it would have taken a lot more kernel hacking to allow this
+ * code to set the ip id). So, to allow two or more users to
+ * use traceroute simultaneously, we use this task's pid as the
+ * source port (the high bit is set to move the port number out
+ * of the "likely" range). To keep track of which probe is being
+ * replied to (so times and/or hop counts don't get confused by a
+ * reply that was delayed in transit), we increment the destination
+ * port number before each probe.
+ *
+ * Don't use this as a coding example. I was trying to find a
+ * routing problem and this code sort-of popped out after 48 hours
+ * without sleep. I was amazed it ever compiled, much less ran.
+ *
+ * I stole the idea for this program from Steve Deering. Since
+ * the first release, I've learned that had I attended the right
+ * IETF working group meetings, I also could have stolen it from Guy
+ * Almes or Matt Mathis. I don't know (or care) who came up with
+ * the idea first. I envy the originators' perspicacity and I'm
+ * glad they didn't keep the idea a secret.
+ *
+ * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
+ * enhancements to the original distribution.
+ *
+ * I've hacked up a round-trip-route version of this that works by
+ * sending a loose-source-routed udp datagram through the destination
+ * back to yourself. Unfortunately, SO many gateways botch source
+ * routing, the thing is almost worthless. Maybe one day...
+ *
+ * -- Van Jacobson (van@ee.lbl.gov)
+ * Tue Dec 20 03:50:13 PST 1988
+ */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <sys/socket.h>
+#include <sys/time.h>
+
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/udp.h>
+
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <memory.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include <net/if.h>
+
+#if __linux__
+#include <endian.h>
+#endif
+
+
+
+/*
+ * rfc1716
+ */
+#ifndef ICMP_UNREACH_FILTER_PROHIB
+#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
+#endif
+#ifndef ICMP_UNREACH_HOST_PRECEDENCE
+#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */
+#endif
+#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
+#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */
+#endif
+
+#define MAXPACKET 65535
+
+/*
+ * Maximum number of gateways (include room for one noop)
+ */
+#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#ifndef FD_SET
+#define NFDBITS (8*sizeof(fd_set))
+#define FD_SETSIZE NFDBITS
+#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#define FD_ZERO(p) memset((p), '\0', sizeof(*(p)))
+#endif
+
+#define Fprintf (void)fprintf
+#define Printf (void)printf
+
+/*
+ * Host name and address list
+ */
+struct hostinfo {
+ char *name;
+ int n;
+ u_int32_t *addrs;
+};
+
+/*
+ * Data section of the probe packet
+ */
+struct outdata {
+ u_char seq; /* sequence number of this packet */
+ u_char ttl; /* ttl packet left with */
+ struct timeval tv; /* time packet left */
+};
+
+#ifndef HAVE_ICMP_NEXTMTU
+/*
+ * Path MTU Discovery (RFC1191)
+ */
+struct my_pmtu {
+ u_short ipm_void;
+ u_short ipm_nextmtu;
+};
+#endif
+
+struct ifaddrlist {
+ u_int32_t addr;
+ char *device;
+};
+
+
+struct pkt_format {
+ u_int32_t ident;
+ u_int32_t seq;
+ struct timeval tv;
+};
+
+
+/*
+ * Forwards
+ */
+unsigned long deltaT(struct timeval *, struct timeval *);
+void freehostinfo(struct hostinfo *);
+void getaddr(u_int32_t *, char *);
+struct hostinfo *gethostinfo(char *);
+u_short in_checksum(u_short *, int);
+char *inetname(struct in_addr);
+void run_traceRoute(unsigned int, void *);
+int packet_ok(u_char *, int, struct sockaddr_in *, int,
+ u_short, int, u_short);
+char *pr_type(u_char);
+ /* void print(u_char *, int, struct sockaddr_in *); */
+void send_probe(struct sockaddr_in *, int, int,
+ struct timeval *, struct ip *, struct udphdr *,
+ int, int, char *, u_short, int, u_short,
+ struct outdata *);
+int str2val(const char *, const char *, int, int);
+void tvsub(struct timeval *, struct timeval *);
+int wait_for_reply(int, struct sockaddr_in *,
+ const struct timeval *, u_char *, int);
+#ifndef HAVE_USLEEP
+int usleep(u_int);
+#endif
+void setsin(struct sockaddr_in *, u_int32_t);
+int ifaddrlist(struct ifaddrlist **, char *);
+const char *findsaddr(const struct sockaddr_in *,
+ struct sockaddr_in *);
+struct addrinfo *host_serv_tr(const char *, const char *, int, int);
+char *sock_ntop_host_tr(const struct sockaddr *, socklen_t);
+
+void send_probe_v6(int, int, char *, pid_t, struct timezone *,
+ int, int, struct sockaddr_in6 *, char *);
+int wait_for_reply_v6(int, struct sockaddr_in6 *, int, int,
+ int, u_char *);
+int packet_ok_v6(u_char *, int, struct sockaddr_in6 *, int,
+ struct timeval *, pid_t);
+void print_v6(unsigned char *, int, struct sockaddr_in6 *);
diff --git a/agent/mibgroup/disman/traceroute/traceRouteHopsTable.c b/agent/mibgroup/disman/traceroute/traceRouteHopsTable.c
new file mode 100644
index 0000000..763757d
--- /dev/null
+++ b/agent/mibgroup/disman/traceroute/traceRouteHopsTable.c
@@ -0,0 +1,420 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:traceRouteHopsTable.c
+ *File Description:Rows of traceRouteHopsTable MIB read.
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "traceRouteCtlTable.h"
+#include "traceRouteResultsTable.h"
+#include "traceRouteProbeHistoryTable.h"
+#include "traceRouteHopsTable.h"
+
+#include "header_complex.h"
+
+
+oid traceRouteHopsTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 81, 1, 5 };
+
+struct variable2 traceRouteHopsTable_variables[] = {
+ {COLUMN_TRACEROUTEHOPSIPTGTADDRESSTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteHopsTable, 2, {1, 2}},
+ {COLUMN_TRACEROUTEHOPSIPTGTADDRESS, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteHopsTable, 2, {1, 3}},
+ {COLUMN_TRACEROUTEHOPSMINRTT, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteHopsTable, 2, {1, 4}},
+ {COLUMN_TRACEROUTEHOPSMAXRTT, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteHopsTable, 2, {1, 5}},
+ {COLUMN_TRACEROUTEHOPSAVERAGERTT, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteHopsTable, 2, {1, 6}},
+ {COLUMN_TRACEROUTEHOPSRTTSUMOFSQUARES, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteHopsTable, 2, {1, 7}},
+ {COLUMN_TRACEROUTEHOPSSENTPROBES, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteHopsTable, 2, {1, 8}},
+ {COLUMN_TRACEROUTEHOPSPROBERESPONSES, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteHopsTable, 2, {1, 9}},
+ {COLUMN_TRACEROUTEHOPSLASTGOODPROBE, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteHopsTable, 2, {1, 10}}
+};
+
+
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+
+extern struct header_complex_index *traceRouteCtlTableStorage;
+extern struct header_complex_index *traceRouteHopsTableStorage;
+void
+traceRouteHopsTable_inadd(struct traceRouteHopsTable_data *thedata);
+
+void
+traceRouteHopsTable_cleaner(struct header_complex_index *thestuff)
+{
+ struct header_complex_index *hciptr = NULL;
+ struct traceRouteHopsTable_data *StorageDel = NULL;
+ DEBUGMSGTL(("traceRouteHopsTable", "cleanerout "));
+ for (hciptr = thestuff; hciptr != NULL; hciptr = hciptr->next) {
+ StorageDel =
+ header_complex_extract_entry(&traceRouteHopsTableStorage,
+ hciptr);
+ if (StorageDel != NULL) {
+ free(StorageDel->traceRouteCtlOwnerIndex);
+ StorageDel->traceRouteCtlOwnerIndex = NULL;
+ free(StorageDel->traceRouteCtlTestName);
+ StorageDel->traceRouteCtlTestName = NULL;
+ free(StorageDel->traceRouteHopsLastGoodProbe);
+ StorageDel->traceRouteHopsLastGoodProbe = NULL;
+ free(StorageDel);
+ StorageDel = NULL;
+ }
+ DEBUGMSGTL(("traceRouteHopsTable", "cleaner "));
+ }
+
+}
+void
+init_traceRouteHopsTable(void)
+{
+
+ DEBUGMSGTL(("traceRouteHopsTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("traceRouteHopsTable", traceRouteHopsTable_variables,
+ variable2, traceRouteHopsTable_variables_oid);
+
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("traceRouteHopsTable",
+ parse_traceRouteHopsTable, NULL, NULL);
+
+ /*
+ * we need to be called back later to store our data
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_traceRouteHopsTable, NULL);
+
+ DEBUGMSGTL(("traceRouteHopsTable", "done.\n"));
+}
+
+/*
+ * parse_mteObjectsTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+
+void
+parse_traceRouteHopsTable(const char *token, char *line)
+{
+ size_t tmpint;
+ struct traceRouteHopsTable_data *StorageTmp =
+ SNMP_MALLOC_STRUCT(traceRouteHopsTable_data);
+
+ DEBUGMSGTL(("traceRouteHopsTable", "parsing config... "));
+
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlOwnerIndex,
+ &StorageTmp->traceRouteCtlOwnerIndexLen);
+ if (StorageTmp->traceRouteCtlOwnerIndex == NULL) {
+ config_perror("invalid specification for traceRouteCtlOwnerIndex");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlTestName,
+ &StorageTmp->traceRouteCtlTestNameLen);
+ if (StorageTmp->traceRouteCtlTestName == NULL) {
+ config_perror("invalid specification for traceRouteCtlTestName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteHopsHopIndex,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteHopsIpTgtAddressType,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteHopsIpTgtAddress,
+ &StorageTmp->traceRouteHopsIpTgtAddressLen);
+ if (StorageTmp->traceRouteHopsIpTgtAddress == NULL) {
+ config_perror
+ ("invalid specification for traceRouteHopsIpTgtAddress");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteHopsMinRtt, &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteHopsMaxRtt, &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteHopsAverageRtt,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteHopsRttSumOfSquares,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteHopsSentProbes,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteHopsProbeResponses,
+ &tmpint);
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteHopsLastGoodProbe,
+ &StorageTmp->traceRouteHopsLastGoodProbeLen);
+ if (StorageTmp->traceRouteHopsLastGoodProbe == NULL) {
+ config_perror
+ ("invalid specification for traceRouteHopsLastGoodProbe");
+ return;
+ }
+
+ traceRouteHopsTable_inadd(StorageTmp);
+
+ /* traceRouteHopsTable_cleaner(traceRouteHopsTableStorage); */
+
+ DEBUGMSGTL(("traceRouteHopsTable", "done.\n"));
+}
+
+
+
+
+
+/*
+ * store_traceRouteHopsTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+
+int
+store_traceRouteHopsTable(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr = NULL;
+ size_t tmpint;
+ struct traceRouteHopsTable_data *StorageTmp = NULL;
+ struct header_complex_index *hcindex = NULL;
+
+
+ DEBUGMSGTL(("traceRouteHopsTable", "storing data... "));
+
+
+ for (hcindex = traceRouteHopsTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct traceRouteHopsTable_data *) hcindex->data;
+
+ if (StorageTmp->storageType != ST_READONLY) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "traceRouteHopsTable ");
+ cptr = line + strlen(line);
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteCtlOwnerIndex,
+ &StorageTmp->
+ traceRouteCtlOwnerIndexLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->traceRouteCtlTestName,
+ &StorageTmp->
+ traceRouteCtlTestNameLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->traceRouteHopsHopIndex,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteHopsIpTgtAddressType,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteHopsIpTgtAddress,
+ &StorageTmp->
+ traceRouteHopsIpTgtAddressLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->traceRouteHopsMinRtt,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->traceRouteHopsMaxRtt,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteHopsAverageRtt, &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteHopsRttSumOfSquares,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteHopsSentProbes, &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteHopsProbeResponses,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteHopsLastGoodProbe,
+ &StorageTmp->
+ traceRouteHopsLastGoodProbeLen);
+
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("traceRouteHopsTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+void
+traceRouteHopsTable_inadd(struct traceRouteHopsTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list = NULL;
+
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &thedata->traceRouteHopsHopIndex, sizeof(thedata->traceRouteHopsHopIndex)); /* traceRouteHopsHopIndex */
+
+ DEBUGMSGTL(("traceRouteHopsTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ header_complex_add_data(&traceRouteHopsTableStorage, vars_list,
+ thedata);
+ DEBUGMSGTL(("traceRouteHopsTable", "registered an entry\n"));
+
+
+ DEBUGMSGTL(("traceRouteHopsTable", "done.\n"));
+}
+
+
+/*
+ * var_traceRouteHopsTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_traceRouteHopsTable above.
+ */
+unsigned char *
+var_traceRouteHopsTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact,
+ size_t *var_len, WriteMethod ** write_method)
+{
+
+
+ struct traceRouteHopsTable_data *StorageTmp = NULL;
+
+ *write_method = NULL;
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(traceRouteHopsTableStorage, vp, name, length,
+ exact, var_len, write_method)) == NULL) {
+ return NULL;
+ }
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+
+ switch (vp->magic) {
+
+ case COLUMN_TRACEROUTEHOPSIPTGTADDRESSTYPE:
+ *var_len = sizeof(StorageTmp->traceRouteHopsIpTgtAddressType);
+ return (u_char *) & StorageTmp->traceRouteHopsIpTgtAddressType;
+
+ case COLUMN_TRACEROUTEHOPSIPTGTADDRESS:
+ *var_len = (StorageTmp->traceRouteHopsIpTgtAddressLen);
+ return (u_char *) StorageTmp->traceRouteHopsIpTgtAddress;
+
+ case COLUMN_TRACEROUTEHOPSMINRTT:
+ *var_len = sizeof(StorageTmp->traceRouteHopsMinRtt);
+ return (u_char *) & StorageTmp->traceRouteHopsMinRtt;
+
+ case COLUMN_TRACEROUTEHOPSMAXRTT:
+ *var_len = sizeof(StorageTmp->traceRouteHopsMaxRtt);
+ return (u_char *) & StorageTmp->traceRouteHopsMaxRtt;
+
+ case COLUMN_TRACEROUTEHOPSAVERAGERTT:
+ *var_len = sizeof(StorageTmp->traceRouteHopsAverageRtt);
+ return (u_char *) & StorageTmp->traceRouteHopsAverageRtt;
+
+ case COLUMN_TRACEROUTEHOPSRTTSUMOFSQUARES:
+ *var_len = sizeof(StorageTmp->traceRouteHopsRttSumOfSquares);
+ return (u_char *) & StorageTmp->traceRouteHopsRttSumOfSquares;
+
+ case COLUMN_TRACEROUTEHOPSSENTPROBES:
+ *var_len = sizeof(StorageTmp->traceRouteHopsSentProbes);
+ return (u_char *) & StorageTmp->traceRouteHopsSentProbes;
+
+ case COLUMN_TRACEROUTEHOPSPROBERESPONSES:
+ *var_len = sizeof(StorageTmp->traceRouteHopsProbeResponses);
+ return (u_char *) & StorageTmp->traceRouteHopsProbeResponses;
+
+ case COLUMN_TRACEROUTEHOPSLASTGOODPROBE:
+ *var_len = (StorageTmp->traceRouteHopsLastGoodProbeLen);
+ return (u_char *) StorageTmp->traceRouteHopsLastGoodProbe;
+
+ default:
+ ERROR_MSG("");
+ }
+
+ return NULL;
+}
diff --git a/agent/mibgroup/disman/traceroute/traceRouteHopsTable.h b/agent/mibgroup/disman/traceroute/traceRouteHopsTable.h
new file mode 100644
index 0000000..f7e7746
--- /dev/null
+++ b/agent/mibgroup/disman/traceroute/traceRouteHopsTable.h
@@ -0,0 +1,41 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:traceRouteHopsTable.h
+ *File Description:The head file of traceRouteHopsTable.c
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+
+#ifndef TRACEROUTEHOPSTABLE_H
+#define TRACEROUTEHOPSTABLE_H
+
+config_require(header_complex);
+
+/*
+ * function declarations
+ */
+void init_traceRouteHopsTable(void);
+FindVarMethod var_traceRouteHopsTable;
+void parse_traceRouteHopsTable(const char *, char *);
+SNMPCallback store_traceRouteHopsTable;
+
+/*
+ * column number definitions for table traceRouteHopsTable
+ */
+#define COLUMN_TRACEROUTEHOPSHOPINDEX 1
+#define COLUMN_TRACEROUTEHOPSIPTGTADDRESSTYPE 2
+#define COLUMN_TRACEROUTEHOPSIPTGTADDRESS 3
+#define COLUMN_TRACEROUTEHOPSMINRTT 4
+#define COLUMN_TRACEROUTEHOPSMAXRTT 5
+#define COLUMN_TRACEROUTEHOPSAVERAGERTT 6
+#define COLUMN_TRACEROUTEHOPSRTTSUMOFSQUARES 7
+#define COLUMN_TRACEROUTEHOPSSENTPROBES 8
+#define COLUMN_TRACEROUTEHOPSPROBERESPONSES 9
+#define COLUMN_TRACEROUTEHOPSLASTGOODPROBE 10
+#endif /* TRACEROUTEHOPSTABLE_H */
diff --git a/agent/mibgroup/disman/traceroute/traceRouteProbeHistoryTable.c b/agent/mibgroup/disman/traceroute/traceRouteProbeHistoryTable.c
new file mode 100644
index 0000000..0b410c5
--- /dev/null
+++ b/agent/mibgroup/disman/traceroute/traceRouteProbeHistoryTable.c
@@ -0,0 +1,417 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:traceRouteProbeHistoryTable.c
+ *File Description:Rows of traceRouteProbeHistoryTable MIB read.
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+#include <net-snmp/net-snmp-config.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "traceRouteCtlTable.h"
+#include "traceRouteResultsTable.h"
+#include "traceRouteProbeHistoryTable.h"
+#include "traceRouteHopsTable.h"
+
+#include "header_complex.h"
+
+
+oid traceRouteProbeHistoryTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 81, 1, 4 };
+
+struct variable2 traceRouteProbeHistoryTable_variables[] = {
+ {COLUMN_TRACEROUTEPROBEHISTORYHADDRTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteProbeHistoryTable, 2, {1, 4}},
+ {COLUMN_TRACEROUTEPROBEHISTORYHADDR, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteProbeHistoryTable, 2, {1, 5}},
+ {COLUMN_TRACEROUTEPROBEHISTORYRESPONSE, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteProbeHistoryTable, 2, {1, 6}},
+ {COLUMN_TRACEROUTEPROBEHISTORYSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteProbeHistoryTable, 2, {1, 7}},
+ {COLUMN_TRACEROUTEPROBEHISTORYLASTRC, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteProbeHistoryTable, 2, {1, 8}},
+ {COLUMN_TRACEROUTEPROBEHISTORYTIME, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteProbeHistoryTable, 2, {1, 9}}
+};
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+
+extern struct header_complex_index *traceRouteCtlTableStorage;
+extern struct header_complex_index *traceRouteProbeHistoryTableStorage;
+void
+traceRouteProbeHistoryTable_inadd(struct traceRouteProbeHistoryTable_data
+ *thedata);
+
+void
+traceRouteProbeHistoryTable_cleaner(struct header_complex_index *thestuff)
+{
+ struct header_complex_index *hciptr = NULL;
+ struct traceRouteProbeHistoryTable_data *StorageDel = NULL;
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "cleanerout "));
+ for (hciptr = thestuff; hciptr != NULL; hciptr = hciptr->next) {
+ StorageDel =
+ header_complex_extract_entry
+ (&traceRouteProbeHistoryTableStorage, hciptr);
+ if (StorageDel != NULL) {
+ free(StorageDel->traceRouteCtlOwnerIndex);
+ StorageDel->traceRouteCtlOwnerIndex = NULL;
+ free(StorageDel->traceRouteCtlTestName);
+ StorageDel->traceRouteCtlTestName = NULL;
+ free(StorageDel->traceRouteProbeHistoryHAddr);
+ StorageDel->traceRouteProbeHistoryHAddr = NULL;
+ free(StorageDel->traceRouteProbeHistoryTime);
+ StorageDel->traceRouteProbeHistoryTime = NULL;
+ free(StorageDel);
+ StorageDel = NULL;
+ }
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "cleaner "));
+ }
+
+}
+void
+init_traceRouteProbeHistoryTable(void)
+{
+
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("traceRouteProbeHistoryTable",
+ traceRouteProbeHistoryTable_variables, variable2,
+ traceRouteProbeHistoryTable_variables_oid);
+
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("traceRouteProbeHistoryTable",
+ parse_traceRouteProbeHistoryTable, NULL,
+ NULL);
+
+ /*
+ * we need to be called back later to store our data
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_traceRouteProbeHistoryTable, NULL);
+
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "done.\n"));
+}
+
+/*
+ * parse_mteObjectsTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+
+void
+parse_traceRouteProbeHistoryTable(const char *token, char *line)
+{
+ size_t tmpint;
+ struct traceRouteProbeHistoryTable_data *StorageTmp =
+ SNMP_MALLOC_STRUCT(traceRouteProbeHistoryTable_data);
+
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "parsing config... "));
+
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlOwnerIndex,
+ &StorageTmp->traceRouteCtlOwnerIndexLen);
+ if (StorageTmp->traceRouteCtlOwnerIndex == NULL) {
+ config_perror("invalid specification for traceRouteCtlOwnerIndex");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlTestName,
+ &StorageTmp->traceRouteCtlTestNameLen);
+ if (StorageTmp->traceRouteCtlTestName == NULL) {
+ config_perror("invalid specification for traceRouteCtlTestName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteProbeHistoryIndex,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteProbeHistoryHopIndex,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->
+ traceRouteProbeHistoryProbeIndex, &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteProbeHistoryHAddrType,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteProbeHistoryHAddr,
+ &StorageTmp->traceRouteProbeHistoryHAddrLen);
+ if (StorageTmp->traceRouteProbeHistoryHAddr == NULL) {
+ config_perror
+ ("invalid specification for traceRouteProbeHistoryHAddr");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteProbeHistoryResponse,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteProbeHistoryStatus,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteProbeHistoryLastRC,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteProbeHistoryTime,
+ &StorageTmp->traceRouteProbeHistoryTimeLen);
+ if (StorageTmp->traceRouteProbeHistoryTime == NULL) {
+ config_perror
+ ("invalid specification for traceRouteProbeHistoryTime");
+ return;
+ }
+
+
+ traceRouteProbeHistoryTable_inadd(StorageTmp);
+
+ /* traceRouteProbeHistoryTable_cleaner(traceRouteProbeHistoryTableStorage); */
+
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "done.\n"));
+}
+
+
+
+
+
+/*
+ * store_traceRouteProbeHistoryTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+
+int
+store_traceRouteProbeHistoryTable(int majorID, int minorID,
+ void *serverarg, void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr = NULL;
+ size_t tmpint;
+ struct traceRouteProbeHistoryTable_data *StorageTmp = NULL;
+ struct header_complex_index *hcindex = NULL;
+
+
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "storing data... "));
+
+
+ for (hcindex = traceRouteProbeHistoryTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp =
+ (struct traceRouteProbeHistoryTable_data *) hcindex->data;
+
+ if (StorageTmp->storageType != ST_READONLY) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "traceRouteProbeHistoryTable ");
+ cptr = line + strlen(line);
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteCtlOwnerIndex,
+ &StorageTmp->
+ traceRouteCtlOwnerIndexLen);
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->traceRouteCtlTestName,
+ &StorageTmp->
+ traceRouteCtlTestNameLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteProbeHistoryIndex,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteProbeHistoryHopIndex,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteProbeHistoryProbeIndex,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteProbeHistoryHAddrType,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteProbeHistoryHAddr,
+ &StorageTmp->
+ traceRouteProbeHistoryHAddrLen);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteProbeHistoryResponse,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteProbeHistoryStatus,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteProbeHistoryLastRC,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteProbeHistoryTime,
+ &StorageTmp->
+ traceRouteProbeHistoryTimeLen);
+
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+
+void
+traceRouteProbeHistoryTable_inadd(struct traceRouteProbeHistoryTable_data
+ *thedata)
+{
+ netsnmp_variable_list *vars_list = NULL;
+
+
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &thedata->traceRouteProbeHistoryIndex, sizeof(thedata->traceRouteProbeHistoryIndex)); /* traceRouteProbeHistoryIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &thedata->traceRouteProbeHistoryHopIndex, sizeof(thedata->traceRouteProbeHistoryHopIndex)); /* traceRouteProbeHistoryHopIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_UNSIGNED, (char *) &thedata->traceRouteProbeHistoryProbeIndex, sizeof(thedata->traceRouteProbeHistoryProbeIndex)); /* traceRouteProbeHistoryProbeIndex */
+
+
+ /*
+ * XXX: fill in default row values here into StorageNew
+ *
+ */
+
+
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ header_complex_add_data(&traceRouteProbeHistoryTableStorage, vars_list,
+ thedata);
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "registered an entry\n"));
+
+
+ DEBUGMSGTL(("traceRouteProbeHistoryTable", "done.\n"));
+}
+
+
+/*
+ * var_traceRouteProbeHistoryTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_traceRouteProbeHistoryTable above.
+ */
+unsigned char *
+var_traceRouteProbeHistoryTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact,
+ size_t *var_len,
+ WriteMethod ** write_method)
+{
+
+
+ struct traceRouteProbeHistoryTable_data *StorageTmp = NULL;
+
+ *write_method = NULL;
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(traceRouteProbeHistoryTableStorage, vp, name,
+ length, exact, var_len, write_method)) == NULL) {
+ return NULL;
+ }
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+
+ switch (vp->magic) {
+
+ case COLUMN_TRACEROUTEPROBEHISTORYHADDRTYPE:
+ *var_len = sizeof(StorageTmp->traceRouteProbeHistoryHAddrType);
+ return (u_char *) & StorageTmp->traceRouteProbeHistoryHAddrType;
+
+ case COLUMN_TRACEROUTEPROBEHISTORYHADDR:
+ *var_len = (StorageTmp->traceRouteProbeHistoryHAddrLen);
+ return (u_char *) StorageTmp->traceRouteProbeHistoryHAddr;
+
+ case COLUMN_TRACEROUTEPROBEHISTORYRESPONSE:
+ *var_len = sizeof(StorageTmp->traceRouteProbeHistoryResponse);
+ return (u_char *) & StorageTmp->traceRouteProbeHistoryResponse;
+
+ case COLUMN_TRACEROUTEPROBEHISTORYSTATUS:
+ *var_len = sizeof(StorageTmp->traceRouteProbeHistoryStatus);
+ return (u_char *) & StorageTmp->traceRouteProbeHistoryStatus;
+
+ case COLUMN_TRACEROUTEPROBEHISTORYLASTRC:
+ *var_len = sizeof(StorageTmp->traceRouteProbeHistoryLastRC);
+ return (u_char *) & StorageTmp->traceRouteProbeHistoryLastRC;
+
+ case COLUMN_TRACEROUTEPROBEHISTORYTIME:
+ *var_len = (StorageTmp->traceRouteProbeHistoryTimeLen);
+ return (u_char *) StorageTmp->traceRouteProbeHistoryTime;
+
+ default:
+ ERROR_MSG("");
+ }
+
+ return NULL;
+}
diff --git a/agent/mibgroup/disman/traceroute/traceRouteProbeHistoryTable.h b/agent/mibgroup/disman/traceroute/traceRouteProbeHistoryTable.h
new file mode 100644
index 0000000..e99d948
--- /dev/null
+++ b/agent/mibgroup/disman/traceroute/traceRouteProbeHistoryTable.h
@@ -0,0 +1,39 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:traceRouteProbeHistoryTable.h
+ *File Description:The head file of traceRouteProbeHistoryTable.c
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+#ifndef TRACEROUTEPROBEHISTORYTABLE_H
+#define TRACEROUTEPROBEHISTORYTABLE_H
+
+config_require(header_complex);
+
+/*
+ * function declarations
+ */
+void init_traceRouteProbeHistoryTable(void);
+FindVarMethod var_traceRouteProbeHistoryTable;
+void parse_traceRouteProbeHistoryTable(const char *, char *);
+SNMPCallback store_traceRouteProbeHistoryTable;
+
+/*
+ * column number definitions for table traceRouteProbeHistoryTable
+ */
+#define COLUMN_TRACEROUTEPROBEHISTORYINDEX 1
+#define COLUMN_TRACEROUTEPROBEHISTORYHOPINDEX 2
+#define COLUMN_TRACEROUTEPROBEHISTORYPROBEINDEX 3
+#define COLUMN_TRACEROUTEPROBEHISTORYHADDRTYPE 4
+#define COLUMN_TRACEROUTEPROBEHISTORYHADDR 5
+#define COLUMN_TRACEROUTEPROBEHISTORYRESPONSE 6
+#define COLUMN_TRACEROUTEPROBEHISTORYSTATUS 7
+#define COLUMN_TRACEROUTEPROBEHISTORYLASTRC 8
+#define COLUMN_TRACEROUTEPROBEHISTORYTIME 9
+#endif /* TRACEROUTEPROBEHISTORYTABLE_H */
diff --git a/agent/mibgroup/disman/traceroute/traceRouteResultsTable.c b/agent/mibgroup/disman/traceroute/traceRouteResultsTable.c
new file mode 100644
index 0000000..aba6cf1
--- /dev/null
+++ b/agent/mibgroup/disman/traceroute/traceRouteResultsTable.c
@@ -0,0 +1,421 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:traceRouteResultsTable.c
+ *File Description:Rows of traceRouteResultsTable MIB read.
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+/*
+ * Note: this file originally auto-generated by mib2c using
+ * : mib2c.create-dataset.conf,v 5.3 2002/12/05 00:29:45 hardaker Exp $
+ */
+
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-features.h>
+
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include "traceRouteResultsTable.h"
+#include "traceRouteCtlTable.h"
+#include "traceRouteProbeHistoryTable.h"
+#include "traceRouteHopsTable.h"
+#include "header_complex.h"
+
+netsnmp_feature_require(table_dataset)
+
+/*
+ *traceRouteResultsTable_variables_oid:
+ *
+ */
+oid traceRouteResultsTable_variables_oid[] =
+ { 1, 3, 6, 1, 2, 1, 81, 1, 3 };
+
+struct variable2 traceRouteResultsTable_variables[] = {
+ {COLUMN_TRACEROUTERESULTSOPERSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteResultsTable, 2, {1, 1}},
+ {COLUMN_TRACEROUTERESULTSCURHOPCOUNT, ASN_GAUGE, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteResultsTable, 2, {1, 2}},
+ {COLUMN_TRACEROUTERESULTSCURPROBECOUNT, ASN_GAUGE, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteResultsTable, 2, {1, 3}},
+ {COLUMN_TRACEROUTERESULTSIPTGTADDRTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteResultsTable, 2, {1, 4}},
+ {COLUMN_TRACEROUTERESULTSIPTGTADDR, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteResultsTable, 2, {1, 5}},
+ {COLUMN_TRACEROUTERESULTSTESTATTEMPTS, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteResultsTable, 2, {1, 6}},
+ {COLUMN_TRACEROUTERESULTSTESTSUCCESSES, ASN_UNSIGNED, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteResultsTable, 2, {1, 7}},
+ {COLUMN_TRACEROUTERESULTSLASTGOODPATH, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
+ var_traceRouteResultsTable, 2, {1, 8}}
+};
+
+
+
+/*
+ * global storage of our data, saved in and configured by header_complex()
+ */
+
+extern struct header_complex_index *traceRouteCtlTableStorage;
+extern struct header_complex_index *traceRouteResultsTableStorage;
+void
+traceRouteResultsTable_inadd(struct traceRouteResultsTable_data *thedata);
+
+void
+traceRouteResultsTable_cleaner(struct header_complex_index *thestuff)
+{
+ struct header_complex_index *hciptr = NULL;
+ struct traceRouteResultsTable_data *StorageDel = NULL;
+ DEBUGMSGTL(("traceRouteResultsTable", "cleanerout "));
+ for (hciptr = thestuff; hciptr != NULL; hciptr = hciptr->next) {
+ StorageDel =
+ header_complex_extract_entry(&traceRouteResultsTableStorage,
+ hciptr);
+ if (StorageDel != NULL) {
+ free(StorageDel->traceRouteCtlOwnerIndex);
+ StorageDel->traceRouteCtlOwnerIndex = NULL;
+ free(StorageDel->traceRouteCtlTestName);
+ StorageDel->traceRouteCtlTestName = NULL;
+ free(StorageDel->traceRouteResultsIpTgtAddr);
+ StorageDel->traceRouteResultsIpTgtAddr = NULL;
+ free(StorageDel->traceRouteResultsLastGoodPath);
+ StorageDel->traceRouteResultsLastGoodPath = NULL;
+ free(StorageDel);
+ StorageDel = NULL;
+
+ }
+ DEBUGMSGTL(("traceRouteResultsTable", "cleaner "));
+ }
+
+}
+
+void
+init_traceRouteResultsTable(void)
+{
+
+ DEBUGMSGTL(("traceRouteResultsTable", "initializing... "));
+
+
+ /*
+ * register ourselves with the agent to handle our mib tree
+ */
+ REGISTER_MIB("traceRouteResultsTable",
+ traceRouteResultsTable_variables, variable2,
+ traceRouteResultsTable_variables_oid);
+
+
+ /*
+ * register our config handler(s) to deal with registrations
+ */
+ snmpd_register_config_handler("traceRouteResultsTable",
+ parse_traceRouteResultsTable, NULL,
+ NULL);
+
+ /*
+ * we need to be called back later to store our data
+ */
+ snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
+ store_traceRouteResultsTable, NULL);
+
+ DEBUGMSGTL(("traceRouteResultsTable", "done.\n"));
+}
+
+/*
+ * parse_mteObjectsTable():
+ * parses .conf file entries needed to configure the mib.
+ */
+
+void
+parse_traceRouteResultsTable(const char *token, char *line)
+{
+ size_t tmpint;
+ struct traceRouteResultsTable_data *StorageTmp =
+ SNMP_MALLOC_STRUCT(traceRouteResultsTable_data);
+
+ DEBUGMSGTL(("traceRouteResultsTable", "parsing config... "));
+
+
+ if (StorageTmp == NULL) {
+ config_perror("malloc failure");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlOwnerIndex,
+ &StorageTmp->traceRouteCtlOwnerIndexLen);
+ if (StorageTmp->traceRouteCtlOwnerIndex == NULL) {
+ config_perror("invalid specification for traceRouteCtlOwnerIndex");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteCtlTestName,
+ &StorageTmp->traceRouteCtlTestNameLen);
+ if (StorageTmp->traceRouteCtlTestName == NULL) {
+ config_perror("invalid specification for traceRouteCtlTestName");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteResultsOperStatus,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_GAUGE, line,
+ &StorageTmp->traceRouteResultsCurHopCount,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_GAUGE, line,
+ &StorageTmp->traceRouteResultsCurProbeCount,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_INTEGER, line,
+ &StorageTmp->traceRouteResultsIpTgtAddrType,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteResultsIpTgtAddr,
+ &StorageTmp->traceRouteResultsIpTgtAddrLen);
+ if (StorageTmp->traceRouteResultsIpTgtAddr == NULL) {
+ config_perror
+ ("invalid specification for traceRouteResultsIpTgtAddr");
+ return;
+ }
+
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteResultsTestAttempts,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_UNSIGNED, line,
+ &StorageTmp->traceRouteResultsTestSuccesses,
+ &tmpint);
+ line =
+ read_config_read_data(ASN_OCTET_STR, line,
+ &StorageTmp->traceRouteResultsLastGoodPath,
+ &StorageTmp->
+ traceRouteResultsLastGoodPathLen);
+ if (StorageTmp->traceRouteResultsLastGoodPath == NULL) {
+ config_perror
+ ("invalid specification for traceRouteResultsLastGoodPath!");
+ return;
+ }
+
+
+ traceRouteResultsTable_inadd(StorageTmp);
+
+ /* traceRouteResultsTable_cleaner(traceRouteResultsTableStorage); */
+
+ DEBUGMSGTL(("traceRouteResultsTable", "done.\n"));
+}
+
+
+
+
+
+/*
+ * store_traceRouteResultsTable():
+ * stores .conf file entries needed to configure the mib.
+ */
+
+int
+store_traceRouteResultsTable(int majorID, int minorID, void *serverarg,
+ void *clientarg)
+{
+ char line[SNMP_MAXBUF];
+ char *cptr = NULL;
+ size_t tmpint;
+ struct traceRouteResultsTable_data *StorageTmp = NULL;
+ struct header_complex_index *hcindex = NULL;
+
+
+ DEBUGMSGTL(("traceRouteResultsTable", "storing data... "));
+
+
+ for (hcindex = traceRouteResultsTableStorage; hcindex != NULL;
+ hcindex = hcindex->next) {
+ StorageTmp = (struct traceRouteResultsTable_data *) hcindex->data;
+
+ if (StorageTmp->storageType != ST_READONLY) {
+ memset(line, 0, sizeof(line));
+ strcat(line, "traceRouteResultsTable ");
+ cptr = line + strlen(line);
+
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteCtlOwnerIndex,
+ &StorageTmp->
+ traceRouteCtlOwnerIndexLen);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->traceRouteCtlTestName,
+ &StorageTmp->
+ traceRouteCtlTestNameLen);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteResultsOperStatus,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_GAUGE, cptr,
+ &StorageTmp->
+ traceRouteResultsCurHopCount,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_GAUGE, cptr,
+ &StorageTmp->
+ traceRouteResultsCurProbeCount,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_INTEGER, cptr,
+ &StorageTmp->
+ traceRouteResultsIpTgtAddrType,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteResultsIpTgtAddr,
+ &StorageTmp->
+ traceRouteResultsIpTgtAddrLen);
+
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteResultsTestAttempts,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_UNSIGNED, cptr,
+ &StorageTmp->
+ traceRouteResultsTestSuccesses,
+ &tmpint);
+ cptr =
+ read_config_store_data(ASN_OCTET_STR, cptr,
+ &StorageTmp->
+ traceRouteResultsLastGoodPath,
+ &StorageTmp->
+ traceRouteResultsLastGoodPathLen);
+
+ snmpd_store_config(line);
+ }
+ }
+ DEBUGMSGTL(("traceRouteResultsTable", "done.\n"));
+ return SNMPERR_SUCCESS;
+}
+
+void
+traceRouteResultsTable_inadd(struct traceRouteResultsTable_data *thedata)
+{
+ netsnmp_variable_list *vars_list = NULL;
+
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlOwnerIndex, thedata->traceRouteCtlOwnerIndexLen); /* traceRouteCtlOwnerIndex */
+ snmp_varlist_add_variable(&vars_list, NULL, 0, ASN_OCTET_STR, (char *) thedata->traceRouteCtlTestName, thedata->traceRouteCtlTestNameLen); /* traceRouteCtlTestName */
+
+ DEBUGMSGTL(("traceRouteResultsTable", "adding data... "));
+ /*
+ * add the index variables to the varbind list, which is
+ * used by header_complex to index the data
+ */
+
+ header_complex_add_data(&traceRouteResultsTableStorage, vars_list,
+ thedata);
+ DEBUGMSGTL(("traceRouteResultsTable", "registered an entry\n"));
+
+
+ DEBUGMSGTL(("traceRouteResultsTable", "done.\n"));
+}
+
+
+/*
+ * var_traceRouteResultsTable():
+ * Handle this table separately from the scalar value case.
+ * The workings of this are basically the same as for var_traceRouteResultsTable above.
+ */
+unsigned char *
+var_traceRouteResultsTable(struct variable *vp,
+ oid * name,
+ size_t *length,
+ int exact,
+ size_t *var_len, WriteMethod ** write_method)
+{
+
+
+ struct traceRouteResultsTable_data *StorageTmp = NULL;
+
+ *write_method = NULL;
+
+ /*
+ * this assumes you have registered all your data properly
+ */
+ if ((StorageTmp =
+ header_complex(traceRouteResultsTableStorage, vp, name, length,
+ exact, var_len, write_method)) == NULL) {
+ return NULL;
+ }
+
+ /*
+ * this is where we do the value assignments for the mib results.
+ */
+
+ switch (vp->magic) {
+
+ case COLUMN_TRACEROUTERESULTSOPERSTATUS:
+ *var_len = sizeof(StorageTmp->traceRouteResultsOperStatus);
+ return (u_char *) & StorageTmp->traceRouteResultsOperStatus;
+
+ case COLUMN_TRACEROUTERESULTSCURHOPCOUNT:
+ *var_len = sizeof(StorageTmp->traceRouteResultsCurHopCount);
+ return (u_char *) & StorageTmp->traceRouteResultsCurHopCount;
+
+ case COLUMN_TRACEROUTERESULTSCURPROBECOUNT:
+ *var_len = sizeof(StorageTmp->traceRouteResultsCurProbeCount);
+ return (u_char *) & StorageTmp->traceRouteResultsCurProbeCount;
+
+ case COLUMN_TRACEROUTERESULTSIPTGTADDRTYPE:
+ *var_len = sizeof(StorageTmp->traceRouteResultsIpTgtAddrType);
+ return (u_char *) & StorageTmp->traceRouteResultsIpTgtAddrType;
+
+ case COLUMN_TRACEROUTERESULTSIPTGTADDR:
+ *var_len = (StorageTmp->traceRouteResultsIpTgtAddrLen);
+ return (u_char *) StorageTmp->traceRouteResultsIpTgtAddr;
+
+ case COLUMN_TRACEROUTERESULTSTESTATTEMPTS:
+ *var_len = sizeof(StorageTmp->traceRouteResultsTestAttempts);
+ return (u_char *) & StorageTmp->traceRouteResultsTestAttempts;
+
+ case COLUMN_TRACEROUTERESULTSTESTSUCCESSES:
+ *var_len = sizeof(StorageTmp->traceRouteResultsTestSuccesses);
+ return (u_char *) & StorageTmp->traceRouteResultsTestSuccesses;
+
+ case COLUMN_TRACEROUTERESULTSLASTGOODPATH:
+ *var_len = (StorageTmp->traceRouteResultsLastGoodPathLen);
+ return (u_char *) StorageTmp->traceRouteResultsLastGoodPath;
+
+ default:
+ ERROR_MSG("");
+ }
+
+ return NULL;
+}
diff --git a/agent/mibgroup/disman/traceroute/traceRouteResultsTable.h b/agent/mibgroup/disman/traceroute/traceRouteResultsTable.h
new file mode 100644
index 0000000..f31ffbf
--- /dev/null
+++ b/agent/mibgroup/disman/traceroute/traceRouteResultsTable.h
@@ -0,0 +1,40 @@
+/*
+ *Copyright(c)2004,Cisco URP imburses and Network Information Center in Beijing University of Posts and Telecommunications researches.
+ *
+ *All right reserved
+ *
+ *File Name:traceRouteResultsTable.h
+ *File Description:The head file of traceRouteResultsTable.c
+ *
+ *Current Version:1.0
+ *Author:ChenJing
+ *Date:2004.8.20
+ */
+
+#ifndef TRACEROUTERESULTSTABLE_H
+#define TRACEROUTERESULTSTABLE_H
+
+
+config_require(header_complex);
+
+/*
+ * function declarations
+ */
+void init_traceRouteResultsTable(void);
+FindVarMethod var_traceRouteResultsTable;
+void parse_traceRouteResultsTable(const char *, char *);
+SNMPCallback store_traceRouteResultsTable;
+
+
+/*
+ * column number definitions for table traceRouteResultsTable
+ */
+#define COLUMN_TRACEROUTERESULTSOPERSTATUS 1
+#define COLUMN_TRACEROUTERESULTSCURHOPCOUNT 2
+#define COLUMN_TRACEROUTERESULTSCURPROBECOUNT 3
+#define COLUMN_TRACEROUTERESULTSIPTGTADDRTYPE 4
+#define COLUMN_TRACEROUTERESULTSIPTGTADDR 5
+#define COLUMN_TRACEROUTERESULTSTESTATTEMPTS 6
+#define COLUMN_TRACEROUTERESULTSTESTSUCCESSES 7
+#define COLUMN_TRACEROUTERESULTSLASTGOODPATH 8
+#endif /* TRACEROUTERESULTSTABLE_H */