Using net-snmp lib, I have to write a simple application "SNMP Manager" that receive traps on UDP port 162. I followed source code in "snmptrapd.c" but I can't get traps in the callback function of my application. In my sources file I can't never get into the callback function "snmpInputWrapper" when I get a trap (snmpV2 or snmpv3). However I have noticed that the UDP port is open correctly when application starts. How can I solve? Thanks in advance.
===============
File trap.h
#ifndef TRAP_H
#define TRAP_H
#include <QDebug>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <sys/time.h>
#include <time.h>
/* change the word "define" to "undef" to try the (insecure) SNMPv1 version */
//#define USE_SNMP_VERSION_3
#define authProtocolSha 0
#define authProtocoMd5 1
#define privProtocolAes 0
#define privProtocolDes 1
#define SUCCESS 0
#define FAILED -1
/* values for type field in get_req_state */
#define ALARM_GET_REQ 1
#define EVENT_GET_REQ 2
#define DEFAULT_RETRIES 5
class Trap
{
public:
Trap();
~Trap();
private:
#ifdef USE_SNMP_VERSION_3
const char *userV3 = "pippo";
const char *authPassphraseV3 = "authPwd";
const char *privPassphraseV3 = "privPwd";
int securityLevelV3 = SNMP_SEC_LEVEL_AUTHPRIV;
int authProtocol = 0;
int privProtocol = 1;
#else
QString communityName = "public";
#endif
netsnmp_transport *transport = NULL;
QString remoteHost = "xxx.xxx.xxx.xxx";
QString cfgFileLbl = "snmpCfg";
static int snmpInputWrapper(int operation, netsnmp_session *ss, int reqId, struct snmp_pdu *pdu, void *magic); /* callback */
int snmpInput(int operation, netsnmp_session *ss, int reqId, struct snmp_pdu *pdu, void *magic);
struct getReqState {
int type;
void *info;
};
netsnmp_session ss; /* snmp session to fill with information */
netsnmp_session *snmpSession; /* pointer of snmp session returned by the library */
int createSession(netsnmp_transport *transport);
int openSession();
void closeSession();
};
#endif // TRAP_H
===============
File trap.cpp
#include "trap.h"
//Global callback object
Trap *globalTrap;
Trap::Trap() {
globalTrap = this;
int status = SUCCESS;
/* initialize the SNMP library */
init_snmp(cfgFileLbl.toLatin1().data());
const char* application = "snmptrap";
const char* portNumber = "162";
transport = netsnmp_transport_open_server(application, portNumber);
if(transport != NULL) {
createSession(transport);
if(status != SUCCESS) {
qDebug() << "error making new snmp session";
return;
}
status = openSession();
if(status != SUCCESS) {
qDebug() << "error opening new snmp session";
}
}
else
qDebug() << "error openning snmp transport for snmp trap";
}
int Trap::snmpInput(int operation, netsnmp_session *ss, int reqId, struct snmp_pdu *pdu, void *magic) {
int status = SUCCESS;
struct getReqState *state = (struct getReqState*)magic;
if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
if (pdu->command == SNMP_MSG_GET) {
if (state->type == EVENT_GET_REQ) {
/* this is just the ack to our inform pdu */
return status;
}
}
} else if(operation == NETSNMP_CALLBACK_OP_TIMED_OUT) {
if (state->type == ALARM_GET_REQ) {
/* need a mechanism to replace obsolete SNMPv2p alarm */
}
}
/* ToDo */
return status;
}
int Trap::snmpInputWrapper(int operation, netsnmp_session *ss, int reqId, struct snmp_pdu *pdu, void *magic) {
int status = SUCCESS;
/* call the non-static member */
if(globalTrap) {
Trap *myCb = (Trap*)globalTrap;
status = myCb->snmpInput(operation, ss, reqId, pdu, magic);
}
return status;
}
int Trap::createSession(netsnmp_transport *transport) {
/* set up the authentication parameters for talking to the server */
int status = SUCCESS;
/* initialize a "session" that defines who we're going to talk to */
snmp_sess_init(&ss); /* set up defaults */
ss.peername = strdup(remoteHost.toLatin1().data()); /* Original code had NULL here */
/* set up the authentication parameters for talking to the server */
#ifdef USE_SNMP_VERSION_3
/* use SNMPv3 to talk to the experimental server */
ss.version=SNMP_VERSION_3; /* set the SNMP version number */
ss.securityName = strdup(userV3); /* set the SNMPv3 user name */
ss.securityNameLen = strlen(ss.securityName);
ss.securityLevel = securityLevelV3; /* set the security level to authenticated, but not encrypted */
if(authProtocol == authProtocolSha) {
ss.securityAuthProto = usmHMACSHA1AuthProtocol; /* set the authentication algorithm */
ss.securityAuthProtoLen = sizeof(usmHMACSHA1AuthProtocol)/sizeof(oid);
}
else {
ss.securityAuthProto = usmHMACMD5AuthProtocol; /* set the authentication algorithm */
ss.securityAuthProtoLen = sizeof(usmHMACMD5AuthProtocol)/sizeof(oid);
}
ss.securityAuthKeyLen = USM_AUTH_KU_LEN;
/* set the authentication key which must be at least 8 characters long */
if(generate_Ku(ss.securityAuthProto,
ss.securityAuthProtoLen,
(u_char *) authPassphraseV3, strlen(authPassphraseV3),
ss.securityAuthKey,
&ss.securityAuthKeyLen) != SNMPERR_SUCCESS) {
const char* error;
snmp_perror(error); /* populate error variable */
qDebug() << "error generating Ku from authentication pass phrase: " << error;
status = FAILED;
return status;
}
if(privProtocol == privProtocolAes) {
ss.securityPrivProto = usmAESPrivProtocol; /* set the privacy algorithm */
ss.securityPrivProtoLen = sizeof(usmAESPrivProtocol)/sizeof(oid);
}
else {
ss.securityPrivProto = usmDESPrivProtocol; /* set the privacy algorithm */
ss.securityPrivProtoLen = sizeof(usmDESPrivProtocol)/sizeof(oid);
}
ss.securityPrivKeyLen = USM_PRIV_KU_LEN;
if(generate_Ku(ss.securityAuthProto,
ss.securityAuthProtoLen,
(u_char *) privPassphraseV3, strlen(privPassphraseV3),
ss.securityPrivKey,
&ss.securityPrivKeyLen) != SNMPERR_SUCCESS) {
const char* error;
snmp_perror(error); /* populate error variable */
qDebug() << "error generating Ku from authentication pass phrase: " << error;
status = FAILED;
return status;
}
#else /* we'll use the insecure (but simplier) SNMPv1 */
ss.version = SNMP_VERSION_1 /* SNMP_VERSION_2c */; /* set the SNMP version number */
ss.community = (unsigned char*)communityName.toLatin1().data(); /* set the SNMPv1 community name used for authentication */
ss.community_len = strlen((const char*)ss.community);
ss.authenticator = NULL;
ss.isAuthoritative = SNMP_SESS_UNKNOWNAUTH;
//ss.retries = SNMP_DEFAULT_RETRIES;
//ss.timeout = SNMP_DEFAULT_TIMEOUT;
#endif
/* define callback function to get traps */
ss.callback = snmpInputWrapper;
ss.callback_magic = (void*)transport;
}
int Trap::openSession() {
/* open the session */
int status = SUCCESS;
SOCK_STARTUP;
snmpSession = snmp_open(&ss); /* establish the session */
if(!snmpSession) {
qDebug() << "error opening snmp session";
snmp_sess_perror("ack", &ss);
SOCK_CLEANUP;
status = FAILED;
}
return status;
}
void Trap::closeSession() {
snmp_close(snmpSession); /* close active session for the current host */
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…