| /* |
| * 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 (%x)\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", ": %x, %x\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); |
| } |