Пример #1
0
/**********************************************************************
 **********************************************************************
 *                                                                    *
 *                                                                    *
 * netsnmp_table_array_helper_handler()                               *
 *                                                                    *
 *                                                                    *
 **********************************************************************
 **********************************************************************/
int
netsnmp_table_array_helper_handler (netsnmp_mib_handler * handler,
                                    netsnmp_handler_registration * reginfo,
                                    netsnmp_agent_request_info * agtreq_info, netsnmp_request_info * requests)
{

    /*
     * First off, get our pointer from the handler. This
     * lets us get to the table registration information we
     * saved in get_table_array_handler(), as well as the
     * container where the actual table data is stored.
     */
    int rc = SNMP_ERR_NOERROR;

    table_container_data *tad = (table_container_data *) handler->myvoid;

    if (agtreq_info->mode < 0 || agtreq_info->mode > 5)
    {
        DEBUGMSGTL (("table_array", "Mode %d, Got request:\n", agtreq_info->mode));
    }
    else
    {
        DEBUGMSGTL (("table_array", "Mode %s, Got request:\n", mode_name[agtreq_info->mode]));
    }

#ifndef NETSNMP_NO_WRITE_SUPPORT
    if (MODE_IS_SET (agtreq_info->mode))
    {
        /*
         * netsnmp_mutex_lock(&tad->lock);
         */
        rc = process_set_requests (agtreq_info, requests, tad, handler->handler_name);
        /*
         * netsnmp_mutex_unlock(&tad->lock);
         */
    }
    else
#endif                            /* NETSNMP_NO_WRITE_SUPPORT */
        rc = process_get_requests (reginfo, agtreq_info, requests, tad);

    if (rc != SNMP_ERR_NOERROR)
    {
        DEBUGMSGTL (("table_array", "processing returned rc %d\n", rc));
    }

    /*
     * Now we've done our processing. If there is another handler below us,
     * call them.
     */
    if (handler->next)
    {
        rc = netsnmp_call_next_handler (handler, reginfo, agtreq_info, requests);
        if (rc != SNMP_ERR_NOERROR)
        {
            DEBUGMSGTL (("table_array", "next handler returned rc %d\n", rc));
        }
    }

    return rc;
}
Пример #2
0
/** updates a given cache depending on whether it needs to or not.
 */
int
_netsnmp_stash_cache_load( netsnmp_cache *cache, void *magic )
{
    netsnmp_mib_handler          *handler  = cache->cache_hint->handler;
    netsnmp_handler_registration *reginfo  = cache->cache_hint->reginfo;
    netsnmp_agent_request_info   *reqinfo  = cache->cache_hint->reqinfo;
    netsnmp_request_info         *requests = cache->cache_hint->requests;
    netsnmp_stash_cache_info     *cinfo    = (netsnmp_stash_cache_info*) magic;
    int old_mode;
    int ret;

    if (!cinfo) {
        cinfo = netsnmp_get_new_stash_cache();
        cache->magic = cinfo;
    }

    /* change modes to the GET_STASH mode */
    old_mode = reqinfo->mode;
    reqinfo->mode = MODE_GET_STASH;
    netsnmp_agent_add_list_data(reqinfo,
                                netsnmp_create_data_list(STASH_CACHE_NAME,
                                                         &cinfo->cache, NULL));

    /* have the next handler fill stuff in and switch modes back */
    ret = netsnmp_call_next_handler(handler->next, reginfo, reqinfo, requests);
    reqinfo->mode = old_mode;

    return ret;
}
static int
_count_handler(netsnmp_mib_handler *handler,
               netsnmp_handler_registration *reginfo,
               netsnmp_agent_request_info *reqinfo,
               netsnmp_request_info *requests)
{
    int                val;

    if (MODE_GET != reqinfo->mode) {
        snmp_log(LOG_ERR, "bad mode in RO handler");
        return SNMP_ERR_GENERR;
    }

    if (NULL == _table->container)
        val = 0;
    else
        val = CONTAINER_SIZE(_table->container);

    snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE,
                             (u_char *) &val, sizeof(val));
   
    if (handler->next && handler->next->access_method)
        return netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                         requests);
    
    return SNMP_ERR_NOERROR;
}
Пример #4
0
/**
 * \deprecated This function is unused and scheduled for removal in Net-SNMP 5.6
 */
int
netsnmp_instance_counter32_handler(netsnmp_mib_handler *handler,
                                   netsnmp_handler_registration *reginfo,
                                   netsnmp_agent_request_info *reqinfo,
                                   netsnmp_request_info *requests)
{

    u_long         *it = (u_long *) handler->myvoid;

    DEBUGMSGTL(("netsnmp_instance_counter32_handler",
                "Got request:  %d\n", reqinfo->mode));

    switch (reqinfo->mode) {
        /*
         * data requests 
         */
    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER,
                                 (u_char *) it, sizeof(*it));
        break;

        /*
         * SET requests.  Should only get here if registered RWRITE 
         */
    default:
        snmp_log(LOG_ERR,
                 "netsnmp_instance_counter32_handler: illegal mode\n");
        netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR);
        return SNMP_ERR_NOERROR;
    }
    if (handler->next && handler->next->access_method)
        return netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                         requests);
    return SNMP_ERR_NOERROR;
}
/** @internal Implements the mode_end_call handler */
int
netsnmp_mode_end_call_helper(netsnmp_mib_handler *handler,
                            netsnmp_handler_registration *reginfo,
                            netsnmp_agent_request_info *reqinfo,
                            netsnmp_request_info *requests)
{

    int             ret;
    int             ret2 = SNMP_ERR_NOERROR;
    netsnmp_mode_handler_list *ptr;

    /* always call the real handlers first */
    ret = netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                    requests);

    /* then call the callback handlers */
    for (ptr = (netsnmp_mode_handler_list*)handler->myvoid; ptr; ptr = ptr->next) {
        if (ptr->mode == NETSNMP_MODE_END_ALL_MODES ||
            reqinfo->mode == ptr->mode) {
            ret2 = netsnmp_call_handler(ptr->callback_handler, reginfo,
                                             reqinfo, requests);
            if (ret != SNMP_ERR_NOERROR)
                ret = ret2;
        }
    }
    
    return ret2;
}
Пример #6
0
static int mib_handle_ifNumber(netsnmp_mib_handler *handler,
                          netsnmp_handler_registration *reginfo,
                          netsnmp_agent_request_info   *reqinfo,
                          netsnmp_request_info         *requests)
{

    
    switch(reqinfo->mode) 
    {
        case MODE_GET:
        {
			u32 val =0;
			ifm_get_port_num_by_type(MIB_IF_TYPE, &val);
			snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,(u_char *) &val, sizeof(val));
            break;
        }

        default:
        {
            snmp_log(LOG_ERR, "unknown mode (%d) in handle_ifNumber\n", reqinfo->mode );
            return SNMP_ERR_GENERR;
        }
    }
	
    if (handler->next && handler->next->access_method)
    {
        return netsnmp_call_next_handler(handler, reginfo, reqinfo,requests);
    }

    return SNMP_ERR_NOERROR;
}
Пример #7
0
/** Implements the serial handler */
int
netsnmp_serialize_helper_handler(netsnmp_mib_handler *handler,
                                 netsnmp_handler_registration *reginfo,
                                 netsnmp_agent_request_info *reqinfo,
                                 netsnmp_request_info *requests)
{

    netsnmp_request_info *request, *requesttmp;

    DEBUGMSGTL(("helper:serialize", "Got request\n"));
    /*
     * loop through requests 
     */
    for (request = requests; request; request = request->next) {
        int             ret;

        /*
         * store next pointer and delete it 
         */
        requesttmp = request->next;
        request->next = NULL;

        /*
         * call the next handler 
         */
        ret =
            netsnmp_call_next_handler(handler, reginfo, reqinfo, request);

        /*
         * restore original next pointer 
         */
        request->next = requesttmp;

        if (ret != SNMP_ERR_NOERROR)
            return ret;
    }

    return SNMP_ERR_NOERROR;
}
static int
_table_row_handler(netsnmp_mib_handler          *handler,
                   netsnmp_handler_registration *reginfo,
                   netsnmp_agent_request_info   *reqinfo,
                   netsnmp_request_info         *requests)
{
    int             rc = SNMP_ERR_NOERROR;
    netsnmp_request_info *req;
    void                 *row;

    /** sanity checks */
    netsnmp_assert((NULL != handler) && (NULL != handler->myvoid));
    netsnmp_assert((NULL != reginfo) && (NULL != reqinfo));

    DEBUGMSGTL(("table_row", "Mode %s, Got request:\n",
                se_find_label_in_slist("agent_mode",reqinfo->mode)));

    /*
     * First off, get our pointer from the handler.
     * This contains the row that was actually registered.
     * Make this available for each of the requests passed in.
     */
    row = handler->myvoid;
    for (req = requests; req; req=req->next)
        netsnmp_request_add_list_data(req,
                netsnmp_create_data_list(TABLE_ROW_DATA, row, NULL));

    /*
     * Then call the next handler, to actually process the request
     */
    rc = netsnmp_call_next_handler(handler, reginfo, reqinfo, requests);
    if (rc != SNMP_ERR_NOERROR) {
        DEBUGMSGTL(("table_row", "next handler returned %d\n", rc));
    }

    return rc;
}
Пример #9
0
/** @internal Implements the baby_steps handler */
static int
_baby_steps_helper(netsnmp_mib_handler *handler,
                         netsnmp_handler_registration *reginfo,
                         netsnmp_agent_request_info *reqinfo,
                         netsnmp_request_info *requests)
{
    netsnmp_baby_steps_modes *bs_modes;
    int save_mode, i, rc = SNMP_ERR_NOERROR;
    u_short *mode_map_ptr;
    
    DEBUGMSGTL(("baby_steps", "Got request, mode %s\n",
                se_find_label_in_slist("agent_mode",reqinfo->mode)));

    bs_modes = handler->myvoid;
    netsnmp_assert(NULL != bs_modes);

    switch (reqinfo->mode) {

    case MODE_SET_RESERVE1:
        /*
         * clear completed modes
         * xxx-rks: this will break for pdus with set requests to different
         * rows in the same table when the handler is set up to use the row
         * merge helper as well (or if requests are serialized).
         */
        bs_modes->completed = 0;
        /** fall through */

    case MODE_SET_RESERVE2:
    case MODE_SET_ACTION:
    case MODE_SET_COMMIT:
    case MODE_SET_FREE:
    case MODE_SET_UNDO:
        mode_map_ptr = set_mode_map[reqinfo->mode];
        break;
            
    default:
        /*
         * clear completed modes
         */
        bs_modes->completed = 0;

        mode_map_ptr = get_mode_map;
    }

    /*
     * NOTE: if you update this chart, please update the versions in
     *       local/mib2c-conf.d/parent-set.m2i
     *       agent/mibgroup/helpers/baby_steps.c
     * while you're at it.
     */
    /*
     ***********************************************************************
     * Baby Steps Flow Chart (2004.06.05)                                  *
     *                                                                     *
     * +--------------+    +================+    U = unconditional path    *
     * |optional state|    ||required state||    S = path for success      *
     * +--------------+    +================+    E = path for error        *
     ***********************************************************************
     *
     *                        +--------------+
     *                        |     pre      |
     *                        |   request    |
     *                        +--------------+
     *                               | U
     * +-------------+        +==============+
     * |    row    |f|<-------||  object    ||
     * |  create   |1|      E ||  lookup    ||
     * +-------------+        +==============+
     *     E |   | S                 | S
     *       |   +------------------>|
     *       |                +==============+
     *       |              E ||   check    ||
     *       |<---------------||   values   ||
     *       |                +==============+
     *       |                       | S
     *       |                +==============+
     *       |       +<-------||   undo     ||
     *       |       |      E ||   setup    ||
     *       |       |        +==============+
     *       |       |               | S
     *       |       |        +==============+
     *       |       |        ||    set     ||-------------------------->+
     *       |       |        ||   value    || E                         |
     *       |       |        +==============+                           |
     *       |       |               | S                                 |
     *       |       |        +--------------+                           |
     *       |       |        |    check     |-------------------------->|
     *       |       |        |  consistency | E                         |
     *       |       |        +--------------+                           |
     *       |       |               | S                                 |
     *       |       |        +==============+         +==============+  |
     *       |       |        ||   commit   ||-------->||     undo   ||  |
     *       |       |        ||            || E       ||    commit  ||  |
     *       |       |        +==============+         +==============+  |
     *       |       |               | S                     U |<--------+
     *       |       |        +--------------+         +==============+
     *       |       |        | irreversible |         ||    undo    ||
     *       |       |        |    commit    |         ||     set    ||
     *       |       |        +--------------+         +==============+
     *       |       |               | U                     U |
     *       |       +-------------->|<------------------------+
     *       |                +==============+
     *       |                ||   undo     ||
     *       |                ||  cleanup   ||
     *       |                +==============+
     *       +---------------------->| U
     *                               |
     *                          (err && f1)------------------->+
     *                               |                         |
     *                        +--------------+         +--------------+
     *                        |    post      |<--------|      row     |
     *                        |   request    |       U |    release   |
     *                        +--------------+         +--------------+
     *
     */
    /*
     * save original mode
     */
    save_mode = reqinfo->mode;
    for(i = 0; i < BABY_STEPS_PER_MODE_MAX; ++i ) {
        /*
         * break if we run out of baby steps for this mode
         */
        if(mode_map_ptr[i] == BABY_STEP_NONE)
            break;

        DEBUGMSGTL(("baby_steps", " baby step mode %s\n",
                    se_find_label_in_slist("babystep_mode",mode_map_ptr[i])));

        /*
         * skip modes the handler didn't register for
         */
        if (BSTEP_USE_ORIGINAL != mode_map_ptr[i]) {
            u_int    mode_flag;

            /*
             * skip undo commit if commit wasn't hit, and
             * undo_cleanup if undo_setup wasn't hit.
             */
            if((MODE_SET_UNDO == save_mode) &&
               (MODE_BSTEP_UNDO_COMMIT == mode_map_ptr[i]) &&
               !(BABY_STEP_COMMIT & bs_modes->completed)) {
                DEBUGMSGTL(("baby_steps",
                            "   skipping commit undo (no commit)\n"));
                continue;
            }
            else if((MODE_SET_FREE == save_mode) &&
               (MODE_BSTEP_UNDO_CLEANUP == mode_map_ptr[i]) &&
               !(BABY_STEP_UNDO_SETUP & bs_modes->completed)) {
                DEBUGMSGTL(("baby_steps",
                            "   skipping undo cleanup (no undo setup)\n"));
                continue;
            }

            reqinfo->mode = mode_map_ptr[i];
            mode_flag = netsnmp_baby_step_mode2flag( mode_map_ptr[i] );
            if((mode_flag & bs_modes->registered))
                bs_modes->completed |= mode_flag;
            else {
                DEBUGMSGTL(("baby_steps",
                            "   skipping mode (not registered)\n"));
                continue;
            }

        
        }
        else {
            reqinfo->mode = save_mode;
        }

#ifdef BABY_STEPS_NEXT_MODE
        /*
         * I can't remember why I wanted the next mode in the request,
         * but it's not used anywhere, so don't use this code. saved,
         * in case I remember why I thought needed it. - rstory 040911
         */
        if((BABY_STEPS_PER_MODE_MAX - 1) == i)
            reqinfo->next_mode_ok = BABY_STEP_NONE;
        else {
            if(BSTEP_USE_ORIGINAL == mode_map_ptr[i+1])
                reqinfo->next_mode_ok = save_mode;
            else
                reqinfo->next_mode_ok = mode_map_ptr[i+1];
        }
#endif

        /*
         * call handlers for baby step
         */
        rc = netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                       requests);

        /*
         * check for error calling handler (unlikely, but...)
         */
        if(rc) {
            DEBUGMSGTL(("baby_steps", "   ERROR:handler error\n"));
            break;
        }

        /*
         * check for errors in any of the requests for GET-like, reserve1,
         * reserve2 and action. (there is no recovery from errors
         * in commit, free or undo.)
         */
        if (MODE_IS_GET(save_mode)
            || (save_mode < SNMP_MSG_INTERNAL_SET_COMMIT)) {
            rc = netsnmp_check_requests_error(requests);
            if(rc) {
                DEBUGMSGTL(("baby_steps", "   ERROR:request error\n"));
                break;
            }
        }
    }

    /*
     * restore original mode
     */
    reqinfo->mode = save_mode;

    
    return rc;
}
Пример #10
0
/** @internal Implements the stash_cache handler */
int
netsnmp_stash_cache_helper(netsnmp_mib_handler *handler,
                           netsnmp_handler_registration *reginfo,
                           netsnmp_agent_request_info *reqinfo,
                           netsnmp_request_info *requests)
{
    netsnmp_cache            *cache;
    netsnmp_stash_cache_info *cinfo;
    netsnmp_oid_stash_node   *cnode;
    netsnmp_variable_list    *cdata;
    netsnmp_request_info     *request;

    DEBUGMSGTL(("helper:stash_cache", "Got request\n"));

    cache = netsnmp_cache_reqinfo_extract( reqinfo, reginfo->handlerName );
    if (!cache) {
        DEBUGMSGTL(("helper:stash_cache", "No cache structure\n"));
        return SNMP_ERR_GENERR;
    }
    cinfo = (netsnmp_stash_cache_info *) cache->magic;

    switch (reqinfo->mode) {

    case MODE_GET:
        DEBUGMSGTL(("helper:stash_cache", "Processing GET request\n"));
        for(request = requests; request; request = request->next) {
            cdata = (netsnmp_variable_list*)
                netsnmp_oid_stash_get_data(cinfo->cache,
                                           requests->requestvb->name,
                                           requests->requestvb->name_length);
            if (cdata && cdata->val.string && cdata->val_len) {
                DEBUGMSGTL(("helper:stash_cache", "Found cached GET varbind\n"));
                DEBUGMSGOID(("helper:stash_cache", cdata->name, cdata->name_length));
                DEBUGMSG(("helper:stash_cache", "\n"));
                snmp_set_var_typed_value(request->requestvb, cdata->type,
                                         cdata->val.string, cdata->val_len);
            }
        }
        break;

    case MODE_GETNEXT:
        DEBUGMSGTL(("helper:stash_cache", "Processing GETNEXT request\n"));
        for(request = requests; request; request = request->next) {
            cnode =
                netsnmp_oid_stash_getnext_node(cinfo->cache,
                                               requests->requestvb->name,
                                               requests->requestvb->name_length);
            if (cnode && cnode->thedata) {
                cdata =  (netsnmp_variable_list*)cnode->thedata;
                if (cdata->val.string && cdata->name && cdata->name_length) {
                    DEBUGMSGTL(("helper:stash_cache", "Found cached GETNEXT varbind\n"));
                    DEBUGMSGOID(("helper:stash_cache", cdata->name, cdata->name_length));
                    DEBUGMSG(("helper:stash_cache", "\n"));
                    snmp_set_var_typed_value(request->requestvb, cdata->type,
                                             cdata->val.string, cdata->val_len);
                    snmp_set_var_objid(request->requestvb, cdata->name,
                                       cdata->name_length);
                }
            }
        }
        break;

    default:
        cinfo->cache_valid = 0;
        return netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                         requests);
    }

    return SNMP_ERR_NOERROR;
}
Пример #11
0
/*
 * The helper handler that takes care of passing a specific row of
 * data down to the lower handler(s).  It sets request->processed if
 * the request should not be handled.
 */
int
netsnmp_table_data_helper_handler(netsnmp_mib_handler *handler,
                                  netsnmp_handler_registration *reginfo,
                                  netsnmp_agent_request_info *reqinfo,
                                  netsnmp_request_info *requests)
{
    netsnmp_table_data *table = (netsnmp_table_data *) handler->myvoid;
    netsnmp_request_info *request;
    int             valid_request = 0;
    netsnmp_table_row *row;
    netsnmp_table_request_info *table_info;
    netsnmp_table_registration_info *table_reg_info =
        netsnmp_find_table_registration_info(reginfo);
    int             result, regresult;
    int             oldmode;

    for (request = requests; request; request = request->next) {
        if (request->processed)
            continue;

        table_info = netsnmp_extract_table_info(request);
        if (!table_info)
            continue;           /* ack */
        switch (reqinfo->mode) {
        case MODE_GET:
        case MODE_GETNEXT:
        case MODE_SET_RESERVE1:
            netsnmp_request_add_list_data(request,
                                      netsnmp_create_data_list(
                                          TABLE_DATA_TABLE, table, NULL));
        }

        /*
         * find the row in question 
         */
        switch (reqinfo->mode) {
        case MODE_GETNEXT:
        case MODE_GETBULK:     /* XXXWWW */
            if (request->requestvb->type != ASN_NULL)
                continue;
            /*
             * loop through data till we find the next row 
             */
            result = snmp_oid_compare(request->requestvb->name,
                                      request->requestvb->name_length,
                                      reginfo->rootoid,
                                      reginfo->rootoid_len);
            regresult = snmp_oid_compare(request->requestvb->name,
                                         SNMP_MIN(request->requestvb->
                                                  name_length,
                                                  reginfo->rootoid_len),
                                         reginfo->rootoid,
                                         reginfo->rootoid_len);
            if (regresult == 0
                && request->requestvb->name_length < reginfo->rootoid_len)
                regresult = -1;

            if (result < 0 || 0 == result) {
                /*
                 * before us entirely, return the first 
                 */
                row = table->first_row;
                table_info->colnum = table_reg_info->min_column;
            } else if (regresult == 0 && request->requestvb->name_length ==
                       reginfo->rootoid_len + 1 &&
                       /* entry node must be 1, but any column is ok */
                       request->requestvb->name[reginfo->rootoid_len] == 1) {
                /*
                 * exactly to the entry 
                 */
                row = table->first_row;
                table_info->colnum = table_reg_info->min_column;
            } else if (regresult == 0 && request->requestvb->name_length ==
                       reginfo->rootoid_len + 2 &&
                       /* entry node must be 1, but any column is ok */
                       request->requestvb->name[reginfo->rootoid_len] == 1) {
                /*
                 * exactly to the column 
                 */
                row = table->first_row;
            } else {
                /*
                 * loop through all rows looking for the first one
                 * that is equal to the request or greater than it 
                 */
                for (row = table->first_row; row; row = row->next) {
                    /*
                     * compare the index of the request to the row 
                     */
                    result =
                        snmp_oid_compare(row->index_oid,
                                         row->index_oid_len,
                                         request->requestvb->name + 2 +
                                         reginfo->rootoid_len,
                                         request->requestvb->name_length -
                                         2 - reginfo->rootoid_len);
                    if (result == 0) {
                        /*
                         * equal match, return the next row 
                         */
                        if (row) {
                            row = row->next;
                        }
                        break;
                    } else if (result > 0) {
                        /*
                         * the current row is greater than the
                         * request, use it 
                         */
                        break;
                    }
                }
            }
            if (!row) {
                table_info->colnum++;
                if (table_info->colnum <= table_reg_info->max_column) {
                    row = table->first_row;
                }
            }
            if (row) {
                valid_request = 1;
                netsnmp_request_add_list_data(request,
                                              netsnmp_create_data_list
                                              (TABLE_DATA_ROW, row,
                                               NULL));
                /*
                 * Set the name appropriately, so we can pass this
                 *  request on as a simple GET request
                 */
                netsnmp_table_data_build_result(reginfo, reqinfo, request,
                                                row,
                                                table_info->colnum,
                                                ASN_NULL, NULL, 0);
            } else {            /* no decent result found.  Give up. It's beyond us. */
                request->processed = 1;
            }
            break;

        case MODE_GET:
            if (request->requestvb->type != ASN_NULL)
                continue;
            /*
             * find the row in question 
             */
            if (request->requestvb->name_length < (reginfo->rootoid_len + 3)) { /* table.entry.column... */
                /*
                 * request too short 
                 */
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_NOSUCHINSTANCE);
                break;
            } else if (NULL ==
                       (row =
                        netsnmp_table_data_get_from_oid(table,
                                                        request->
                                                        requestvb->name +
                                                        reginfo->
                                                        rootoid_len + 2,
                                                        request->
                                                        requestvb->
                                                        name_length -
                                                        reginfo->
                                                        rootoid_len -
                                                        2))) {
                /*
                 * no such row 
                 */
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_NOSUCHINSTANCE);
                break;
            } else {
                valid_request = 1;
                netsnmp_request_add_list_data(request,
                                              netsnmp_create_data_list
                                              (TABLE_DATA_ROW, row,
                                               NULL));
            }
            break;

        case MODE_SET_RESERVE1:
            valid_request = 1;
            if (NULL !=
                (row =
                 netsnmp_table_data_get_from_oid(table,
                                                 request->requestvb->name +
                                                 reginfo->rootoid_len + 2,
                                                 request->requestvb->
                                                 name_length -
                                                 reginfo->rootoid_len -
                                                 2))) {
                netsnmp_request_add_list_data(request,
                                              netsnmp_create_data_list
                                              (TABLE_DATA_ROW, row,
                                               NULL));
            }
            break;

        case MODE_SET_RESERVE2:
        case MODE_SET_ACTION:
        case MODE_SET_COMMIT:
        case MODE_SET_FREE:
        case MODE_SET_UNDO:
            valid_request = 1;

        }
    }

    if (valid_request &&
       (reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK)) {
        /*
         * If this is a GetNext or GetBulk request, then we've identified
         *  the row that ought to include the appropriate next instance.
         *  Convert the request into a Get request, so that the lower-level
         *  handlers don't need to worry about skipping on, and call these
         *  handlers ourselves (so we can undo this again afterwards).
         */
        oldmode = reqinfo->mode;
        reqinfo->mode = MODE_GET;
        result = netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                         requests);
        reqinfo->mode = oldmode;
        handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
        return result;
    }
    else
        /* next handler called automatically - 'AUTO_NEXT' */
        return SNMP_ERR_NOERROR;
}
Пример #12
0
int
netsnmp_scalar_helper_handler(netsnmp_mib_handler *handler,
                                netsnmp_handler_registration *reginfo,
                                netsnmp_agent_request_info *reqinfo,
                                netsnmp_request_info *requests)
{

    netsnmp_variable_list *var = requests->requestvb;

    int             ret, cmp;
    int             namelen;

    DEBUGMSGTL(("helper:scalar", "Got request:\n"));
    namelen = SNMP_MIN(requests->requestvb->name_length,
                       reginfo->rootoid_len);
    cmp = snmp_oid_compare(requests->requestvb->name, namelen,
                           reginfo->rootoid, reginfo->rootoid_len);

    DEBUGMSGTL(("helper:scalar", "  oid:", cmp));
    DEBUGMSGOID(("helper:scalar", var->name, var->name_length));
    DEBUGMSG(("helper:scalar", "\n"));

    switch (reqinfo->mode) {
    case MODE_GET:
        if (cmp != 0) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_NOSUCHOBJECT);
            return SNMP_ERR_NOERROR;
        } else {
            reginfo->rootoid[reginfo->rootoid_len++] = 0;
            ret = netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                             requests);
            reginfo->rootoid_len--;
            return ret;
        }
        break;

    case MODE_SET_RESERVE1:
    case MODE_SET_RESERVE2:
    case MODE_SET_ACTION:
    case MODE_SET_COMMIT:
    case MODE_SET_UNDO:
    case MODE_SET_FREE:
        if (cmp != 0) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_NOCREATION);
            return SNMP_ERR_NOERROR;
        } else {
            reginfo->rootoid[reginfo->rootoid_len++] = 0;
            ret = netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                             requests);
            reginfo->rootoid_len--;
            return ret;
        }
        break;

    case MODE_GETNEXT:
        reginfo->rootoid[reginfo->rootoid_len++] = 0;
        ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, requests);
        reginfo->rootoid_len--;
        return ret;
    }
    /*
     * got here only if illegal mode found 
     */
    return SNMP_ERR_GENERR;
}
Пример #13
0
int
netsnmp_instance_num_file_handler(netsnmp_mib_handler *handler,
                                  netsnmp_handler_registration *reginfo,
                                  netsnmp_agent_request_info *reqinfo,
                                  netsnmp_request_info *requests)
{
    netsnmp_num_file_instance *nfi;
    u_long it, *it_save;
    int rc;

    netsnmp_assert(NULL != handler);
    nfi = (netsnmp_num_file_instance *)handler->myvoid;
    netsnmp_assert(NULL != nfi);
    netsnmp_assert(NULL != nfi->file_name);

    DEBUGMSGTL(("netsnmp_instance_int_handler", "Got request:  %d\n",
                reqinfo->mode));

    switch (reqinfo->mode) {
        /*
         * data requests 
         */
    case MODE_GET:
	/*
	 * Use a long here, otherwise on 64 bit use of an int would fail
	 */
        netsnmp_assert(NULL == nfi->filep);
        nfi->filep = fopen(nfi->file_name, "r");
        if (NULL == nfi->filep) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_NOSUCHINSTANCE);
            return SNMP_ERR_NOERROR;
        }
        rc = fscanf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
                    &it);
        fclose(nfi->filep);
        nfi->filep = NULL;
        if (rc != 1) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_NOSUCHINSTANCE);
            return SNMP_ERR_NOERROR;
        }
        snmp_set_var_typed_value(requests->requestvb, nfi->type,
                                 (u_char *) &it, sizeof(it));
        break;

        /*
         * SET requests.  Should only get here if registered RWRITE 
         */
    case MODE_SET_RESERVE1:
        netsnmp_assert(NULL == nfi->filep);
        if (requests->requestvb->type != nfi->type)
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_WRONGTYPE);
        break;

    case MODE_SET_RESERVE2:
        netsnmp_assert(NULL == nfi->filep);
        nfi->filep = fopen(nfi->file_name, "w+");
        if (NULL == nfi->filep) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_NOTWRITABLE);
            return SNMP_ERR_NOERROR;
        }
        /*
         * store old info for undo later 
         */
        if (fscanf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
                   &it) != 1) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_RESOURCEUNAVAILABLE);
            return SNMP_ERR_NOERROR;
        }

        memdup((u_char **) & it_save, (u_char *)&it, sizeof(u_long));
        if (it_save == NULL) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_RESOURCEUNAVAILABLE);
            return SNMP_ERR_NOERROR;
        }
        netsnmp_request_add_list_data(requests,
                                      netsnmp_create_data_list
                                      (INSTANCE_HANDLER_NAME, it_save,
                                       free));
        break;

    case MODE_SET_ACTION:
        /*
         * update current 
         */
        DEBUGMSGTL(("helper:instance", "updated %s -> %ld\n", nfi->file_name,
                    *(requests->requestvb->val.integer)));
        it = *(requests->requestvb->val.integer);
        rewind(nfi->filep); /* rewind to make sure we are at the beginning */
        rc = fprintf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
                     it);
        if (rc < 0) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_GENERR);
            return SNMP_ERR_NOERROR;
        }
        break;

    case MODE_SET_UNDO:
        it =
            *((u_int *) netsnmp_request_get_list_data(requests,
                                                      INSTANCE_HANDLER_NAME));
        rc = fprintf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
                     it);
        if (rc < 0)
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_UNDOFAILED);
        /** fall through */

    case MODE_SET_COMMIT:
    case MODE_SET_FREE:
        if (NULL != nfi->filep) {
            fclose(nfi->filep);
            nfi->filep = NULL;
        }
        break;
    }

    if (handler->next && handler->next->access_method)
        return netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                         requests);
    return SNMP_ERR_NOERROR;
}
Пример #14
0
/** @internal Implements the stash_to_next handler */
int
netsnmp_stash_to_next_helper(netsnmp_mib_handler *handler,
                            netsnmp_handler_registration *reginfo,
                            netsnmp_agent_request_info *reqinfo,
                            netsnmp_request_info *requests)
{

    int             ret = SNMP_ERR_NOERROR;
    int             namelen;
    int             finished = 0;
    netsnmp_oid_stash_node **cinfo;
    netsnmp_variable_list   *vb;
    netsnmp_request_info    *reqtmp;

    /*
     * this code depends on AUTO_NEXT being set
     */
    netsnmp_assert(handler->flags & MIB_HANDLER_AUTO_NEXT);

    /*
     * Don't do anything for any modes except GET_STASH. Just return,
     * and the agent will call the next handler (AUTO_NEXT).
     *
     * If the handler chain already supports GET_STASH, we don't
     * need to do anything here either.  Once again, we just return
     * and the agent will call the next handler (AUTO_NEXT).
     *
     * Otherwise, we munge the mode to GET_NEXT, and call the
     * next handler ourselves, repeatedly until we've retrieved the
     * full contents of the table or subtree.
     *   Then restore the mode and return to the calling handler 
     * (setting AUTO_NEXT_OVERRRIDE so the agent knows what we did).
     */
    if (MODE_GET_STASH == reqinfo->mode) {
        if ( reginfo->modes & HANDLER_CAN_STASH ) {
            return ret;
        }
        cinfo  = netsnmp_extract_stash_cache( reqinfo );
        reqtmp = SNMP_MALLOC_TYPEDEF(netsnmp_request_info);
        vb = reqtmp->requestvb = SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
        vb->type = ASN_NULL;
        snmp_set_var_objid( vb, reginfo->rootoid, reginfo->rootoid_len );

        reqinfo->mode = MODE_GETNEXT;
        while (!finished) {
            ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, reqtmp);
            namelen = SNMP_MIN(vb->name_length, reginfo->rootoid_len);
            if ( !snmp_oid_compare( reginfo->rootoid, reginfo->rootoid_len,
                                   vb->name, namelen) &&
                 vb->type != ASN_NULL && vb->type != SNMP_ENDOFMIBVIEW ) {
                /*
                 * This result is relevant so save it, and prepare
                 * the request varbind for the next query.
                 */
                netsnmp_oid_stash_add_data( cinfo, vb->name, vb->name_length,
                                            snmp_clone_varbind( vb ));
                    /*
                     * Tidy up the response structure,
                     *  ready for retrieving the next entry
                     */
                netsnmp_free_all_list_data(reqtmp->parent_data);
                reqtmp->parent_data = NULL;
                reqtmp->processed = 0;
                vb->type = ASN_NULL;
            } else {
                finished = 1;
            }
        }
        reqinfo->mode = MODE_GET_STASH;

        /*
         * let the handler chain processing know that we've already
         * called the next handler
         */
        handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
    }

    return ret;
}
Пример #15
0
int
netsnmp_scalar_group_helper_handler(netsnmp_mib_handler *handler,
                                netsnmp_handler_registration *reginfo,
                                netsnmp_agent_request_info *reqinfo,
                                netsnmp_request_info *requests)
{
    netsnmp_variable_list *var = requests->requestvb;

    netsnmp_scalar_group *sgroup = (netsnmp_scalar_group *)handler->myvoid;
    int             ret, cmp;
    int             namelen;
    oid             subid, root_tmp[MAX_OID_LEN], *root_save;

    DEBUGMSGTL(("helper:scalar_group", "Got request:\n"));
    namelen = SNMP_MIN(requests->requestvb->name_length,
                       reginfo->rootoid_len);
    cmp = snmp_oid_compare(requests->requestvb->name, namelen,
                           reginfo->rootoid, reginfo->rootoid_len);

    DEBUGMSGTL(( "helper:scalar_group", "  cmp=%d, oid:", cmp));
    DEBUGMSGOID(("helper:scalar_group", var->name, var->name_length));
    DEBUGMSG((   "helper:scalar_group", "\n"));

    /*
     * copy root oid to root_tmp, set instance to 0. (subid set later on)
     * save rootoid, since we'll replace it before calling next handler,
     * and need to restore it afterwards.
     */
    memcpy(root_tmp, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid));
    root_tmp[reginfo->rootoid_len + 1] = 0;
    root_save = reginfo->rootoid;

    ret = SNMP_ERR_NOCREATION;
    switch (reqinfo->mode) {
    /*
     * The handling of "exact" requests is basically the same.
     * The only difference between GET and SET requests is the
     *     error/exception to return on failure.
     */
    case MODE_GET:
        ret = SNMP_NOSUCHOBJECT;
        /* Fallthrough */

#ifndef NETSNMP_NO_WRITE_SUPPORT
    case MODE_SET_RESERVE1:
    case MODE_SET_RESERVE2:
    case MODE_SET_ACTION:
    case MODE_SET_COMMIT:
    case MODE_SET_UNDO:
    case MODE_SET_FREE:
#endif /* NETSNMP_NO_WRITE_SUPPORT */
        if (cmp != 0 ||
            requests->requestvb->name_length <= reginfo->rootoid_len) {
	    /*
	     * Common prefix doesn't match, or only *just* matches 
	     *  the registered root (so can't possibly match a scalar)
	     */
            netsnmp_set_request_error(reqinfo, requests, ret);
            return SNMP_ERR_NOERROR;
        } else {
	    /*
	     * Otherwise,
	     *     extract the object subidentifier from the request, 
	     *     check this is (probably) valid, and then fudge the
	     *     registered 'rootoid' to match, before passing the
	     *     request off to the next handler ('scalar').
	     *
	     * Note that we don't bother checking instance subidentifiers
	     *     here.  That's left to the scalar helper.
	     */
            subid = requests->requestvb->name[reginfo->rootoid_len];
	    if (subid < sgroup->lbound ||
	        subid > sgroup->ubound) {
                netsnmp_set_request_error(reqinfo, requests, ret);
                return SNMP_ERR_NOERROR;
	    }
            root_tmp[reginfo->rootoid_len] = subid;
            reginfo->rootoid_len += 2;
            reginfo->rootoid = root_tmp;
            ret = netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                            requests);
            reginfo->rootoid = root_save;
            reginfo->rootoid_len -= 2;
            return ret;
        }
        break;

    case MODE_GETNEXT:
	/*
	 * If we're being asked for something before (or exactly matches)
	 *     the registered root OID, then start with the first object.
	 * If we're being asked for something that exactly matches an object
	 *    OID, then that's what we pass down.
	 * Otherwise, we pass down the OID of the *next* object....
	 */
        if (cmp < 0 ||
            requests->requestvb->name_length <= reginfo->rootoid_len) {
            subid  = sgroup->lbound;
        } else if (requests->requestvb->name_length == reginfo->rootoid_len+1)
            subid = requests->requestvb->name[reginfo->rootoid_len];
        else
            subid = requests->requestvb->name[reginfo->rootoid_len]+1;

	/*
	 * ... always assuming this is (potentially) valid, of course.
	 */
        if (subid < sgroup->lbound)
            subid = sgroup->lbound;
	else if (subid > sgroup->ubound)
            return SNMP_ERR_NOERROR;
        
        root_tmp[reginfo->rootoid_len] = subid;
        reginfo->rootoid_len += 2;
        reginfo->rootoid = root_tmp;
        ret = netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                            requests);
        /*
         * If we didn't get an answer (due to holes in the group)
	 *   set things up to retry again.
         */
        if (!requests->delegated &&
            (requests->requestvb->type == ASN_NULL ||
             requests->requestvb->type == SNMP_NOSUCHOBJECT ||
             requests->requestvb->type == SNMP_NOSUCHINSTANCE)) {
            snmp_set_var_objid(requests->requestvb,
                               reginfo->rootoid, reginfo->rootoid_len - 1);
            requests->requestvb->name[reginfo->rootoid_len - 2] = ++subid;
            requests->requestvb->type = ASN_PRIV_RETRY;
        }
        reginfo->rootoid = root_save;
        reginfo->rootoid_len -= 2;
        return ret;
    }
    /*
     * got here only if illegal mode found 
     */
    return SNMP_ERR_GENERR;
}
Пример #16
0
/**
 * The helper handler that takes care of passing a specific row of
 * data down to the lower handler(s).  It sets request->processed if
 * the request should not be handled.
 */
int
netsnmp_table_data_helper_handler(netsnmp_mib_handler *handler,
                                  netsnmp_handler_registration *reginfo,
                                  netsnmp_agent_request_info *reqinfo,
                                  netsnmp_request_info *requests)
{

    netsnmp_table_data *table = (netsnmp_table_data *) handler->myvoid;
    netsnmp_request_info *request;
    int             valid_request = 0;
    netsnmp_table_row *row;
    netsnmp_table_request_info *table_info;
    netsnmp_table_registration_info *table_reg_info =
        netsnmp_find_table_registration_info(reginfo);
    int             result, regresult;
    int             oldmode;

    for (request = requests; request; request = request->next) {
        if (request->processed)
            continue;

        table_info = netsnmp_extract_table_info(request);
        if (!table_info)
            continue;           /* ack */

        /*
         * find the row in question 
         */
        switch (reqinfo->mode) {
        case MODE_GETNEXT:
        case MODE_GETBULK:     /* XXXWWW */
            if (request->requestvb->type != ASN_NULL)
                continue;
            /*
             * loop through data till we find the next row 
             */
            result = snmp_oid_compare(request->requestvb->name,
                                      request->requestvb->name_length,
                                      reginfo->rootoid,
                                      reginfo->rootoid_len);
            regresult = snmp_oid_compare(request->requestvb->name,
                                         SNMP_MIN(request->requestvb->
                                                  name_length,
                                                  reginfo->rootoid_len),
                                         reginfo->rootoid,
                                         reginfo->rootoid_len);
            if (regresult == 0
                && request->requestvb->name_length < reginfo->rootoid_len)
                regresult = -1;

            if (result < 0 || 0 == result) {
                /*
                 * before us entirely, return the first 
                 */
                row = table->first_row;
                table_info->colnum = table_reg_info->min_column;
            } else if (regresult == 0 && request->requestvb->name_length ==
                       reginfo->rootoid_len + 1 &&
                       /* entry node must be 1, but any column is ok */
                       request->requestvb->name[reginfo->rootoid_len] == 1) {
                /*
                 * exactly to the entry 
                 */
                row = table->first_row;
                table_info->colnum = table_reg_info->min_column;
            } else if (regresult == 0 && request->requestvb->name_length ==
                       reginfo->rootoid_len + 2 &&
                       /* entry node must be 1, but any column is ok */
                       request->requestvb->name[reginfo->rootoid_len] == 1) {
                /*
                 * exactly to the column 
                 */
                row = table->first_row;
            } else {
                /*
                 * loop through all rows looking for the first one
                 * that is equal to the request or greater than it 
                 */
                for (row = table->first_row; row; row = row->next) {
                    /*
                     * compare the index of the request to the row 
                     */
                    result =
                        snmp_oid_compare(row->index_oid,
                                         row->index_oid_len,
                                         request->requestvb->name + 2 +
                                         reginfo->rootoid_len,
                                         request->requestvb->name_length -
                                         2 - reginfo->rootoid_len);
                    if (result == 0) {
                        /*
                         * equal match, return the next row 
                         */
                        if (row) {
                            row = row->next;
                        }
                        break;
                    } else if (result > 0) {
                        /*
                         * the current row is greater than the
                         * request, use it 
                         */
                        break;
                    }
                }
            }
            if (!row) {
                table_info->colnum++;
                if (table_info->colnum <= table_reg_info->max_column) {
                    row = table->first_row;
                }
            }
            if (row) {
                valid_request = 1;
                netsnmp_request_add_list_data(request,
                                              netsnmp_create_data_list
                                              (TABLE_DATA_NAME, row,
                                               NULL));
                /*
                 * Set the name appropriately, so we can pass this
                 *  request on as a simple GET request
                 */
                netsnmp_table_data_build_result(reginfo, reqinfo, request,
                                                row,
                                                table_info->colnum,
                                                ASN_NULL, NULL, 0);
            } else {            /* no decent result found.  Give up. It's beyond us. */
                request->processed = 1;
            }
            break;

        case MODE_GET:
            if (request->requestvb->type != ASN_NULL)
                continue;
            /*
             * find the row in question 
             */
            if (request->requestvb->name_length < (reginfo->rootoid_len + 3)) { /* table.entry.column... */
                /*
                 * request too short 
                 */
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_NOSUCHINSTANCE);
                break;
            } else if (NULL ==
                       (row =
                        netsnmp_table_data_get_from_oid(table,
                                                        request->
                                                        requestvb->name +
                                                        reginfo->
                                                        rootoid_len + 2,
                                                        request->
                                                        requestvb->
                                                        name_length -
                                                        reginfo->
                                                        rootoid_len -
                                                        2))) {
                /*
                 * no such row 
                 */
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_NOSUCHINSTANCE);
                break;
            } else {
                valid_request = 1;
                netsnmp_request_add_list_data(request,
                                              netsnmp_create_data_list
                                              (TABLE_DATA_NAME, row,
                                               NULL));
            }
            break;

        case MODE_SET_RESERVE1:
            valid_request = 1;
            if (NULL !=
                (row =
                 netsnmp_table_data_get_from_oid(table,
                                                 request->requestvb->name +
                                                 reginfo->rootoid_len + 2,
                                                 request->requestvb->
                                                 name_length -
                                                 reginfo->rootoid_len -
                                                 2))) {
                netsnmp_request_add_list_data(request,
                                              netsnmp_create_data_list
                                              (TABLE_DATA_NAME, row,
                                               NULL));
            }
            break;

        case MODE_SET_RESERVE2:
        case MODE_SET_ACTION:
        case MODE_SET_COMMIT:
        case MODE_SET_FREE:
        case MODE_SET_UNDO:
            valid_request = 1;

        }
    }

    if (valid_request) {
        /*
         * If this is a GetNext or GetBulk request, then we've identified
         *  the row that ought to include the appropriate next instance.
         *  Convert the request into a Get request, so that the lower-level
         *  handlers don't need to worry about skipping on....
         */
        oldmode = reqinfo->mode;
        if (reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK) {
            reqinfo->mode = MODE_GET;
        }
        result = netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                         requests);
        if (oldmode == MODE_GETNEXT || oldmode == MODE_GETBULK) {       /* XXX */
            for (request = requests; request; request = request->next) {
                /*
                 *  ... but if the lower-level handlers aren't dealing with
                 *  skipping on to the next instance, then we must handle
                 *  this situation here.
                 *    Mark 'holes' in the table as needing to be retried.
                 *
                 *    This approach is less efficient than handling such
                 *  holes directly in the table_dataset handler, but allows
                 *  user-provided handlers to override the dataset handler
                 *  if this proves necessary.
                 */
                if (request->requestvb->type == ASN_NULL ||
                    request->requestvb->type == SNMP_NOSUCHINSTANCE) {
                    request->requestvb->type = ASN_PRIV_RETRY;
                }
                    /* XXX - Move on to the next object */
                if (request->requestvb->type == SNMP_NOSUCHOBJECT) {
                    request->requestvb->type = ASN_PRIV_RETRY;
                }
            }
            reqinfo->mode = oldmode;
        }
        return result;
    }
    else
        return SNMP_ERR_NOERROR;
}
Пример #17
0
/** implements the table_iterator helper */
int
netsnmp_table_iterator_helper_handler(netsnmp_mib_handler *handler,
                                      netsnmp_handler_registration
                                      *reginfo,
                                      netsnmp_agent_request_info *reqinfo,
                                      netsnmp_request_info *requests)
{

    netsnmp_table_registration_info *tbl_info;
    oid             coloid[MAX_OID_LEN];
    size_t          coloid_len;
    int             ret;
    static oid      myname[MAX_OID_LEN];
    size_t	    myname_len;
    int             oldmode;
    netsnmp_iterator_info *iinfo;

    iinfo = (netsnmp_iterator_info *) handler->myvoid;
    if (!iinfo || !reginfo || !reqinfo)
        return SNMPERR_GENERR;

    tbl_info = iinfo->table_reginfo;

    /*
     * copy in the table registration oid for later use 
     */
    coloid_len = reginfo->rootoid_len + 2;
    memcpy(coloid, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid));
    coloid[reginfo->rootoid_len] = 1;   /* table.entry node */

    /*
     * illegally got here if these functions aren't defined 
     */
    if (iinfo->get_first_data_point == NULL ||
        iinfo->get_next_data_point == NULL) {
        snmp_log(LOG_ERR,
                 "table_iterator helper called without data accessor functions\n");
        return SNMP_ERR_GENERR;
    }

    /*
     * XXXWWW: deal with SET caching 
     */

#ifdef NOT_SERIALIZED
    while (requests)            /* XXX: currently only serialized */
#endif
    {
        /*
         * XXXWWW: optimize by reversing loops (look through data only once) 
         */
        netsnmp_variable_list *results = NULL;
        netsnmp_variable_list *index_search = NULL;     /* WWW: move up? */
        netsnmp_variable_list *free_this_index_search = NULL;
        netsnmp_table_request_info *table_info =
            netsnmp_extract_table_info(requests);
        void           *callback_loop_context = NULL;
        void           *callback_data_context = NULL;
        void           *callback_data_keep = NULL;

        if (requests->processed != 0) {
#ifdef NOT_SERIALIZED
            continue;
#else
            return SNMP_ERR_NOERROR;
#endif
        }

        if (reqinfo->mode != MODE_GET && reqinfo->mode != MODE_GETNEXT && reqinfo->mode != MODE_GETBULK &&      /* XXX */
            reqinfo->mode != MODE_SET_RESERVE1) {
            goto skip_processing;
        }


        if (table_info->colnum > tbl_info->max_column) {
            requests->processed = 1;
#ifdef NOT_SERIALIZED
            break;
#else
            return SNMP_ERR_NOERROR;
#endif
        }

        /*
         * XXX: if loop through everything, these are never free'd
         * since iterator returns NULL and thus we forget about
         * these 
         */

        index_search = snmp_clone_varbind(table_info->indexes);
        if (!index_search) {
            /*
             * hmmm....  invalid table? 
             */
            snmp_log(LOG_WARNING,
                     "invalid index list or failed malloc for table %s\n",
                     reginfo->handlerName);
            return SNMP_ERR_NOERROR;
        }

        free_this_index_search = index_search;

        /*
         * below our minimum column? 
         */
        if (table_info->colnum < tbl_info->min_column) {
            results =
                (iinfo->get_first_data_point) (&callback_loop_context,
                                               &callback_data_context,
                                               index_search, iinfo);
            if (iinfo->free_loop_context) {
                (iinfo->free_loop_context) (callback_loop_context, iinfo);
		callback_loop_context = NULL;
	    }
            goto got_results;
        }

        /*
         * XXX: do "only got some indexes" 
         */

        /*
         * find the next legal result to return 
         */
        /*
         * find the first node 
         */
        index_search =
            (iinfo->get_first_data_point) (&callback_loop_context,
                                           &callback_data_context,
                                           index_search, iinfo);
        /*
         * table.entry.column node 
         */
        coloid[reginfo->rootoid_len + 1] = table_info->colnum;

        switch (reqinfo->mode) {
        case MODE_GETNEXT:
        case MODE_GETBULK:     /* XXXWWW */
            /*
             * loop through all data and find next one 
             */
            while (index_search) {
                /*
                 * compare the node with previous results 
                 */
                if (netsnmp_check_getnext_reply
                    (requests, coloid, coloid_len, index_search,
                     &results)) {

                    /*
                     * result is our current choice, so keep a pointer to
                     * the data that the lower handler wants us to
                     * remember (possibly freeing the last known "good"
                     * result data pointer) 
                     */
                    if (callback_data_keep && iinfo->free_data_context) {
                        (iinfo->free_data_context) (callback_data_keep,
                                                    iinfo);
                        callback_data_keep = NULL;
                    }
                    if (iinfo->make_data_context && !callback_data_context) {
                        callback_data_context =
                            (iinfo->
                             make_data_context) (callback_loop_context,
                                                 iinfo);

                    }
                    callback_data_keep = callback_data_context;
                    callback_data_context = NULL;
                } else {
                    if (callback_data_context && iinfo->free_data_context)
                        (iinfo->free_data_context) (callback_data_context,
                                                    iinfo);
                    callback_data_context = NULL;
                }

                /*
                 * get the next node in the data chain 
                 */
                index_search =
                    (iinfo->get_next_data_point) (&callback_loop_context,
                                                  &callback_data_context,
                                                  index_search, iinfo);

                if (!index_search && !results &&
                    tbl_info->max_column > table_info->colnum) {
                    /*
                     * restart loop.  XXX: Should cache this better 
                     */
                    table_info->colnum++;
                    coloid[reginfo->rootoid_len + 1] = table_info->colnum;
                    if (free_this_index_search != NULL)
                        snmp_free_varbind(free_this_index_search);
                    index_search = snmp_clone_varbind(table_info->indexes);
		    free_this_index_search = index_search;

                    if (callback_loop_context &&
                        iinfo->free_loop_context_at_end) {
                        (iinfo->free_loop_context_at_end)(callback_loop_context,
                                                          iinfo);
                        callback_loop_context = NULL;
                    }
                    if (iinfo->free_loop_context && callback_loop_context) {
                        (iinfo->free_loop_context) (callback_loop_context,
                                                    iinfo);
                        callback_loop_context = NULL;
                    }
                    if (callback_data_context && iinfo->free_data_context) {
                        (iinfo->free_data_context) (callback_data_context,
                                                    iinfo);
                        callback_data_context = NULL;
                    }
                    
                    index_search =
                        (iinfo->
                         get_first_data_point) (&callback_loop_context,
                                                &callback_data_context,
                                                index_search, iinfo);
                }
            }

            break;

        case MODE_GET:
        case MODE_SET_RESERVE1:
            /*
             * loop through all data till exact results are found 
             */

            while (index_search) {
                build_oid_noalloc(myname, MAX_OID_LEN, &myname_len,
                                  coloid, coloid_len, index_search);
                if (snmp_oid_compare(myname, myname_len,
                                     requests->requestvb->name,
                                     requests->requestvb->name_length) ==
                    0) {
                    /*
                     * found the exact match, so we're done 
                     */
                    if (iinfo->make_data_context && !callback_data_context) {
                        callback_data_context =
                            (iinfo->
                             make_data_context) (callback_loop_context,
                                                 iinfo);

                    }
                    callback_data_keep = callback_data_context;
                    callback_data_context = NULL;
                    results = snmp_clone_varbind(index_search);
                    snmp_set_var_objid(results, myname, myname_len);
                    goto got_results;
                } else {
                    /*
                     * free not-needed data context 
                     */
                    if (callback_data_context && iinfo->free_data_context) {
                        (iinfo->free_data_context) (callback_data_context,
                                                    iinfo);
                        callback_data_context = NULL;
                    }

                }

                /*
                 * get the next node in the data chain 
                 */
                index_search =
                    (iinfo->get_next_data_point) (&callback_loop_context,
                                                  &callback_data_context,
                                                  index_search, iinfo);
            }
            break;

        default:
            /*
             * the rest of the set states have been dealt with already 
             */
            goto got_results;
        }

        /*
         * XXX: free index_search? 
         */
        if (callback_loop_context && iinfo->free_loop_context) {
            (iinfo->free_loop_context) (callback_loop_context, iinfo);
            callback_loop_context = NULL;
        }

      got_results:             /* not milk */
   
       /*
        * This free_data_context call is required in the event that your
        * get_next_data_point method allocates new memory, even during the
        * calls where it eventually returns a NULL
        */
        if (callback_data_context && iinfo->free_data_context) {
               (iinfo->free_data_context) (callback_data_context,
                                           iinfo);
               callback_data_context = NULL;
        }

        if (!results && !MODE_IS_SET(reqinfo->mode)) {
            /*
             * no results found. 
             */
            /*
             * XXX: check for at least one entry at the very top 
             */
#ifdef NOT_SERIALIZED
            break;
#else
            if (callback_loop_context && iinfo->free_loop_context_at_end) {
                (iinfo->free_loop_context_at_end) (callback_loop_context,
                                                   iinfo);
		callback_loop_context = NULL;
	    }
            if (free_this_index_search != NULL) {
                snmp_free_varbind(free_this_index_search);
            }
            return SNMP_ERR_NOERROR;
#endif
        }

      skip_processing:
        /*
         * OK, here results should be a pointer to the data that we
         * actually need to GET 
         */
        oldmode = reqinfo->mode;
        if (reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK) {   /* XXX */
            snmp_set_var_objid(requests->requestvb, results->name,
                               results->name_length);
            reqinfo->mode = MODE_GET;
        }
        if (reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK ||      /* XXX */
            reqinfo->mode == MODE_SET_RESERVE1) {
            /*
             * first (or only) pass stuff 
             */
            /*
             * let set requsets use previously constructed data 
             */
            snmp_free_varbind(results);
            if (callback_data_keep)
                netsnmp_request_add_list_data(requests,
                                              netsnmp_create_data_list
                                              (TABLE_ITERATOR_NAME,
                                               callback_data_keep, NULL));
            netsnmp_request_add_list_data(requests,
                                          netsnmp_create_data_list
                                          (TABLE_ITERATOR_LAST_CONTEXT,
                                           callback_loop_context, NULL));
        }

        DEBUGMSGTL(("table_iterator", "doing mode: %s\n",
                    se_find_label_in_slist("agent_mode", oldmode)));
        ret =
            netsnmp_call_next_handler(handler, reginfo, reqinfo, requests);
        if (oldmode == MODE_GETNEXT || oldmode == MODE_GETBULK) {       /* XXX */
            if (requests->requestvb->type == ASN_NULL ||
                requests->requestvb->type == SNMP_NOSUCHINSTANCE) {
                /*
                 * get next skipped this value for this column, we
                 * need to keep searching forward 
                 */
                requests->requestvb->type = ASN_PRIV_RETRY;
            }
            reqinfo->mode = oldmode;
        }

        callback_data_keep =
            netsnmp_request_get_list_data(requests, TABLE_ITERATOR_NAME);
        callback_loop_context =
            netsnmp_request_get_list_data(requests,
                                          TABLE_ITERATOR_LAST_CONTEXT);

        /* 
         * This has to be done to prevent a memory leak. Notice that on
         * SET_RESERVE1 we're assigning something to
         * 'free_this_index_search' at the beginning of this handler (right
         * above the line that says 'below our minimum column?'), 
         * but we're not given a chance to free it below with the other 
         * SET modes, hence our doing it here. 
         */
        if (reqinfo->mode == MODE_SET_RESERVE1) {
            if (free_this_index_search) {
                snmp_free_varbind(free_this_index_search);
                free_this_index_search = NULL;
            }
        }
        if (reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT ||
            reqinfo->mode == MODE_GETBULK ||      /* XXX */
            reqinfo->mode == MODE_SET_FREE ||
            reqinfo->mode == MODE_SET_UNDO ||
            reqinfo->mode == MODE_SET_COMMIT) {
            if (callback_data_keep && iinfo->free_data_context) {
                (iinfo->free_data_context) (callback_data_keep, iinfo);
                callback_data_keep = NULL;
            }

            if (free_this_index_search) {
                snmp_free_varbind(free_this_index_search);
                free_this_index_search = NULL;
            }
#ifndef NOT_SERIALIZED
            if (callback_loop_context && iinfo->free_loop_context_at_end) {
                (iinfo->free_loop_context_at_end) (callback_loop_context,
                                                   iinfo);
 		callback_loop_context = NULL;
            }
#endif
        }
#ifdef NOT_SERIALIZED
        return ret;
#else
        requests = requests->next;
#endif
    }
#ifdef NOT_SERIALIZED
    if (reqinfo->mode == MODE_GET || reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK ||  /* XXX */
        reqinfo->mode == MODE_SET_FREE ||
        reqinfo->mode == MODE_SET_UNDO ||
        reqinfo->mode == MODE_SET_COMMIT) {
        if (callback_loop_context && iinfo->free_loop_context_at_end) {
            (iinfo->free_loop_context_at_end) (callback_loop_context,
                                               iinfo);
	    callback_loop_context = NULL;
	}
    }
#endif
    return SNMP_ERR_NOERROR;
}
Пример #18
0
/**
 * \deprecated This function is unused and scheduled for removal in Net-SNMP 5.6
 */
int
netsnmp_instance_uint_handler(netsnmp_mib_handler *handler,
                              netsnmp_handler_registration *reginfo,
                              netsnmp_agent_request_info *reqinfo,
                              netsnmp_request_info *requests)
{

    unsigned int *it = (unsigned int *) handler->myvoid;
    unsigned int *it_save;
    unsigned long tmp_it;
    
    DEBUGMSGTL(("netsnmp_instance_uint_handler", "Got request:  %d\n",
                reqinfo->mode));

    switch (reqinfo->mode) {
        /*
         * data requests 
         */
    case MODE_GET:
	/*
	 * Use a long here, otherwise on 64 bit use of an int would fail
	 */
	tmp_it = *it;
        snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
                                 (u_char *) &tmp_it, sizeof(unsigned long));
        break;

        /*
         * SET requests.  Should only get here if registered RWRITE 
         */
    case MODE_SET_RESERVE1:
        if (requests->requestvb->type != ASN_UNSIGNED)
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_WRONGTYPE);
        break;

    case MODE_SET_RESERVE2:
        /*
         * store old info for undo later 
         */
        memdup((u_char **) & it_save, (u_char *) it, sizeof(u_int));
        if (it_save == NULL) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_RESOURCEUNAVAILABLE);
            return SNMP_ERR_NOERROR;
        }
        netsnmp_request_add_list_data(requests,
                                      netsnmp_create_data_list
                                      (INSTANCE_HANDLER_NAME, it_save,
                                       free));
        break;

    case MODE_SET_ACTION:
        /*
         * update current 
         */
        DEBUGMSGTL(("testhandler", "updated uint %d -> %ld\n", *it,
                    *(requests->requestvb->val.integer)));
        *it = (unsigned int) *(requests->requestvb->val.integer);
        break;

    case MODE_SET_UNDO:
        *it =
            *((u_int *) netsnmp_request_get_list_data(requests,
                                                      INSTANCE_HANDLER_NAME));
        break;

    case MODE_SET_COMMIT:
    case MODE_SET_FREE:
        /*
         * nothing to do 
         */
        break;
    }
    if (handler->next && handler->next->access_method)
        return netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                         requests);
    return SNMP_ERR_NOERROR;
}
Пример #19
0
/* implements the table_iterator helper */
int
netsnmp_table_iterator_helper_handler(netsnmp_mib_handler *handler,
                                      netsnmp_handler_registration *reginfo,
                                      netsnmp_agent_request_info *reqinfo,
                                      netsnmp_request_info *requests)
{
    netsnmp_table_registration_info *tbl_info;
    netsnmp_table_request_info *table_info = NULL;
    oid             coloid[MAX_OID_LEN];
    size_t          coloid_len;
    int             ret;
    static oid      myname[MAX_OID_LEN];
    size_t          myname_len;
    int             oldmode = 0;
    netsnmp_iterator_info *iinfo;
    int notdone;
    netsnmp_request_info *request, *reqtmp = NULL;
    netsnmp_variable_list *index_search = NULL;
    netsnmp_variable_list *free_this_index_search = NULL;
    void           *callback_loop_context = NULL, *last_loop_context;
    void           *callback_data_context = NULL;
    ti_cache_info  *ti_info = NULL;
    int             request_count = 0;
    netsnmp_oid_stash_node **cinfo = NULL;
    netsnmp_variable_list *old_indexes = NULL, *vb;
    netsnmp_table_registration_info *table_reg_info = NULL;
    int i;
    netsnmp_data_list    *ldata = NULL;
    
    iinfo = (netsnmp_iterator_info *) handler->myvoid;
    if (!iinfo || !reginfo || !reqinfo)
        return SNMPERR_GENERR;

    tbl_info = iinfo->table_reginfo;

    /*
     * copy in the table registration oid for later use 
     */
    coloid_len = reginfo->rootoid_len + 2;
    memcpy(coloid, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid));
    coloid[reginfo->rootoid_len] = 1;   /* table.entry node */

    /*
     * illegally got here if these functions aren't defined 
     */
    if (iinfo->get_first_data_point == NULL ||
        iinfo->get_next_data_point == NULL) {
        snmp_log(LOG_ERR,
                 "table_iterator helper called without data accessor functions\n");
        return SNMP_ERR_GENERR;
    }

    /* preliminary analysis */
    switch (reqinfo->mode) {
    case MODE_GET_STASH:
        cinfo = netsnmp_extract_stash_cache(reqinfo);
        table_reg_info = netsnmp_find_table_registration_info(reginfo);

        /* XXX: move this malloc to stash_cache handler? */
        reqtmp = SNMP_MALLOC_TYPEDEF(netsnmp_request_info);
        reqtmp->subtree = requests->subtree;
        table_info = netsnmp_extract_table_info(requests);
        netsnmp_request_add_list_data(reqtmp,
                                      netsnmp_create_data_list
                                      (TABLE_HANDLER_NAME,
                                       (void *) table_info, NULL));

        /* remember the indexes that were originally parsed. */
        old_indexes = table_info->indexes;
        break;

    case MODE_GETNEXT:
        for(request = requests ; request; request = request->next) {
            if (request->processed)
                continue;
            table_info = netsnmp_extract_table_info(request);
            if (table_info->colnum < tbl_info->min_column - 1) {
                /* XXX: optimize better than this */
                /* for now, just increase to colnum-1 */
                /* we need to jump to the lowest result of the min_column
                   and take it, comparing to nothing from the request */
                table_info->colnum = tbl_info->min_column - 1;
            } else if (table_info->colnum > tbl_info->max_column) {
                request->processed = TABLE_ITERATOR_NOTAGAIN;
            }

            ti_info =
                netsnmp_request_get_list_data(request, TI_REQUEST_CACHE);
            if (!ti_info) {
                ti_info = SNMP_MALLOC_TYPEDEF(ti_cache_info);
                netsnmp_request_add_list_data(request,
                                              netsnmp_create_data_list
                                              (TI_REQUEST_CACHE,
                                               ti_info,
                                               netsnmp_free_ti_cache));
            }

            /* XXX: if no valid requests, don't even loop below */
        }
        break;
    }

    /*
     * collect all information for each needed row
     */
    if (reqinfo->mode == MODE_GET ||
        reqinfo->mode == MODE_GETNEXT ||
        reqinfo->mode == MODE_GET_STASH ||
        reqinfo->mode == MODE_SET_RESERVE1) {
        /*
         * Count the number of request in the list,
         *   so that we'll know when we're finished
         */
        for(request = requests ; request; request = request->next)
          if (!request->processed)
            request_count++;
        notdone = 1;
        while(notdone) {
            notdone = 0;

            /* find first data point */
            if (!index_search) {
                if (free_this_index_search) {
                    /* previously done */
                    index_search = free_this_index_search;
                } else {
                    for(request=requests ; request; request=request->next) {
                        table_info = netsnmp_extract_table_info(request);
                        if (table_info)
                            break;
                    }
                    if (!table_info) {
                        snmp_log(LOG_WARNING,
                                 "no valid requests for iterator table %s\n",
                                 reginfo->handlerName);
                        netsnmp_free_request_data_sets(reqtmp);
                        SNMP_FREE(reqtmp);
                        return SNMP_ERR_NOERROR;
                    }
                    index_search = snmp_clone_varbind(table_info->indexes);
                    free_this_index_search = index_search;

                    /* setup, malloc search data: */
                    if (!index_search) {
                        /*
                         * hmmm....  invalid table? 
                         */
                        snmp_log(LOG_WARNING,
                                 "invalid index list or failed malloc for table %s\n",
                                 reginfo->handlerName);
                        netsnmp_free_request_data_sets(reqtmp);
                        SNMP_FREE(reqtmp);
                        return SNMP_ERR_NOERROR;
                    }
                }
            }

            /* if sorted, pass in a hint */
            if (iinfo->flags & NETSNMP_ITERATOR_FLAG_SORTED) {
                callback_loop_context = table_info;
            }
            index_search =
                (iinfo->get_first_data_point) (&callback_loop_context,
                                               &callback_data_context,
                                               index_search, iinfo);

            /* loop over each data point */
            while(index_search) {

                /* remember to free this later */
                free_this_index_search = index_search;
            
                /* compare against each request*/
                for(request = requests ; request; request = request->next) {
                    if (request->processed)
                        continue;

                    /* XXX: store in an array for faster retrival */
                    table_info = netsnmp_extract_table_info(request);
                    coloid[reginfo->rootoid_len + 1] = table_info->colnum;

                    ti_info =
                        netsnmp_request_get_list_data(request, TI_REQUEST_CACHE);

                    switch(reqinfo->mode) {
                    case MODE_GET:
                    case MODE_SET_RESERVE1:
                        /* looking for exact matches */
                        build_oid_noalloc(myname, MAX_OID_LEN, &myname_len,
                                          coloid, coloid_len, index_search);
                        if (snmp_oid_compare(myname, myname_len,
                                             request->requestvb->name,
                                             request->requestvb->name_length) == 0) {
                            /* keep this */
                            netsnmp_iterator_remember(request,
                                                      myname, myname_len,
                                                      callback_data_context,
                                                      callback_loop_context, iinfo);
                            request_count--;   /* One less to look for */
                        } else {
                            if (iinfo->free_data_context && callback_data_context) {
                                (iinfo->free_data_context)(callback_data_context,
                                                           iinfo);
                            }
                        }
                        break;

                    case MODE_GET_STASH:
                        /* collect data for each column for every row */
                        build_oid_noalloc(myname, MAX_OID_LEN, &myname_len,
                                          coloid, coloid_len, index_search);
                        reqinfo->mode = MODE_GET;
                        if (reqtmp)
                            ldata =
                                netsnmp_get_list_node(reqtmp->parent_data,
                                                      TABLE_ITERATOR_NAME);
                        if (!ldata) {
                            netsnmp_request_add_list_data(reqtmp,
                                                          netsnmp_create_data_list
                                                          (TABLE_ITERATOR_NAME,
                                                           callback_data_context,
                                                           NULL));
                        } else {
                            /* may have changed */
                            ldata->data = callback_data_context;
                        }

                        table_info->indexes = index_search;
                        for(i = table_reg_info->min_column;
                            i <= (int)table_reg_info->max_column; i++) {
                            myname[reginfo->rootoid_len + 1] = i;
                            table_info->colnum = i;
                            vb = reqtmp->requestvb =
                                SNMP_MALLOC_TYPEDEF(netsnmp_variable_list);
                            vb->type = ASN_NULL;
                            snmp_set_var_objid(vb, myname, myname_len);
                            netsnmp_call_next_handler(handler, reginfo,
                                                      reqinfo, reqtmp);
                            reqtmp->requestvb = NULL;
                            reqtmp->processed = 0;
                            if (vb->type != ASN_NULL) { /* XXX, not all */
                                netsnmp_oid_stash_add_data(cinfo, myname,
                                                           myname_len, vb);
                            } else {
                                snmp_free_var(vb);
                            }
                        }
                        reqinfo->mode = MODE_GET_STASH;
                        break;

                    case MODE_GETNEXT:
                        /* looking for "next" matches */
                        if (netsnmp_check_getnext_reply
                            (request, coloid, coloid_len, index_search,
                             &ti_info->results)) {
                            netsnmp_iterator_remember(request,
                                                      ti_info->results->name,
                                                      ti_info->results->name_length,
                                                      callback_data_context,
                                                      callback_loop_context, iinfo);
                            /*
                             *  If we've been told that the rows are sorted,
                             *   then the first valid one we find
                             *   must be the right one.
                             */
                            if (iinfo->flags & NETSNMP_ITERATOR_FLAG_SORTED)
                                request_count--;
                        
                        } else {
                            if (iinfo->free_data_context && callback_data_context) {
                                (iinfo->free_data_context)(callback_data_context,
                                                           iinfo);
                            }
                        }
                        break;

                    case MODE_SET_RESERVE2:
                    case MODE_SET_FREE:
                    case MODE_SET_UNDO:
                    case MODE_SET_COMMIT:
                        /* needed processing already done in RESERVE1 */
                        break;

                    default:
                        snmp_log(LOG_ERR,
                                 "table_iterator called with unsupported mode\n");
                        break;  /* XXX return */
                
                    }
                }

                /* Is there any point in carrying on? */
                if (!request_count)
                    break;
                /* get the next search possibility */
                last_loop_context = callback_loop_context;
                index_search =
                    (iinfo->get_next_data_point) (&callback_loop_context,
                                                  &callback_data_context,
                                                  index_search, iinfo);
                if (iinfo->free_loop_context && last_loop_context &&
                    callback_data_context != last_loop_context) {
                    (iinfo->free_loop_context) (last_loop_context, iinfo);
                    last_loop_context = NULL;
                }
            }

            /* free loop context before going on */
            if (callback_loop_context && iinfo->free_loop_context_at_end) {
                (iinfo->free_loop_context_at_end) (callback_loop_context,
                                                   iinfo);
                callback_loop_context = NULL;
            }

            /* decide which (GETNEXT) requests are not yet filled */
            if (reqinfo->mode == MODE_GETNEXT) {
                for(request = requests ; request; request = request->next) {
                    if (request->processed)
                        continue;
                    ti_info =
                        netsnmp_request_get_list_data(request,
                                                      TI_REQUEST_CACHE);
                    if (!ti_info->results) {
                      int nc;
                        table_info = netsnmp_extract_table_info(request);
                        nc = netsnmp_table_next_column(table_info);
                        if (0 == nc) {
                            coloid[reginfo->rootoid_len+1] = table_info->colnum+1;
                            snmp_set_var_objid(request->requestvb,
                                               coloid, reginfo->rootoid_len+2);
                            request->processed = TABLE_ITERATOR_NOTAGAIN;
                            break;
                        } else {
                          table_info->colnum = nc;
                            notdone = 1;
                        }
                    }
                }
            }
        }
    }

    if (reqinfo->mode == MODE_GET ||
        reqinfo->mode == MODE_GETNEXT ||
        reqinfo->mode == MODE_SET_RESERVE1) {
        /* per request last minute processing */
        for(request = requests ; request; request = request->next) {
            if (request->processed)
                continue;
            ti_info =
                netsnmp_request_get_list_data(request, TI_REQUEST_CACHE);
            table_info =
                netsnmp_extract_table_info(request);

            if (!ti_info)
                continue;
        
            switch(reqinfo->mode) {

            case MODE_GETNEXT:
                if (ti_info->best_match_len)
                    snmp_set_var_objid(request->requestvb, ti_info->best_match,
                                       ti_info->best_match_len);
                else {
                    coloid[reginfo->rootoid_len+1] = 
                        netsnmp_table_next_column(table_info);
                    if (0 == coloid[reginfo->rootoid_len+1]) {
                        /* out of range. */
                        coloid[reginfo->rootoid_len+1] = tbl_info->max_column + 1;
                        request->processed = TABLE_ITERATOR_NOTAGAIN;
                    }
                    snmp_set_var_objid(request->requestvb,
                                       coloid, reginfo->rootoid_len+2);
                    request->processed = 1;
                }
                snmp_free_varbind(table_info->indexes);
                table_info->indexes = snmp_clone_varbind(ti_info->results);
                /* FALL THROUGH */

            case MODE_GET:
            case MODE_SET_RESERVE1:
                if (ti_info->data_context)
                    /* we don't add a free pointer, since it's in the
                       TI_REQUEST_CACHE instead */
                    netsnmp_request_add_list_data(request,
                                                  netsnmp_create_data_list
                                                  (TABLE_ITERATOR_NAME,
                                                   ti_info->data_context,
                                                   NULL));
                break;
            
            default:
                break;
            }
        }
            
        /* we change all GETNEXT operations into GET operations.
           why? because we're just so nice to the lower levels.
           maybe someday they'll pay us for it.  doubtful though. */
        oldmode = reqinfo->mode;
        if (reqinfo->mode == MODE_GETNEXT) {
            reqinfo->mode = MODE_GET;
        }
    } else if (reqinfo->mode == MODE_GET_STASH) {
        netsnmp_free_request_data_sets(reqtmp);
        SNMP_FREE(reqtmp);
        table_info->indexes = old_indexes;
    }


    /* Finally, we get to call the next handler below us.  Boy, wasn't
       all that simple?  They better be glad they don't have to do it! */
    if (reqinfo->mode != MODE_GET_STASH) {
        DEBUGMSGTL(("table_iterator", "call subhandler for mode: %s\n",
                    se_find_label_in_slist("agent_mode", oldmode)));
        ret =
            netsnmp_call_next_handler(handler, reginfo, reqinfo, requests);
    }

    /* reverse the previously saved mode if we were a getnext */
    if (oldmode == MODE_GETNEXT) {
        reqinfo->mode = oldmode;
    }

    /* cleanup */
    if (free_this_index_search)
        snmp_free_varbind(free_this_index_search);

    return SNMP_ERR_NOERROR;
}
Пример #20
0
int
netsnmp_instance_helper_handler(netsnmp_mib_handler *handler,
                                netsnmp_handler_registration *reginfo,
                                netsnmp_agent_request_info *reqinfo,
                                netsnmp_request_info *requests)
{

    netsnmp_variable_list *var = requests->requestvb;

    int             ret, cmp;

    DEBUGMSGTL(("helper:instance", "Got request:\n"));
    cmp = snmp_oid_compare(requests->requestvb->name,
                           requests->requestvb->name_length,
                           reginfo->rootoid, reginfo->rootoid_len);

    DEBUGMSGTL(("helper:instance", "  oid:"));
    DEBUGMSGOID(("helper:instance", var->name, var->name_length));
    DEBUGMSG(("helper:instance", "\n"));

    switch (reqinfo->mode) {
    case MODE_GET:
        if (cmp != 0) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_NOSUCHINSTANCE);
            return SNMP_ERR_NOERROR;
        } else {
            return netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                             requests);
        }
        break;

    case MODE_SET_RESERVE1:
    case MODE_SET_RESERVE2:
    case MODE_SET_ACTION:
    case MODE_SET_COMMIT:
    case MODE_SET_UNDO:
    case MODE_SET_FREE:
        if (cmp != 0) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_NOCREATION);
            return SNMP_ERR_NOERROR;
        } else {
            return netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                             requests);
        }
        break;

    case MODE_GETNEXT:
        if (cmp < 0 || (cmp == 0 && requests->inclusive)) {
            reqinfo->mode = MODE_GET;
            snmp_set_var_objid(requests->requestvb, reginfo->rootoid,
                               reginfo->rootoid_len);
            ret =
                netsnmp_call_next_handler(handler, reginfo, reqinfo,
                                          requests);
            reqinfo->mode = MODE_GETNEXT;
            /*
             * if the instance doesn't have data, set type to ASN_NULL
             * to move to the next sub-tree. Ignore delegated requests; they
             * might have data later on.
             */
            if (!requests->delegated &&
                (requests->requestvb->type == SNMP_NOSUCHINSTANCE ||
                 requests->requestvb->type == SNMP_NOSUCHOBJECT)) {
                requests->requestvb->type = ASN_NULL;
            }
            return ret;
        } else {
            return SNMP_ERR_NOERROR;
        }
        break;
    }
    /*
     * got here only if illegal mode found 
     */
    return SNMP_ERR_GENERR;
}