使用 net-snmp lib 接收 SNMP V3 陷阱的 C++ 源代码

问题描述

使用 net-snmp lib,我必须编写一个简单的应用程序“SNMP 管理器”来接收 UDP 端口 162 上的陷阱。我遵循了“snmptrapd.c”中的源代码,但我无法在回调函数中获取陷阱我的应用程序。在我的源文件中,当我遇到陷阱(snmpV2 或 snmpv3)时,我永远无法进入回调函数“snmpInputWrapper”。但是我注意到 UDP 端口在应用程序启动时正确打开。我该如何解决?提前致谢。

================ 文件陷阱.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,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

================ 文件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,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,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,(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 */
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...