How get trap with indy TidSNMP component

1.2k Views Asked by At

I'm using c++builderXE with Indy 10.5.7 and I'm trying to receive trap from another agent snmp.

I have no info describing how to do the program to receive trap.

Below you can find the snippet of code which I'm trying to use now.

The ReceiveTrap() method always return 0, which means non data received.

I tested the PC configuration with another program I made several years ago using spare API and the trap is received so I don't this it should be a configuration problem.

Have you some suggestions of hat I'm wrong in the routine below?

void __fastcall TForm1::LabelReceiveTrapClick(TObject * Sender)
{
    static bool status = false;
    int ists;
    String Fun           = "[SimpleReceiveTrap] ";
    TSNMPInfo * infoSnmp = 0;

    try
    {
        status = !status;

        if (status)
        {
            std::auto_ptr< TIdSNMP >clientSnmp(new TIdSNMP(NULL));
            clientSnmp->Community      = "public";
            clientSnmp->ReceiveTimeout = 1000;
            clientSnmp->Binding->Port  = 162;
            while (status)
            {
                Application->ProcessMessages();
                ists = clientSnmp->ReceiveTrap();
                Mylog(L"%s ReceiveTrap status = [%d]", Fun.c_str(), ists);
                if (ists > 0)
                {
                    infoSnmp = clientSnmp->Trap;
                }
            }
        }
    }
    catch (Exception & ex)
    {
        Mylog(L"%s ERROR", Fun.c_str(), ex.Message.c_str());
    }
}
2

There are 2 best solutions below

0
On

That is not the correct way to set the listening Port for receiving traps. Reading the Binding property allocates and binds a socket to a local IP/Port using the TIdSNMP::BoundIP and TIdSNMP::BoundPort properties. You can't change that socket's local Port after it has already been bound, so your assignment of the Binding->Port property is effectively a no-op.

For that matter, you are trying to manipulate the wrong socket anyway. The Binding socket is used for sending queries to the remote SNMP system. TIdSNMP uses a separate socket for receiving traps. TIdSNMP has a separate TrapPort property for specifying the listening Port of that socket. When the Binding is accessed, the trap socket is allocated and bound to Binding->IP and TIdSNMP::TrapPort. The TrapPort property defaults to 162.

std::auto_ptr< TIdSNMP >clientSnmp(new TIdSNMP(NULL));
clientSnmp->Community = "public";
clientSnmp->ReceiveTimeout = 1000;
clientSnmp->TrapPort = 162; // <--
...
ists = clientSnmp->ReceiveTrap();

Looking at Indy's changelog, there have been some trap-related changes to the listening socket since 10.5.7 was released, so you may need to upgrade to a newer Indy version to get bug fixes. Or you could download the latest version and then just add IdSNMP.pas to your project directly, at least.

0
On

Using only the Indi component I can't read the trap rev 2c But I found a solution using TWSocket and TSNMPInfo which seems to works well

Belowe the code I used:

To get the data I use a TWSocket fro FPiette components suite:

void __fastcall TForm1::LabelStartServerTracSnmpClick(TObject * Sender)
{
    String Fun = "[LabelStartServerTracSnmp] ";
    try
    {
        if (WSocket1->State == wsClosed)
        {
            WSocket1->Proto = "udp";
            WSocket1->Addr  = "0.0.0.0";
            WSocket1->Port  = 162;
            WSocket1->Listen();
        }
        else
        {
            WSocket1->Close();
        }
    }
    catch (Exception & ex)
    {
        Mylog(L"%s ERROR: [%s]", Fun.c_str(), ex.Message.c_str());
    }
}

To analyze the data received I use the Indy

void __fastcall TForm1::WSocket1DataAvailable(TObject * Sender, WORD ErrCode)
{
    char buffer[1024];
    int len, cnt, srcLen;
    TSockAddrIn srcSocket;
    String rcvmsg, remHost, s1, s2, Fun = "[WSocket1DataAvailable] ";
    TIdSNMP * clientSnmp = NULL;
    TSNMPInfo * infoSnmp = NULL;
    try
    {
        srcLen = sizeof(srcSocket);
        len    = WSocket1->ReceiveFrom(buffer, sizeof(buffer), srcSocket, srcLen);
        if (len >= 0)
        {
            buffer[len] = 0;
            rcvmsg      = String(buffer, len);

            __try
            {
                clientSnmp = new TIdSNMP(NULL);
                infoSnmp   = new TSNMPInfo(clientSnmp);
                infoSnmp->DecodeBuf(rcvmsg);
                cnt = infoSnmp->ValueCount;
                if (cnt > 0)
                {
                    // ---------------------------------------------------
                    for (int idx = 0; idx < cnt; ++idx)
                    {
                        s1 = infoSnmp->ValueOID[idx];
                        s2 = infoSnmp->Value[idx];
                        Mylog(L"[%s] Trap : [%s] => [%s]", s1.c_str(), s2.c_str());
                    }
                }
            }
            __finally
            {
                if (infoSnmp)
                {
                    delete infoSnmp;
                    infoSnmp = 0;
                }
                if (clientSnmp)
                {
                    delete clientSnmp;
                    clientSnmp = 0;
                }
            }
        }
    }
    catch (Exception & ex)
    {
        Mylog(L"%s ERROR", Fun.c_str(), ex.Message.c_str());
    }

}