I think the biggest pain when it comes to net-snmp is all those Doxygen pages that contain Google indexes, but which provide almost zero useful content. Reading .h files is probably already obvious to most developers, and the truth is that net-snmp provides many different levels of APIs with very little documentation that I found useful. We need not a few dozen identical copies of the websites that host Doxygen, but some good examples instead.
After all, the mib2c tool is how I got enough sample code to make it all work. I think I tried running mib2c with every net-snmp .conf file and spent a lot of time reading the code generated for better understanding. Here are the ones I found gave me the best tips:
- mib2c -c mib2c.create-dataset.conf MyMib
- mib2c -c mib2c.table_data.conf MyMib
The .conf files are located here: /etc/snmp/mib2c.*
The following pages were also useful:
From what I understand, there are many helpers / layers available in the net-snmp API. Thus, this pseudo code for example may not work for everyone, but that’s how I personally got my tables to work with net-snmp v5.4:
A variable is needed for several functions (make it global or a member of the structure?)
netsnmp_tdata *table = NULL;
Structure for representing one row of the table (must comply with the MIB definition)
struct MyTable_entry { long myTableIndex; ...insert one line here for each column of the table... int valid;
Initialize a table using snmpd
std::string name( "name_of_the_table_from_mib" ); table = netsnmp_tdata_create_table( name.c_str(), 0 ); netsnmp_table_registration_info *table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info ); netsnmp_table_helper_add_indexes( table_info, ASN_INTEGER, 0 );
Request Handler
int myTable_handler( netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests ) { if ( reqInfo->mode != MODE_GET ) return SNMP_ERR_NOERROR; for ( netsnmp_request_info *request = requests; request; request = request->next ) { MyTable_entry *table_entry = (MyTable_entry*)netsnmp_tdata_extract_entry( request ); netsnmp_table_request_info *table_info = netsnmp_extract_table_info( request ); if ( table_entry == NULL ) { netsnmp_set_request_error( reqinfo, request, SNMP_NOSUCHINSTANCE); continue; } switch ( table_info->colnum ) {
Creating / adding rows to a table
if ( table == NULL ) return;
Combination
In my case, this last function, which builds strings, is periodically triggered by some other events in the system. Therefore, every time new statistics are available, the table is rebuilt, all old rows are deleted, and new ones are inserted. I did not try to change the existing lines. Instead, I found it easier to just rebuild the table from scratch.