Penso che il più grande dolore quando si tratta di net-snmp sono tutte quelle pagine Doxygen degli indici di Google ma che forniscono contenuti utilizzabili quasi zero. Leggere i file .h
è probabilmente già ovvio per la maggior parte degli sviluppatori, e la verità è che net-snmp fornisce molti livelli diversi di API con pochissima documentazione che ho trovato utile. Ciò di cui abbiamo bisogno non sono alcune decine di copie identiche di siti Web che ospitano Doxygen, ma invece alcuni buoni esempi.
Alla fine, lo strumento mib2c è come ho ottenuto abbastanza codice di esempio per far funzionare tutto. Penso di aver provato a eseguire mib2c con ogni singolo file net-snmp .conf
e ho trascorso molto tempo a leggere il codice generato per ottenere una migliore comprensione. Qui sono quelli che ho trovato mi hanno dato i migliori suggerimenti:
- mib2c -c mib2c.create-dataset.conf MyMib
- mib2c -c mib2c.table_data.conf MyMib
I file .conf
sono qui: /etc/snmp/mib2c.*
utili sono stati anche le seguenti pagine:
Da quello che ho capito, ci sono molti aiutanti/livelli disponibili nell'API net-SNMP. Quindi questo esempio pseudocodice potrebbe non funzionare per tutti, ma questo è come io personalmente ho le mie tabelle di lavorare utilizzando net-snmp v5.4:
variabile necessaria tra diverse funzioni (renderlo globale, o un membro di un struct?)
netsnmp_tdata *table = NULL;
Struttura per rappresentare una riga della tabella (deve corrispondere alla definizione MIB)
struct MyTable_entry
{
long myTableIndex;
...insert one line here for each column of the table...
int valid; // add this one to the end
}
inizializzare la tabella con 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); // index: myTableIndex
// specify the number of columns in the table (exclude the index which was already added)
table_info->min_column = COLUMN_BLAH;
table_info->max_column = MAX_COLUMN_INDEX;
netsnmp_handler_registration *reg = netsnmp_create_handler_registration(name.c_str(), MyTable_handler, oid, oid.size(), HANDLER_CAN_RONLY);
netsnmp_tdata_register(reg, table, table_info);
Handler per elaborare le richieste
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)
{
// ...this is similar to non-table situations, eg:
case COLUMN_BLAH:
snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, table_entry->blah); break;
// ...
default: netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
}
}
return SNMP_ERR_NOERROR;
}
Costruire/aggiunta di righe alla tabella
if (table == NULL) return; // remember our "global" variable named "table"?
// start by deleting all of the existing rows
while (netsnmp_tdata_row_count(table) > 0)
{
netsnmp_tdata_row *row = netsnmp_tdata_row_first(table);
netsnmp_tdata_remove_and_delete_row(table, row);
}
for (...loop through all the data you want to add as rows into the table...)
{
MyTable_entry *entry = SNMP_MALLOC_TYPEDEF(MyTable_entry);
if (entry == NULL) ... return;
netsnmp_tdata_row *row = netsnmp_tdata_create_row();
if (row == NULL) SNMP_FREE(entry); .... return;
entry->myTableIndex = 123; // the row index number
// populate the table the way you need
entry->blah = 456;
// ...
// add the data into the row, then add the row to the table
entry->valid = 1;
row->data = entry;
netsnmp_tdata_row_add_index(row, ASN_INTEGER, &(entry->myTableIndex), sizeof(entry->myTableIndex));
netsnmp_tdata_add_row(table, row);
}
Mettere insieme
Nel mio caso, quell'ultima funzione che crea le righe viene attivata periodicamente da alcuni altri eventi nel sistema. Quindi ogni tanto quando sono disponibili nuove statistiche, la tabella viene ricostruita, tutte le vecchie file vengono rimosse e quelle nuove vengono inserite. Non mi sono preoccupato di provare a modificare le righe esistenti. Invece, ho trovato che era più facile ricostruire il tavolo da zero.
Stai scrivendo il tuo agente da zero o usando 'mib2c'? 'mib2c' può generare l'intero scheletro per te. Dopo di che, convertirlo in un sub-agente è facile. Hai già letto "http://net-snmp.sourceforge.net/wiki/index.php/TUT:Writing_a_Subagent"? – j4x