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