diff options
Diffstat (limited to 'agent/mibgroup/disman/event/mteEventConf.c')
-rw-r--r-- | agent/mibgroup/disman/event/mteEventConf.c | 588 |
1 files changed, 588 insertions, 0 deletions
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; +} |