diff options
Diffstat (limited to 'agent/mibgroup/disman')
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(¶m_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( ¶m_var, ASN_INTEGER, + (u_char*)&n, sizeof(long)); + owner_var.next_variable = &name_var; + name_var.next_variable = ¶m_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, ¤t_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(¤t_temp) != + SNMPERR_SUCCESS) + DEBUGMSGTL(("pingProbeHistoryTable", + "registered an entry error\n")); + } else { + pingProbeHistoryTable_delLast(item); + if (pingProbeHistoryTable_add(¤t_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, ¤t_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 *) ⌖ + 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(¤t->traceRouteHopsLastGoodProbe, + date_n_time(&timep, + ¤t->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(¤t->traceRouteHopsLastGoodProbe, + date_n_time(&timep, + ¤t->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 */ |