Erlang Central

Difference between revisions of "SNMP Quick Start"

From ErlangCentral Wiki

(Updated to match testing with R12B-4)
m (update snmpwalk)
(21 intermediate revisions by one user not shown)
Line 6: Line 6:
 
In the following examples we will assume we are logged in as the user otpuser and working from a home directory of otpuser. 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.  
 
In the following examples we will assume we are logged in as the user otpuser and working from a home directory of otpuser. 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.  
  
{{CodeSnippet|Code listing 1.1: Create the Agent Configuration and Database Directories|<pre>
+
{{CodeSnippet|Code listing 2.1: Create the Agent Configuration and Database Directories|<pre>
 
$ mkdir -p snmp/agent/conf
 
$ mkdir -p snmp/agent/conf
 
$ mkdir -p snmp/agent/db
 
$ mkdir -p snmp/agent/db
Line 14: Line 14:
 
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.  
 
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.  
  
{{CodeSnippet|Code listing 1.2: Create the Agent Information File|<pre>
+
{{CodeSnippet|Code listing 2.2: Create the Agent Information File|<pre>
 
$ cat &gt; snmp/agent/conf/agent.conf
 
$ cat &gt; snmp/agent/conf/agent.conf
 
{intAgentIpAddress, [127,0,0,1]}.
 
{intAgentIpAddress, [127,0,0,1]}.
Line 27: Line 27:
 
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 [http://www.iana.org/cgi-bin/enterprise.pl apply for a private enterprise number assignment] and create your own sysObjectID for your network element.
 
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 [http://www.iana.org/cgi-bin/enterprise.pl apply for a private enterprise number assignment] and create your own sysObjectID for your network element.
  
{{CodeSnippet|Code listing 1.3: Create the System Information File|<pre>
+
{{CodeSnippet|Code listing 2.3: Create the System Information File|<pre>
 
$ cat &gt; snmp/agent/conf/standard.conf
 
$ cat &gt; snmp/agent/conf/standard.conf
 
{sysName, "SNMP Quick Start HowTo Demo"}.
 
{sysName, "SNMP Quick Start HowTo Demo"}.
Line 43: Line 43:
 
The snmp/agent/conf/community.conf file defines the communities for the system being managed. It is required for SNMPv1 or SNMPv2c.  
 
The snmp/agent/conf/community.conf file defines the communities for the system being managed. It is required for SNMPv1 or SNMPv2c.  
  
{{CodeSnippet|Code listing 1.4: Create the Community File|<pre>
+
{{CodeSnippet|Code listing 2.4: Create the Community File|<pre>
 
$ cat &gt; snmp/agent/conf/community.conf
 
$ cat &gt; snmp/agent/conf/community.conf
 
{"public", "public", "initial", "", ""}.
 
{"public", "public", "initial", "", ""}.
Line 53: Line 53:
 
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.  
 
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.  
  
{{CodeSnippet| Code listing 1.5: Create the VACM File|<pre>
+
{{CodeSnippet| Code listing 2.5: Create the VACM File|<pre>
 
$ cat &gt; snmp/agent/conf/vacm.conf
 
$ cat &gt; snmp/agent/conf/vacm.conf
%% vacmViewTreeFamilyTable in the SNMP-VIEW-BASED-ACM-MIB.
 
%%
 
%% Each entry is one of the terms, one entry corresponds to one row in one of the tables.
 
%%
 
%% {vacmSecurityToGroup, SecModel, SecurityName, GroupName}.
 
%% {vacmAccess, GroupName, Prefix, SecModel, SecLevel, Match, ReadView, WriteView, NotifyView}.
 
%% {vacmViewTreeFamily, ViewIndex, ViewSubtree, ViewStatus, ViewMask}.
 
%%
 
%%    * SecModel is any, v1, v2c, or usm.
 
%%    * SecurityName is a string.
 
%%    * GroupName is a string.
 
%%    * Prefix is a string.
 
%%    * SecLevel is noAuthNoPriv, authNoPriv, or authPriv
 
%%    * Match is prefix or exact.
 
%%    * ReadView is a string.
 
%%    * WriteView is a string.
 
%%    * NotifyView is a string.
 
%%    * ViewIndex is an integer.
 
%%    * ViewSubtree is a list of integer.
 
%%    * ViewStatus is either included or excluded
 
%%    * ViewMask is either null or a list of ones and zeros. Ones nominate that
 
%%      an exact match is used for this sub-identifier. Zeros are wildcards which
 
%%      match any sub-identifier. If the mask is shorter than the subtree, the tail
 
%%      is regarded as all ones. null is shorthand for a mask with all ones.
 
 
 
{vacmSecurityToGroup, v2c, "initial", "initial"}.
 
{vacmSecurityToGroup, v2c, "initial", "initial"}.
 
{vacmSecurityToGroup, usm, "initial", "initial"}.
 
{vacmSecurityToGroup, usm, "initial", "initial"}.
Line 91: Line 66:
 
</pre>}}
 
</pre>}}
  
===Traps and Notifications===
 
This section describes configuration files required for sending traps and notifications. You can skip it if you don't need to support this functionality by your SNMP agent. The snmp/agent/conf/notify.conf file contains information about SNMP trap definitions
 
 
{{CodeSnippet|Code listing 1.6: Create the Notify File|<pre>
 
$ cat &gt; snmp/agent/conf/notify.conf
 
%% Contains information about SNMP Trap Notify Definitions
 
%% {NotifyName, Tag, Type}.
 
%%    * NotifyName is a unique non-empty string.
 
%%    * Tag is a string referenced in TagList of the target_addr.conf file.
 
%%    * Type = trap or inform.
 
 
{"MyFirstCoolTrap", "tag1", trap}.
 
^D
 
$
 
</pre>}}
 
 
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.
 
 
{{CodeSnippet|Code listing 1.7: Create the Target Address File|<pre>
 
$ cat &gt; snmp/agent/conf/target_addr.conf
 
%% Stores the information about Target Address Definitions.
 
%%
 
%% The corresponding tables are snmpTargetAddrTable in the SNMP-TARGET-MIB and
 
%% snmpTargetAddrExtTable in the SNMP-COMMUNITY-MIB.
 
%%
 
%% Each entry is a term of one of the following forms:
 
%%
 
%% {TargetName, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId}.
 
%% {TargetName, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}.
 
%%
 
%%  * TargetName is a unique non-empty string matching the NotifyName entry in the nofity.conf file.
 
%%  * Ip is a list of four integers.
 
%%  * Udp is an integer.
 
%%  * Timeout is an integer.
 
%%  * RetryCount is an integer.
 
%%  * TagList is a string.
 
%%  * ParamsName is a string.
 
%%  * EngineId is a string.
 
%%  * TMask is a string of size 0, or size 6 (default: []).
 
%%  * MaxMessageSize is an integer (default: 2048).
 
 
{"MyFirstCoolTrap", [127,0,0,1], 162, 5000, 3, "tag1", "MyCoolTrapParams", "agent's engine"}.
 
^D
 
$
 
</pre>}}
 
 
The snmp/agent/conf/target_params.conf file contains information about SNMP Target Parameters Definitions.
 
 
{{CodeSnippet|Code listing 1.8: Create the Target Parameters File|<pre>
 
$ cat &gt; snmp/agent/conf/target_params.conf
 
%% The information about Target Parameters Definitions
 
%% The corresponding table is snmpTargetParamsTable in the SNMP-TARGET-MIB.
 
%%
 
%% Each entry is a term:
 
%%
 
%% {ParamsName, MPModel, SecurityModel, SecurityName, SecurityLevel}.
 
%%    * ParamsName is a unique non-empty string.
 
%%    * MPModel is v1, v2c or v3
 
%%    * SecurityModel is v1, v2c, or usm.
 
%%    * SecurityName is a string from the vacmSecurityToGroup table in the VASM file.
 
%%    * SecurityLevel is noAuthNoPriv, authNoPriv or authPriv
 
 
{"MyCoolTrapParams", v2c, v2c, "initial", noAuthNoPriv}.
 
^D
 
$
 
</pre>}}
 
  
 
===Application Environment===
 
===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 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.  
  
{{CodeSnippet|Code listing 1.9: Create the Agent OTP System Configuration File|<pre>
+
{{CodeSnippet|Code listing 2.6: Create the Agent OTP System Configuration File|<pre>
 
$ cat &gt; snmp/agent.config
 
$ cat &gt; snmp/agent.config
 
[{snmp,
 
[{snmp,
Line 170: Line 79:
 
$
 
$
 
</pre>}}
 
</pre>}}
 +
  
 
==Running the Agent==
 
==Running the Agent==
 
The configuration in snmp/agent.config will be used when we start the emulator with the -config snmp/agent commandline option.
 
The configuration in snmp/agent.config will be used when we start the emulator with the -config snmp/agent commandline option.
  
{{CodeSnippet|Code listing 2.1: Starting the Agent for the First Time|<pre>
+
{{CodeSnippet|Code listing 3.1: Starting the Agent for the First Time|<pre>
 
$ erl -sname agent -config snmp/agent
 
$ erl -sname agent -config snmp/agent
Erlang (BEAM) emulator version 5.6.4 [source] [smp:2] [async-threads:0]
 
  
Eshell V5.6.4 (abort with ^G)
+
Eshell V5.9 (abort with ^G)
 
(agent@myhost)1&gt; application:start(snmp).
 
(agent@myhost)1&gt; application:start(snmp).
  
=ERROR REPORT==== 8-Sep-2008::16:08:04 ===
+
=ERROR REPORT==== 10-Feb-2012::15:15:31 ===
 
** Configuration error: [FRAMEWORK-MIB]: missing context.conf file => generating a default file
 
** Configuration error: [FRAMEWORK-MIB]: missing context.conf file => generating a default file
  
=INFO REPORT==== 8-Sep-2008::16:08:05 ===
+
=INFO REPORT==== 10-Feb-2012::15:15:31 ===
[ snmp : agent : snmp_user_based_sm_mib : <0.44.0> ]  
+
[ snmp : agent : snmp_user_based_sm_mib : <0.45.0> ]  
 
USM: Incomplete configuration. Generating empty usm.conf.
 
USM: Incomplete configuration. Generating empty usm.conf.
 
ok
 
ok
Line 191: Line 100:
 
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>The system will create some missing files for us.</p></td></tr></table>
 
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>The system will create some missing files for us.</p></td></tr></table>
  
The agent is now running using SNMPv1, SNMPv2 and SNMPv3.
+
The agent is now running using SNMPv1, SNMPv2c and SNMPv3.
  
 
===Verifying Configuration===
 
===Verifying Configuration===
{{CodeSnippet|Code listing 2.2: Get the System Name|<pre>
+
{{CodeSnippet|Code listing 3.2: Get the System Name|<pre>
(agent@myhost)2&gt; snmpa:name_to_oid(sysName).
+
(agent@myhost)2&gt; {value, OID} = snmpa:name_to_oid(sysName).
 
{value,[1,3,6,1,2,1,1,5]}
 
{value,[1,3,6,1,2,1,1,5]}
We need to add a '0' to the OID to access the value
+
(agent@myhost)2&gt; % We need to add a '0' to the OID to access the value
(agent@myhost)3&gt; snmpa:get(snmp_master_agent, [[1,3,6,1,2,1,1,5,0]]).
+
(agent@myhost)3&gt; snmpa:get(snmp_master_agent, [OID ++ [0]]).
 
["SNMP Quick Start HowTo Demo"]
 
["SNMP Quick Start HowTo Demo"]
 
</pre>}}
 
</pre>}}
 +
  
 
==Manager Configuration==
 
==Manager Configuration==
Line 206: Line 116:
 
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 a subdirectory to contain the configuration files of the manager named snmp/manager/conf and another for the working files named snmp/manager/db.  
  
{{CodeSnippet|Code listing 3.1: Create the Manager Configuration and Database Directories|<pre>
+
{{CodeSnippet|Code listing 4.1: Create the Manager Configuration and Database Directories|<pre>
 
$ mkdir -p snmp/manager/conf
 
$ mkdir -p snmp/manager/conf
 
$ mkdir -p snmp/manager/db
 
$ mkdir -p snmp/manager/db
Line 214: Line 124:
 
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.  
 
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.  
  
{{CodeSnippet|Code listing 3.2: Create the Manager Information File|<pre>
+
{{CodeSnippet|Code listing 4.2: Create the Manager Information File|<pre>
 
$ cat &gt; snmp/manager/conf/manager.conf
 
$ cat &gt; snmp/manager/conf/manager.conf
 
{port, 5000}.
 
{port, 5000}.
Line 227: Line 137:
 
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.  
 
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.  
  
{{CodeSnippet|Code listing 3.3: Create the Users File|<pre>
+
{{CodeSnippet|Code listing 4.3: Create the Users File|<pre>
 
$ cat &gt; snmp/manager/conf/users.conf
 
$ cat &gt; snmp/manager/conf/users.conf
 
{"simple_user", snmpm_user_default, undefined}.
 
{"simple_user", snmpm_user_default, undefined}.
Line 235: Line 145:
  
 
===Agents===
 
===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 SNMPv2.  
+
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.  
  
{{CodeSnippet|Code listing 3.4: Create the Agents File|<pre>
+
{{CodeSnippet|Code listing 4.4: Create the Agents File|<pre>
 
$ cat &gt; snmp/manager/conf/agents.conf
 
$ cat &gt; snmp/manager/conf/agents.conf
 
{"simple_user", "otp agent", "public", [127,0,0,1], 4000, "agent's engine",
 
{"simple_user", "otp agent", "public", [127,0,0,1], 4000, "agent's engine",
Line 248: Line 158:
 
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 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.  
  
{{CodeSnippet|Code listing 3.5: Create the Manager OTP System Configuration File|<pre>
+
{{CodeSnippet|Code listing 4.5: Create the Manager OTP System Configuration File|<pre>
 
$ cat &gt; snmp/manager.config
 
$ cat &gt; snmp/manager.config
 
[{snmp,
 
[{snmp,
Line 257: Line 167:
 
$
 
$
 
</pre>}}
 
</pre>}}
 +
  
 
==Running the Manager==
 
==Running the Manager==
Line 262: Line 173:
 
The configuration in snmp/manager.config will be used when we start the emulator with the -config snmp/manager commandline option.  
 
The configuration in snmp/manager.config will be used when we start the emulator with the -config snmp/manager commandline option.  
  
{{CodeSnippet|Code listing 4.1: Starting the Manager for the First Time|<pre>
+
{{CodeSnippet|Code listing 5.1: Starting the Manager for the First Time|<pre>
 
$ erl -sname manager -config snmp/manager
 
$ erl -sname manager -config snmp/manager
Erlang (BEAM) emulator version 5.6.4 [source] [smp:2] [async-threads:0]
 
  
Eshell V5.6.4 (abort with ^G)
+
Eshell V5.9 (abort with ^G)
 
(manager@myhost)1&gt; application:start(snmp).
 
(manager@myhost)1&gt; application:start(snmp).
 
ok
 
ok
Line 272: Line 182:
  
 
===Verifying Configuration===
 
===Verifying Configuration===
{{CodeSnippet|Code listing 4.2: List Users|<pre>
+
{{CodeSnippet|Code listing 5.2: List Users|<pre>
 
(manager@myhost)2&gt; snmpm:which_users().
 
(manager@myhost)2&gt; snmpm:which_users().
 
["simple_user"]
 
["simple_user"]
 
</pre>}}
 
</pre>}}
  
{{CodeSnippet|Code listing 4.3: List Agents|<pre>
+
{{CodeSnippet|Code listing 5.3: List Agents|<pre>
 
(manager@myhost)3&gt; snmpm:which_agents().
 
(manager@myhost)3&gt; snmpm:which_agents().
[{{127,0,0,1},4000}]
+
["otp agent"]
 
</pre>}}
 
</pre>}}
  
{{CodeSnippet|Code listing 4.4: Verify Agent Configuration|<pre>
+
{{CodeSnippet|Code listing 5.4: Verify Agent Configuration|<pre>
(manager@myhost)5&gt; snmpm:agent_info({127,0,0,1}, 4000, target_name).
+
(manager@myhost)5&gt; snmpm:agent_info("otp agent", community).
{ok,"otp agent"}
+
(manager@myhost)6&gt; snmpm:agent_info({127,0,0,1}, 4000, community).
+
 
{ok,"public"}
 
{ok,"public"}
(manager@myhost)7&gt; snmpm:agent_info({127,0,0,1}, 4000, engine_id).
+
(manager@myhost)6&gt; snmpm:agent_info("otp agent", engine_id).
 
{ok,"agent's engine"}
 
{ok,"agent's engine"}
 
</pre>}}
 
</pre>}}
Line 294: Line 202:
 
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.  
 
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.  
  
{{CodeSnippet|Code listing 4.5: Get System Name from Agent|<pre>
+
{{CodeSnippet|Code listing 5.5: Get System Name from Agent|<pre>
(manager@myhost)8&gt; snmpm:g("simple_user", {127,0,0,1}, 4000, [[1,3,6,1,2,1,1,5,0]]).
+
(manager@myhost)7&gt; snmpm:sync_get("simple_user", "otp agent", [[1,3,6,1,2,1,1,5,0]]).
 
{ok,{noError,0,
 
{ok,{noError,0,
 
             [#varbind{oid = [1,3,6,1,2,1,1,5,0],
 
             [#varbind{oid = [1,3,6,1,2,1,1,5,0],
 
                       variabletype = 'OCTET STRING',
 
                       variabletype = 'OCTET STRING',
                       value = "SNMP Quick Start HowTo Demo",
+
                       value = "SNMP Quick Start HowTo Demo",org_index = 1}]},
                      org_index = 1}]},
+
     4992}
     4977}
+
 
</pre>}}
 
</pre>}}
  
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>
+
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>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.  E.g. rr("lib/erlang/lib/snmp-*/include/*").</p></td></tr></table>
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.  E.g. rr("lib/erlang/lib/snmp-*/include/*").
+
</p></td></tr></table>
+
  
 
==Adding Authentication and Privacy==
 
==Adding Authentication and Privacy==
 
===User Based Security Model (USM)===
 
===User Based Security Model (USM)===
With SNMPv3 the agent and manager may share a secret for authentication of each user using either MD5 or SHA. [http://www.ietf.org/rfc/rfc2274.txt RFC 2274] specifies an algorithm to generate a localized key using a passphrase and the local engineID.  This localized authentication key is defined in the agent's or manager's usm.conf file.
+
With SNMPv3 the agent and manager may share a secret for authentication using either MD5 or SHA. [http://www.ietf.org/rfc/rfc2274.txt RFC 2274] 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===
 
===Generating Localized Keys===
 
The snmp application can be used to generate a localized key.  
 
The snmp application can be used to generate a localized key.  
  
{{CodeSnippet|Code listing 5.1: Generating the Localized Authentication Key for the Agent|<pre>
+
{{CodeSnippet|Code listing 6.1: Generating a Localized Authentication Key for the Agent|<pre>
 
$ erl
 
$ erl
Erlang (BEAM) emulator version 5.6.4 [source] [smp:2] [async-threads:0]
 
  
Eshell V5.6.4 (abort with ^G)
+
Eshell V5.9 (abort with ^G)
 
1&gt; application:start(crypto).
 
1&gt; application:start(crypto).
 
ok
 
ok
 
2&gt; snmp:passwd2localized_key(md5, "The quick brown fox jumps over the lazy dog.", "agent's engine").
 
2&gt; 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]
 
[40,165,209,16,245,231,199,157,53,56,248,82,228,181,160,143]
</pre>}}
 
 
{{CodeSnippet|Code listing 5.2: Generating the Localized Authentication Key for the Manager|<pre>
 
3&gt; snmp:passwd2localized_key(md5, "The quick brown fox jumps over the lazy dog.", "manager's engine").
 
[86,237,217,213,151,156,198,231,97,197,88,114,136,195,213,176]
 
 
 
</pre>}}
 
</pre>}}
  
 
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.  
 
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.  
  
{{CodeSnippet|Code listing 5.3: Generating the Localized Privacy Key for the Agent|<pre>
+
{{CodeSnippet|Code listing 6.2: Generating a Localized Privacy Key for the Agent|<pre>
 
4&gt; snmp:passwd2localized_key(md5, "Pack my box with five dozen liquor jugs.", "agent's engine").
 
4&gt; 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]
 
[4,11,162,206,20,118,62,83,28,129,124,10,66,5,100,136]
</pre>}}
 
 
{{CodeSnippet|Code listing 5.4: Generating the Localized Privacy Key for the Manager|<pre>
 
5&gt; snmp:passwd2localized_key(md5, "Pack my box with five dozen liquor jugs.", "manager's engine").
 
"\270\304:e\326\372\277\323'jAfF\373\251D"
 
 
</pre>}}
 
</pre>}}
  
Line 349: Line 241:
 
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.  
 
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.  
  
{{CodeSnippet|Code listing 5.5: Create the USM Configuration File for the Agent|<pre>
+
{{CodeSnippet|Code listing 6.3: Create the USM Configuration File for the Agent|<pre>
 
$ cat &gt; snmp/agent/conf/usm.conf
 
$ cat &gt; snmp/agent/conf/usm.conf
 
{"agent's engine", "simple_user", "initial", zeroDotZero,
 
{"agent's engine", "simple_user", "initial", zeroDotZero,
 
     usmHMACMD5AuthProtocol, "", "",
 
     usmHMACMD5AuthProtocol, "", "",
 
     usmDESPrivProtocol, "", "", "",
 
     usmDESPrivProtocol, "", "", "",
     [40,165,209,16,245,231,199,157,53,56,248,82,228,181,160,143]
+
     [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]}.
 
     [4,11,162,206,20,118,62,83,28,129,124,10,66,5,100,136]}.
 
^D
 
^D
Line 360: Line 252:
 
</pre>}}
 
</pre>}}
  
The snmp/manager/conf/usm.conf file defines the security data for each manager user.  
+
The snmp/manager/conf/usm.conf file defines the security data for each manager user on each agent.  
  
{{CodeSnippet|Code listing 5.6: Create the USM Configuration File for the Manager|<pre>
+
{{CodeSnippet|Code listing 6.4: Create the USM Configuration File for the Manager|<pre>
 
$ cat &gt; snmp/manager/conf/usm.conf
 
$ cat &gt; snmp/manager/conf/usm.conf
 
{"agent's engine", "simple_user", "initial",
 
{"agent's engine", "simple_user", "initial",
     usmHMACMD5AuthProtocol, [86,237,217,213,151,156,198,231,97,197,88,114,136,195,213, 176],
+
     usmHMACMD5AuthProtocol, [40,165,209,16,245,231,199,157,53,56,248,82,228,181,160,143],
     usmDESPrivProtocol, "\270\304:e\326\372\277\323'jAfF\373\251D"}.
+
     usmDESPrivProtocol, [4,11,162,206,20,118,62,83,28,129,124,10,66,5,100,136]}.
 
^D
 
^D
 
$
 
$
Line 372: Line 264:
  
 
===Agent Configuration===
 
===Agent Configuration===
Earlier we configured the manager to use SNMPv2 to contact the agent. Here we'll replace that with an SNMPv3 USM configuration using MD5 authentication and DES privacy.  
+
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.  
  
{{CodeSnippet|Code listing 5.7: Create the Agents Configuration File for the Manager|<pre>
+
{{CodeSnippet|Code listing 6.5: Create the Agents Configuration File for the Manager|<pre>
 
$ cat &gt; snmp/manager/conf/agents.conf
 
$ cat &gt; snmp/manager/conf/agents.conf
 
{"simple_user", "otp agent", "public", [127,0,0,1], 4000, "agent's engine",
 
{"simple_user", "otp agent", "public", [127,0,0,1], 4000, "agent's engine",
Line 381: Line 273:
 
$
 
$
 
</pre>}}
 
</pre>}}
 
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#ffbbbb"><p class="note"><b>Warning: </b>Currently (R10B-4) the manager's handling of USM is broken and
 
unusable.  You may still use USM for the agent if you are monitoring with
 
another manager application.</p></td></tr></table>
 
  
 
===Start the Application===
 
===Start the Application===
 
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>The crypto application is required for authentication/privacy.</p></td></tr></table>
 
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>The crypto application is required for authentication/privacy.</p></td></tr></table>
  
{{CodeSnippet|Code listing 5.8: Start the Agent|<pre>
+
{{CodeSnippet|Code listing 6.6: Start the Agent|<pre>
 
$ erl -sname agent -config snmp/agent
 
$ erl -sname agent -config snmp/agent
Erlang (BEAM) emulator version 5.6.4 [source] [smp:2] [async-threads:0]
 
  
Eshell V5.6.4 (abort with ^G)
+
Eshell V5.9 (abort with ^G)
 
(agent@myhost)1&gt; application:start(crypto).
 
(agent@myhost)1&gt; application:start(crypto).
 
ok
 
ok
Line 400: Line 287:
 
</pre>}}
 
</pre>}}
  
{{CodeSnippet|Code listing 5.9: Start the Manager|<pre>
+
{{CodeSnippet|Code listing 6.7: Load the User Table|<pre>
erl -sname manager -config snmp/manager
+
(agent@myhost)3&gt;  Dir = code:priv_dir(snmp) ++ "/mibs/",
Erlang (BEAM) emulator version 5.6.4 [source] [smp:2] [async-threads:0]
+
(agent@myhost)3&gt;  snmpa:load_mibs([Dir ++ "SNMP-USER-BASED-SM-MIB"]).
 +
ok
 +
(agent@myhost)4&gt;  snmp_user_based_sm_mib:configure("snmp/agent/conf").
 +
</pre>}}
 +
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>You may add the snmp application environment variable {mibs, ["<path-to-snmp>/priv/mibs/SNMP-USER-BASED-SM-MIB"]} to the agent.config file to automatically load on start.</p></td></tr></table>
  
  
 +
{{CodeSnippet|Code listing 6.8: Start the Manager|<pre>
 +
$ erl -sname manager -config snmp/manager
 +
 +
Eshell V5.9  (abort with ^G)
 
(manager@myhost)1&gt; application:start(crypto).
 
(manager@myhost)1&gt; application:start(crypto).
 
ok
 
ok
Line 410: Line 305:
 
ok
 
ok
 
</pre>}}
 
</pre>}}
 +
 +
{{CodeSnippet|Code listing 6.9: Querying the Agent|<pre>
 +
(manager@myhost)3&gt; snmpm:load_mib(code:priv_dir(snmp) ++ "/mibs/SNMPv2-MIB").
 +
ok
 +
(manager@myhost)4&gt; snmpm:sync_get("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&gt; snmpm:sync_get("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}
 +
</pre>}}
 +
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>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.</p></td></tr></table>
 +
  
 
==Using the OTP MIBs==
 
==Using the OTP MIBs==
Line 415: Line 332:
 
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>The otp_mib instrumentation uses mnesia.</p></td></tr></table>
 
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>The otp_mib instrumentation uses mnesia.</p></td></tr></table>
  
{{CodeSnippet|Code listing 6.1: Starting the Agent|<pre>
+
{{CodeSnippet|Code listing 7.1: Starting the Agent|<pre>
 
(agent@myhost)1&gt; application:start(mnesia).
 
(agent@myhost)1&gt; application:start(mnesia).
 
ok
 
ok
Line 422: Line 339:
 
</pre>}}
 
</pre>}}
  
{{CodeSnippet|Code listing 6.2: Loading the OTP MIB|<pre>
+
{{CodeSnippet|Code listing 7.2: Loading the OTP MIB|<pre>
 
(agent@myhost)3&gt; otp_mib:load(snmp_master_agent).
 
(agent@myhost)3&gt; otp_mib:load(snmp_master_agent).
 
ok
 
ok
Line 428: Line 345:
  
 
===Manager===
 
===Manager===
{{CodeSnippet|Code listing 6.3: Starting the Manager|<pre>
+
{{CodeSnippet|Code listing 7.3: Starting the Manager|<pre>
 
(manager@myhost)1&gt; application:start(snmp).
 
(manager@myhost)1&gt; application:start(snmp).
 
ok
 
ok
Line 435: Line 352:
 
Here we use the OID for otp.erlNodeName.1 to query the nodename of the agent's Erlang/OTP node.  
 
Here we use the OID for otp.erlNodeName.1 to query the nodename of the agent's Erlang/OTP node.  
  
{{CodeSnippet|Code listing 6.4: Querying the Agent|<pre>
+
{{CodeSnippet|Code listing 7.4: Querying the Agent|<pre>
(manager@myhost)2&gt; snmpm:g("simple_user", {127,0,0,1}, 4000, [[1,3,6,1,4,1,193,19,3,1,2,1,1,1,2,1]]).
+
(manager@myhost)2&gt; snmpm:load_mib(code:priv_dir(otp_mibs) ++ "/mibs/OTP-MIB").
 +
ok
 +
(manager@myhost)3&gt; snmpm:sync_get("simple_user", "agent's engine", [[erlNodeName,1]]).                                        
 
{ok,{noError,0,
 
{ok,{noError,0,
 
             [#varbind{oid = [1,3,6,1,4,1,193,19,3,1,2,1,1,1,2,1],
 
             [#varbind{oid = [1,3,6,1,4,1,193,19,3,1,2,1,1,1,2,1],
                       variabletype = 'OCTET STRING',
+
                       variabletype = 'OCTET STRING',value = "agent@myhost",
                      value = "agent@blank",
+
 
                       org_index = 1}]},
 
                       org_index = 1}]},
     4754}
+
     4926}
ok
+
 
</pre>}}
 
</pre>}}
  
Line 449: Line 366:
 
If we run the os_mon application more info is available.  
 
If we run the os_mon application more info is available.  
  
{{CodeSnippet|Code listing 6.5: Starting os_mon|<pre>
+
{{CodeSnippet|Code listing 7.5: Starting os_mon|<pre>
 
(agent@myhost)4&gt; application:start(sasl).
 
(agent@myhost)4&gt; application:start(sasl).
 
ok
 
ok
Line 463: Line 380:
 
To demonstrate the information managed with the OTP-MIB I've used the net-snmp application from a Unix shell prompt to walk the OTP MIB.
 
To demonstrate the information managed with the OTP-MIB I've used the net-snmp application from a Unix shell prompt to walk the OTP MIB.
  
{{CodeSnippet|Code listing 6.6: Using net-snmp to walk the agent's OTP MIB|<pre>
+
{{CodeSnippet|Code listing 7.6: Using net-snmp to walk the agent's OTP MIB|<pre>
 
$ snmpwalk -c public -v2c 127.0.0.1:4000 otp
 
$ snmpwalk -c public -v2c 127.0.0.1:4000 otp
 
OTP-MIB::erlNodeName.1 = STRING: agent@myhost
 
OTP-MIB::erlNodeName.1 = STRING: agent@myhost
 
OTP-MIB::erlNodeMachine.1 = STRING: BEAM
 
OTP-MIB::erlNodeMachine.1 = STRING: BEAM
OTP-MIB::erlNodeVersion.1 = STRING: 5.4.5
+
OTP-MIB::erlNodeVersion.1 = STRING: 5.9
OTP-MIB::erlNodeRunQueue.1 = Gauge32: 1
+
OTP-MIB::erlNodeRunQueue.1 = Gauge32: 0
OTP-MIB::erlNodeRunTime.1 = Counter32: 4343
+
OTP-MIB::erlNodeRunTime.1 = Counter32: 430
OTP-MIB::erlNodeWallClock.1 = Counter32: 5366488
+
OTP-MIB::erlNodeWallClock.1 = Counter32: 112176
OTP-MIB::erlNodeReductions.1 = Counter32: 1447166
+
OTP-MIB::erlNodeReductions.1 = Counter32: 1329646
 
OTP-MIB::erlNodeProcesses.1 = Gauge32: 84
 
OTP-MIB::erlNodeProcesses.1 = Gauge32: 84
OTP-MIB::erlNodeInBytes.1 = Counter32: 3990886
+
OTP-MIB::erlNodeInBytes.1 = Counter32: 7958884
OTP-MIB::erlNodeOutBytes.1 = Counter32: 142649
+
OTP-MIB::erlNodeOutBytes.1 = Counter32: 1684165
OTP-MIB::applName.1.1 = STRING: os_mon
+
OTP-MIB::applName.1.1 = STRING: otp_mibs
OTP-MIB::applName.1.2 = STRING: sasl
+
OTP-MIB::applName.1.2 = STRING: os_mon
 
OTP-MIB::applName.1.3 = STRING: snmp
 
OTP-MIB::applName.1.3 = STRING: snmp
 
OTP-MIB::applName.1.4 = STRING: mnesia
 
OTP-MIB::applName.1.4 = STRING: mnesia
OTP-MIB::applName.1.5 = STRING: stdlib
+
OTP-MIB::applName.1.5 = STRING: sasl
OTP-MIB::applName.1.6 = STRING: kernel
+
OTP-MIB::applName.1.6 = STRING: stdlib
OTP-MIB::applDescr.1.1 = STRING: CPO  CXC 138 46
+
OTP-MIB::applName.1.7 = STRING: kernel
OTP-MIB::applDescr.1.2 = STRING: SASL CXC 138 11
+
OTP-MIB::applDescr.1.1 = STRING: SNMP managment information base for Erlang/OTP nodes.
 +
OTP-MIB::applDescr.1.2 = STRING: CPO CXC 138 46
 
OTP-MIB::applDescr.1.3 = STRING: SNMP  CXC 138 13
 
OTP-MIB::applDescr.1.3 = STRING: SNMP  CXC 138 13
 
OTP-MIB::applDescr.1.4 = STRING: MNESIA  CXC 138 12
 
OTP-MIB::applDescr.1.4 = STRING: MNESIA  CXC 138 12
OTP-MIB::applDescr.1.5 = STRING: ERTS CXC 138 10
+
OTP-MIB::applDescr.1.5 = STRING: SASL CXC 138 11
 
OTP-MIB::applDescr.1.6 = STRING: ERTS  CXC 138 10
 
OTP-MIB::applDescr.1.6 = STRING: ERTS  CXC 138 10
OTP-MIB::applVsn.1.1 = STRING: 1.7.3
+
OTP-MIB::applDescr.1.7 = STRING: ERTS  CXC 138 10
OTP-MIB::applVsn.1.2 = STRING: 2.0.1
+
OTP-MIB::applVsn.1.1 = STRING: 1.0.7
OTP-MIB::applVsn.1.3 = STRING: 4.1.2
+
OTP-MIB::applVsn.1.2 = STRING: 2.2.8
OTP-MIB::applVsn.1.4 = STRING: 4.2.1
+
OTP-MIB::applVsn.1.3 = STRING: 4.21.4
OTP-MIB::applVsn.1.5 = STRING: 1.13.5
+
OTP-MIB::applVsn.1.4 = STRING: 4.6
OTP-MIB::applVsn.1.6 = STRING: 2.10.6
+
OTP-MIB::applVsn.1.5 = STRING: 2.2
 +
OTP-MIB::applVsn.1.6 = STRING: 1.18
 +
OTP-MIB::applVsn.1.7 = STRING: 2.15
 
OTP-OS-MON-MIB::loadMemorySystemWatermark.0 = INTEGER: 80
 
OTP-OS-MON-MIB::loadMemorySystemWatermark.0 = INTEGER: 80
 
OTP-OS-MON-MIB::loadMemoryErlProcWatermark.0 = INTEGER: 5
 
OTP-OS-MON-MIB::loadMemoryErlProcWatermark.0 = INTEGER: 5
OTP-OS-MON-MIB::loadSystemTotalMemory."agent@myhost" = Gauge32: 60985344 bytes
+
OTP-OS-MON-MIB::loadSystemTotalMemory."agent@myhost" = Gauge32: 3045288000 bytes
OTP-OS-MON-MIB::loadSystemUsedMemory."agent@myhost" = Gauge32: 60559360 bytes
+
OTP-OS-MON-MIB::loadSystemUsedMemory."agent@myhost" = Gauge32: 2129992000 bytes
OTP-OS-MON-MIB::loadLargestErlProcess."agent@myhost" = STRING: &lt;0.6.&gt;0
+
OTP-OS-MON-MIB::loadLargestErlProcess."agent@myhost" = STRING: <0.6.0>
OTP-OS-MON-MIB::loadLargestErlProcessUsedMemory."agent@myhost" = Gauge32: 71320 bytes
+
OTP-OS-MON-MIB::loadLargestErlProcessUsedMemory."agent@myhost" = Gauge32: 142328 bytes
OTP-OS-MON-MIB::loadCpuLoad."agent@myhost" = INTEGER: 13
+
OTP-OS-MON-MIB::loadCpuLoad."agent@myhost" = INTEGER: 19
OTP-OS-MON-MIB::loadCpuLoad5."agent@myhost" = INTEGER: 6
+
OTP-OS-MON-MIB::loadCpuLoad5."agent@myhost" = INTEGER: 22
OTP-OS-MON-MIB::loadCpuLoad15."agent@myhost" = INTEGER: 1
+
OTP-OS-MON-MIB::loadCpuLoad15."agent@myhost" = INTEGER: 23
 +
OTP-OS-MON-MIB::loadOsWordsize."agent@myhost" = Gauge32: 32
 +
OTP-OS-MON-MIB::loadSystemTotalMemory64."agent@myhost" = Counter64: 3045288000 bytes
 +
OTP-OS-MON-MIB::loadSystemUsedMemory64."agent@myhost" = Counter64: 2129992000 bytes
 +
OTP-OS-MON-MIB::loadLargestErlProcessUsedMemory64."agent@myhost" = Counter64: 142328 bytes
 
OTP-OS-MON-MIB::diskAlmostFullThreshold.0 = INTEGER: 80
 
OTP-OS-MON-MIB::diskAlmostFullThreshold.0 = INTEGER: 80
 
OTP-OS-MON-MIB::diskDescr.1.1 = STRING: /
 
OTP-OS-MON-MIB::diskDescr.1.1 = STRING: /
OTP-OS-MON-MIB::diskDescr.1.2 = STRING: /tmp
+
OTP-OS-MON-MIB::diskKBytes.1.1 = Gauge32: 243862672 kbytes
OTP-OS-MON-MIB::diskDescr.1.3 = STRING: /usr
+
OTP-OS-MON-MIB::diskCapacity.1.1 = INTEGER: 79
OTP-OS-MON-MIB::diskDescr.1.4 = STRING: /usr/local
+
OTP-OS-MON-MIB::diskKBytes.1.1 = Gauge32: 253678 kbytes
+
OTP-OS-MON-MIB::diskKBytes.1.2 = Gauge32: 253678 kbytes
+
OTP-OS-MON-MIB::diskKBytes.1.3 = Gauge32: 8122126 kbytes
+
OTP-OS-MON-MIB::diskKBytes.1.4 = Gauge32: 20091646 kbytes
+
OTP-OS-MON-MIB::diskCapacity.1.1 = INTEGER: 41
+
OTP-OS-MON-MIB::diskCapacity.1.2 = INTEGER: 1
+
OTP-OS-MON-MIB::diskCapacity.1.3 = INTEGER: 48
+
OTP-OS-MON-MIB::diskCapacity.1.4 = INTEGER: 4
+
 
</pre>}}
 
</pre>}}
 +
  
 
==Sending SNMP traps==
 
==Sending SNMP traps==
 +
 +
===Traps and Notifications===
 +
The snmp/agent/conf/notify.conf file contains information about SNMP trap definitions.
 +
 +
{{CodeSnippet|Code listing 8.1: Create the Notify File|<pre>
 +
$ cat &gt; snmp/agent/conf/notify.conf
 +
{"MyFirstCoolTrap", "tag1", trap}.
 +
^D
 +
$
 +
</pre>}}
 +
 +
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.
 +
 +
{{CodeSnippet|Code listing 8.2: Create the Target Address File|<pre>
 +
$ cat &gt; snmp/agent/conf/target_addr.conf
 +
{"MyFirstCoolTrap", [127,0,0,1], 162, 5000, 3, "tag1", "MyCoolTrapParams", "agent's engine"}.
 +
^D
 +
$
 +
</pre>}}
 +
 +
The snmp/agent/conf/target_params.conf file contains information about SNMP Target Parameters Definitions.
 +
 +
{{CodeSnippet|Code listing 8.3: Create the Target Parameters File|<pre>
 +
$ cat &gt; snmp/agent/conf/target_params.conf
 +
{"MyCoolTrapParams", v2c, v2c, "initial", noAuthNoPriv}.
 +
^D
 +
$
 +
</pre>}}
 +
 
===Creating a MIB file containing a trap definition===
 
===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.
 
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.
  
{{CodeSnippet|Code listing 7.1: Create a sample MIB file with a trap definition|<pre>
+
{{CodeSnippet|Code listing 8.4: Create a sample MIB file with a trap definition|<pre>
 
$ mkdir -p snmp/agent/mibs
 
$ mkdir -p snmp/agent/mibs
 
$ cat &gt; snmp/agent/mibs/MY-TRAP-MIB.mib
 
$ cat &gt; snmp/agent/mibs/MY-TRAP-MIB.mib
Line 578: Line 523:
 
Let's start a trap daemon so that we can verify that traps are getting sent
 
Let's start a trap daemon so that we can verify that traps are getting sent
  
{{CodeSnippet|Code listing 7.2: Start a snmptrapd daemon|<pre>
+
{{CodeSnippet|Code listing 8.5: Start a snmptrapd daemon|<pre>
 
$ sudo snmptrapd -P -F "%02.2h:%02.2j TRAP%w.%q from %A\n  %v\n%" -m "snmp/agent/mibs/MY-TRAP-MIB.mib"
 
$ sudo snmptrapd -P -F "%02.2h:%02.2j TRAP%w.%q from %A\n  %v\n%" -m "snmp/agent/mibs/MY-TRAP-MIB.mib"
 
</pre>}}
 
</pre>}}
Line 584: Line 529:
 
Once this is done, we are ready to compile our MIB and send a sample trap
 
Once this is done, we are ready to compile our MIB and send a sample trap
  
{{CodeSnippet|Code listing 7.3: Create a sample MIB file with a trap definition|<pre>
+
{{CodeSnippet|Code listing 8.6: Create a sample MIB file with a trap definition|<pre>
 
(agent@myhost)7&gt; snmpc:compile("snmp/agent/mibs/MY-TRAP-MIB", [{il, ["otp_mibs/priv/mibs/"]}]).
 
(agent@myhost)7&gt; snmpc:compile("snmp/agent/mibs/MY-TRAP-MIB", [{il, ["otp_mibs/priv/mibs/"]}]).
 
{ok, "snmp/agent/mibs/MY-TRAP-MIB.bin"}
 
{ok, "snmp/agent/mibs/MY-TRAP-MIB.bin"}
Line 595: Line 540:
 
The following output appears in the snmptrapd terminal window
 
The following output appears in the snmptrapd terminal window
  
{{CodeSnippet|Code listing 7.4: SNMP trap received|<pre>
+
{{CodeSnippet|Code listing 8.7: SNMP trap received|<pre>
 
2005-06-10 16:12:27 UCD-snmp version 4.2.4 Started.
 
2005-06-10 16:12:27 UCD-snmp version 4.2.4 Started.
 
16:12 TRAP0.0 from 0.0.0.0
 
16:12 TRAP0.0 from 0.0.0.0
Line 606: Line 551:
 
</pre>}}
 
</pre>}}
  
==Download xml==
 
[http://wiki.trapexit.erlang-consulting.com/upload/howto/snmp_howto.xml snmp_howto.xml]
 
  
 
[[Category:HowTo]]
 
[[Category:HowTo]]
 
[[Category:Interfacing Erlang|SNMP]]
 
[[Category:Interfacing Erlang|SNMP]]

Revision as of 15:08, 26 March 2012

Contents

Author

Vance Shipley and Serge Aleynikov

Agent Configuration

Directories

In the following examples we will assume we are logged in as the user otpuser and working from a home directory of otpuser. 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.

Code listing 2.1: 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.

Code listing 2.2: 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.

Code listing 2.3: 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.

Code listing 2.4: 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.

Code listing 2.5: 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
$


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.

Code listing 2.6: 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 commandline option.

Code listing 3.1: 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).

=ERROR REPORT==== 10-Feb-2012::15:15:31 ===
** Configuration error: [FRAMEWORK-MIB]: missing context.conf file => generating a default file

=INFO REPORT==== 10-Feb-2012::15:15:31 ===
[ snmp : agent : snmp_user_based_sm_mib : <0.45.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

Code listing 3.2: 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)2> % We need to add a '0' to the OID to access the value
(agent@myhost)3> snmpa:get(snmp_master_agent, [OID ++ [0]]).
["SNMP Quick Start HowTo Demo"]


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.

Code listing 4.1: 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.

Code listing 4.2: 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.

Code listing 4.3: 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.

Code listing 4.4: 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.

Code listing 4.5: 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.

Code listing 5.1: 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

Code listing 5.2: List Users

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

Code listing 5.3: List Agents

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

Code listing 5.4: Verify Agent Configuration

(manager@myhost)5> snmpm:agent_info("otp agent", community).
{ok,"public"}
(manager@myhost)6> 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.

Code listing 5.5: Get System Name from Agent

(manager@myhost)7> snmpm:sync_get("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}]},
    4992}

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. E.g. rr("lib/erlang/lib/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. RFC 2274 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.

Code listing 6.1: 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.

Code listing 6.2: 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.

Code listing 6.3: 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.

Code listing 6.4: 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.

Code listing 6.5: 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

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

Code listing 6.6: 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

Code listing 6.7: 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").

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


Code listing 6.8: 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

Code listing 6.9: Querying the Agent

(manager@myhost)3> snmpm:load_mib(code:priv_dir(snmp) ++ "/mibs/SNMPv2-MIB").
ok
(manager@myhost)4> snmpm:sync_get("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_get("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.


Using the OTP MIBs

Agent

Note: The otp_mib instrumentation uses mnesia.

Code listing 7.1: Starting the Agent

(agent@myhost)1> application:start(mnesia).
ok
(agent@myhost)2> application:start(snmp).
ok

Code listing 7.2: Loading the OTP MIB

(agent@myhost)3> otp_mib:load(snmp_master_agent).
ok

Manager

Code listing 7.3: Starting the Manager

(manager@myhost)1> application:start(snmp).
ok

Here we use the OID for otp.erlNodeName.1 to query the nodename of the agent's Erlang/OTP node.

Code listing 7.4: Querying the Agent

(manager@myhost)2> snmpm:load_mib(code:priv_dir(otp_mibs) ++ "/mibs/OTP-MIB").
ok
(manager@myhost)3> snmpm:sync_get("simple_user", "agent's engine", [[erlNodeName,1]]).                                          
{ok,{noError,0,
             [#varbind{oid = [1,3,6,1,4,1,193,19,3,1,2,1,1,1,2,1],
                       variabletype = 'OCTET STRING',value = "agent@myhost",
                       org_index = 1}]},
    4926}

Adding the os_mon Application

If we run the os_mon application more info is available.

Code listing 7.5: Starting os_mon

(agent@myhost)4> application:start(sasl).
ok
(agent@myhost)5> application:start(os_mon).
ok
(agent@myhost)6> os_mon_mib:load(snmp_master_agent).
ok

Note: SASL progress reports were hidden for our example.

Walking the OTP MIB

To demonstrate the information managed with the OTP-MIB I've used the net-snmp application from a Unix shell prompt to walk the OTP MIB.

Code listing 7.6: Using net-snmp to walk the agent's OTP MIB

$ snmpwalk -c public -v2c 127.0.0.1:4000 otp
OTP-MIB::erlNodeName.1 = STRING: agent@myhost
OTP-MIB::erlNodeMachine.1 = STRING: BEAM
OTP-MIB::erlNodeVersion.1 = STRING: 5.9
OTP-MIB::erlNodeRunQueue.1 = Gauge32: 0
OTP-MIB::erlNodeRunTime.1 = Counter32: 430
OTP-MIB::erlNodeWallClock.1 = Counter32: 112176
OTP-MIB::erlNodeReductions.1 = Counter32: 1329646
OTP-MIB::erlNodeProcesses.1 = Gauge32: 84
OTP-MIB::erlNodeInBytes.1 = Counter32: 7958884
OTP-MIB::erlNodeOutBytes.1 = Counter32: 1684165
OTP-MIB::applName.1.1 = STRING: otp_mibs
OTP-MIB::applName.1.2 = STRING: os_mon
OTP-MIB::applName.1.3 = STRING: snmp
OTP-MIB::applName.1.4 = STRING: mnesia
OTP-MIB::applName.1.5 = STRING: sasl
OTP-MIB::applName.1.6 = STRING: stdlib
OTP-MIB::applName.1.7 = STRING: kernel
OTP-MIB::applDescr.1.1 = STRING: SNMP managment information base for Erlang/OTP nodes.
OTP-MIB::applDescr.1.2 = STRING: CPO  CXC 138 46
OTP-MIB::applDescr.1.3 = STRING: SNMP  CXC 138 13
OTP-MIB::applDescr.1.4 = STRING: MNESIA  CXC 138 12
OTP-MIB::applDescr.1.5 = STRING: SASL  CXC 138 11
OTP-MIB::applDescr.1.6 = STRING: ERTS  CXC 138 10
OTP-MIB::applDescr.1.7 = STRING: ERTS  CXC 138 10
OTP-MIB::applVsn.1.1 = STRING: 1.0.7
OTP-MIB::applVsn.1.2 = STRING: 2.2.8
OTP-MIB::applVsn.1.3 = STRING: 4.21.4
OTP-MIB::applVsn.1.4 = STRING: 4.6
OTP-MIB::applVsn.1.5 = STRING: 2.2
OTP-MIB::applVsn.1.6 = STRING: 1.18
OTP-MIB::applVsn.1.7 = STRING: 2.15
OTP-OS-MON-MIB::loadMemorySystemWatermark.0 = INTEGER: 80
OTP-OS-MON-MIB::loadMemoryErlProcWatermark.0 = INTEGER: 5
OTP-OS-MON-MIB::loadSystemTotalMemory."agent@myhost" = Gauge32: 3045288000 bytes
OTP-OS-MON-MIB::loadSystemUsedMemory."agent@myhost" = Gauge32: 2129992000 bytes
OTP-OS-MON-MIB::loadLargestErlProcess."agent@myhost" = STRING: <0.6.0>
OTP-OS-MON-MIB::loadLargestErlProcessUsedMemory."agent@myhost" = Gauge32: 142328 bytes
OTP-OS-MON-MIB::loadCpuLoad."agent@myhost" = INTEGER: 19
OTP-OS-MON-MIB::loadCpuLoad5."agent@myhost" = INTEGER: 22
OTP-OS-MON-MIB::loadCpuLoad15."agent@myhost" = INTEGER: 23
OTP-OS-MON-MIB::loadOsWordsize."agent@myhost" = Gauge32: 32
OTP-OS-MON-MIB::loadSystemTotalMemory64."agent@myhost" = Counter64: 3045288000 bytes
OTP-OS-MON-MIB::loadSystemUsedMemory64."agent@myhost" = Counter64: 2129992000 bytes
OTP-OS-MON-MIB::loadLargestErlProcessUsedMemory64."agent@myhost" = Counter64: 142328 bytes
OTP-OS-MON-MIB::diskAlmostFullThreshold.0 = INTEGER: 80
OTP-OS-MON-MIB::diskDescr.1.1 = STRING: /
OTP-OS-MON-MIB::diskKBytes.1.1 = Gauge32: 243862672 kbytes
OTP-OS-MON-MIB::diskCapacity.1.1 = INTEGER: 79


Sending SNMP traps

Traps and Notifications

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

Code listing 8.1: 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.

Code listing 8.2: 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.

Code listing 8.3: 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.

Code listing 8.4: 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 start a trap daemon so that we can verify that traps are getting sent

Code listing 8.5: 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

Code listing 8.6: 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)7> snmp:load_mibs(snmp_master_agent, ["/path/to/.../snmp/agent/mibs/MY-TRAP-MIB"]).
ok
(agent@myhost)8> 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

Code listing 8.7: SNMP trap received

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