diff options
Diffstat (limited to 'agent/mibgroup/disman/expr/expValueTable.c')
-rw-r--r-- | agent/mibgroup/disman/expr/expValueTable.c | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/agent/mibgroup/disman/expr/expValueTable.c b/agent/mibgroup/disman/expr/expValueTable.c new file mode 100644 index 0000000..3c36f38 --- /dev/null +++ b/agent/mibgroup/disman/expr/expValueTable.c @@ -0,0 +1,327 @@ +/* + * 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 0; + } + + 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 (%x)\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 (%x)\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 != %d)\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 (%x)\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 (%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 (%x)\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 (%x)\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 (%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 (%x)\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); + } + res = expValue_evaluateExpression( exp, vp->val.objid+1, len-1); + DEBUGMSGTL(( "disman:expr:val", "w/card next returned (%x)\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; +} |