2012-04-03 7 views
2

私が正常に地元のsnmpdからいくつかの単純なSNMP値を読み取るために、次の使用しました:netsnmp_query_walk()またはnetsnmp_query_get()はどのように使用しますか?

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 
} 

これはいくつかの簡単な整数スカラーのために動作しますが、私はまた私が読む必要があるいくつかのテーブルを持っています。 snmp_add_null_var()でテーブルのOIDとテーブルエントリのoidの両方を試しましたが、snmp_sync_response()はOIDが見つからないことを示すエラーコードを返します。

ヘッダーファイルを参照すると、私はこれらの呼び出しに遭遇しました。私はこれらの一つは、私が使用しているしたいものである可能性が高い疑う:

  1. netsnmp_query_walk()
  2. netsnmp_query_get()

しかし、私はそれらを使用する方法を見つけ出すことはできません。

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); 

...しかし、この時点で、RCは== -1、私は推測しているときにエラーが発生したことを意味し、常に次のとおりです。これは私が試したものです。これらをどうやって使うのですか、それとももっと良いAPIがありますか?

答えて

2

いくつか問題があると思われます。最初はこの行です:

snmp_pdu_create(SNMP_MSG_GET); 

代わりのMSG_GETを呼び出して、私はSNMP_MSG_GETBULKを使用してに見たい場合には、それはおそらく役立っただろう。しかし、私が接続しているSNMPサーバはSNMPv1しかサポートしていないことが分かりました.GETBULKはSNMPv2 +に固有のものなので、掘り起こすことはありませんでした。

私が代わりに見つけたのは、一度に1つの変数をテーブルをトラバースするために使用できるGETNEXTを使用する方法です。ここでは、コードがどのように動作するかです:snmpgetコマンドを使用するために

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); 
} 
0

このライン=> PDU = snmp_pdu_create(SNMP_MSG_GET)。 snmpwalkのための はこの行を使用します=> pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); コードの残りは同じ

0

snmpwalkのコードを見てから、私はコードでそれを行う方法の簡単な例を得ました。

#include <net-snmp/net-snmp-config.h> 
#include <net-snmp/net-snmp-includes.h> 
#include <string.h> 

void 
snmp_get_and_print(netsnmp_session * ss, oid * theoid, size_t theoid_len) 
{ 
    netsnmp_pdu *pdu, *response; 
    netsnmp_variable_list *vars; 
    int    status; 

    pdu = snmp_pdu_create(SNMP_MSG_GET); 
    snmp_add_null_var(pdu, theoid, theoid_len); 

    status = snmp_synch_response(ss, pdu, &response); 
    if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { 
     for (vars = response->variables; vars; vars = vars->next_variable) { 
      print_variable(vars->name, vars->name_length, vars); 
     } 
    } 
    if (response) { 
     snmp_free_pdu(response); 
    } 
} 

int main(int argc, char ** argv) 
{ 
    netsnmp_session session, *ss; 
    netsnmp_pdu *pdu, *response; 
    netsnmp_variable_list *vars; 

    oid    name[MAX_OID_LEN]; 
    size_t   name_length; 
    oid    root[MAX_OID_LEN]; 
    size_t   rootlen; 
    oid    end_oid[MAX_OID_LEN]; 
    size_t   end_len = 0; 
    int    count; 
    int    running; 

    int status = STAT_ERROR;; 

    init_snmp("snmpwalk"); 

    snmp_sess_init(&session); 
    session.peername = strdup("SNMP.device.domain"); 


    //session.version = SNMP_VERSION_1; 
    session.version = SNMP_VERSION_2c; 

    session.community = "public"; 
    session.community_len = strlen(session.community); 

    SOCK_STARTUP; 
    ss = snmp_open(&session); 

    if (!ss) { 
     snmp_sess_perror("ack", &session); 
     SOCK_CLEANUP; 
     exit(1); 
    } 

    rootlen = MAX_OID_LEN; 
    if (snmp_parse_oid("RFC1213-MIB::ifIndex", root, &rootlen) == NULL) { 
     snmp_perror("RFC1213-MIB::ifIndex"); 
     exit(1); 
    } 

    memmove(end_oid, root, rootlen*sizeof(oid)); 
    end_len = rootlen; 
    end_oid[end_len-1]++; 

    memmove(name, root, rootlen * sizeof(oid)); 
    name_length = rootlen; 

    running = 1; 

    while (running) { 
     // create PDU for GETNEXT request and add object name to request 
     pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); 
     snmp_add_null_var(pdu, name, name_length); 

     status = snmp_synch_response(ss, pdu, &response); 

     if (status == STAT_SUCCESS) { 
      if (response->errstat == SNMP_ERR_NOERROR) { 
       // check resulting variables 
       for (vars = response->variables; vars; 
        vars = vars->next_variable) { 
        if (snmp_oid_compare(end_oid, end_len, 
         vars->name, vars->name_length) <= 0) { 
         //not part of this subtree 
         running = 0; 
         continue; 
        } 
        print_variable(vars->name, vars->name_length, vars); 
        memmove((char *) name, (char *) vars->name, 
         vars->name_length * sizeof(oid)); 
        name_length = vars->name_length; 
       } 
      } 
     } 
     if (response) 
      snmp_free_pdu(response); 
    } 

    snmp_close(ss); 

    SOCK_CLEANUP; 
    return (0); 

} // main() 
0

この機能にはほとんどドキュメントがありません。しかし、あなたは正しいですが、それは下位レベルの機能を使用するよりはるかにエレガントです。

セッションを開き、NULL変数リストを初期化してから、snmp_varlist_add_variableを使用してoidおよびoid_lenを入力するだけです。

ss = snmp_open(&session); 
if (!ss) { 
    snmp_sess_perror("snmp_open", &session); 
    exit(STATUS_UNKNOWN); 
} 

/* Walk Indexes */ 
snmp_varlist_add_variable(&hrprload_var, hrprload_oid, hrprload_len, ASN_NULL, NULL, 0); 

query_status = netsnmp_query_walk(hrprload_var, ss); 
if (query_status != SNMP_ERR_NOERROR) { 
    if (query_status == STAT_TIMEOUT) { 
     fprintf(stderr, "Timeout: No Response from %s\n", ss->peername); 
    } else { 
     fprintf(stderr, "Error in packet: %s\n", snmp_api_errstring(ss->s_snmp_errno)); 
    } 
    exit(STATUS_UNKNOWN); 
} 

これで、クエリ結果が入力されたvarlistを使用できます。 PDUで迷惑をかけるよりもはるかにクリーンです。

関連する問題