Пример #1
0
/*
 * The helper handler that takes care of passing a specific row of
 * data down to the lower handler(s).  The table_container helper
 * has already taken care of identifying the appropriate row of the
 * table (and converting GETNEXT requests into an equivalent GET request)
 * So all we need to do here is make sure that the row is accessible
 * using tdata-style retrieval techniques as well.
 */
int
_netsnmp_tdata_helper_handler (netsnmp_mib_handler * handler,
                               netsnmp_handler_registration * reginfo,
                               netsnmp_agent_request_info * reqinfo, netsnmp_request_info * requests)
{
    netsnmp_tdata *table = (netsnmp_tdata *) handler->myvoid;

    netsnmp_request_info *request;

    netsnmp_table_request_info *table_info;

    netsnmp_tdata_row *row;

    int need_processing = 1;

    switch (reqinfo->mode)
    {
        case MODE_GET:
            need_processing = 0;    /* only need processing if some vars found */

        /** Fall through */

#ifndef NETSNMP_NO_WRITE_SUPPORT
        case MODE_SET_RESERVE1:
#endif                            /* NETSNMP_NO_WRITE_SUPPORT */

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

                table_info = netsnmp_extract_table_info (request);
                if (!table_info)
                {
                    netsnmp_assert (table_info);    /* yes, this will always hit */
                    netsnmp_set_request_error (reqinfo, request, SNMP_ERR_GENERR);
                    continue;    /* eek */
                }
                row = (netsnmp_tdata_row *) netsnmp_container_table_row_extract (request);
                if (!row && (reqinfo->mode == MODE_GET))
                {
                    netsnmp_assert (row);    /* yes, this will always hit */
                    netsnmp_set_request_error (reqinfo, request, SNMP_ERR_GENERR);
                    continue;    /* eek */
                }
                ++need_processing;
                netsnmp_request_add_list_data (request, netsnmp_create_data_list (TABLE_TDATA_TABLE, table, NULL));
                netsnmp_request_add_list_data (request, netsnmp_create_data_list (TABLE_TDATA_ROW, row, NULL));
            }

        /** skip next handler if processing not needed */
            if (!need_processing)
                handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
    }

    /* next handler called automatically - 'AUTO_NEXT' */
    return SNMP_ERR_NOERROR;
}
Пример #2
0
/**
 * Initialize the table dot11UsrLinkTable 
 *    (Define its contents and how it's structured)
 */
void
initialize_table_dot11UsrLinkTable(void)
{
    dot11UsrLinkTable_registration_ptr user_context;
    u_long flags;

    DEBUGMSGTL(("verbose:dot11UsrLinkTable:initialize_table_dot11UsrLinkTable","called\n"));

    /*
     * TODO:301:o: Perform dot11UsrLinkTable one-time table initialization.
     */

    /*
     * TODO:302:o: |->Initialize dot11UsrLinkTable user context
     * if you'd like to pass in a pointer to some data for this
     * table, allocate or set it up here.
     */
    /*
     * a netsnmp_data_list is a simple way to store void pointers. A simple
     * string token is used to add, find or remove pointers.
     */
    user_context = netsnmp_create_data_list("dot11UsrLinkTable", NULL, NULL);
    
    /*
     * No support for any flags yet, but in the future you would
     * set any flags here.
     */
    flags = 0;
    mad_dev_oid(dot11UsrLinkTable_oid,USRLINKTABLE,&dot11UsrLinkTable_oid_size,enterprise_pvivate_oid);
    /*
     * call interface initialization code
     */
    _dot11UsrLinkTable_initialize_interface(user_context, flags);
} /* initialize_table_dot11UsrLinkTable */
Пример #3
0
/** adds data to a datalist
 * @param head a pointer to the head node of a data_list
 * @param name the name of the node to cache the data.
 * @param data the data to be stored under that name
 * @param beer A function that can free the data pointer (in the future)
 * @return a newly created data_list node which was inserted in the list
 */
NETSNMP_INLINE netsnmp_data_list *
netsnmp_data_list_add_data(netsnmp_data_list **head, const char *name,
                           void *data, Netsnmp_Free_List_Data * beer)
{
    netsnmp_data_list *ptr;
    netsnmp_data_list *node = netsnmp_create_data_list(name, data, beer);
    if(NULL == node) {
        snmp_log(LOG_ERR,"could not allocte memory for node.");
        return NULL;
    }
    
    if (!*head) {
        *head = node;
        return node;
    }

    /*
     * xxx-rks: check for duplicate names? 
     */
    for (ptr = *head; ptr->next != NULL; ptr = ptr->next) {
        /*
         * noop 
         */
    }

    if (ptr)                    /* should always be true */
        ptr->next = node;

    return node;
}
Пример #4
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;
}
Пример #5
0
/**
 * Initialize the table ipv4InterfaceTable 
 *    (Define its contents and how it's structured)
 */
void
initialize_table_ipv4InterfaceTable(void)
{
    u_long          flags;

    DEBUGMSGTL(("verbose:ipv4InterfaceTable:initialize_table_ipv4InterfaceTable", "called\n"));

    /*
     * TODO:301:o: Perform ipv4InterfaceTable one-time table initialization.
     */

    /*
     * TODO:302:o: |->Initialize ipv4InterfaceTable user context
     * if you'd like to pass in a pointer to some data for this
     * table, allocate or set it up here.
     */
    /*
     * a netsnmp_data_list is a simple way to store void pointers. A simple
     * string token is used to add, find or remove pointers.
     */
    ipv4InterfaceTable_user_context_p =
        netsnmp_create_data_list("ipv4InterfaceTable", NULL, NULL);

    /*
     * No support for any flags yet, but in the future you would
     * set any flags here.
     */
    flags = 0;

    /*
     * call interface initialization code
     */
    _ipv4InterfaceTable_initialize_interface
	(ipv4InterfaceTable_user_context_p, flags);
}                               /* initialize_table_ipv4InterfaceTable */
Пример #6
0
/** registers a table_dataset so that the "add_row" snmpd.conf token
  * can be used to add data to this table.  If registration_name is
  * NULL then the name used when the table was created will be used
  * instead.
  *
  * @todo create a properly free'ing registeration pointer for the
  * datalist, and get the datalist freed at shutdown.
  */
void
netsnmp_register_auto_data_table(netsnmp_table_data_set *table_set,
                                 char *registration_name)
{
    data_set_tables *tables;
    tables = SNMP_MALLOC_TYPEDEF(data_set_tables);
    if (!tables)
        return;
    tables->table_set = table_set;
    if (!registration_name) {
        registration_name = table_set->table->name;
    }
    netsnmp_add_list_data(&auto_tables, netsnmp_create_data_list(registration_name, tables, NULL));     /* XXX */
}
Пример #7
0
/* caches information (in the request) we'll need at a later point in time */
static ti_cache_info *
netsnmp_iterator_remember(netsnmp_request_info *request,
                          oid *oid_to_save,
                          size_t oid_to_save_len,
                          void *callback_data_context,
                          void *callback_loop_context,
                          netsnmp_iterator_info *iinfo)
{
    ti_cache_info *ti_info;

    if (!request || !oid_to_save || oid_to_save_len > MAX_OID_LEN)
        return NULL;

    /* extract existing cached state */
    ti_info = netsnmp_request_get_list_data(request, TI_REQUEST_CACHE);

    /* no existing cached state.  make a new one. */
    if (!ti_info) {
        ti_info = SNMP_MALLOC_TYPEDEF(ti_cache_info);
        if (ti_info == NULL)
            return NULL;
        netsnmp_request_add_list_data(request,
                                      netsnmp_create_data_list
                                      (TI_REQUEST_CACHE,
                                       ti_info,
                                       netsnmp_free_ti_cache));
    }

    /* free existing cache before replacing */
    if (ti_info->data_context && ti_info->free_context)
        (ti_info->free_context)(ti_info->data_context, iinfo);

    /* maybe generate it from the loop context? */
    if (iinfo->make_data_context && !callback_data_context) {
        callback_data_context =
            (iinfo->make_data_context)(callback_loop_context, iinfo);

    }

    /* save data as requested */
    ti_info->data_context = callback_data_context;
    ti_info->free_context = iinfo->free_data_context;
    ti_info->best_match_len = oid_to_save_len;
    ti_info->iinfo = iinfo;
    if (oid_to_save_len)
        memcpy(ti_info->best_match, oid_to_save, oid_to_save_len * sizeof(oid));

    return ti_info;
}    
/*
 * The helper handler that takes care of passing a specific row of
 * data down to the lower handler(s).  The table_container helper
 * has already taken care of identifying the appropriate row of the
 * table (and converting GETNEXT requests into an equivalent GET request)
 * So all we need to do here is make sure that the row is accessible
 * using tdata-style retrieval techniques as well.
 */
int
_netsnmp_tdata_helper_handler(netsnmp_mib_handler *handler,
                                  netsnmp_handler_registration *reginfo,
                                  netsnmp_agent_request_info *reqinfo,
                                  netsnmp_request_info *requests)
{
    netsnmp_tdata *table = (netsnmp_tdata *) handler->myvoid;
    netsnmp_request_info       *request;
    netsnmp_table_request_info *table_info;
    netsnmp_tdata_row          *row;

    switch ( reqinfo->mode ) {
    case MODE_GET:
    case MODE_SET_RESERVE1:

        for (request = requests; request; request = request->next) {
            if (request->processed)
                continue;
    
            table_info = netsnmp_extract_table_info(request);
            if (!table_info)
                continue;           /* ack */
            row = netsnmp_container_table_row_extract( request );

            netsnmp_request_add_list_data(request,
                                      netsnmp_create_data_list(
                                          TABLE_TDATA_TABLE, table, NULL));
            netsnmp_request_add_list_data(request,
                                      netsnmp_create_data_list(
                                          TABLE_TDATA_ROW,   row,   NULL));
        }
    }

    /* next handler called automatically - 'AUTO_NEXT' */
    return SNMP_ERR_NOERROR;
}
Пример #9
0
/** Insert the cache information for a given request (PDU) */
void
netsnmp_cache_reqinfo_insert(netsnmp_cache* cache,
                             netsnmp_agent_request_info * reqinfo,
                             const char *name)
{
    char *cache_name = _build_cache_name(name);
    if (NULL == netsnmp_agent_get_list_data(reqinfo, cache_name)) {
        DEBUGMSGTL(("verbose:helper:cache_handler", " adding '%s' to %p\n",
                    cache_name, reqinfo));
        netsnmp_agent_add_list_data(reqinfo,
                                    netsnmp_create_data_list(cache_name,
                                                             cache, NULL));
    }
    SNMP_FREE(cache_name);
}
Пример #10
0
/** registers to store a data_list set of data at persistent storage time
 *
 * @param datalist the data to be saved
 * @param type the name of the application to save the data as.  If left NULL the default application name that was registered during the init_snmp call will be used (recommended).
 * @param token the unique token identifier string to use as the first word in the persistent file line.
 * @param data_list_save_ptr a function pointer which will be called to save the rest of the data to a buffer.
 * @param data_list_read_ptr a function pointer which can read the remainder of a saved line and return the application specific void * pointer.
 * @param data_list_free_ptr a function pointer which will be passed to the data node for freeing it in the future when/if the list/node is cleaned up or destroyed.
 */
void
netsnmp_register_save_list(netsnmp_data_list **datalist,
                           const char *type, const char *token,
                           Netsnmp_Save_List_Data *data_list_save_ptr,
                           Netsnmp_Read_List_Data *data_list_read_ptr,
                           Netsnmp_Free_List_Data *data_list_free_ptr)
{
    netsnmp_data_list_saveinfo *info;

    if (!data_list_save_ptr && !data_list_read_ptr)
        return;

    info = SNMP_MALLOC_TYPEDEF(netsnmp_data_list_saveinfo);

    if (!info) {
        snmp_log(LOG_ERR, "couldn't malloc a netsnmp_data_list_saveinfo typedef");
        return;
    }

    info->datalist = datalist;
    info->token = token;
    info->type = type;
    if (!info->type) {
        info->type = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
                                           NETSNMP_DS_LIB_APPTYPE);
    }

    /* function which will save the data */
    info->data_list_save_ptr = data_list_save_ptr;
    if (data_list_save_ptr)
        snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
                               netsnmp_save_all_data_callback, info);

    /* function which will read the data back in */
    info->data_list_read_ptr = data_list_read_ptr;
    if (data_list_read_ptr) {
        /** @todo netsnmp_register_save_list should handle the same token name being saved from different types? */
        netsnmp_add_list_data(&saveHead,
                              netsnmp_create_data_list(token, info, NULL));
        register_config_handler(type, token, netsnmp_read_data_callback,
                                NULL /* XXX */, NULL);
    }

    info->data_list_free_ptr = data_list_free_ptr;
}
Пример #11
0
int
process_set_requests(netsnmp_agent_request_info *agtreq_info,
                     netsnmp_request_info *requests,
                     table_container_data * tad, char *handler_name)
{
    set_context         context;
    netsnmp_container  *request_group;

    /*
     * create and save structure for set info
     */
    request_group = (netsnmp_container*) netsnmp_agent_get_list_data
        (agtreq_info, handler_name);
    if (request_group == NULL) {
        netsnmp_data_list *tmp;
        request_group = netsnmp_container_find("request_group:"
                                               "table_container");
        request_group->compare = netsnmp_compare_netsnmp_index;
        request_group->ncompare = netsnmp_ncompare_netsnmp_index;

        DEBUGMSGTL(("table_array", "Grouping requests by oid\n"));

        tmp = netsnmp_create_data_list(handler_name,
                                       request_group,
                                       release_netsnmp_request_groups);
        netsnmp_agent_add_list_data(agtreq_info, tmp);
        /*
         * group requests.
         */
        group_requests(agtreq_info, requests, request_group, tad);
    }

    /*
     * process each group one at a time
     */
    context.agtreq_info = agtreq_info;
    context.tad = tad;
    context.status = SNMP_ERR_NOERROR;
    CONTAINER_FOR_EACH(request_group,
                       (netsnmp_container_obj_func*)process_set_group,
                       &context);

    return context.status;
}
Пример #12
0
/** adds data to a datalist
 * @param head a pointer to the head node of a data_list
 * @param name the name of the node to cache the data.
 * @param data the data to be stored under that name
 * @param beer A function that can free the data pointer (in the future)
 * @return a newly created data_list node which was inserted in the list
 */
NETSNMP_INLINE netsnmp_data_list *
netsnmp_data_list_add_data(netsnmp_data_list **head, const char *name,
                           void *data, Netsnmp_Free_List_Data * beer)
{
    netsnmp_data_list *node;
    if (!name) {
        snmp_log(LOG_ERR,"no name provided.");
        return NULL;
    }
    node = netsnmp_create_data_list(name, data, beer);
    if(NULL == node) {
        snmp_log(LOG_ERR,"could not allocate memory for node.");
        return NULL;
    }

    netsnmp_add_list_data(head, node);

    return node;
}
Пример #13
0
/** intended to be registerd as a .conf parser
 * It should be registered using:
 *
 * register_app_config_handler("token", netsnmp_read_data_callback, XXX)
 *
 * where INFO_POINTER is a pointer to a netsnmp_data_list_saveinfo object
 * containing apporpriate registration information
 * @todo make netsnmp_read_data_callback deal with a free routine
 */
void
netsnmp_read_data_callback(const char *token, char *line) {
    netsnmp_data_list_saveinfo *info;
    char *dataname = NULL;
    size_t dataname_len;
    void *data = NULL;

    /* find the stashed information about what we're parsing */
    info = (netsnmp_data_list_saveinfo *) netsnmp_get_list_data(saveHead, token);
    if (!info) {
        snmp_log(LOG_WARNING, "netsnmp_read_data_callback called without previously registered subparser");
        return;
    }

    /* read in the token */
    line =
        read_config_read_data(ASN_OCTET_STR, line,
                              &dataname, &dataname_len);

    if (!line || !dataname)
        return;

    /* call the sub-parser to read the rest */
    data = (info->data_list_read_ptr)(line, strlen(line));

    if (!data) {
        free(dataname);
        return;
    }

    /* add to the datalist */
    netsnmp_add_list_data(info->datalist,
                          netsnmp_create_data_list(dataname, data,
                                  info->data_list_free_ptr));

    return;
}
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;
}
Пример #15
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;
}
Пример #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
void
return_delayed_response(unsigned int clientreg, void *clientarg)
{
    /*
     * extract the cache from the passed argument 
     */
    netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *) clientarg;

    netsnmp_request_info *requests;
    netsnmp_agent_request_info *reqinfo;
    u_long         *delay_time_cache = NULL;

    /*
     * here we double check that the cache we created earlier is still
     * * valid.  If not, the request timed out for some reason and we
     * * don't need to keep processing things.  Should never happen, but
     * * this double checks. 
     */
    cache = netsnmp_handler_check_cache(cache);

    if (!cache) {
        snmp_log(LOG_ERR, "illegal call to return delayed response\n");
        return;
    }

    /*
     * re-establish the previous pointers we are used to having 
     */
    reqinfo = cache->reqinfo;
    requests = cache->requests;

    DEBUGMSGTL(("delayed_instance",
                "continuing delayed request, mode = %d\n",
                cache->reqinfo->mode));

    /*
     * mention that it's no longer delegated, and we've now answered
     * the query (which we'll do down below). 
     */
    requests->delegated = 0;

    switch (cache->reqinfo->mode) {
        /*
         * registering as an instance means we don't need to deal with
         * getnext processing, so we don't handle it here at all.
         * 
         * However, since the instance handler already reset the mode
         * back to GETNEXT from the faked GET mode, we need to do the
         * same thing in both cases.  This should be fixed in future
         * versions of net-snmp hopefully. 
         */

    case MODE_GET:
    case MODE_GETNEXT:
        /*
         * return the currend delay time 
         */
        snmp_set_var_typed_value(cache->requests->requestvb,
                                 ASN_INTEGER,
                                 (u_char *) & delay_time,
                                 sizeof(delay_time));
        break;

#ifndef NETSNMP_NO_WRITE_SUPPORT
    case MODE_SET_RESERVE1:
        /*
         * check type 
         */
        if (requests->requestvb->type != ASN_INTEGER) {
            /*
             * not an integer.  Bad dog, no bone. 
             */
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_WRONGTYPE);
            /*
             * we don't need the cache any longer 
             */
            netsnmp_free_delegated_cache(cache);
            return;
        }
        break;

    case MODE_SET_RESERVE2:
        /*
         * store old value for UNDO support in the future. 
         */
        delay_time_cache = netsnmp_memdup(&delay_time, sizeof(delay_time));

        /*
         * malloc failed 
         */
        if (delay_time_cache == NULL) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_RESOURCEUNAVAILABLE);
            netsnmp_free_delegated_cache(cache);
            return;
        }

        /*
         * Add our temporary information to the request itself.
         * This is then retrivable later.  The free function
         * passed auto-frees it when the request is later
         * deleted.  
         */
        netsnmp_request_add_list_data(requests,
                                      netsnmp_create_data_list
                                      (DELAYED_INSTANCE_SET_NAME,
                                       delay_time_cache, free));
        break;

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

    case MODE_SET_UNDO:
        /*
         * ack, something somewhere failed.  We reset back to the
         * previously old value by extracting the previosuly
         * stored information back out of the request 
         */
        delay_time =
            *((u_long *) netsnmp_request_get_list_data(requests,
                                                       DELAYED_INSTANCE_SET_NAME));
        break;

    case MODE_SET_COMMIT:
    case MODE_SET_FREE:
        /*
         * the only thing to do here is free the old memdup'ed
         * value, but it's auto-freed by the datalist recovery, so
         * we don't have anything to actually do here 
         */
        break;
#endif /* NETSNMP_NO_WRITE_SUPPORT */
    }

    /*
     * free the information cache 
     */
    netsnmp_free_delegated_cache(cache);
}
Пример #18
0
int
handle_ipForwarding(netsnmp_mib_handler *handler,
                          netsnmp_handler_registration *reginfo,
                          netsnmp_agent_request_info   *reqinfo,
                          netsnmp_request_info         *requests)
{
    int      rc;
    u_long   value;

    /* We are never called for a GETNEXT if it's registered as a
       "instance", as it's "magically" handled for us.  */

    /* a instance handler also only hands us one request at a time, so
       we don't need to loop over a list of requests; we'll only get one. */

    switch(reqinfo->mode) {

        case MODE_GET:
            rc = netsnmp_arch_ip_scalars_ipForwarding_get(&value);
            if (rc != 0) {
                netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_NOSUCHINSTANCE);
            }
            else {
                value = value ? 1 : 2;
                snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
                                     (u_char *)&value, sizeof(value));
            }
            break;

        /*
         * SET REQUEST
         *
         * multiple states in the transaction.  See:
         * http://www.net-snmp.org/tutorial-5/toolkit/mib_module/set-actions.jpg
         */
        case MODE_SET_RESERVE1:
            break;

        case MODE_SET_RESERVE2:
            /*
             * store old info for undo later
             */
            rc = netsnmp_arch_ip_scalars_ipForwarding_get(&value);
            if (rc < 0) {
                netsnmp_set_request_error(reqinfo, requests,
                                          SNMP_ERR_NOCREATION);
            } else {
                u_long *value_save = NULL;
				u_char * _value_save = (u_char *)value_save;
                memdup(& _value_save, (u_char *) &value,
                       sizeof(value));
                if ( NULL == value_save )
                    netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_RESOURCEUNAVAILABLE);
                else
                    netsnmp_request_add_list_data(requests,
                                                  netsnmp_create_data_list
                                                  ("ipfw", value_save,
                                                  free));
	    }
            break;

        case MODE_SET_FREE:
            /* XXX: free resources allocated in RESERVE1 and/or
               RESERVE2.  Something failed somewhere, and the states
               below won't be called. */
            break;

        case MODE_SET_ACTION:
            /* XXX: perform the value change here */
            value =  *(requests->requestvb->val.integer);
            rc = netsnmp_arch_ip_scalars_ipForwarding_set(value);
            if ( 0 != rc ) {
                netsnmp_set_request_error(reqinfo, requests, rc);
            }
            break;

        case MODE_SET_COMMIT:
            break;

        case MODE_SET_UNDO:
             value =
                 *((u_long *) netsnmp_request_get_list_data(requests,
                                                            "ipfw"));
             rc = netsnmp_arch_ip_scalars_ipForwarding_set(value);
             if ( 0 != rc ) {
                 netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_UNDOFAILED);
             }
             break;

        default:
            /* we should never get here, so this is a really bad error */
            snmp_log(LOG_ERR, "unknown mode (%d) in handle_ipForwarding\n", reqinfo->mode );
            return SNMP_ERR_GENERR;
    }

    return SNMP_ERR_NOERROR;
}
Пример #19
0
/** implements the old_api handler */
int
netsnmp_old_api_helper(netsnmp_mib_handler *handler,
                       netsnmp_handler_registration *reginfo,
                       netsnmp_agent_request_info *reqinfo,
                       netsnmp_request_info *requests)
{

#if MIB_CLIENTS_ARE_EVIL
    oid             save[MAX_OID_LEN];
    size_t          savelen = 0;
#endif
    struct variable compat_var, *cvp = &compat_var;
    int             exact = 1;
    int             status;

    struct variable *vp;
    netsnmp_old_api_cache *cacheptr;
    netsnmp_agent_session *oldasp = NULL;
    u_char         *access = NULL;
    WriteMethod    *write_method = NULL;
    size_t          len;
    size_t          tmp_len;
    oid             tmp_name[MAX_OID_LEN];

    vp = (struct variable *) handler->myvoid;

    /*
     * create old variable structure with right information 
     */
    memcpy(cvp->name, reginfo->rootoid,
           reginfo->rootoid_len * sizeof(oid));
    cvp->namelen = reginfo->rootoid_len;
    cvp->type = vp->type;
    cvp->magic = vp->magic;
    cvp->acl = vp->acl;
    cvp->findVar = vp->findVar;

    switch (reqinfo->mode) {
    case MODE_GETNEXT:
    case MODE_GETBULK:
        exact = 0;
    }

    for (; requests; requests = requests->next) {

#if MIB_CLIENTS_ARE_EVIL
        savelen = requests->requestvb->name_length;
        memcpy(save, requests->requestvb->name, savelen * sizeof(oid));
#endif

        switch (reqinfo->mode) {
        case MODE_GET:
        case MODE_GETNEXT:
#ifndef NETSNMP_NO_WRITE_SUPPORT
        case MODE_SET_RESERVE1:
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
            /*
             * Actually call the old mib-module function 
             */
            if (vp && vp->findVar) {
                memcpy(tmp_name, requests->requestvb->name,
                                 requests->requestvb->name_length*sizeof(oid));
                tmp_len = requests->requestvb->name_length;
                access = (*(vp->findVar)) (cvp, tmp_name, &tmp_len,
                                           exact, &len, &write_method);
                snmp_set_var_objid( requests->requestvb, tmp_name, tmp_len );
            }
            else
                access = NULL;

#ifdef WWW_FIX
            if (IS_DELEGATED(cvp->type)) {
                add_method = (AddVarMethod *) statP;
                requests->delayed = 1;
                have_delegated = 1;
                continue;       /* WWW: This may not get to the right place */
            }
#endif

            /*
             * WWW: end range checking 
             */
            if (access) {
                /*
                 * result returned 
                 */
#ifndef NETSNMP_NO_WRITE_SUPPORT
                if (reqinfo->mode != MODE_SET_RESERVE1)
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
                    snmp_set_var_typed_value(requests->requestvb,
                                             cvp->type, access, len);
            } else {
                /*
                 * no result returned 
                 */
#if MIB_CLIENTS_ARE_EVIL
                if (access == NULL) {
                    if (netsnmp_oid_equals(requests->requestvb->name,
                                         requests->requestvb->name_length,
                                         save, savelen) != 0) {
                        DEBUGMSGTL(("old_api", "evil_client: %s\n",
                                    reginfo->handlerName));
                        memcpy(requests->requestvb->name, save,
                               savelen * sizeof(oid));
                        requests->requestvb->name_length = savelen;
                    }
                }
#endif
            }

            /*
             * AAA: fall through for everything that is a set (see BBB) 
             */
#ifndef NETSNMP_NO_WRITE_SUPPORT
            if (reqinfo->mode != MODE_SET_RESERVE1)
#endif /* !NETSNMP_NO_WRITE_SUPPORT */
                break;

            cacheptr = SNMP_MALLOC_TYPEDEF(netsnmp_old_api_cache);
            if (!cacheptr)
                return netsnmp_set_request_error(reqinfo, requests,
                                                 SNMP_ERR_RESOURCEUNAVAILABLE);
            cacheptr->data = access;
            cacheptr->write_method = write_method;
            write_method = NULL;
            netsnmp_request_add_list_data(requests,
                                          netsnmp_create_data_list
                                          (OLD_API_NAME, cacheptr,
                                           &free_wrapper));
            /*
             * BBB: fall through for everything that is a set (see AAA) 
             */

        default:
            /*
             * WWW: explicitly list the SET conditions 
             */
            /*
             * (the rest of the) SET contions 
             */
            cacheptr =
                (netsnmp_old_api_cache *)
                netsnmp_request_get_list_data(requests, OLD_API_NAME);

            if (cacheptr == NULL || cacheptr->write_method == NULL) {
                /*
                 * WWW: try to set ourselves if possible? 
                 */
                return netsnmp_set_request_error(reqinfo, requests,
                                                 SNMP_ERR_NOTWRITABLE);
            }

            oldasp = netsnmp_get_current_agent_session();
            set_current_agent_session(reqinfo->asp);
            status =
                (*(cacheptr->write_method)) (reqinfo->mode,
                                             requests->requestvb->val.
                                             string,
                                             requests->requestvb->type,
                                             requests->requestvb->val_len,
                                             cacheptr->data,
                                             requests->requestvb->name,
                                             requests->requestvb->
                                             name_length);
            set_current_agent_session(oldasp);

            if (status != SNMP_ERR_NOERROR) {
                netsnmp_set_request_error(reqinfo, requests, status);
            }

            /*
             * clean up is done by the automatic freeing of the
             * cache stored in the request. 
             */

            break;
        }
    }
    return SNMP_ERR_NOERROR;
}
Пример #20
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;
}
Пример #21
0
int
my_test_instance_handler(netsnmp_mib_handler *handler,
                         netsnmp_handler_registration *reginfo,
                         netsnmp_agent_request_info *reqinfo,
                         netsnmp_request_info *requests)
{

    static u_long   accesses = 0;
    u_long         *accesses_cache = NULL;

    DEBUGMSGTL(("testhandler", "Got instance request:\n"));

    switch (reqinfo->mode) {
    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
                                 (u_char *) & accesses, sizeof(accesses));
        break;

#ifndef NETSNMP_NO_WRITE_SUPPORT
    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 
         */
        accesses_cache = netsnmp_memdup(&accesses, sizeof(accesses));
        if (accesses_cache == NULL) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_RESOURCEUNAVAILABLE);
            return SNMP_ERR_NOERROR;
        }
        netsnmp_request_add_list_data(requests,
                                      netsnmp_create_data_list
                                      (TESTHANDLER_SET_NAME,
                                       accesses_cache, free));
        break;

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

    case MODE_SET_UNDO:
        accesses =
            *((u_long *) netsnmp_request_get_list_data(requests,
                                                       TESTHANDLER_SET_NAME));
        break;

    case MODE_SET_COMMIT:
    case MODE_SET_FREE:
        /*
         * nothing to do 
         */
        break;
#endif /* NETSNMP_NO_WRITE_SUPPORT */
    }

    return SNMP_ERR_NOERROR;
}
Пример #22
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;
}
Пример #23
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;
}
Пример #24
0
int
netsnmp_watcher_helper_handler(netsnmp_mib_handler *handler,
                               netsnmp_handler_registration *reginfo,
                               netsnmp_agent_request_info *reqinfo,
                               netsnmp_request_info *requests)
{
    netsnmp_watcher_info  *winfo = (netsnmp_watcher_info *) handler->myvoid;
    netsnmp_watcher_cache *old_data;

    DEBUGMSGTL(("helper:watcher", "Got request:  %d\n", reqinfo->mode));
    DEBUGMSGTL(( "helper:watcher", "  oid:"));
    DEBUGMSGOID(("helper:watcher", requests->requestvb->name,
                                   requests->requestvb->name_length));
    DEBUGMSG((   "helper:watcher", "\n"));

    switch (reqinfo->mode) {
        /*
         * data requests 
         */
    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb,
                                 winfo->type,
                                 winfo->data,
                                 get_data_size(winfo));
        break;

        /*
         * SET requests.  Should only get here if registered RWRITE 
         */
    case MODE_SET_RESERVE1:
        if (requests->requestvb->type != winfo->type) {
            netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGTYPE);
            handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
        } else if (((winfo->flags & WATCHER_MAX_SIZE) &&
                     requests->requestvb->val_len > winfo->max_size) ||
            ((winfo->flags & WATCHER_FIXED_SIZE) &&
                requests->requestvb->val_len != get_data_size(winfo))) {
            netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGLENGTH);
            handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
        } else if ((winfo->flags & WATCHER_SIZE_STRLEN) &&
            (memchr(requests->requestvb->val.string, '\0',
                requests->requestvb->val_len) != NULL)) {
            netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGVALUE);
            handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
        }
        break;

    case MODE_SET_RESERVE2:
        /*
         * store old info for undo later 
         */
        old_data =
            netsnmp_watcher_cache_create(winfo->data, get_data_size(winfo));
        if (old_data == NULL) {
            netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_RESOURCEUNAVAILABLE);
            handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
        } else
            netsnmp_request_add_list_data(requests,
                                          netsnmp_create_data_list
                                          ("watcher", old_data, &free_wrapper));
        break;

    case MODE_SET_FREE:
        /*
         * nothing to do 
         */
        break;

    case MODE_SET_ACTION:
        /*
         * update current 
         */
        set_data(winfo, (void *)requests->requestvb->val.string,
                                requests->requestvb->val_len);
        break;

    case MODE_SET_UNDO:
        old_data = (netsnmp_watcher_cache*)netsnmp_request_get_list_data(requests, "watcher");
        set_data(winfo, old_data->data, old_data->size);
        break;

    case MODE_SET_COMMIT:
        break;

    }

    /* next handler called automatically - 'AUTO_NEXT' */
    return SNMP_ERR_NOERROR;
}
Пример #25
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;
}
Пример #26
0
/** inserts table_iterator specific data for a newly
 *  created row into a request */
NETSNMP_INLINE void
netsnmp_insert_iterator_context(netsnmp_request_info *request, void *data)
{
    netsnmp_request_info       *req;
    netsnmp_table_request_info *table_info = NULL;
    netsnmp_variable_list      *this_index = NULL;
    netsnmp_variable_list      *that_index = NULL;
    oid      base_oid[] = {0, 0};	/* Make sure index OIDs are legal! */
    oid      this_oid[MAX_OID_LEN];
    oid      that_oid[MAX_OID_LEN];
    size_t   this_oid_len, that_oid_len;

    if (!request)
        return;

    /*
     * We'll add the new row information to any request
     * structure with the same index values as the request
     * passed in (which includes that one!).
     *
     * So construct an OID based on these index values.
     */

    table_info = netsnmp_extract_table_info(request);
    this_index = table_info->indexes;
    build_oid_noalloc(this_oid, MAX_OID_LEN, &this_oid_len,
                      base_oid, 2, this_index);

    /*
     * We need to look through the whole of the request list
     * (as received by the current handler), as there's no
     * guarantee that this routine will be called by the first
     * varbind that refers to this row.
     *   In particular, a RowStatus controlled row creation
     * may easily occur later in the variable list.
     *
     * So first, we rewind to the head of the list....
     */
    for (req=request; req->prev; req=req->prev)
        ;

    /*
     * ... and then start looking for matching indexes
     * (by constructing OIDs from these index values)
     */
    for (; req; req=req->next) {
        table_info = netsnmp_extract_table_info(req);
        that_index = table_info->indexes;
        build_oid_noalloc(that_oid, MAX_OID_LEN, &that_oid_len,
                          base_oid, 2, that_index);
      
        /*
         * This request has the same index values,
         * so add the newly-created row information.
         */
        if (snmp_oid_compare(this_oid, this_oid_len,
                             that_oid, that_oid_len) == 0) {
            netsnmp_request_add_list_data(req,
                netsnmp_create_data_list(TABLE_ITERATOR_NAME, data, NULL));
        }
    }
}
Пример #27
0
/* neIeee8021QBridgeVlanCurrentTable table mapper */
int
neIeee8021QBridgeVlanCurrentTable_mapper (
	netsnmp_mib_handler *handler,
	netsnmp_handler_registration *reginfo,
	netsnmp_agent_request_info *reqinfo,
	netsnmp_request_info *requests)
{
	netsnmp_request_info *request;
	netsnmp_table_request_info *table_info;
	neIeee8021QBridgeVlanCurrentEntry_t *table_entry;
	register ieee8021QBridgeVlanCurrentEntry_t *poEntry = NULL;
	void *pvOldDdata = NULL;
	int ret;
	
	switch (reqinfo->mode)
	{
	/*
	 * Read-support (also covers GetNext requests)
	 */
	case MODE_GET:
		for (request = requests; request != NULL; request = request->next)
		{
			poEntry = (ieee8021QBridgeVlanCurrentEntry_t*) netsnmp_extract_iterator_context (request);
			table_info = netsnmp_extract_table_info (request);
			if (poEntry == NULL)
			{
				netsnmp_set_request_error (reqinfo, request, SNMP_NOSUCHINSTANCE);
				continue;
			}
			table_entry = &poEntry->oNe;
			
			switch (table_info->colnum)
			{
			case NEIEEE8021QBRIDGEVLANCURRENTADMINFLAGS:
				snmp_set_var_typed_value (request->requestvb, ASN_OCTET_STR, (u_char*) table_entry->au8AdminFlags, table_entry->u16AdminFlags_len);
				break;
			case NEIEEE8021QBRIDGEVLANCURRENTOPERSTATE:
				snmp_set_var_typed_integer (request->requestvb, ASN_INTEGER, table_entry->i32OperState);
				break;
			case NEIEEE8021QBRIDGEVLANCURRENTLEARNT:
				snmp_set_var_typed_value (request->requestvb, ASN_OCTET_STR, (u_char*) table_entry->pu8Learnt, table_entry->u16Learnt_len);
				break;
			case NEIEEE8021QBRIDGEVLANCURRENTIFINDEX:
				snmp_set_var_typed_integer (request->requestvb, ASN_INTEGER, table_entry->u32IfIndex);
				break;
				
			default:
				netsnmp_set_request_error (reqinfo, request, SNMP_NOSUCHOBJECT);
				break;
			}
		}
		break;
		
	/*
	 * Write-support
	 */
	case MODE_SET_RESERVE1:
		for (request = requests; request != NULL; request = request->next)
		{
			poEntry = (ieee8021QBridgeVlanCurrentEntry_t*) netsnmp_extract_iterator_context (request);
			table_info = netsnmp_extract_table_info (request);
			table_entry = &poEntry->oNe;
			
			switch (table_info->colnum)
			{
			case NEIEEE8021QBRIDGEVLANCURRENTADMINFLAGS:
				ret = netsnmp_check_vb_type_and_max_size (request->requestvb, ASN_OCTET_STR, sizeof (table_entry->au8AdminFlags));
				if (ret != SNMP_ERR_NOERROR)
				{
					netsnmp_set_request_error (reqinfo, request, ret);
					return SNMP_ERR_NOERROR;
				}
				break;
				
			default:
				netsnmp_set_request_error (reqinfo, request, SNMP_ERR_NOTWRITABLE);
				return SNMP_ERR_NOERROR;
			}
		}
		break;
		
	case MODE_SET_RESERVE2:
		for (request = requests; request != NULL; request = request->next)
		{
			poEntry = (ieee8021QBridgeVlanCurrentEntry_t*) netsnmp_extract_iterator_context (request);
			table_info = netsnmp_extract_table_info (request);
			if (poEntry == NULL)
			{
				netsnmp_set_request_error (reqinfo, request, SNMP_NOSUCHINSTANCE);
				continue;
			}
			table_entry = &poEntry->oNe;
			
			switch (table_info->colnum)
			{
			case NEIEEE8021QBRIDGEVLANCURRENTADMINFLAGS:
				if (poEntry->u8RowStatus == xRowStatus_active_c || poEntry->u8RowStatus == xRowStatus_notReady_c)
				{
					netsnmp_set_request_error (reqinfo, request, SNMP_ERR_RESOURCEUNAVAILABLE);
					return SNMP_ERR_NOERROR;
				}
				break;
			}
		}
		break;
		
	case MODE_SET_FREE:
		break;
		
	case MODE_SET_ACTION:
		for (request = requests; request != NULL; request = request->next)
		{
			pvOldDdata = netsnmp_request_get_list_data (request, ROLLBACK_BUFFER);
			poEntry = (ieee8021QBridgeVlanCurrentEntry_t*) netsnmp_extract_iterator_context (request);
			table_info = netsnmp_extract_table_info (request);
			table_entry = &poEntry->oNe;
			
			switch (table_info->colnum)
			{
			case NEIEEE8021QBRIDGEVLANCURRENTADMINFLAGS:
				if (pvOldDdata == NULL && (pvOldDdata = xBuffer_cAlloc (sizeof (xOctetString_t) + sizeof (table_entry->au8AdminFlags))) == NULL)
				{
					netsnmp_set_request_error (reqinfo, request, SNMP_ERR_RESOURCEUNAVAILABLE);
					return SNMP_ERR_NOERROR;
				}
				else if (pvOldDdata != table_entry)
				{
					((xOctetString_t*) pvOldDdata)->pData = pvOldDdata + sizeof (xOctetString_t);
					((xOctetString_t*) pvOldDdata)->u16Len = table_entry->u16AdminFlags_len;
					memcpy (((xOctetString_t*) pvOldDdata)->pData, table_entry->au8AdminFlags, sizeof (table_entry->au8AdminFlags));
					netsnmp_request_add_list_data (request, netsnmp_create_data_list (ROLLBACK_BUFFER, pvOldDdata, &xBuffer_free));
				}
				
				memset (table_entry->au8AdminFlags, 0, sizeof (table_entry->au8AdminFlags));
				memcpy (table_entry->au8AdminFlags, request->requestvb->val.string, request->requestvb->val_len);
				table_entry->u16AdminFlags_len = request->requestvb->val_len;
				break;
			}
		}
		break;
		
	case MODE_SET_UNDO:
		for (request = requests; request != NULL; request = request->next)
		{
			pvOldDdata = netsnmp_request_get_list_data (request, ROLLBACK_BUFFER);
			poEntry = (ieee8021QBridgeVlanCurrentEntry_t*) netsnmp_extract_iterator_context (request);
			table_info = netsnmp_extract_table_info (request);
			if (poEntry == NULL || pvOldDdata == NULL)
			{
				continue;
			}
			table_entry = &poEntry->oNe;
			
			switch (table_info->colnum)
			{
			case NEIEEE8021QBRIDGEVLANCURRENTADMINFLAGS:
				memcpy (table_entry->au8AdminFlags, ((xOctetString_t*) pvOldDdata)->pData, ((xOctetString_t*) pvOldDdata)->u16Len);
				table_entry->u16AdminFlags_len = ((xOctetString_t*) pvOldDdata)->u16Len;
				break;
			}
		}
		break;
		
	case MODE_SET_COMMIT:
		break;
	}
	
	return SNMP_ERR_NOERROR;
}
Пример #28
0
/** implements the table data helper.  This is the routine that takes
 *  care of all SNMP requests coming into the table. */
int
netsnmp_table_data_set_helper_handler(netsnmp_mib_handler *handler,
                                      netsnmp_handler_registration
                                      *reginfo,
                                      netsnmp_agent_request_info *reqinfo,
                                      netsnmp_request_info *requests)
{

    netsnmp_table_data_set_storage *data = NULL;
    newrow_stash   *newrowstash = NULL;
    netsnmp_table_row *row, *newrow = NULL;
    netsnmp_table_request_info *table_info;
    netsnmp_request_info *request;
    oid            *suffix;
    size_t          suffix_len;
    netsnmp_oid_stash_node **stashp = NULL;

    if (!handler)
        return SNMPERR_GENERR;
        
    DEBUGMSGTL(("netsnmp_table_data_set", "handler starting\n"));
    for (request = requests; request; request = request->next) {
        netsnmp_table_data_set *datatable =
            (netsnmp_table_data_set *) handler->myvoid;
        if (request->processed)
            continue;

        /*
         * extract our stored data and table info 
         */
        row = netsnmp_extract_table_row(request);
        table_info = netsnmp_extract_table_info(request);
        suffix = requests->requestvb->name + reginfo->rootoid_len + 2;
        suffix_len = requests->requestvb->name_length -
            (reginfo->rootoid_len + 2);

        if (MODE_IS_SET(reqinfo->mode)) {

            char buf[256]; /* is this reasonable size?? */
            int  rc;
            size_t len;

            /*
             * use a cached copy of the row for modification 
             */

            /*
             * cache location: may have been created already by other
             * SET requests in the same master request. 
             */
            rc = snprintf(buf, sizeof(buf), "dataset_row_stash:%s:",
                          datatable->table->name);
            if ((-1 == rc) || (rc >= sizeof(buf))) {
                snmp_log(LOG_ERR,"%s handler name too long\n",
                         datatable->table->name);
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_ERR_GENERR);
                continue;
            }
            len = sizeof(buf) - rc;
            rc = snprint_objid(&buf[rc], len, table_info->index_oid,
                               table_info->index_oid_len);
            if (-1 == rc) {
                snmp_log(LOG_ERR,"%s oid or name too long\n",
                         datatable->table->name);
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_ERR_GENERR);
                continue;
            }
            stashp = (netsnmp_oid_stash_node **)
                netsnmp_table_get_or_create_row_stash(reqinfo, buf);

            newrowstash
                = netsnmp_oid_stash_get_data(*stashp, suffix, suffix_len);

            if (!newrowstash) {
                if (!row) {
                    if (datatable->allow_creation) {
                        /*
                         * entirely new row.  Create the row from the template 
                         */
                        newrowstash =
                             netsnmp_table_data_set_create_newrowstash(
                                                 datatable, table_info);
                        newrow = newrowstash->newrow;
                    } else if (datatable->rowstatus_column == 0) {
                        /*
                         * A RowStatus object may be used to control the
                         *  creation of a new row.  But if this object
                         *  isn't declared (and the table isn't marked as
                         *  'auto-create'), then we can't create a new row.
                         */
                        netsnmp_set_request_error(reqinfo, request,
                                                  SNMP_ERR_NOCREATION);
                        continue;
                    }
                } else {
                    /*
                     * existing row that needs to be modified 
                     */
                    newrowstash = SNMP_MALLOC_TYPEDEF(newrow_stash);
                    newrow = netsnmp_table_data_set_clone_row(row);
                    newrowstash->newrow = newrow;
                }
                netsnmp_oid_stash_add_data(stashp, suffix, suffix_len,
                                           newrowstash);
            } else {
                newrow = newrowstash->newrow;
            }
            /*
             * all future SET data modification operations use this
             * temp pointer 
             */
            if (reqinfo->mode == MODE_SET_RESERVE1 ||
                reqinfo->mode == MODE_SET_RESERVE2)
                row = newrow;
        }

        if (row)
            data = (netsnmp_table_data_set_storage *) row->data;

        if (!row || !table_info || !data) {
            if (!MODE_IS_SET(reqinfo->mode)) {
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_NOSUCHINSTANCE);
                continue;
            }
        }

        data =
            netsnmp_table_data_set_find_column(data, table_info->colnum);

        switch (reqinfo->mode) {
        case MODE_GET:
        case MODE_GETNEXT:
        case MODE_GETBULK:     /* XXXWWW */
            if (data && data->data.voidp)
                netsnmp_table_data_build_result(reginfo, reqinfo, request,
                                                row,
                                                table_info->colnum,
                                                data->type,
                                                data->data.voidp,
                                                data->data_len);
            break;

        case MODE_SET_RESERVE1:
            if (data) {
                /*
                 * Can we modify the existing row?
                 */
                if (!data->writable) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_ERR_NOTWRITABLE);
                } else if (request->requestvb->type != data->type) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_ERR_WRONGTYPE);
                }
            } else if (datatable->rowstatus_column == table_info->colnum) {
                /*
                 * Otherwise, this is where we create a new row using
                 * the RowStatus object (essentially duplicating the
                 * steps followed earlier in the 'allow_creation' case)
                 */
                switch (*(request->requestvb->val.integer)) {
                case RS_CREATEANDGO:
                case RS_CREATEANDWAIT:
                    newrowstash =
                             netsnmp_table_data_set_create_newrowstash(
                                                 datatable, table_info);
                    newrow = newrowstash->newrow;
                    row    = newrow;
                    netsnmp_oid_stash_add_data(stashp, suffix, suffix_len,
                                               newrowstash);
                }
            }
            break;

        case MODE_SET_RESERVE2:
            /*
             * If the agent receives a SET request for an object in a non-existant
             *  row, then the RESERVE1 pass will create the row automatically.
             *
             * But since the row doesn't exist at that point, the test for whether
             *  the object is writable or not will be skipped.  So we need to check
             *  for this possibility again here.
             *
             * Similarly, if row creation is under the control of the RowStatus
             *  object (i.e. allow_creation == 0), but this particular request
             *  doesn't include such an object, then the row won't have been created,
             *  and the writable check will also have been skipped.  Again - check here.
             */
            if (data && data->writable == 0) {
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_ERR_NOTWRITABLE);
                continue;
            }
            if (datatable->rowstatus_column == table_info->colnum) {
                switch (*(request->requestvb->val.integer)) {
                case RS_ACTIVE:
                case RS_NOTINSERVICE:
                    /*
                     * Can only operate on pre-existing rows.
                     */
                    if (!newrowstash || newrowstash->created) {
                        netsnmp_set_request_error(reqinfo, request,
                                                  SNMP_ERR_INCONSISTENTVALUE);
                        continue;
                    }
                    break;

                case RS_CREATEANDGO:
                case RS_CREATEANDWAIT:
                    /*
                     * Can only operate on newly created rows.
                     */
                    if (!(newrowstash && newrowstash->created)) {
                        netsnmp_set_request_error(reqinfo, request,
                                                  SNMP_ERR_INCONSISTENTVALUE);
                        continue;
                    }
                    break;

                case RS_DESTROY:
                    /*
                     * Can operate on new or pre-existing rows.
                     */
                    break;

                case RS_NOTREADY:
                default:
                    /*
                     * Not a valid value to Set 
                     */
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_ERR_WRONGVALUE);
                    continue;
                }
            }
            if (!data ) {
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_ERR_NOCREATION);
                continue;
            }

            /*
             * modify row and set new value 
             */
            SNMP_FREE(data->data.string);
            data->data.string =
                netsnmp_strdup_and_null(request->requestvb->val.string,
                                        request->requestvb->val_len);
            if (!data->data.string) {
                netsnmp_set_request_error(reqinfo, requests,
                                          SNMP_ERR_RESOURCEUNAVAILABLE);
            }
            data->data_len = request->requestvb->val_len;

            if (datatable->rowstatus_column == table_info->colnum) {
                switch (*(request->requestvb->val.integer)) {
                case RS_CREATEANDGO:
                    /*
                     * XXX: check legality 
                     */
                    *(data->data.integer) = RS_ACTIVE;
                    break;

                case RS_CREATEANDWAIT:
                    /*
                     * XXX: check legality 
                     */
                    *(data->data.integer) = RS_NOTINSERVICE;
                    break;

                case RS_DESTROY:
                    newrowstash->deleted = 1;
                    break;
                }
            }
            break;

        case MODE_SET_ACTION:

            /*
             * Install the new row into the stored table.
	     * Do this only *once* per row ....
             */
            if (newrowstash->state != STATE_ACTION) {
                newrowstash->state = STATE_ACTION;
		if (newrowstash->created) {
                    netsnmp_table_dataset_add_row(datatable, newrow);
                } else {
                    netsnmp_table_dataset_replace_row(datatable,
                                                      row, newrow);
                }
            }
            /*
             * ... but every (relevant) varbind in the request will
	     * need to know about this new row, so update the
	     * per-request row information regardless
             */
            if (newrowstash->created) {
		netsnmp_request_add_list_data(request,
			netsnmp_create_data_list(TABLE_DATA_NAME,
						 newrow, NULL));
            }
            break;

        case MODE_SET_UNDO:
            /*
             * extract the new row, replace with the old or delete 
             */
            if (newrowstash->state != STATE_UNDO) {
                newrowstash->state = STATE_UNDO;
                if (newrowstash->created) {
                    netsnmp_table_dataset_remove_and_delete_row(datatable, newrow);
                } else {
                    netsnmp_table_dataset_replace_row(datatable,
                                                      newrow, row);
                    netsnmp_table_dataset_delete_row(newrow);
                }
            }
            break;

        case MODE_SET_COMMIT:
            if (newrowstash->state != STATE_COMMIT) {
                newrowstash->state = STATE_COMMIT;
                if (!newrowstash->created) {
                    netsnmp_table_dataset_delete_row(row);
                }
                if (newrowstash->deleted) {
                    netsnmp_table_dataset_remove_and_delete_row(datatable, newrow);
                }
            }
            break;

        case MODE_SET_FREE:
            if (newrowstash && newrowstash->state != STATE_FREE) {
                newrowstash->state = STATE_FREE;
                netsnmp_table_dataset_delete_row(newrow);
            }
            break;
        }
    }

    /* next handler called automatically - 'AUTO_NEXT' */
    return SNMP_ERR_NOERROR;
}
Пример #29
0
void
get_status(unsigned int clientreg, void *clientarg)
{
  /*
   * This function returns the value of the status variable.
   * If the value of status is 0 (no collection is running), it
   * calles collect_data to start one.
   *  
   */
	
  /*
   * Extract the cache from the passed argument.
   */
    netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *) clientarg;
    netsnmp_request_info *requests;
    netsnmp_agent_request_info *reqinfo;
    u_long         *delay_time_cache = NULL;

    /*
     * Make sure the cache created earlier is still
     * valid.  If not, the request timed out for some reason and we
     * do not need to keep processing things.  Should never happen, but
     * this double checks. 
     */
    cache = netsnmp_handler_check_cache(cache);

    if (!cache) {
        snmp_log(LOG_ERR, "illegal call to return delayed response\n");
        return;
    }

    /*
     * Re-establish the previous pointers,
     */
    reqinfo = cache->reqinfo;
    requests = cache->requests;

    DEBUGMSGTL(("demo_module_10",
                "continuing delayed request, mode = %d\n",
                cache->reqinfo->mode));
    
    /*
     * Set delegated to zero to indicate that the request is no longer
     * delegated and answer the query.
     */
    requests->delegated = 0;

    switch (cache->reqinfo->mode) {
        /*
         * Registering as an instance means we do not need to deal with
         * GETNEXT processing, so we do not handle it here at all.
         * 
         * However, since the instance handler already reset the mode
         * back to GETNEXT from the GET mode, we need to do the
         * same thing in both cases.
	 *
         */
	case MODE_GET:
            // no collection running, start one.
	    if (status == 0)
		    collect_data();
	    snmp_set_var_typed_value(requests->requestvb,
	        ASN_INTEGER, (u_char *) & status,
		    sizeof (status) /* length in bytes */);
		break;
	case MODE_SET_RESERVE1:
	    /*
	     * check type 
	     */
	    if (requests->requestvb->type != ASN_INTEGER) {
		    /*
		     * If not an integer, return SNMP error. 
		     */
		    netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_WRONGTYPE);
		    /*
		     * Free cache. It is no longer needed. 
		     */
		    netsnmp_free_delegated_cache(cache);
		    return;
	    }
	    break;
   	case MODE_SET_RESERVE2:
		    /*
		     * Store old value for UNDO support in the future. 
		     */
		    memdup((u_char **) & delay_time_cache,
			(u_char *) & delay_time, sizeof(delay_time));

		    /*
		     * malloc failed 
		     */
		    if (delay_time_cache == NULL) {
			    netsnmp_set_request_error(reqinfo, requests,
                                      SNMP_ERR_RESOURCEUNAVAILABLE);
			    netsnmp_free_delegated_cache(cache);
			    return;
		    }

		    /*
		     * Add our temporary information to the request itself.
		     * This is then retrivable later.  The free function
		     * passed auto-frees it when the request is later
		     * deleted.  
		     */
		    netsnmp_request_add_list_data(requests,
                                      netsnmp_create_data_list
                                      (DELAYED_INSTANCE_SET_NAME,
                                       delay_time_cache, free));
		    break;
	case MODE_SET_ACTION:
		// get status integer from request
		// if status == 0, start data collection, else return error
		if (*(requests->requestvb->val.integer) == 0) {
			status = *(requests->requestvb->val.integer);
		        collect_data();
		} else
			netsnmp_set_request_error(reqinfo, requests,
			    SNMP_ERR_WRONGTYPE);
		break;
	case MODE_SET_UNDO:
	    /*
	     * A failure occurred. Reset to the
	     * previously value by extracting the previosuly
	     * stored information from the request.
	     */
	    delay_time =
		*((u_long *) netsnmp_request_get_list_data(requests,
                                                       DELAYED_INSTANCE_SET_NAME));
	    break;
	case MODE_SET_COMMIT:
		break;
	case MODE_SET_FREE:
	    /*
	     * The only thing to do here is free the old memdup'ed
	     * value, but it's auto-freed by the datalist recovery, so
	     * we don't have anything to actually do here 
	     */
	    break;
    }

    /*
     * free the information cache 
     */
    netsnmp_free_delegated_cache(cache);
		
}