我已成功使用以下内容从本地snmpd读取一些简单的SNMP值:
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
}
虽然这适用于一些简单的整数标量,但我也有一些我需要阅读的表。我已经尝试了表的OID和snmp_add_null_var()中表条目的oid,但是snmp_sync_response()返回错误代码,表明找不到OID。
因此浏览头文件时遇到了这些调用。我怀疑其中一个可能就是我想要使用的东西:
netsnmp_query_walk()
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吗?
答案 0 :(得分:2)
我怀疑有几个问题。第一个是这一行:
snmp_pdu_create( SNMP_MSG_GET );
如果我考虑使用SNMP_MSG_GETBULK
,它可能会有所帮助,而不是调用MSG_GET。但事实证明我所连接的SNMP服务器只支持SNMPv1,而GETBULK特定于SNMPv2 +,所以我没有费心去挖掘。
我发现的是如何使用GETNEXT,它可以用来一次遍历一个变量表。以下是代码的工作原理:
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 );
}
答案 1 :(得分:0)
for snmpget使用此行=&gt; pdu = snmp_pdu_create(SNMP_MSG_GET); 对于snmpwalk使用此行=&gt; pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); 其余代码相同
答案 2 :(得分: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()
答案 3 :(得分:0)
我花了一些时间来解决这个问题,因为该功能的文档很少。无论你是对的,它都比使用低级函数更优雅。
您只需打开会话,初始化NULL varlist,然后使用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更清洁。