Table Iterator Crashes in free_data_context

Ian C via Net-snmp-coders <[email protected]>
Newsgroups gmane.network.net-snmp.devel
Message-ID <[email protected]>
I'm still having a crash issue with my table agent, I can't figure out a solution, hoping the list members could help. In a nutshell I want to read a QNX pps object (file) each time (no caching) it is queried (snmpwalk). The data gets read and returned but a crash happens on the free (datactx).
I would really appreciate a hand.
thanks,Ian  

Net-Snmp 5.9QNX 7.1
/* * Note: this file originally auto-generated by mib2c using
 *  : mib2c.iterate.conf 19302 2010-08-13 12:19:42Z dts12 $
 */
/* generated from net-snmp-config */
extern "C" {
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "chAsinHwSbcNtpTable.h"
#include <syslog.h>
#include <string.h>
}


void populateLocalSNMPstruct( struct chAsinHwSbcNtpTable_entry **table, const char channel );


/** Initializes the chAsinHwSbcNtpTable module */
extern "C" void
init_chAsinHwSbcNtpTable(void)
{
  /* here we initialize all the tables we're planning on supporting */
    //syslog( LOG_DEBUG, "init_chAsinHwSbcNtpTable()");
    initialize_table_chAsinHwSbcNtpTable();
}

//  # Determine the first/last column names


void
nsModuleTable_loop_free(void *context, netsnmp_iterator_info *dont_care)
{
    free(context);
}


void freeTableEntry( void *data_context, netsnmp_iterator_info *useless ) {
      if (data_context != NULL) {
          free(data_context); <<<<<<<==== CRASHES HERE ON 1st CALL
      }
    return;
}

/** Initialize the chAsinHwSbcNtpTable table by defining its contents and how it's structured */
void
initialize_table_chAsinHwSbcNtpTable(void)
{
    //syslog( LOG_ERR, "initialize_table_chAsinHwSbcNtpTable()");
    const oid chAsinHwSbcNtpTable_oid[] = {1,3,6,1,4,1,12345,3,3,1,9,6,6}; // 12345 is fictitious
    const size_t chAsinHwSbcNtpTable_oid_len   = OID_LENGTH(chAsinHwSbcNtpTable_oid);
    netsnmp_handler_registration    *reg;
    netsnmp_iterator_info           *iinfo;
    netsnmp_table_registration_info *table_info;

    DEBUGMSGTL(("chAsinHwSbcNtpTable:init", "initializing table chAsinHwSbcNtpTable\n"));

    reg = netsnmp_create_handler_registration(
              "chAsinHwSbcNtpTable",     chAsinHwSbcNtpTable_handler,
              chAsinHwSbcNtpTable_oid, chAsinHwSbcNtpTable_oid_len,
              HANDLER_CAN_RONLY
              );

    table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info );
    netsnmp_table_helper_add_indexes(table_info,
                           ASN_OCTET_STR,  /* index: chAsinHwSbcNtpSbcName */
                           0);
    table_info->min_column = COLUMN_CHASINHWSBCNTPSBCNAME;
    table_info->max_column = COLUMN_CHASINHWSBCNTPSTATUSSTRING;
    
    iinfo = SNMP_MALLOC_TYPEDEF( netsnmp_iterator_info );
    iinfo->get_first_data_point = chAsinHwSbcNtpTable_get_first_data_point;
    iinfo->get_next_data_point  = chAsinHwSbcNtpTable_get_next_data_point;
    iinfo->table_reginfo        = table_info;
    iinfo->free_loop_context_at_end = nsModuleTable_loop_free;
    iinfo->free_data_context = freeTableEntry; // <<<<<<==== MEM LEAK WITHOUT THIS! 

    netsnmp_register_table_iterator( reg, iinfo );

    /* Initialise the contents of the table here */
}

struct chAsinHwSbcNtpTable_entry  *chAsinHwSbcNtpTable_head;

/* create a new row in the (unsorted) table */
struct chAsinHwSbcNtpTable_entry *
chAsinHwSbcNtpTable_createEntry(
                 char* chAsinHwSbcNtpSbcName,
                 size_t chAsinHwSbcNtpSbcName_len
                ) {
    struct chAsinHwSbcNtpTable_entry *entry;

    entry = SNMP_MALLOC_TYPEDEF(struct chAsinHwSbcNtpTable_entry);
    if (!entry)
        return NULL;

    memcpy(entry->chAsinHwSbcNtpSbcName, chAsinHwSbcNtpSbcName, chAsinHwSbcNtpSbcName_len);
    entry->chAsinHwSbcNtpSbcName_len = chAsinHwSbcNtpSbcName_len;
    entry->next = chAsinHwSbcNtpTable_head;
    chAsinHwSbcNtpTable_head = entry;
    return entry;
}

/* remove a row from the table */
void
chAsinHwSbcNtpTable_removeEntry( struct chAsinHwSbcNtpTable_entry *entry ) {
    struct chAsinHwSbcNtpTable_entry *ptr, *prev;

    if (!entry)
        return;    /* Nothing to remove */

    for ( ptr  = chAsinHwSbcNtpTable_head, prev = NULL;
          ptr != NULL;
          prev = ptr, ptr = ptr->next ) {
        if ( ptr == entry )
            break;
    }
    if ( !ptr )
        return;    /* Can't find it */

    if ( prev == NULL )
        chAsinHwSbcNtpTable_head = ptr->next;
    else
        prev->next = ptr->next;

    SNMP_FREE( entry );   /* XXX - release any other internal resources */
}


/* Example iterator hook routines - using 'get_next' to do most of the work */
netsnmp_variable_list *
chAsinHwSbcNtpTable_get_first_data_point(void **my_loop_context,
                          void **my_data_context,
                          netsnmp_variable_list *put_index_data,
                          netsnmp_iterator_info *mydata)
{
    populateLocalSNMPstruct( &chAsinHwSbcNtpTable_head, 'A' ); // collect NTP data for channel 'A'
    *my_loop_context = chAsinHwSbcNtpTable_head;
    return chAsinHwSbcNtpTable_get_next_data_point(my_loop_context, my_data_context,
                                    put_index_data,  mydata );
}

netsnmp_variable_list *
chAsinHwSbcNtpTable_get_next_data_point(void **my_loop_context,
                          void **my_data_context,
                          netsnmp_variable_list *put_index_data,
                          netsnmp_iterator_info *mydata)
{
    struct chAsinHwSbcNtpTable_entry *entry = (struct chAsinHwSbcNtpTable_entry *)*my_loop_context;
    netsnmp_variable_list *idx = put_index_data;

    if ( entry ) {
        snmp_set_var_value( idx, entry->chAsinHwSbcNtpSbcName, sizeof(entry->chAsinHwSbcNtpSbcName) );
        idx = idx->next_variable;
        *my_data_context = (void *)entry;
        *my_loop_context = (void *)entry->next;
        return put_index_data;
    } else {
        return NULL;
    }
}


/** handles requests for the chAsinHwSbcNtpTable table */
int
chAsinHwSbcNtpTable_handler(
    netsnmp_mib_handler               *handler,
    netsnmp_handler_registration      *reginfo,
    netsnmp_agent_request_info        *reqinfo,
    netsnmp_request_info              *requests) {

    netsnmp_request_info       *request;
    netsnmp_table_request_info *table_info;
    struct chAsinHwSbcNtpTable_entry          *table_entry;

    DEBUGMSGTL(("chAsinHwSbcNtpTable:handler", "Processing request (%d)\n", reqinfo->mode));

    switch (reqinfo->mode) {
        /*
         * Read-support (also covers GetNext requests)
         */
    case MODE_GET:
        for (request=requests; request; request=request->next) {
            table_entry = (struct chAsinHwSbcNtpTable_entry *)
                              netsnmp_extract_iterator_context(request);
            table_info  =     netsnmp_extract_table_info(      request);
    
            switch (table_info->colnum) {
            case COLUMN_CHASINHWSBCNTPSBCNAME:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_value( request->requestvb, ASN_OCTET_STR,
                                          table_entry->chAsinHwSbcNtpSbcName,
                                          table_entry->chAsinHwSbcNtpSbcName_len);
                break;
            case COLUMN_CHASINHWSBCNTPSTATUSSTRING:
                if ( !table_entry ) {
                    netsnmp_set_request_error(reqinfo, request,
                                              SNMP_NOSUCHINSTANCE);
                    continue;
                }
                snmp_set_var_typed_value( request->requestvb, ASN_OCTET_STR,
                                          table_entry->chAsinHwSbcNtpStatusString,
                                          table_entry->chAsinHwSbcNtpStatusString_len);
                break;
            default:
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_NOSUCHOBJECT);
                break;
            }
        }
        break;

    }
    return SNMP_ERR_NOERROR;
}





// ====================================================================================================
// Populate the given Net-Snmp-generated struct with PPS data, in this case we want all /pps/ntp
// data from all SBCs of the given channel.
//
void populateLocalSNMPstruct( struct chAsinHwSbcNtpTable_entry **table, const char channel )
{
    std::list< fpair_type > allSbcNtps;  // full path, sbc name
    // For testing/dev only one file to read...
    allSbcNtps.push_back( std::make_pair( "/pps/ntp", "A1" )); // pps is QNX-specific, think of it as a file

    // process the list of paths extracting the json formatted ntp data
    struct chAsinHwSbcNtpTable_entry * tail, * head;
    head = NULL;
    tail = NULL;

    BOOST_FOREACH( const fpair_type & s, allSbcNtps ) {

        // open, read and close pps object
        char ppsData[2000];
        readFile( s.first.c_str(), ppsData, sizeof( ppsData )); // readFile reads entire pps/file in one shot (impl not included here)

        std::string json( ppsData );
        // get rid of all lines before json line (which starts with "sources:"
        size_t pos;
        if( std::string::npos != ( pos = json.find("sources:"))) {
            json.erase( 0, pos );
        }
        // get rid of all lines after the json line (which ends with "}]}"
        if( std::string::npos != ( pos = json.find("}]}"))) {
            json.erase( pos + strlen("}]}") );
        }

        // at this point ppsData is of the form "sources:json:{"data":[{...}]}
        // the 'sources:json:' isn't actually part of our json data, it's the way QNX PPS objects identify json data, so strip it away
        json.erase( 0, strlen("sources:json:"));

        struct chAsinHwSbcNtpTable_entry * current;
        current = reinterpret_cast< chAsinHwSbcNtpTable_entry *>( SNMP_MALLOC_TYPEDEF( struct chAsinHwSbcNtpTable_entry ));
        strncpy( current->chAsinHwSbcNtpStatusString, json.c_str(), JSONSIZE );
        current->chAsinHwSbcNtpStatusString_len = json.size();
        strncpy( current->chAsinHwSbcNtpSbcName, s.second.c_str(), NAMESIZE );
        current->chAsinHwSbcNtpSbcName_len = s.second.size();
        current->next = NULL;

        if( head == NULL ) {
            head = current;
        }
        else {
            tail->next = current;
        }
        tail = current;
    }
    *table = head;
}

_______________________________________________
Net-snmp-coders mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.