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