Blame agent/mibgroup/disman/expr/expValueTable.c

Packit fcad23
/*
Packit fcad23
 * DisMan Expression MIB:
Packit fcad23
 *    Implementation of the expValueTable MIB interface
Packit fcad23
 * See 'expValue.c' for active evaluation of expressions.
Packit fcad23
 *
Packit fcad23
 *  (Based roughly on mib2c.raw-table.conf output)
Packit fcad23
 */
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#include <net-snmp/net-snmp-includes.h>
Packit fcad23
#include <net-snmp/agent/net-snmp-agent-includes.h>
Packit fcad23
#include "expValue.h"
Packit fcad23
#include "expValueTable.h"
Packit fcad23
Packit fcad23
/** Initializes the expValueTable module */
Packit fcad23
void
Packit fcad23
init_expValueTable(void)
Packit fcad23
{
Packit fcad23
    static oid  expValueTable_oid[]   = { 1, 3, 6, 1, 2, 1, 90, 1, 3, 1 };
Packit fcad23
    size_t      expValueTable_oid_len = OID_LENGTH(expValueTable_oid);
Packit fcad23
    netsnmp_handler_registration *reg;
Packit fcad23
    netsnmp_table_registration_info *table_info;
Packit fcad23
Packit fcad23
    reg =
Packit fcad23
        netsnmp_create_handler_registration("expValueTable",
Packit fcad23
                                            expValueTable_handler,
Packit fcad23
                                            expValueTable_oid,
Packit fcad23
                                            expValueTable_oid_len,
Packit fcad23
                                            HANDLER_CAN_RONLY);
Packit fcad23
Packit fcad23
    table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
Packit fcad23
    netsnmp_table_helper_add_indexes(table_info,
Packit fcad23
                                     ASN_OCTET_STR, /* expExpressionOwner */
Packit fcad23
                                     ASN_OCTET_STR, /* expExpressionName  */
Packit fcad23
                                                    /* expValueInstance   */
Packit fcad23
                                     ASN_PRIV_IMPLIED_OBJECT_ID,
Packit fcad23
                                     0);
Packit fcad23
Packit fcad23
    table_info->min_column = COLUMN_EXPVALUECOUNTER32VAL;
Packit fcad23
    table_info->max_column = COLUMN_EXPVALUECOUNTER64VAL;
Packit fcad23
Packit fcad23
    netsnmp_register_table(reg, table_info);
Packit fcad23
    DEBUGMSGTL(("disman:expr:init", "Expression Value Table\n"));
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
netsnmp_variable_list *
Packit fcad23
expValueTable_getEntry(netsnmp_variable_list * indexes,
Packit fcad23
                       int mode, unsigned int colnum)
Packit fcad23
{
Packit fcad23
    struct expExpression  *exp;
Packit fcad23
    netsnmp_variable_list *res, *vp, *vp2;
Packit fcad23
    oid nullInstance[] = {0, 0, 0};
Packit fcad23
    int  plen;
Packit fcad23
    size_t len;
Packit fcad23
    unsigned int type = colnum-1; /* column object subIDs and type
Packit fcad23
                                      enumerations are off by one. */
Packit fcad23
Packit fcad23
    if (!indexes || !indexes->next_variable ||
Packit fcad23
        !indexes->next_variable->next_variable ) {
Packit fcad23
        /* XXX - Shouldn't happen! */
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DEBUGMSGTL(( "disman:expr:val", "get (%d) entry (%s, %s, ", mode,
Packit fcad23
               indexes->val.string, indexes->next_variable->val.string));
Packit fcad23
    DEBUGMSGOID(("disman:expr:val",
Packit fcad23
               indexes->next_variable->next_variable->val.objid,
Packit fcad23
               indexes->next_variable->next_variable->val_len/sizeof(oid)));
Packit fcad23
    DEBUGMSG((   "disman:expr:val", ")\n"));
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Locate the expression that we've been asked to evaluate
Packit fcad23
     */
Packit fcad23
    if (!indexes->val_len || !indexes->next_variable->val_len ) {
Packit fcad23
        /*
Packit fcad23
         * Incomplete expression specification
Packit fcad23
         */
Packit fcad23
        if (mode == MODE_GETNEXT || mode == MODE_GETBULK) {
Packit fcad23
            exp = expExpression_getFirstEntry();
Packit fcad23
            DEBUGMSGTL(( "disman:expr:val", "first entry (%p)\n", exp ));
Packit fcad23
        } else {
Packit fcad23
            DEBUGMSGTL(( "disman:expr:val", "incomplete request\n" ));
Packit fcad23
            return NULL;        /* No match */
Packit fcad23
        }
Packit fcad23
    } else {
Packit fcad23
        exp = expExpression_getEntry( (char*)indexes->val.string,
Packit fcad23
                                      (char*)indexes->next_variable->val.string);
Packit fcad23
        DEBUGMSGTL(( "disman:expr:val", "using entry (%p)\n", exp ));
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * We know what type of value was requested,
Packit fcad23
     *   so ignore any non-matching expressions.
Packit fcad23
     */
Packit fcad23
    while (exp && exp->expValueType != type) {
Packit fcad23
        if (mode != MODE_GETNEXT && mode != MODE_GETBULK) {
Packit fcad23
            DEBUGMSGTL(( "disman:expr:val", "wrong type (%d != %ld)\n",
Packit fcad23
                          type, (exp ? exp->expValueType : 0 )));
Packit fcad23
            return NULL;        /* Wrong type */
Packit fcad23
        }
Packit fcad23
NEXT_EXP:
Packit fcad23
        exp = expExpression_getNextEntry( exp->expOwner, exp->expName );
Packit fcad23
        DEBUGMSGTL(( "disman:expr:val", "using next entry (%p)\n", exp ));
Packit fcad23
    }
Packit fcad23
    if (!exp) {
Packit fcad23
        DEBUGMSGTL(( "disman:expr:val", "no more entries\n"));
Packit fcad23
        return NULL;    /* No match (of the required type) */
Packit fcad23
    }
Packit fcad23
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Now consider which instance of the chosen expression is needed
Packit fcad23
     */
Packit fcad23
    vp  = indexes->next_variable->next_variable;
Packit fcad23
    if ( mode == MODE_GET ) {
Packit fcad23
        /*
Packit fcad23
         * For a GET request, check that the specified value instance
Packit fcad23
         *   is valid, and evaluate the expression using this.
Packit fcad23
         */
Packit fcad23
        if ( !vp || !vp->val_len ) {
Packit fcad23
            DEBUGMSGTL(( "disman:expr:val", "no instance index\n"));
Packit fcad23
            return NULL;  /* No instance provided */
Packit fcad23
        }
Packit fcad23
        if ( vp->val.objid[0] != 0 ) {
Packit fcad23
            DEBUGMSGTL(( "disman:expr:val",
Packit fcad23
                         "non-zero instance (%" NETSNMP_PRIo "d)\n", vp->val.objid[0]));
Packit fcad23
            return NULL;  /* Invalid instance */
Packit fcad23
        }
Packit fcad23
Packit fcad23
        if (exp->expPrefix_len == 0 ) {
Packit fcad23
            /*
Packit fcad23
             * The only valid instance for a non-wildcarded
Packit fcad23
             *     expression is .0.0.0
Packit fcad23
             */
Packit fcad23
            if ( vp->val_len != 3*sizeof(oid) ||
Packit fcad23
                 vp->val.objid[1] != 0 ||
Packit fcad23
                 vp->val.objid[2] != 0 ) {
Packit fcad23
                DEBUGMSGTL(( "disman:expr:val", "invalid scalar instance\n"));
Packit fcad23
                return NULL;
Packit fcad23
            }
Packit fcad23
            res = expValue_evaluateExpression( exp, NULL, 0 );
Packit fcad23
            DEBUGMSGTL(( "disman:expr:val", "scalar get returned (%p)\n", res));
Packit fcad23
        } else {
Packit fcad23
            /*
Packit fcad23
             * Otherwise, skip the leading '.0' and use
Packit fcad23
             *   the remaining instance subidentifiers.
Packit fcad23
             */
Packit fcad23
            res = expValue_evaluateExpression( exp, vp->val.objid+1,
Packit fcad23
                                           vp->val_len/sizeof(oid)-1);
Packit fcad23
            DEBUGMSGTL(( "disman:expr:val", "w/card get returned (%p)\n", res));
Packit fcad23
        }
Packit fcad23
    } else {
Packit fcad23
        /*
Packit fcad23
         * For a GETNEXT request, identify the appropriate next
Packit fcad23
         *   value instance, and evaluate the expression using
Packit fcad23
         *   that, updating the index list appropriately.
Packit fcad23
         */
Packit fcad23
        if ( vp->val_len > 0 && vp->val.objid[0] != 0 ) {
Packit fcad23
            DEBUGMSGTL(( "disman:expr:val",
Packit fcad23
                         "non-zero next instance (%" NETSNMP_PRIo "d)\n", vp->val.objid[0]));
Packit fcad23
            return NULL;        /* All valid instances start with .0 */
Packit fcad23
        }
Packit fcad23
        plen = exp->expPrefix_len;
Packit fcad23
        if (plen == 0 ) {
Packit fcad23
            /*
Packit fcad23
             * The only valid instances for GETNEXT on a
Packit fcad23
             *   non-wildcarded expression are .0 and .0.0
Packit fcad23
             *   Anything else is too late.
Packit fcad23
             */
Packit fcad23
            if ((vp->val_len > 2*sizeof(oid)) ||
Packit fcad23
                (vp->val_len == 2*sizeof(oid) &&
Packit fcad23
                      vp->val.objid[1] != 0)) {
Packit fcad23
                DEBUGMSGTL(( "disman:expr:val", "invalid scalar next instance\n"));
Packit fcad23
                return NULL;        /* Invalid instance */
Packit fcad23
            }
Packit fcad23
     
Packit fcad23
            /*
Packit fcad23
             * Make sure the index varbind list refers to the
Packit fcad23
             *   (only) valid instance of this expression,
Packit fcad23
             *   and evaluate it.
Packit fcad23
             */
Packit fcad23
            snmp_set_var_typed_value( indexes, ASN_OCTET_STR,
Packit fcad23
                       (u_char*)exp->expOwner, strlen(exp->expOwner));
Packit fcad23
            snmp_set_var_typed_value( indexes->next_variable, ASN_OCTET_STR,
Packit fcad23
                       (u_char*)exp->expName,  strlen(exp->expName));
Packit fcad23
            snmp_set_var_typed_value( vp, ASN_PRIV_IMPLIED_OBJECT_ID,
Packit fcad23
                       (u_char*)nullInstance, 3*sizeof(oid));
Packit fcad23
            res = expValue_evaluateExpression( exp, NULL, 0 );
Packit fcad23
            DEBUGMSGTL(( "disman:expr:val", "scalar next returned (%p)\n", res));
Packit fcad23
        } else {
Packit fcad23
            /*
Packit fcad23
             * Now comes the interesting case - finding the
Packit fcad23
             *   appropriate instance of a wildcarded expression.
Packit fcad23
             */
Packit fcad23
            if ( vp->val_len == 0 ) {
Packit fcad23
                 if ( !exp->pvars ) {
Packit fcad23
                     DEBUGMSGTL(( "disman:expr:val", "no instances\n"));
Packit fcad23
                     goto NEXT_EXP;
Packit fcad23
                 }
Packit fcad23
                 DEBUGMSGTL(( "disman:expr:val", "using first instance\n"));
Packit fcad23
                 vp2 = exp->pvars;
Packit fcad23
            } else {
Packit fcad23
                 /*
Packit fcad23
                  * Search the list of instances for the (first) greater one
Packit fcad23
                  *   XXX - This comparison relies on the OID of the prefix
Packit fcad23
                  *         object being the same length as the wildcarded
Packit fcad23
                  *         parameter objects.  It ain't necessarily so.
Packit fcad23
                  */
Packit fcad23
                 for ( vp2 = exp->pvars; vp2; vp2 = vp2->next_variable ) {
Packit fcad23
                     if ( snmp_oid_compare( vp2->name        + plen,
Packit fcad23
                                            vp2->name_length - plen,
Packit fcad23
                                            vp->name,
Packit fcad23
                                            vp->name_length) < 0 ) {
Packit fcad23
                         DEBUGMSGTL(( "disman:expr:val", "next instance "));
Packit fcad23
                         DEBUGMSGOID(("disman:expr:val",  vp2->name, vp2->name_length ));
Packit fcad23
                         DEBUGMSG((   "disman:expr:val", "\n"));
Packit fcad23
                         break;
Packit fcad23
                     }
Packit fcad23
                 }
Packit fcad23
                 if (!vp2) {
Packit fcad23
                     DEBUGMSGTL(( "disman:expr:val", "no next instance\n"));
Packit fcad23
                     goto NEXT_EXP;
Packit fcad23
                 }
Packit fcad23
            }
Packit fcad23
            snmp_set_var_typed_value( indexes, ASN_OCTET_STR,
Packit fcad23
                       (u_char*)exp->expOwner, strlen(exp->expOwner));
Packit fcad23
            snmp_set_var_typed_value( indexes->next_variable, ASN_OCTET_STR,
Packit fcad23
                       (u_char*)exp->expName,  strlen(exp->expName));
Packit fcad23
            if (vp2) {
Packit fcad23
                len = vp2->name_length - exp->expPrefix_len;
Packit fcad23
                snmp_set_var_typed_value( vp, ASN_PRIV_IMPLIED_OBJECT_ID,
Packit fcad23
                      (u_char*)(vp2->name+exp->expPrefix_len), len);
Packit fcad23
            } else {
Packit fcad23
                len = 1;
Packit fcad23
            }
Packit fcad23
            res = expValue_evaluateExpression( exp, vp->val.objid+1, len-1);
Packit fcad23
            DEBUGMSGTL(( "disman:expr:val", "w/card next returned (%p)\n", res));
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    return res;
Packit fcad23
}
Packit fcad23
Packit fcad23
/** handles requests for the expValueTable table */
Packit fcad23
int
Packit fcad23
expValueTable_handler(netsnmp_mib_handler *handler,
Packit fcad23
                      netsnmp_handler_registration *reginfo,
Packit fcad23
                      netsnmp_agent_request_info *reqinfo,
Packit fcad23
                      netsnmp_request_info *requests)
Packit fcad23
{
Packit fcad23
Packit fcad23
    netsnmp_request_info       *request;
Packit fcad23
    netsnmp_table_request_info *tinfo;
Packit fcad23
    netsnmp_variable_list      *value;
Packit fcad23
    oid    expValueOID[] = { 1, 3, 6, 1, 2, 1, 90, 1, 3, 1, 1, 99 };
Packit fcad23
    size_t expValueOID_len = OID_LENGTH(expValueOID);
Packit fcad23
    oid    name_buf[ MAX_OID_LEN ];
Packit fcad23
    size_t name_buf_len = MAX_OID_LEN;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("disman:expr:mib", "Expression Value Table handler (%d)\n",
Packit fcad23
                                    reqinfo->mode));
Packit fcad23
    switch (reqinfo->mode) {
Packit fcad23
    case MODE_GET:
Packit fcad23
    case MODE_GETNEXT:
Packit fcad23
        for (request = requests; request; request = request->next) {
Packit fcad23
            tinfo = netsnmp_extract_table_info(request);
Packit fcad23
            value = expValueTable_getEntry(tinfo->indexes,
Packit fcad23
                                           reqinfo->mode,
Packit fcad23
                                           tinfo->colnum);
Packit fcad23
            if (!value || !value->val.integer) {
Packit fcad23
                netsnmp_set_request_error(reqinfo, request,
Packit fcad23
                                         (reqinfo->mode == MODE_GET) ? 
Packit fcad23
                                                 SNMP_NOSUCHINSTANCE :
Packit fcad23
                                                 SNMP_ENDOFMIBVIEW);
Packit fcad23
                continue;
Packit fcad23
            }
Packit fcad23
            if ( reqinfo->mode == MODE_GETNEXT ) {
Packit fcad23
                 /*
Packit fcad23
                  * Need to update the request varbind OID
Packit fcad23
                  *   to match the instance just evaluated.
Packit fcad23
                  * (XXX - Is this the appropriate mechanism?)
Packit fcad23
                  */
Packit fcad23
                build_oid_noalloc( name_buf, MAX_OID_LEN, &name_buf_len,
Packit fcad23
                           expValueOID, expValueOID_len, tinfo->indexes );
Packit fcad23
                name_buf[ expValueOID_len -1 ] = tinfo->colnum;
Packit fcad23
                snmp_set_var_objid(request->requestvb, name_buf, name_buf_len);
Packit fcad23
            }
Packit fcad23
Packit fcad23
            switch (tinfo->colnum) {
Packit fcad23
            case COLUMN_EXPVALUECOUNTER32VAL:
Packit fcad23
                snmp_set_var_typed_integer(request->requestvb, ASN_COUNTER,
Packit fcad23
                                          *value->val.integer);
Packit fcad23
                break;
Packit fcad23
            case COLUMN_EXPVALUEUNSIGNED32VAL:
Packit fcad23
                snmp_set_var_typed_integer(request->requestvb, ASN_UNSIGNED,
Packit fcad23
                                          *value->val.integer);
Packit fcad23
                break;
Packit fcad23
            case COLUMN_EXPVALUETIMETICKSVAL:
Packit fcad23
                snmp_set_var_typed_integer(request->requestvb, ASN_TIMETICKS,
Packit fcad23
                                          *value->val.integer);
Packit fcad23
                break;
Packit fcad23
            case COLUMN_EXPVALUEINTEGER32VAL:
Packit fcad23
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
Packit fcad23
                                          *value->val.integer);
Packit fcad23
                break;
Packit fcad23
            case COLUMN_EXPVALUEIPADDRESSVAL:
Packit fcad23
                snmp_set_var_typed_integer(request->requestvb, ASN_IPADDRESS,
Packit fcad23
                                          *value->val.integer);
Packit fcad23
                break;
Packit fcad23
            case COLUMN_EXPVALUEOCTETSTRINGVAL:
Packit fcad23
                snmp_set_var_typed_value(  request->requestvb, ASN_OCTET_STR,
Packit fcad23
                                           value->val.string,  value->val_len);
Packit fcad23
                break;
Packit fcad23
            case COLUMN_EXPVALUEOIDVAL:
Packit fcad23
                snmp_set_var_typed_value(  request->requestvb, ASN_OBJECT_ID,
Packit fcad23
                                   (u_char *)value->val.objid, value->val_len);
Packit fcad23
                break;
Packit fcad23
            case COLUMN_EXPVALUECOUNTER64VAL:
Packit fcad23
                snmp_set_var_typed_value(  request->requestvb, ASN_COUNTER64,
Packit fcad23
                               (u_char *)value->val.counter64, value->val_len);
Packit fcad23
                break;
Packit fcad23
            }
Packit fcad23
            /* remember to free the variable list, or we will leak here.. */
Packit fcad23
            snmp_free_varbind(value);
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    }
Packit fcad23
    DEBUGMSGTL(("disman:expr:mib", "Expression Value handler - done \n"));
Packit fcad23
    return SNMP_ERR_NOERROR;
Packit fcad23
}