2 Functional Description
The SNMP development toolkit contains the following parts:
- An Extensible bilingual SNMP agent. Understands SNMPv1 (according to RFC1157), SNMPv2c (according to RFC1901, 1905, 1906, 1907), or both of them at the same time.
- A MIB compiler which understands SMIv1 (according to RFC1155, 1212, and 1215) and SMIv2 (according to RFC1902, 1903, and 1904)
- An SNMP manager that can be used for simple interactive testing, and for writing test suites.
The SNMP agent system consists of one Master Agent (MA) and optional Subagents.
This tool makes it easy to dynamically extend an SNMP agent in runtime. MIBs can be loaded and unloaded at any time. It is also easy to change the implementation of an MIB in runtime, without having to recompile the MIB. The MIB implementation is clearly separated from the agent.
To facilitate incremental MIB implementation, the tool can generate a prototype implementation for a whole MIB, or parts thereof. This allows different MIBs and management applications to be developed at the same time.
2.1 Definitions
The following definitions will help in understand the material presented in this user guide.
- MIB.
- The conceptual repository for management information is called the Management Information Base (MIB). It is conceptual because it does not hold any data, merely a definition of what data can be accessed. It can be compared to a header file in the C programming language. A definition of an MIB is a description of a collection of managed objects.
- ASN.1.
- The MIB is specified in a subset of the Abstract Syntax Notation One (ASN.1) language.
- Managed object.
- A resource to be managed is represented by a managed object which resides in the MIB. In an SNMP MIB, the managed objects are either:
- scalar variables which have only one instance per agent. They have single values, not multiple values like vectors or structures.
- tables which can grow dynamically.
- a table element which is a special type of scalar variable.
- Operations.
- SNMP relies on the three basic operations: get (value), set (value) and get-next (value). The next item defines how operations are implemented.
- Instrumentation function.
- An instrumentation function is associated with each managed object. This is the function which actually implements the operations and will be called by the agent when it receives a request from the management station.
2.2 Features
To implement an agent, the programmer writes instrumentation functions for the variables and the tables in the MIBs that the agent is going to support. A running prototype which handles set, get, and get-next can be created without any programming.
The toolkit provides the following:
- bilingual multi-threaded extensible SNMP agent
- easy writing of instrumentation functions with a high-level programming language
- basic fault handling such as automatic type checking and authentication
- loading and unloading of MIBs in runtime
- the ability to change instrumentation functions without recompiling the MIB
- rapid prototyping environment where the MIB compiler can generate instrumentation functions in ASN.1 from an MIB
- a simple and extensible model for transaction handling and consistency checking of set-requests
- support of the the subagent concept via distributed Erlang
- a mechanism for sending notifications (traps and informs)
- support for implementing SNMP tables in the Mnesia DBMS.
2.3 SNMPv1, SNMPv2 and SNMPv3
Currently (spring 1998), SNMPv1 is the full internet standard to use for network management. However, the "new" set of SNMPv2 specifications (RFC1902-1907) are now draft internet standards. Many managers choose to support both of these protocols. The main features of SNMPv2 compared to SNMPv1 are:
- The
get-bulk
operation for transfering large amounts of data.- Enhanced error codes.
- A more precise language for MIB specification
The standard documents that define SNMPv2 are incomplete, in the sense that they do not specify what a SNMPv2 message looks like. The message format and security issues are left to a special Administrative Framework. One such framework is the Community-based SNMPv2 Framework (SNMPv2c), which uses the same message format and framework as SNMPv1. There are other experimental frameworks as well, e.g. SNMPv2u and SNMPv2*.
The SNMPv3 specifications (RFC2271-2275) are now draft internet standrads as well. These specifications take a modular approach to SNMP. All modules are separated from each other, and can be extended or replaced individually. Examples of modules are Message definition, Security and Access Control. The main features of SNMPv3 are:
- Encryption and authentication is added.
- MIBs for agent configuration are defined.
All these specifications are commonly refered to as "SNMPv3", but it is actually only the Message module, which defines a new message format, and Security module, which takes care of encryption and authentication, that can't be used with SNMPv1 or SNMPv2. In this version of the agent toolkit, some of the MIBs for agent configuration are used, specifically the MIBs for definition of management targets for notifications.
The extensible agent in this toolkit understands both SNMPv1 and SNMPv2c. Recall that SNMP consists of two separate parts, the MIB definition language (SMI), and the protocol. On the protocol level, the agent can be configured to speak v1, v2c or both of them at the same time, i.e. a v1 request gets an v1 reply, and a v2c request gets a v2c reply. On MIB level, the MIB compiler can compile both SMIv1 and SMIv2 MIBs. Once compiled, any of the formats can be loaded into the agent, regardless of which protocol version the agent is configured to use. This means that the agent translates from v2 notifictaions to v1 traps, and vice versa. For example, v2 MIBs can be loaded into an agent that speaks v1 only. The procedures for the translation between the two protocols are described in RFC1908 and RFC2089.
In order for an implementation to make full use of the new SNMPv2 error codes, it is essential that the instrumentation functions always return v2 error codes, in case of error. These are translated into the corresponding v1 error codes by the agent, if necessary.
The translation from a v1 MIB to a v2 reply is always very straightforward, but the translation from a v2 MIB to a v1 reply is somewhat more complicated. There is one data type in v2, called Counter64, that a v1 manager can't decode correctly. Therefore, an agent may never send a Counter64 object to a v1 manager. The common practise in these situations is to simple ignore the any Counter64 objects, when sending a reply or a trap to a v1 manager. For example, if a v1 manager tries to GET an object of type Counter64, he will get a
noSuchName
error, while a v2 manager would get a correct value.2.4 Operation
The following steps are needed to get a running agent:
- Write your MIB in ASN.1 in a text file.
- Write the instrumentation functions in Erlang and compile them.
- Put their names in the association file.
- Run the MIB together with the association file through the MIB compiler.
- Configure the agent.
- Start the agent.
- Load the compiled MIB into the agent.
The figures in this section illustrate the steps involved in the development of an SNMP agent.
MIB Compiler PrinciplesThe compiler parses the ASN.1 file and associates each table or variable with an instrumentation function (see MIB Compiler Principles). The actual instrumentation functions are not needed at MIB compile time, only their names.
The binary output file produced by the compiler is read by the agent at MIB load time (see Starting the Agent). The instrumentation is ordinary Erlang code which is loaded explicitly or automatically the first time it is called.
Starting the AgentThe SNMP agent system consists of one Master Agent and optional subagents. The Master Agent can be thought of as a special kind of subagent. It implements the core agent functionality, UDP packet processing, type checking, access control, trap distribution, and so on. From a user perspective, it is used as an ordinary subagent.
Subagents are only needed if your application requires special support for distribution from the SNMP toolkit. A subagent can also be used if the application requires a more complex set transaction scheme than is found in the master agent.
The following illustration shows how the system can look at runtime.
ArchitectureA typical operation could include the following steps:
- The Manager sends a request to the Agent.
- The Master Agent decodes the incoming UDP packet.
- The Master Agent determines which items in the request that should be processed here and which items should be forwarded to its subagent.
- Step 3 is repeated by all subagents.
- Every subagent calls the instrumentation for its loaded MIBs.
- The results of calling the instrumentation are propagated back to the Master Agent.
- The answer to the request is encoded to a UDP Protocol Data Unit (PDU).
The sequence of steps shown is probably more complex than normal, but it illustrates the amount of functionality which is available. The following points should be noted:
- An agent can have many MIBs loaded at the same time.
- Subagents can also have subagents. Each subagent can have an arbitrary number of child subagents registered, forming a hierarchy.
- One MIB can communicate with many applications.
- Instrumentation can use Distributed Erlang to communicate with an application.
Most applications only need the Master Agent because an agent can have multiple MIBs loaded at the same time.
2.5 Subagents and MIB Loading
Since applications tend to be transient (they are dynamically loaded and unloaded), the management of these applications must be dynamic as well. For example, if we have an equipment MIB for a rack and different MIBs for cards which can be installed in the rack, the MIB for a card should be loaded when the card is inserted, and unloaded when the card is removed.
In this agent system, there are two ways to dynamically install management information. The most common way is to load an MIB into an agent. The other way is to use a subagent which is controlled by the application and registers and de-registers itself. A subagent can register itself below a subtree (not to be mixed up with
erlang:register
). The subtree is identified by an Object Identifier. When a subagent is registered, it receives all requests for this particular subtree and it is responsible for answering them. It should also be noted that a subagent can be started and stopped at any time.Compared to other SNMP agent packages, there is a significant difference in this way of using subagents. Other packages normally use subagents to load and unload MIBs in runtime. In Erlang, it is easy to load code in runtime and it is possible to load an MIB into an existing subagent. We do not need to create a new process for handling a new MIB.
Subagents are used for the following reasons:
- to provide a more complex set-transaction scheme than master agent
- to avoid unnecessary process communication
- to provide a more lightweight mechanism for loading and unloading MIBs in runtime
- to provide interaction with other SNMP agent toolkits.
Refer to the chapter Advanced Topics in this User's Guide for more information about these topics.
The communication protocol between subagents is the normal message passing which is used in distributed Erlang systems. This implies that subagent communication is very efficient compared to SMUX, DPI, and similar protocols.
2.6 Management of the Agent
Any SNMP agent must implement the
system
group and thesnmp
group, defined in MIB-II. The definitions of these groups have changed from SNMPv1 to SNMPv2. Provided in the distribution are MIBs and implementations for both of these versions. The MIB file for SNMPv1 is called STANDARD-MIB, and the corresponding for SNMPv2 is called SNMPv2-MIB. If the agent is configured to speak SNMPv1, the STANDARD-MIB is loaded by default. If it is configured to speak SNMPv2 or both protocols, the SNMPv2-MIB is loaded by defualt. It is possible to override this default behaviour, by explicitly load another MIB, for example, you could choose to implement the union of all objects in these two MIBs.There is another MIB that may be loaded into the agent. It is called OTP-SNMPEA-MIB (in previous versions of the toolkit it was called INTERNAL-MIB). This MIB defines managed objects for the configuration of the agent itself.
There are two standard MIBs, defined in RFC2273, that also may be loaded into the agent. The MIBs are SNMP-TARGET-MIB and SNMP-NOTIFICATION-MIB, and defines managed objects for configuration of management targets, i.e. receivers of notifications (traps and informs).
All of these MIBs should be loaded into the Master Agent. The ASN.1 code, the Erlang source code, and the generated
.hrl
files for them are provided in the distribution.The
.hrl
files are generated withsnmp:mib_to_hrl/1
and they are located in theinclude
directory of thesnmp
application. Include these files in your code as follows:-include_lib("snmp/include/STANDARD-MIB.hrl").2.6.1 STANDARD-MIB and SNMPv2-MIB
These MIBs contain the
snmp
- andsystem
groups from MIB-II which is defined in RFC1213 (STANDARD-MIB) or RFC1907 (SNMPv2-MIB). They are implemented in thesnmp_standard_mib
module. Thesnmp
counters all reside in volatile memory and thesystem
andsnmpEnableAuthenTraps
variables in persistent memory, using the SNMP built-in database (refer to the Reference Manual, section snmp, modulesnmp_local_db
for more details).If you need another implementation of any of these objects, e.g. you may want to store the persistent variables in the Mnesia database instead, you will have to make your own implementation of these variables (you can of course use the standard implementation for the other variables), compile and load the MIB instead of the default MIB. The new compiled MIB must have the same name as the original MIB (i.e. STANDARD-MIb or SNMPv2-MIB), and be located in the SNMP configuration directory (see Configuration Files.)
2.6.1.1 Data Types
There are some new data types in SNMPv2 that are useful in SNMPv1 as well. In the STANDARD-MIB, three data types are defined,
RowStatus
,TruthValue
andDateAndTime
. These data types are originally defined as textual conventions in SNMPv2-TC (RFC1903).2.6.2 OTP-SNMPEA-MIB
There are a few unspecified issues in SNMPv1 as well as in SNMPv2c. These include:
- how MIB views should be specified
- how access is controlled
- how to determine which managers a trap should be sent to
- how to determine UDP related information for SNMP entities.
These problems have been solved in other versions of SNMPv2, and in SNMPv3. We use some of the SNMPv2p approaches to solve the problems in this agent. In this version of the agent, standard (RFC2273) MIBs are used for configuration of which managers should receive traps. In future versions of the agent, all standard mechanisms will be used, and the OTP-SNMPEA-MIB will no longer be used for this purpose.
The OTP-SNMPEA-MIB defines managed objects for configuration which is used internally by the agent (see Configuration Files for further details). All data in this MIB is stored in volatile memory. This means that the data in the configuration files is read at start-up and inserted into the database. If another behaviour is needed, change the implementation of the functions in the module
snmp_internal_mib
.This MIB does not have to be loaded in the Master Agent. If it was, managers would have access to configuration data such as MIB views, communities, and trap destinations. Unless security is provided, it is generally not a good idea to make this MIB visible for managers. However, it is possible to load this MIB, or parts of it, and use the MIB view mechanism to restrict the visibility to certain managers.
If only parts of the MIB are wanted, delete the unwanted objects from the MIB file and recompile.
All tables use the
RowStatus
textual convention from SNMPv2, which is defined in STANDARD-MIB, to provide a uniform row handling mechanism.2.6.2.1 intCommunityTable
This table contains access information for different communities known to the agent. The ASN.1 definition looks as follows:
IntCommunityEntry ::= SEQUENCE { intCommunityDestination IpAddress, intCommunityString DisplayString, intCommunityViewIndex INTEGER, intCommunityAccess INTEGER, intCommunityStatus RowStatus } INDEX { intCommunityDestination, intCommunityString }A MIB view, and a corresponding access to that MIB view, is defined for each pair of
intCommunityDestination
andintCommunityString
. The view is defined inintViewTable
. The access can beread
orreadWrite
.The special IP address {0.0.0.0} is used as a wildcard. This wildcard matches all IP addresses which makes it possible to give certain access to all IP addresses.
This table is used by the agent as follows:
- A request which includes a reference to a community string comes in from a certain IP address.
- The agent looks in the table for the MIB view and the access which corresponds to the IP address and the community string.
- The operation is validated against the access and all requested objects are validated against the MIB view.
If the standard variable
snmpEnableAuthenTraps
is set toenabled
, anauthenticationFailure
notification is sent when the validation fails. This notification is sent to all management targets.2.6.2.2 intAgentIpAddress
This variable holds the IP address of the agent. It is used when sending traps and is included in the trap PDU sent to the management stations.
2.6.2.3 intAgentUDPPort
This variable holds the UDP port which the agent listens to.
2.6.2.4 intAgentMaxPacketSize
This variable describes the maximum packet size that this agent will send to a management station. The size is specified in bytes.
2.6.2.5 intAddressTable
This table contains UDP related information for each management station that is known to the agent. The ASN.1 definition looks as follows:
IntAddressEntry ::= SEQUENCE { intAddressDestination IpAddress, intAddressUDPPort INTEGER, intAddressMaxPacketSize INTEGER (484..65535), intAddressStatus RowStatus } INDEX { intAddressDestination }The following criteria is defined for each management station IP address:
- the UDP port
- the maximum UDP packet size it can handle.
This table is used when the agent sends a message to a management station. When sending a response, the agent checks that the packet size is less than specified in the
intAgentMaxPacketSize
variable and theintAddressMaxPacketSize
for the management station. Otherwise, atooBig
error is returned.When sending a trap, a check is performed to ensure that the trap is not too big. If it is, the trap will not be sent to the management station destination.
2.6.2.6 intTrapDestTable
This table is obsolete, and is no longer used. The tables in SNMP-TARGET-MIB and SNMP-NOTIFICATION-MIB are used for this purpose.
2.6.2.7 intViewTable
This table contains definitions for the MIB views. It is the same table as
viewTable
in SNMPv2. The ASN.1 definition looks as follows:IntViewEntry ::= SEQUENCE { intViewIndex INTEGER, intViewSubtree OBJECT IDENTIFIER, intViewMask OCTET STRING, intViewType INTEGER, intViewStorageType StorageType, intViewStatus RowStatus } INDEX { intViewIndex, intViewSubtree }The
intViewStorageType
column is not used.Each
intViewIndex
refers to a collection of sub-trees. Refer to the file OTP-SNMPEA-MIB.mib, or to RFC1447, for a complete description on this table2.6.2.7.1 MIB View Semantics
The formal definition of MIB views can be found in RFC1445 (from SNMPv2) . The following paragraphs are an extract from this RFC.
An MIB view is a collection of included and excluded subtrees. A subtree is identified by an OBJECT IDENTIFIER. A mask is associated with each subtree.
For each possible MIB object instance, the instance belongs to a subtree if:
- the OBJECT IDENTIFIER name of that MIB object instance comprises at least as many sub-identifiers as does the subtree, and
- each sub-identifier in the name of that MIB object instance matches the corresponding sub-identifier of the subtree whenever the corresponding bit of the associated mask is 1 (0 is a wildcard that matches anything).
Membership of an object instance in an MIB view is determined by the following algorithm:
- If a MIB object instance does not belong to any of the relevant subtrees, then the instance is not in the MIB view.
- If a MIB object instance belongs to exactly one subtree, then the instance is included in, or excluded from, the relevant MIB view according to the type of that entry.
- If a MIB object instance belongs to more than one subtree, then the subtree which comprises the greatest number of sub-identifiers, and is the lexicographically greatest, is used.
If the OBJECT IDENTIFIER is longer than an OBJECT IDENTIFIER of an object type in the MIB, it refers to object instances. Because of this, it is possible to control whether or not particular rows in a table shall be visible.
2.6.3 SNMP-TARGET-MIB and SNMP-NOTIFICATION-MIB
These MIBs define managed objects for configuration of notification receivers. They are described in detail in RFC2273. Here is only a brief description given.
2.6.3.1 snmpNotifyTable
An entry in this table selects a set of management targets which should receive notifications, as well as the type (trap or inform) of notification which should be sent to each selected management target.
The key in this table,
snmpNotifyName
is used in a special way in this version of the agent. It is used as the CommunityString which is included in each SNMPv1 or SNMPv2c notification. When an application sends a notification using the functionsend_notification/5
or the old functionsend_trap
the parameterNotifyName
specified in the call is used as an index in this table. The notification is sent to the management targets selected by that entry.2.6.3.2 snmpTargetAddrTable
An entry in this table defines transport parameters (such as IP address and UDP port) for each management target. Each row in the
snmpNotifyTable
refers to potentially many rows in this table. Each row in thesnmpTargetAddrTable
refers to an entry in thesnmpTargetParamsTable
.2.6.3.3 snmpTargetParamsTable
An entry in this table defines which SNMP version to use, and which security parameters to use.
Which SNMP version to use is implicitly defined by specifying the Message Processing Model. This version of the agent handles the models
v1
andv2c
.Each row specifies which security model to use, along with security level and security parameters. This version of the agent handles the security model
otp_sec
, which provides simple security by validating the IP address from which a request is sent. TheSnmpSecurityModel
value for this security model is 49427 (which is calculated as ericsson * 256 + otp.)2.7 Notifications
Notifications are defined in SNMPv1 with the TRAP-TYPE macro in the ASN.1 definition of an MIB (see RFC1215). The corresponding macro in SNMPv2 is NOTIFICATION-TYPE. When an application decides to send a notification, it calls one of the following function:
snmp:send_notification(Agent,Notification,Receiver[,NotifyName,Varbinds]) snmp:send_trap(Agent,Notification,Community[,Receiver,Varbinds])providing the registered name or process identifier of the agent where the MIB which defines the notification is loaded and the symbolic name of the notification.
If the
send_notification/3,4
function is used, all management targets are selected, as defined in RFC2273. TheReceiver
parameter defines where the agent should send information about the delivery of inform requests.If the
send_notification/5
function is used, anNotifyName
must be provided. This parameter is used as an index in thesnmpNotifyTable
, and the management targets defined by that single entry is used.The function
send_trap
is kept for backwards compatibility. TheCommunity
is used as aNotifyName
described above.Applications that use the old function
send_trap
will continue to work. ThesnmpNotifyName
is used as the community string by the agent when a notification is sent.2.7.1 Notification Sending
The simplest way is to call the function as
snmp:send_notification(Agent, Notification, no_receiver)
. In this case, the agent performs a get-operation to retrieve the object values which are defined in the notification specification (with the TRAP-TYPE or NOTIFICATION-TYPE macros). The notification is sent to all managers defined in the target and notify tables, either unacknowledged as traps, or acknowledged as inform requests.If the caller of the function wants to know whether or not acknowledgements are received for a certain notification (provided it is sent as an inform), the
Receiver
parameter can be specified as{Tag, ProcessName}
(refer to the Reference Manual, section snmp, modulesnmp
for more details). In this case, the agent send a message{snmp_notification, Tag, {got_response, ManagerAddr}}
or{snmp_notification, Tag, {no_response, ManagerAddr}}
for each management target.Sometimes it is not possible to retrieve the values for some of the objects in the notification specification with a get-operation. However, they are known when the
send_notification
function is called. This is the case if an object is an element in a table. It is possible to give the values of some objects to thesend_notification
functionsnmp:send_notification(Agent, Notification, Receiver, Varbinds)
. In this function,Varbinds
is a list ofVarbind
, where eachVarbind
is one of:
{Variable, Value}
, whereVariable
is the symbolic name of a scalar variable referred to in the notification specification.{Column, RowIndex, Value}
, whereColumn
is the symbolic name of a column variable.RowIndex
is a list of indices for the specified element. If this is the case, the OBJECT IDENTIFIER sent in the trap is theRowIndex
appended to the OBJECT IDENTIFIER for the table column. This is the OBJECT IDENTIFIER which specifies the element.{OID, Value}
, whereOID
is the OBJECT IDENTIFIER for an instance of an object, scalar variable or column variable.For example, to specify that
sysLocation
should have the value"upstairs"
in the notification, we could use one of:
{sysLocation, "upstairs"}
or{[1,3,6,1,2,1,1,6,0], "upstairs"}
It is also possible to specify names and values for extra variables that should be sent in the notification, but were not defined in the notification specification.
The notification is sent to all management targets found in the tables. However, make sure that each manager has access to the variables in the notification. If a variable is outside a manager's MIB view, this manager will not receive the notification.
By definition, it is not possible to send objects with ACCESS
not-accessible
in notifications. However, historically this is often done and for this reason we allow it in notification sending. If a variable has ACCESSnot-accessible
, the user must provide a value for the variable in theVarbinds
list. It is not possible for the agent to perform a get-operation to retrieve this value.2.7.2 Subagent Path
If a value for an object is not given to the
send_notification
function, the subagent will perform a get-operation to retrieve it. If the object is not implemented in this subagent, its parent agent tries to perform a get-operation to retrieve it. If the object is not implemented in this agent either, it forwards the object to its parent, and so on. Eventually the Master Agent is reached and at this point all unknown object values must be resolved. If some object is unknown even to the Master Agent, this is regarded as an error and is reported with a call tosnmp_error:user_err/2
. No notifications are sent in this case.For a given notification, the variables which are referred to in the notification specification must be implemented by the agent which has the MIB loaded, or by some parent to this agent. If not, the application must provide values for the unknown variables. The application must also provide values for all elements in tables.