Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
446 views
in Technique[技术] by (71.8m points)

qt - C++ source code to receive SNMP V3 trap with net-snmp lib

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 */
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...