Snmp_ex2_simple_standard_test throws an error “failed retrieving agent data”

I have planned to develop an SNMP manager using snmpm module. In the process, I have referred to the modules snmp_ex2_simple_standard_test & snmp_ex2_manager.

The SNMP test module snmp_ex2_simple_standard_test has different test cases to test various SNMP operations. I considered the test case related to the SNMP GET operation to simplify the debugging. I am getting an error “failed retrieving agent data”. Please help me in resolving the issue.

To debug the issue, I added snmpm:verbosity(all, info). in snmp_ex2_manager.erl. I also enabled dbg logs for snmpm_config. Following is the analysis of the logs.

  1. snmp_ex2_simple_standard_test uses an agent 127.0.1.1:161. snmpm_config:agent_info(“127.0.1.1:161”) resulted in the vtrace messages "SNMP M-SERVER INFO -- failed retrieving agent data for get:"
  2. snmpm_config:agent_info(default_agent,all) is also called, which successfully returned a value. default_agent is the default agent defined in snmpm_config -define(DEFAULT_TARGETNAME, default_agent).
  3. Looks like the agent 127.0.1.1:161 is not initialized properly.

LOGS

Erlang/OTP 27 [DEVELOPMENT] [erts-14.1.1] [source] [64-bit] [smp:6:6] [ds:6:6:10] [async-threads:1]

Eshell V14.1.1 (press Ctrl+G to abort, type help(). for help)
(node1@vm-alarm)1> dbg:tracer().
{ok,<0.93.0>}
(node1@vm-alarm)2> dbg:tpl(snmpm_config, agent_info, []).
{ok,[{matched,'node1@vm-alarm',4}]}
(node1@vm-alarm)3> dbg:p(all, c).
{ok,[{matched,'node1@vm-alarm',51}]}
(node1@vm-alarm)4> snmp_ex2_simple_standard_test:start().
(<0.103.0>) call snmpm_config:agent_info()
(<0.103.0>) call snmpm_config:agent_info(default_agent,all)
(<0.100.0>) call snmpm_config:agent_info()
(<0.100.0>) call snmpm_config:agent_info(default_agent,all)
snmpm:snmpm:mk_target_name(snmpUDPDomain, {{127,0,1,1},161}, [{community,
                                                               "public"}]) -> "127.0.1.1:161-v1".

(<0.103.0>) call snmpm_config:agent_info("127.0.1.1:161-v1",user_id)
(<0.103.0>) call snmpm_config:agent_info({"127.0.1.1:161-v1",user_id})
(<0.114.0>) call snmpm_config:agent_info({127,0,1,1},version)
(<0.114.0>) call snmpm_config:agent_info({{127,0,1,1},version})
*** [2024-02-09 21:59:58.372] SNMP M-SERVER INFO *** 
   failed retrieving agent data for get:
   TargetName: {127,0,1,1}
   Error:      {error,not_found}
ok

CODE
To simplify the debugging, I modified the function snmp_ex2_simple_standard_test:start/3 to test the SNMP GET operation alone.

start(Mibs, AgentAddr, AgentConfig) ->
    Conf = [{mibs, Mibs}],
    {ok, _Pid} = snmp_ex2_manager:start_link(Conf),
    snmp_ex2_manager:agent(AgentAddr, AgentConfig),
    %%simple_standard_test(AgentAddr),
    %%simple_standard_test_ori(AgentAddr),
    g(AgentAddr, [1,3,6,1,2,1,1,1]), %%sysDescr
    %%g(AgentAddr, [1,3,6,1,2,1,11,1]), %%snmpInPkts
    snmp_ex2_manager:stop().
1 Like

I fished this HOWTO out of the wayback machine, ported it to markdown, and included it below so that it may live on.

SNMP Quick Start

Authors

Vance Shipley (@vances) and Serge Aleynikov (@saleyn)

Agent Configuration

Directories

Create a subdirectory to contain the configuration files of the agent named snmp/agent/conf and another for the working files named snmp/agent/db.

Create the agent configuration and database directories:

$ mkdir -p snmp/agent/conf
$ mkdir -p snmp/agent/db

Agent Information

The snmp/agent/conf/agent.conf file defines the information for this agent. The IP address and port which the agent will respond to must be provided as well as a unique identifier called an engineID. The maximum size of a packet must also be provided.

Create the agent information file:

$ cat > snmp/agent/conf/agent.conf
{intAgentIpAddress, [127,0,0,1]}.
{intAgentUDPPort, 4000}.
{snmpEngineID, "agent's engine"}.
{snmpEngineMaxMessageSize, 484}.
^D

Note: Control-D to terminate

System Information

The snmp/agent/conf/standard.conf file defines the information for the system being managed. Here we will use the sysObjectID for the Ericsson OTP application. If you are creating an agent to manage your own embedded system you may want to apply for a private enterprise number assignment and create your own sysObjectID for your network element.

Create the system information file:

$ cat > snmp/agent/conf/standard.conf
{sysName, "SNMP Quick Start HowTo Demo"}.
{sysDescr, "Erlang/OTP Agent"}.
{sysContact, "vances@motivity.ca"}.
{sysLocation, "5th Floor machine room, rack 21A"}.
{sysObjectID, [3,6,1,4,1,193,19]}.  % {ericsson otp}
{sysServices, 72}.
{snmpEnableAuthenTraps, enabled}.
^D

Community

The snmp/agent/conf/community.conf file defines the communities for the system being managed. It is required for SNMPv1 or SNMPv2c.

Create the community file:

$ cat > snmp/agent/conf/community.conf
{"public", "public", "initial", "", ""}.
^D

MIB Views

The snmp/agent/conf/vacm.conf file defines the views for VACM. This determines what access rights users have to areas of the MIBS. Here we will define access rights for the community defined above.

Create the VACM file:

$ cat > snmp/agent/conf/vacm.conf
{vacmSecurityToGroup, v2c, "initial", "initial"}.
{vacmSecurityToGroup, usm, "initial", "initial"}.
{vacmAccess, "initial", "", any, noAuthNoPriv, exact, "restricted", "", "restricted"}.
{vacmAccess, "initial", "", usm, authNoPriv, exact, "internet", "internet", "internet"}.
{vacmAccess, "initial", "", usm, authPriv, exact, "internet", "internet", "internet"}.
{vacmViewTreeFamily, "internet", [1,3,6,1], included, null}.
{vacmViewTreeFamily, "restricted", [1,3,6,1], included, null}.
^D

Notify

Create an empty notify.conf file for now:

$ touch snmp/agent/conf/notify.conf

Application Environment

Create the snmp/agent.config system configuration file to be used when we start the node to run the agent. Here we define the required application environment variables. The paths to the subdirectories we created earlier are given so the agent application can find it’s configuration files and persistent database.

Create the agent OTP system configuration file:

$ cat > snmp/agent.config
[{snmp,
        [{agent,
                [{config,
                        [{dir, "snmp/agent/conf/"}]},
                        {db_dir, "snmp/agent/db/"}]}]}].
^D

Running the Agent

The configuration in snmp/agent.config will be used when we start the emulator with the -config snmp/agent command line option.

Starting the agent for the first time:

$ erl -sname agent -config snmp/agent
	
Eshell V5.9  (abort with ^G)
(agent@myhost)1> application:start(snmp).
=INFO REPORT==== 11-Feb-2024::16:43:03.523806 ===
[ snmp : agent : snmp_user_based_sm_mib : <0.97.0> ] 
USM: Incomplete configuration. Generating empty usm.conf.

ok

Note: The system will create some missing files for us.

The agent is now running using SNMPv1, SNMPv2c and SNMPv3.

Verifying Configuration

Get the system name:

(agent@myhost)2> {value, OID} = snmpa:name_to_oid(sysName).
{value,[1,3,6,1,2,1,1,5]}
(agent@myhost)3> snmpa:get(snmp_master_agent, [OID ++ [0]]).
["SNMP Quick Start HowTo Demo"]

Note: We need to add a 0 to the OID to access the value.

Manager Configuration

Directories

Create a subdirectory to contain the configuration files of the manager named snmp/manager/conf and another for the working files named snmp/manager/db.

Create the manager configuration and database directories:

$ mkdir -p snmp/manager/conf
$ mkdir -p snmp/manager/db

Manager Information

The snmp/manager/conf/manager.conf file defines the information for this manager. The IP address and port which the manager will use must be provided as well as a unique identifier called an engineID. The maximum size of a packet must also be provided.

Create the manager information file:

$ cat > snmp/manager/conf/manager.conf
{port, 5000}.
{address, [127,0,0,1]}.
{engine_id, "manager's engine"}.
{max_message_size, 484}.
^D

Users

The snmp/manager/conf/users.conf file defines the manager users. A manager user is implemented in a callback module. Here we will define a simple manager user using the default module.

Create the users file:

$ cat > snmp/manager/conf/users.conf
{"simple_user", snmpm_user_default, undefined}.
^D

Agents

The snmp/manager/conf/agents.conf file defines the agents the manager will use. Here we’ll define one agent; the one we started above. For now we’ll define it to use SNMPv2c.

Create the agents file:

$ cat > snmp/manager/conf/agents.conf
{"simple_user", "otp agent", "public", [127,0,0,1], 4000, "agent's engine", infinity, 484, v2, v2c, "initial", noAuthNoPriv}.
^D

Application Environment

Create the snmp/manager.config system configuration file to be used when we start the node to run the manager. Here we define the required application environment variables. The paths to the subdirectories we created earlier are given so the manager application can find it’s configuration files and persistent database.

Create the manager OTP system configuration file:

$ cat > snmp/manager.config
[{snmp,
        [{manager,
                [{config,
                        [{dir, "snmp/manager/conf/"},
                        {db_dir, "snmp/manager/db/"}]}]}]}].
^D

Running the Manager

Startup

The configuration in snmp/manager.config will be used when we start the emulator with the -config snmp/manager commandline option.

Starting the manager for the first time:

$ erl -sname manager -config snmp/manager

Eshell V5.9  (abort with ^G)
(manager@myhost)1> application:start(snmp).
ok

Verifying Configuration

List users:

(manager@myhost)2> snmpm:which_users().
["simple_user"]

List agents:

(manager@myhost)3> snmpm:which_agents().
["otp agent"]

Verify agent configuration:

(manager@myhost)4> snmpm:agent_info("otp agent", community).
{ok,"public"}
(manager@myhost)5> snmpm:agent_info("otp agent", engine_id).
{ok,"agent's engine"}

Query the Agent

Here we will send an SNMP query to the (possibly remote) agent and return the result. We will make the request using the OID for sysName as above.

Get system name from agent:

(manager@myhost)6> snmpm:sync_get2("simple_user", "otp agent", [[1,3,6,1,2,1,1,5,0]]).
{ok,{noError,0,
        [#varbind{oid = [1,3,6,1,2,1,1,5,0],
                variabletype = 'OCTET STRING',
                value = "SNMP Quick Start HowTo Demo",org_index = 1}]},
        4982}

Note: In the above example we have previously used the shell command rr/1 to load the record definitions so that the output is parsed with record field names: rr(code:lib_dir() ++ "/snmp-*/include/*").

Adding Authentication and Privacy

User Based Security Model (USM)

With SNMPv3 the agent and manager may share a secret for authentication using either MD5 or SHA. RFC2274 specifies an algorithm to generate a localized key using a passphrase and engineID. This localized authentication key is defined in the agent’s and manager’s usm.conf file.

Generating Localized Keys

The snmp application can be used to generate a localized key.

Generating a localized authentication key for the agent:

$ erl

Eshell V5.9  (abort with ^G)
1> application:start(crypto).
ok
2> snmp:passwd2localized_key(md5, "The quick brown fox jumps over the lazy dog.", "agent's engine").
[40,165,209,16,245,231,199,157,53,56,248,82,228,181,160,143]

When authentication is used it is also possible to ensure privacy of the transmitted information. A shared secret is used to encrypt the scopedPDU using DES.

Generating a localized privacy key for the agent:

4> snmp:passwd2localized_key(md5, "Pack my box with five dozen liquor jugs.", "agent's engine").
[4,11,162,206,20,118,62,83,28,129,124,10,66,5,100,136]

Security Data Configuration

The snmp/agent/conf/usm.conf file defines the security data for each user of an agent. Here we have chosen MD5 based authentication and DES encryption privacy.

Create the USM configuration file for the agent:

$ cat > snmp/agent/conf/usm.conf
{"agent's engine", "simple_user", "initial", zeroDotZero,
        usmHMACMD5AuthProtocol, "", "",
        usmDESPrivProtocol, "", "", "",
        [40,165,209,16,245,231,199,157,53,56,248,82,228,181,160,143],
        [4,11,162,206,20,118,62,83,28,129,124,10,66,5,100,136]}.
^D

The snmp/manager/conf/usm.conf file defines the security data for each manager user on each agent.

Create the USM configuration file for the manager:

$ cat > snmp/manager/conf/usm.conf
{"agent's engine", "simple_user", "initial",
        usmHMACMD5AuthProtocol [40,165,209,16,245,231,199,157,53,56,248,82,228,181,160,143],
        usmDESPrivProtocol, [4,11,162,206,20,118,62,83,28,129,124,10,66,5,100,136]}.
^D

Agent Configuration

Earlier we configured the manager to use SNMPv2c to contact the agent. Here we’ll replace that with an SNMPv3 USM configuration using MD5 authentication and DES privacy.

Create the agents configuration file for the manager:

$ cat > snmp/manager/conf/agents.conf
{"simple_user", "otp agent", "public", [127,0,0,1], 4000, "agent's engine", infinity, 484, v3, usm, "initial", authPriv}.
^D

Start the Application

After any configuration file changes it is necessary to delete the db files. The cached configuration is rebuilt automatically:

$ rm snmp/agent/db/*
$ rm snmp/manager/db/*

Note: The crypto application is required for authentication/privacy.

Start the agent:

$ erl -sname agent -config snmp/agent

Eshell V5.9  (abort with ^G)
(agent@myhost)1> application:start(crypto).
ok
(agent@myhost)2> application:start(snmp).
ok

Load the user table:

(agent@myhost)3>  Dir = code:priv_dir(snmp) ++ "/mibs/",
(agent@myhost)3>  snmpa:load_mibs([Dir ++ "SNMP-USER-BASED-SM-MIB"]).
ok
(agent@myhost)4>  snmp_user_based_sm_mib:configure("snmp/agent/conf").
ok

Note: You may add the snmp application environment variable {mibs, [".../priv/mibs/SNMP-USER-BASED-SM-MIB"]} to the agent.config file to automatically load on start.

Start the manager:

$ erl -sname manager -config snmp/manager

Eshell V5.9  (abort with ^G)
(manager@myhost)1> application:start(crypto).
ok
(manager@myhost)2> application:start(snmp).
ok

Querying the agent:

(manager@myhost)3> snmpm:load_mib(code:priv_dir(snmp) ++ "/mibs/SNMPv2-MIB").
ok
(manager@myhost)4> snmpm:sync_get2("simple_user", "otp agent", [[sysName,0]]).

=INFO REPORT==== 10-Feb-2012::22:31:31 ===
SNMPM default user callback received handle_inform:
   TargetName:   "otp agent"
   SnmpReport: {noError,0,
                        [{varbind,[1,3,6,1,6,3,15,1,1,2,0],'Counter32',0,1}]}
   UserData:   undefined
{error,{timeout,1305755172}}
(manager@myhost)5> snmpm:sync_get2("simple_user", "otp agent", [[1,3,6,1,2,1,1,5,0]]).
{ok,{noError,0,
        [#varbind{oid = [1,3,6,1,2,1,1,5,0],
                variabletype = 'OCTET STRING',
                value = "SNMP Quick Start HowTo Demo",org_index = 1}]},
        4632}

Note: The initial query does not contain the correct snmpEngineBoots and snmpEngineTime values and so is discarded by the agent. Subsequent queries will be properly authenticated.

Sending SNMP Alarms

Traps and Notifications

The snmp/agent/conf/notify.conf file contains information about SNMP trap definitions.

Create the notify file:

$ cat > snmp/agent/conf/notify.conf
{"MyFirstCoolTrap", "tag1", trap}.
^D

The snmp/agent/conf/target_addr.conf file contains information about SNMP target address definitions. Note that TagList can contain multiple tags separated by spaces.

Create the target address file:

$ cat > snmp/agent/conf/target_addr.conf
{"MyFirstCoolTrap", [127,0,0,1], 162, 5000, 3, "tag1", "MyCoolTrapParams", "agent's engine"}.
^D

The snmp/agent/conf/target_params.conf file contains information about SNMP target parameters definitions.

Create the target parameters file:

$ cat > snmp/agent/conf/target_params.conf
{"MyCoolTrapParams", v2c, v2c, "initial", noAuthNoPriv}.
^D

Creating a MIB File Containing a Trap Definition

Now it’s time to create a MIB file that defines a test trap. While it is possible to reference traps in existing MIB files, we are going to beef up this tutorial by creating a sample MIB.

Create a sample MIB file with a trap definition:

$ mkdir -p snmp/agent/mibs
$ cat > snmp/agent/mibs/MY-TRAP-MIB.mib
MY-TRAP-MIB DEFINITIONS ::= BEGIN

IMPORTS
    MODULE-IDENTITY, NOTIFICATION-TYPE
        FROM SNMPv2-SMI
    NOTIFICATION-GROUP
        FROM SNMPv2-CONF
    sysContact, sysName, sysLocation
        FROM SNMPv2-MIB
    otpModules, otpApplications
        FROM OTP-REG
    ;

 testMIBModule MODULE-IDENTITY
       LAST-UPDATED "200506100000Z"
       ORGANIZATION "IDT"
       CONTACT-INFO "Serge Aleynikov (serge@hq.idt.net)"
       DESCRIPTION  "Experimental MIB module."
       ::= { otpModules 10 }

testMIB        OBJECT IDENTIFIER ::= { otpApplications 1000 }
testMIBConformance
               OBJECT IDENTIFIER ::= { testMIB 1 }
testMIBTraps   OBJECT IDENTIFIER ::= { testMIB 2 }

testMIBMyFirstCoolTrap NOTIFICATION-TYPE
    OBJECTS {
        sysContact,
        sysName,
        sysLocation
        }
    STATUS  current
    DESCRIPTION
        "This event is sent when an OTP user is desperately
         trying to get the SNMP traps working."
    ::= { testMIBTraps 1 }

testMIBTrapGroups
                OBJECT IDENTIFIER ::= { testMIBConformance 2 }

testMIBTrapGroup NOTIFICATION-GROUP
    NOTIFICATIONS { testMIBMyFirstCoolTrap }
    STATUS        current
    DESCRIPTION
        "The notification which is generated from EVA."
    ::= { testMIBTrapGroups 4 }

END
^D

Let’s use Net-SNMP again to verify that traps are getting sent.

Start a snmptrapd daemon:

$ sudo snmptrapd -P -F "%02.2h:%02.2j TRAP%w.%q from %A\n  %v\n%" -m "snmp/agent/mibs/MY-TRAP-MIB.mib"

Once this is done, we are ready to compile our MIB and send a sample trap.

Create a sample MIB file with a trap definition:

(agent@myhost)7> snmpc:compile("snmp/agent/mibs/MY-TRAP-MIB", [{il, ["otp_mibs/priv/mibs/"]}]).
{ok, "snmp/agent/mibs/MY-TRAP-MIB.bin"}
(agent@myhost)8> snmp:load_mibs(snmp_master_agent, ["/path/to/.../snmp/agent/mibs/MY-TRAP-MIB"]).
ok
(agent@myhost)9> snmpa:send_notification(snmp_master_agent, testMIBMyFirstCoolTrap, no_receiver, "DrpManager", "", []).
{send_trap,testMIBMyFirstCoolTrap,"DrpManager",[],no_receiver,[]}

The following output appears in the snmptrapd terminal window:

2005-06-10 16:12:27 UCD-snmp version 4.2.4 Started.
16:12 TRAP0.0 from 0.0.0.0
  system.sysUpTime.0 = Timeticks: (92244) 0:15:22.44
  .iso.org.dod.internet.snmpV2.snmpModules.snmpMIB.snmpMIBObjects.snmpTrap.snmpTrapOID.0 =
	      OID: enterprises.ericsson.otp.otpApplications.testMIB.testMIBTraps.testMIBMyFirstCoolTrap
  system.sysLocation.0 = 5th Floor machine room, rack 21A
  system.sysName.0 = SNMP Quick Start HowTo Demo
  system.sysContact.0 = serge@hq.idt.net
3 Likes

Thanks vances for a detailed solution. It worked. I have specified agent info using snmpm:register_agent instead of the config file.