I've successfully used the following to read some simple SNMP values from a local snmpd:
snmp_open( &session )
snmp_pdu_create( SNMP_MSG_GET );
snmp_add_null_var( pdu, oid, len ); // multiple lines like this
snmp_sync_response( ss, pdu, &response );
for ( netsnmp_variable_list *vars = response->variables; vars; vars = vars->next_variable )
{
// look at vars->name, vars->name_length, and vars->val.integer
}
While this works for a few simple integer scalars, I also have some tables I need to read. I've tried both the OID of the table and the oid of the table entry in snmp_add_null_var(), but snmp_sync_response() returns with an error code indicating that OID cannot be found.
So browsing the header files I came across these calls. I suspect one of these is likely to be what I want to be using:
netsnmp_query_walk()
netsnmp_query_get()
However, I cannot figure out how to use them. This is what I've tried:
netsnmp_variable_list *vb = (netsnmp_variable_list*)SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
if ( vb == NULL ) ...
snmp_set_var_objid( vb, oid, len );
int rc = netsnmp_query_walk( vb, ss );
//int rc = netsnmp_query_get( vb, ss );
...but at this point, rc is always == -1 which I'm guessing means there was an error. How do I use these, or, is there a better API I should be using?
I suspect there were several problems. The first is this line:
snmp_pdu_create( SNMP_MSG_GET );
Instead of calling MSG_GET, it would probably have helped if I'd looked into using SNMP_MSG_GETBULK
. But it turns out the SNMP server against which I'm connecting only supports SNMPv1, and GETBULK is specific to SNMPv2+, so I didn't bother digging.
What I found instead is how to use GETNEXT, which can be used to traverse the table one variable at a time. Here is how the code works:
oid = ....; // start with a known OID, like the table you want to read
while ( true )
{
pdu = snmp_pdu_create( SNMP_MSG_GETNEXT );
snmp_add_null_var( pdu, oid, len );
status = snmp_synch_response( ss, pdu, reply );
if ( status != STAT_SUCCESS )
{
// either an error, or there is nothing left to read
snmp_free_pdu( reply );
break;
}
for ( netsnmp_variable_list *vars=reply->variables; vars; vars=vars->next_variable )
{
// make sure you remember this OID so you know what to use
// when you get back to the top of the while() loop
oid = ...vars->name[], vars->name_length...;
// do something with this snmp value, such as:
std::cout << oid << ": " << *vars->val.integer << std::endl;
}
snmp_free_pdu( reply );
}