SNMP Programmer's Reference

Jump to: navigation, search

Table of Contents


Contents

Introduction

SNMP Overview

The Simple Network Management Protocol (SNMP) is today the de-facto industry standard to manage devices on data communication networks, telecommunication systems and other globally reachable devices. Practically every organization dealing with computers and related devices expects to be able to monitor, diagnose and configure each such device from a central Network Operations Center (NOC). In order to do so, the applications at the NOC need to actively interact with the managed heterogeneous devices spread all over the organization and beyond, often across continents. SNMP is the protocol that enables these interactions.


The SNMP architectural model consists of the following key elements:

  • Management station
  • Management agent
  • Management information base (MIB)
  • Network management protocol


The management station is typically a stand-alone device, but it may be a capability implemented on a shared system. In either case, the management station serves as the interface for the human network manager into the network management system. At a minimum, the management station will have:

  • A set of management applications for the data analysis, fault recovery, etc.
  • A user interface by which the network manager may monitor and control the network.
  • The capability of translating the network manager's requirements into the actual monitoring and control of remote elements of the network.
  • A database of information extracted from the MIBs of all the managed entities in the network.

Only the last two elements are the subject of SNMP standardization.


The other active element in the network management system is the managed agent. Key platforms, such as hosts, routers or switches, may be equipped with SNMP agents so that they can be managed from a management station. The managed agent responds to requests for information and actions from the management station and may asynchronously provide the management station with important but unsolicited information.


Resources in the network may be managed by representing these resources as objects. Each object is a data variable representing one aspect of the managed agent. The collection of objects is referred to as a MIB. The MIB functions as a collection of access points at the agent for the management station. A management station performs the monitoring function by retrieving the value of MIB objects. A management station can cause an action to take place at an agent or can change the configuration settings at an agent by modifying the value of specific variables.


The management station and agents are linked by the SNMP protocol, which includes the following capabilities:

  • Enabling the management station to retrieve the value of objects at the agent.
  • Enabling the management station to modify the value of objects at the agent.
  • Enabling the agent to notify the management station of significant events.


The first SNMP version (SNMPv1) was introduced in the late 1980s and is a de-facto standard for multi-vendor network management. SNMPv2c (1992) provided more functionality and greater efficiency than SNMPv1 by expanding on error identifications and by introducing the GETBULK operator. It also introduced a simplified TRAP format. The functionality of SNMPv3 (finalized 1999) is defined in RFC 2570, RFC 2571, RFC 2572, RFC 2573, RFC 2574, and RFC 2575.


Terminology varies from version to version but in SNMPv1 terms (from RFC 1157):

"Network management stations execute management applications which monitor and control network elements. Network elements are devices such as hosts, gateways, terminal servers, and the like, which have management agents responsible for performing the network management functions requested by the network management stations. The Simple Network Management Protocol (SNMP) is used to communicate management information between the network management stations and the agents in the network elements."

"The SNMP architecture admits a variety of administrative relationships among entities that participate in the protocol. The entities residing at management stations and network elements which communicate with one another using the SNMP are termed SNMP application entities. The peer processes which implement the SNMP, and thus support the SNMP application entities, are termed protocol entities."

Terminology changes in SNMPv3 (from RFC 2570):

"The SNMPv1 Framework describes the encapsulation of SNMPv1 PDUs in SNMP messages between SNMP entities and distinguishes between application entities and protocol entities. In SNMPv3, these are renamed applications and engines, respectively."

MIB Structure

MIBs are either standard or proprietary. Standard MIBs are published by the Internet Engineering Task Force (IETF) as Requests For Comments (RFCs) (see http://www.rfc-editor.org/rfc.html). Proprietary MIBs can be designed and implemented by any organization as long as the MIB is defined under an enterprise specific object ID (see below). Of all standard or proposed standard MIBs, the group of managed objects known as MIB-II is the most basic and the most popular MIB. All SNMP agents implement a subset of MIB-II (some MIB-II components are optional for most systems and some components were deprecated by later RFCs). MIB-II is defined in RFC 1213.


MIB is a rooted tree structure that contains globally unique object identifiers (OIDs). To describe an object, you walk from the root of the tree through the branches to the object, concatenating ISO numbers for OID or text strings for Object Descriptors. While walking through the tree, subordinate limbs may be sparse. This allows for private MIBs to be attached to the standard MIB in any fashion. From an unlabeled root, the limbs in the internet tree are shown below.


A specific instance of a MIB element is defined by its position in the rooted tree, followed by a string specifying its instance.


Example 1
Part of the MIB-II is a count of how long a device has been up. The Object ID for this element is:

iso.org.dod.internet.mgmt.mib.system.sysUpTime
1.3.6.1.2.1.1.3


In addition to knowing its Object ID, the instance must be specified. There is only one system group per "mib view", so a zero is appended to the Object ID to specify this instance of sysUpTime. The objects with this property are called scalar objects, or scalars.

iso.org.dod.internet.mgmt.mib.system.sysUpTime.0
1.3.6.1.2.1.1.3.0


Example 2
Another part of the MIB-II is a count of how many octets a device has received. The Object ID for this element is:

iso.org.dod.internet.mgmt.mib.interfaces.ifTable.ifEntry.ifInOctets
1.3.6.1.2.1.2.2.1.10


In addition to knowing its Object ID, the instance must be specified. Since devices may have more than one interface, the interface number is appended to the Object ID. The objects with this property are called tabular objects.

iso.org.dod.internet.mgmt.mib.interfaces.ifTable.ifEntry.ifInOctets.interface1
1.3.6.1.2.1.2.2.1.10.1


The instance does not have to be indexed by an integer. Various MIBs define tables with octet strings, IP addresses, and OIDs as indices. The index does not have to be simple and may consists of a number of fields. For example, the TCP Connections Table of MIB-II is indexed by local address (type IP address), local port (type integer), remote address (type IP address), remote port (type integer) – in that order.


The enterprises node is defined as OID iso.org.dod.internet.private.enterprises (1.3.6.1.4.1). All proprietary MIBs are attached to this node via Private Assigned Enterprise Numbers which are issued by IETF following the request from an organization. For example, all Cisco MIBs contain the enterprise number 9, and Cisco path is 1.3.6.1.4.1.9, Oracle is under enterprise number 111, etc. Close to 10,000 enterprise numbers are issued to date. The private enterprise numbers are listed in RFC 1700.


SNMPv1 Messages

All SNMP messages contain a Protocol Data Unit (PDU) as a part of the message. Each PDU includes variable bindings field(s) by which the requested object is defined. Each variable bindings (varbind) field consists of two entities: the identity (basically OID) and the value. The number of varbinds in a PDU is not limited.

The SNMPv1 defines five type of PDUs. These PDUs are:

  • GetRequest PDU
  • GetNextRequest PDU
  • SetRequest PDU
  • GetResponse PDU
  • Trap PDU

Of these, the first three may be issued only by a manager, and the last two only by an agent.


GetRequest PDU

The manager issues this PDU when it knows the exact OID of the variable it is going to retrieve. For example, in the example above, the manager may issue this PDU to get sysUpTime with the following OID: 1.3.6.1.2.1.1.3.0. If, on the other hand, the manager asks for 1.3.6.1.2.1.1.3, the agent would respond with an error since it won't be able to find a variable with the indicated OID. The value field in the varbinds is set to zero in GetRequest PDU.


GetNextRequest PDU

This PDU is almost identical to the GetRequest PDU. The only difference is the following: In the GetRequest PDU, each variable in the varbinds field refers to an object instance whose value is to be returned. In the GetNextRequest PDU, for each variable, the agent is to return the value of the object instance that is next in lexicographical order. This difference, though, has tremendous implications. It allows the manager to discover the structure of a MIB dynamically. It also provides an efficient mechanism for searching a table whose entries are unknown. Suppose the manager does not know anything about the MIBs the agent implements. The manager might start with issuing GetNextRequest with the varbind identity field (OID) .1. Since any path in the MIB tree must contain the root, this request is guaranteed to succeed. Suppose further, the agent responds with the lexicographically next object 1.3.6.1.2.1.1.1.0 (sysDescr) and the corresponding value field. The manager then issues a new GetNextRequest with the OID 1.3.6.1.2.1.1.1.0. If the agent implements all object in the system group of MIB-II (as it should), it responds with 1.3.6.1.2.1.1.2.0 (sysObjectID). The manager issues another GetNextRequest with the OID 1.3.6.1.2.1.1.2.0 and so on. This strategy allows the manager to retrieve the entire MIB, and the end is signaled by the agent when it issues the error code noSuchName (see error code definitions below). The value field in the varbinds is set to zero in GetNextRequest PDU.


SetRequest PDU

This PDU is used by a manager to write an object value. Thus the varbinds list in the SetRequest PDU include both OID and a value to be assigned to each OID listed. As in GetRequest PDU, the manager must know the exact OID of the variable it is going to set.


GetResponse PDU

This PDU is issued by the agent in response to GetRequest, GetNextRequest and SetRequest PDUs. In the response to the first two, the agent simply populates the value field of the varbinds, and in case of the SetRequest, the varbinds list is returned unchanged.


Trap PDU

This PDU is issued by the SNMP agent to provide the manager with an asynchronous notification of some significant event. The manager is responsible for catching and interpreting a Trap PDU. The traps may be generic or enterprise-specific. The following generic traps are defined:

  • coldStart (value 0) - The agent must send this trap on initialization.
  • warmStart (1) - The agent sends this trap when it is initialized in such a way that its configuration and protocol implementation is not altered.
  • linkDown (2) - Failure of one of the communication links.
  • linkUp (3) - One of the communication links has come up.
  • authenticationFailure (4) - The agent received a PDU that failed authentication.
  • egpNeighborLoss (5) - Only for devices implementing EGP protocol.
  • enterpriseSpecific (6) - Some specific event defined in the enterprise MIB has occurred.


Each trap PDU contains generic-trap and specific-trap fields. For generic traps 0 – 5 above, the specific-trap field is set to zero, and for an enterprise-specific trap this field is set to the value defined in the enterprise MIB.


SNMPv2c Messages

In addition to the messages defined in SNMPv1, SNMPv2 defines GetBulkRequest. Its purpose is to minimize the number of protocol exchanges required to retrieve a large amount of management information. The GetBulkRequest uses the same selection principle as the GetNextRequest, i.e. selection is always of the next object instance in lexicographical order. The difference is that, with GetBulkRequest it is possible to specify that multiple lexicographical successors be selected. It is achieved through the use of two field in the PDU: non-repeaters and max-repetitions. The non-repeaters field specifies the number of variables in the varbinds list for which a single lexicographical successor is to be returned. The max-repetitions field specifies the number of lexicographical successors to be returned for the remaining variables in the varbinds list.


SNMPv2 specification also includes a Report PDU, but without a definition of how and when to use it. This agent utilizes the Report PDU to convey SNMPv3 security violations (see below).


SNMP Security

SNMPv1 and SNMPv2c provide only very limited security protection in form of a community field which is a part of every SNMP message. The community field is a printable octet string, usually with the length not exceeding some predefined maximum, and functions similar to a password. Most of the agents implement different communities for retrieval and modification operations, though this is not explicitly required by the protocol. The agent may choose to accept more than one community for each operation. This is implementation–dependent. The manager(s) and the agent(s) have to agree by means outside of the SNMP protocol on which communities will be accepted to authenticate the message. Upon receiving the SNMP message, the agent compares the community field in the incoming message with those to which it was configured, and, if a match is found, considers the message properly authenticated and continues with processing. If no match is found, the agent stops processing, and does not issue the GetResponse PDU. The manager may request to be notified of such events by setting snmpEnableAuthenTraps object of MIB-II to 'enabled'. In this case, when authentication failure occurs, the agent issues an authenticationFailure trap to the manager IP address(es) for which it was configured.


The SNMPv3 protocol was introduced to correct the weak security protection of SNMPv1 and SNMPv2c. Specifically SNMPv3 protects against the following principal threats:

  • Modification of information
An entry could alter an in-transit message generated by an authorized entry in such a way as to effect unauthorized management operations, including the setting of object values. The essence of this threat is that an authorized entity could change any management parameter, including those related to configuration, operations, and accounting.
  • Masquerade
Management operations that are not authorized for some entity may be attempted by that entity by assuming the identity of an authorized entity.
  • Message stream modification
SNMP is designed to operate over a connectionless transport protocol. There is a threat that SNMP messages could be reordered, delayed, or duplicated to effect unauthorized management operations.
  • Disclosure
An entry could observe exchanges between a manager and an agent and thereby learn the values of managed objects and learn of notifiable events.


SNMPv3 is not intended to secure against the following threats:

  • Denial of service
An attacker can prevent exchanges between manager and agent.
  • Traffic analysis
An attacker can observe the general pattern of traffic between manages and agents.


The protection that SNMPv3 provides against the four threats listed above is achieved through the use of the User-Based Security Model and the View-Based Access Control Model.


The Used-Based Security Model (USM) is defined in RFC 2574, and consists of:

  • Authentication
Provides data integrity and data origin authentication. The message authentication code, HMAC, with either the hash function MD5 or SHA-1, provides authentication.
  • Timeliness
Protects against message delay or replay.
  • Privacy
Protects against disclosure of message payload. The cipher block chaining mode (CBC) of DES is used for encryption.
  • Message format
Defines format of msgSecurityParameters field, which supports the functions of authentication, timeliness and privacy, and contains the following elements:
  1. msgAuthoritativeEngineID - A unique identifier of an SNMP entity.
  2. msgAuthoritativeEngineBoots - Represents the number of times that this SNMP engine has initialized itself since its initial configuration.
  3. msgAuthoritativeEngineTime - Represents the number of seconds since this authoritative SNMP engine last incremented the msgAuthoritativeEngineBoots object.
  4. msgUserName - The principal on whose behalf the message is being exchanged.
  5. msgAuthenticationParameters - HMAC message authentication code, or null if authentication is not used.
  6. msgPrivacyParameters - A value used to form the initialization vector in the DES CBC algorithm.
  • Key management. Defines procedures for key generation, update and use.


In addition, each SNMP entity maintains a MIB, usmUser group, which consists of a single scalar object, usmUserSpinLock, and also the table usmUserTable which contains information about authorized users.


The View-Based Access Control Model (VACM) is defined in RFC 2575 and contains the following elements:

  • Groups - Defines a set of zero or more <securityModel, securityName> tuples on whose behalf SNMP management objects can be accessed.
  • Security Level - The access rights for groups.
  • Contexts - A subset of the object instances in the local MIB, providing a way of aggregating objects into collections with different access policies.
  • MIB views - Defines the set of rules to restrict the access of particular groups to a subset of the managed objects.
  • Access Policy - Enforces sets of access privileges for different users.


Each SNMP entity maintains a VACM MIB which consists of the following tables:

  • vacmContextTable
  • vacmSecurityToGroupTable
  • vacmAccessTable
  • vacmViewTreeFamilyTable and vacmViewSpinLock scalar object.

SNMP Messages: Language and Encoding Rules

SNMP operations occur through message exchange over a message transport service. That calls for a unified message format. Out of existing formal languages (XDR is one example), the SNMP protocol adopted a subset of the Abstract Syntax Notation One (ASN.1) language (standardized by CCITT, X.208, and ISO, ISO 8824). This format, called an abstract syntax, is independent of the representation of data on any particular computer system. Three kinds of managed objects are defined in ASN.1:

1. Types - Define the new data structures. ASN.1 types include (but are not limited to):
  • BOOLEAN(1)
  • INTEGER(2)
  • BIT STRING(3)
  • OCTET STRING(4)
  • NULL(5)
  • SEQUENCE OF(16)
  • OBJECT IDENTIFIER(6)
2. Values - Instances of a type.
3. Macros - Used to change the actual grammar of ASN.1.


ASN.1 has only one "operation", the assignment statement which uses the "::=" operator. All comments begin with two hyphens "-" and end either with another set of hyphens or with the end of line character.


Example 1

Status ::= INTEGER { up(1), down(2), testing(3) }
myStatus Status ::= up - 1


To transmit a message, it must be first converted into a string of octets. A transfer syntax specifies the format of the converted data. SNMP protocol uses a subset of the Basic Encoding Rules (BER) (standardized by CCITT, X.209, and ISO, ISO 8825) to define the format of encoded (serialized) messages. The encoding is based on on the use of type-length-value structure. That is, any ASN.1 value can be encoded as a triplet with the following components:

  • Tag - indicates the ASN.1 type.
  • Length - indicates the length of the actual value representation
  • Value - represents the value of the ASN.1 type as a string of octets.


The tag field consists of eight bits (most significant bit is 8, least significant bit is 1), with the bits 8,7 denoting class – Universal {00}, or Application {01}, or Context-specific {10}, or Private {11}; bit 6 is "f" bit indicating Primitive {0} or Constructed {1}; bits 5 to 1 denote the tag number. Some defined tag numbers are:


Type Tag Class Tag Number Value of Tag Field
INTEGER/Integer32 UNIVERSAL 0x02 0x02
OCTET STRING UNIVERSAL 0x04 0x04
NULL UNIVERSAL 0x05 0x05
SEQUENCE UNIVERSAL 0x10 0x30
IpAddress APPLICATION 0x00 0x40
Gauge/Gauge32 APPLICATION 0x02 0x42
TimeTicks APPLICATION 0x03 0x43


Note Note: SEQUENCE is the only constructed (versus primitive) type in this list.


Some examples of ASN.1 encoding:

1. Type is INTEGER, value = 100 (decimal)
Encoding:
Tag (1 octet): 0x02
Length (1 octet): 0x01
Value (1 octet): 0x64
2. Type is OCTET STRING, value = "Treck"
Encoding:
Tag (1 octet): 0x04
Length (1 octet): 0x05
Value (5 octets): 0x45, 0x6c, 0x6d, 0x69, 0x63
3. Type is IpAddress, value = 192.168.100.9
Encoding:
Tag (1 octet): 0x40
Length (1 octet): 0x04
Value (4 octets): 0xc0, 0xa8, 0x64, 0x09
4. Type is NULL
Encoding:
Tag (1 octet): 0x05
Length (1 octet): 0x00

SNMP Messages and PDU Formats

SNMPv1 Messages and PDU Formats

The SNMPv1 message consists of three fields, encoded in ASN.1 format:

  • Version - INTEGER with the value 0
  • Community string - OCTET STRING
  • PDU - SEQUENCE OF fields


Two PDU formats are defined, one for GetRequest, GetNextRequest, GetResponse, and SetRequest, and another for Trap.


The Request or Response PDU consists of the following fields, encoded in ASN.1 format:

  • request-id - INTEGER
  • error-status - INTEGER
  • error-index - INTEGER
  • variable-bindings - SEQUENCE


The request-id field is filled by the issuer of GetRequest, GetNextRequest, or SetRequest (the manager). In GetResponse message this field remains identical with the corresponding request message. This field allows the manager to separate duplicate responses for the same request from responses for other requests. The error-status and error-index fields are zeroed in the request messages, and filled in by the agent in GetResponse if the execution of the request results in error. For the definitions of error-status values see RFC 1157. The error-index field points to the variable-bindings field causing the error, and is 1-based.


The variable-bindings field consists of a sequence of V1-VarBind. Each V1-VarBind consists of two fields, encoded in ASN.1 format:

  • identity - OBJECT_IDENTIFIER
  • value - depends on ASN.1 type of value


The Trap PDU consists of the following fields, encoded in ASN.1 format:

  • enterprise - OBJECT_IDENTIFIER
  • agent-addr - IpAddress
  • generic-trap - INTEGER
  • specific-trap - INTEGER
  • time-stamp - TimeTicks
  • variable-bindings - SEQUENCE


The enterprise field relays the agent identity. For example, if the company Generic Networks obtained the Enterprise Number 8888 from IETF, and they manufacture three type of products (bridges, routers and hubs), and the product router contains five different categories, then the agent in the category 4 of the router product might be assigned the enterprise .1.3.6.1.4.1.8888.2.4. The agent-addr field contains the IP address of the agent issuing the trap, or the address of a network entity on whose behalf the agent issued the trap.


SNMPv2c Messages and PDU Formats

The SNMPv2c message consists of three fields, encoded in ASN.1 format:

  • Version - INTEGER with the value 1
  • Community string - OCTET STRING
  • PDU - SEQUENCE OF fields


Two PDU formats are defined, one for GetRequest, GetNextRequest, GetResponse, SetRequest, Report and Trap, and another for GetBulk.


The first type is identical with the SNMPv1 Request or Response PDU, and the second is almost identical, except that the meanings of fields error-status and error index becomes non-repeaters and max-repetitions. The error-status values have been expanded in SNMPv2. For the definitions of error-status values see RFC 1905.


SNMPv3 Messages and PDU Formats

The SNMPv3 message consists of the following fields, encoded in ASN.1 format:

  • msgVersion - INTEGER with the value 3
  • msgGlobalData
msgID - INTEGER
msgMaxSize - INTEGER
msgFlags - INTEGER
msgSecurityModel - INTEGER
  • msgSecurityParameters
msgAuthoritativeEngineID - OCTET STRING
msgAuthoritativeEngineBoots - INTEGER
msgAuthoritativeEngineTime - TimeTicks
msgUserName - OCTET STRING
msgAuthenticationParameters - OCTET STRING
msgPrivacyParameters - OCTET STRING
  • ScopedPDU (plaintext or encrypted)
ContextEngineID - OCTET STRING
ContextName - OCTET STRING
PDU - SEQUENCE OF fields


For the full definitions of fields in an SNMPv3 message, see RFC 2572 and RFC 2574. The PDU format is identical to that of SNMPv2.


Recommended Literature

  1. "Understanding SNMP MIBs", by David Perkins and Evan McGinnis, Prentice Hall, 1997
  2. "SNMP, SNMPv2, SNMPv, and RMON 1 and 2", by William Stallings, 3rd edition, Addison-Wesley, 1999
  3. "Abstract Syntax Notation One (ASN.1). The Tutorial and Reference", by Douglas Steedman, Technology Appraisals Ltd., 1993
  4. "The Simple Book. An Introduction to Internet Management", by Marshall Rose, 2nd edition, Prentice Hall, 1994


Treck SNMP Agent Design

Treck SNMP Agent is an embedded trilingual (v1/v2c/v3) SNMP agent fully independent of processor, RTOS and development tools. It is an extensible agent allowing adding an unlimited number of MIBs to the code automatically by running Treck Automatic Code Generator. Treck SNMP Agent is fully compliant to the following RFCs:

  • RFC 1155: SNMP and SNMP MIB
  • RFC 1157: SNMP, version 1
  • RFC 1212: Concise MIB definitions
  • RFC 1213: MIB II for TCP/IP
  • RFC 1215: Convention for defining traps for use with the SNMP
  • RFC 1901: Introduction to Community-based SNMPv2
  • RFC 2011: SNMPv2 MIBs for IP
  • RFC 2012: SNMPv2 MIBs for TCP
  • RFC 2013: SNMPv2 MIBs for UDP
  • RFC 2576: Co-existence between Version 1 and Version 2
  • RFC 2578: Structure of Management Information (SMI), v2
  • RFC 2579: Textual Conventions
  • RFC 2580: Conformance Statements
  • RFC 3416: Protocol Operations
  • RFC 3417: Transport Mappings
  • RFC 3418: Management Information Base
  • RFC 3411: An Architecture for Describing SNMP Management Frameworks
  • RFC 3412: Message Processing and Dispatching for SNMP
  • RFC 3413: SNMP Applications
  • RFC 3414: User-based Security Model (USM) for SNMPv3
  • RFC 3415: View-based Access Control Model
  • RFC 3584: Coexistence between Version 1, Version 2, and Version 3 of the Internet-standard Network Management Framework
  • RFC 4001: Textual Conventions for Internet Network Addresses
  • draft-ietf-ipv6-rfc2011-update-03: Management Information Base for the Transmission Control Protocol (TCP)
  • RFC 4022: Management Information Base for the Transmission Control Protocol (TCP)
  • draft-ietf-ipv6-rfc2013-update-00: Management Information Base for the User Datagram Protocol (UDP)
  • RFC 4292: IP Forwarding Table MIB


The agent can be compiled as v1-only (#define TM_SNMP_VERSION 1), or as a bilingual v1/v2c (#define TM_SNMP_VERSION 2), or as a trilingual v1/v2c/v3 (#define TM_SNMP_VERSION 3). When compiled as v1, the agent accepts only SNMP v1 messages and issues v1 traps. When compiled as bilingual, it accepts v1 as well as v2 messages and issues responses accordingly. It sends both v1 and v2 traps to the configured trap sinks. In the trilingual mode it accepts all three version messages and issues traps in all three formats.


Treck SNMP Agent supports two architectural models of operation:

  • Non-blocking SNMP Agent:
Incoming SNMP packets are delivered to the SNMP agent in-line, which means the UDP directly calls the SNMP via a subroutine call. The SNMP parses the SNMP packet, and returns a response immediately, in a single pass through the TCP/IP stack. Note that this also forces a non-blocking implementation of the SNMP agent. This architecture is well suited to implementations in which all variables managed via SNMP are readily available, which is typical of single-board systems.
  • Multi-tasking SNMP Agent:
Requires an SNMP task to process SNMP messages. The operating system or RTOS starts a task that binds itself to the SNMP port. Once an SNMP packet is parsed by UDP stack, it is put on the receive queue of the SNMP socket. The SNMP task is put in a ready-to-run state. The SNMP task reads the SNMP packet off the receive queue, processes the request, and calls the UDP transmit routines to send the response. This decouples the SNMP processing from the operating system processing, and thus simplifies debugging.


The following features highlight the advantages of Treck SNMP Agent design.

  • Compact code size
Care was taken to reduce the agent code size: v1/v2c code ROM size is 48K, RAM 14.5; for the v1/v2c/v3 code the corresponding figures are - ROM 110K, RAM 18.6K. In both cases stack size required does not exceed 2K. These figures can be reduced if full compliance to the corresponding RFCs is not required.
  • Optimized SET request processing
Normally the agents require four to five passes to process a SET request. Due to a unique Treck SNMP Agent design, this agent does it in only two passes. The first pass performs test SET operations to make sure all of the varbind SET operations are valid. The second pass commits the changes. If it is found at the end of the first pass that a violation took place, or an operation is requested on an object with other than read-create clause, no second pass becomes necessary, and the response PDU with the indicated error is built right away. Any number of different row or tables operations can be processed.
  • Optimized and unified search of table and scalar objects for GET and GETNEXT requests
A standard function with two arguments is called each time the table or the group object is to be accessed. The first argument is the flag indicating if an exact match is requested, and the second is the pointer to the corresponding structure with the index pointing to the specific row (groups are considered tables with one row). The function returns success if the row is found (exact match), or the lexicographically next row is found (non-exact match). The function returns failure if the row is not found (exact match), or there is no next row in the table (non-exact match). The sorting based on table index of any complexity is done inline inside the function in two passes and does not involve dynamic memory allocation. In case of success the functions fills the related structure with the row object instances.
  • Separate processing of SNMP v3 messages
At the onset the agent finds out if the request is v3, and if so, the processing (authentication, privacy, access control, timeliness and other checks) is done separately, then merged with the regular variable bindings processing, and then separated again to build a specific v3 response.
  • The Configuration API functions
Enable the user to add / modify / delete the vital parameters at runtime. The example would be changing communities fields or trap sink addresses while the agent is running.
  • Treck Automatic Code Generator
Based on the libsmi MIB Compiler which adds necessary code based on MIB files to the core agent. The SNMP stub functions to get and set MIB objects and rows creation and deletion stub functions are generated, so the developer unfamiliar with the SNMP protocol can fill in the implementation-dependent code inside these stubs. An unlimited number of MIBs can be added to the agent this way, with two source and two header files per MIB added to the code. The developer has to be concerned with only one source file containing stub functions.


Treck SNMP Agent Description

The items in this section describe building of an agent, running the agent, specific macros, testing the agent, MIB Compiler and Code generator, configuration API properties, and protocol stack independent functions.


How to Build the Agent

The SNMP agent can be built as SNMPv1-only agent, or SNMPv1/v2c bilingual agent, or full SNMP v1/v2c/v3 trilingual agent.


If the agent is built as SNMPv1, it will recognize and respond only to SNMPv1 messages, the eror-status field being used as defined in RFC 1157, and issue only SNMPv1 traps.


If the agent is built as SNMPv1/v2c, it will recognize SNMPv1 and SNMPv2c messages and respond accordingly. The error-status field in SNMPv1 GetResponse messages conforms to the definitions in RFC 1157, and in SNMPv2c responses to those in RFC 1905. The traps are issued both in SNMP1 and SNMPv2c formats.


If the agent is built as SNMPv1/v2c/v3, it will recognize SNMPv1, SNMPv2c and SNMPv3 messages and respond accordingly. The error-status field in SNMPv1 responses conforms to the definitions in RFC 1157, and in SNMPv2c and SNMPv3 responses to those in RFC 1905. The traps are issued in SNMP1, SNMPv2c and SNMPv3 formats.


To enable SNMP agent functionality with the Treck TCP/IP stack, you must edit your trsystem.h file, and uncomment exactly one of the following macro definitions corresponding to whether you want SNMPv1-only agent, or SNMPv1/v2c bilingual agent, or full SNMP v1/v2c/v3 trilingual agent:

/*
* Uncomment the following line for SNMPv1 only.
* (SNMP option only.)
*/
/* #define TM_SNMP_VERSION 1 */
/*
* Uncomment the following line for SNMPv1 and SNMPv2c (bilingual).
* (SNMP option only.)
*/
/* #define TM_SNMP_VERSION 2 */
/*
* Uncomment the following line for SNMPv1, SNMPv2c and SNMPv3 (trilingual).
* (SNMP option only.)
*/
/* #define TM_SNMP_VERSION 3 */


Additionally, if you want the SNMP Agent to support GETNEXT requests with the MIB-II tables ipNetToMediaTable (ARP cache), ipRouteTable (Routing table), udpTable (UDP listening sockets) and tcpConnTable (TCP sockets), then you will also need to #define the TM_SNMP_CACHE macro in your trsystem.h file. After you make these changes to your trsystem.h file, you will need to do a full recompile of both the Treck TCP/IP stack and the SNMP Agent source code.


Other compile-time options

Comment out TM_USE_RFC1213_MIB2 if you do not want the deprecated RFC 1213 MIB2 objects that are designed only for IPv4 to be included in the SNMP agent. This option requires you to enable TM_USE_SNMP_CACHE to be fully functional.


If you are running the stack in dual mode (IPV4 and IPV6), IPv6 objects will not be displayed in those tables. Comment out TM_USE_NG_MIB2 to disable the Next Generation MIB2, which consists of tables that support both IPv4 and IPv6 entities. This option requires TM_SNMP_CACHE to be defined to be fully functional.


To limit code size and memory usage you may want to use 8-bit or 16-bit OIDs. This will make the agent to change the type "oid", by default a 32-bit long to either a 16-bit short or a 8-bit character. Use TM_SNMP_8BIT_SUBIDS or TM_SNMP_16BIT_SUBIDS if you want to use enable this feature. For this option to work, you must be sure that no OID returned or processed by the agent will be greater than 255 (for TM_SNMP_8BIT_SUBIDS) or 65535 (for TM_SNMP_16BIT_SUBIDS).


Running the Agent

The user can start or stop the agent by calling tfSnmpdMain() or tfSnmpdStop() respectively. The user needs to include the <trapi.h> header file in the module which calls these APIs.


tfSnmpdMain

Ther user calls tfSnmpdMain() to initialize the agent and start listening for incoming messages. It can be either blocking or non-blocking, as specified by the last parameter.


Blocking Mode

tfSnmpdMain() should be called from a task. It will not return unless a system error occurs or the agent is stopped by tfSnmpdStop(). It will wait for and respond to incoming messages, and execute the code in the context of the calling task. Choose blocking mode if you are using an RTOS/Kernel and prefer to run the SNMP agent as a separate task.


Non-blocking Mode

tfSnmpdMain() will return immediately after initialization. Reception, processing, and responding to SNMP messages occurs afterwards in a socket callback function. Choose non-blocking mode if you do not have an RTOS/Kernel.


tfSnmpdStop

The user calls tfSnmpdStop() to close the SNMP sockets and kill the agent. It does the reverse of initializing the agent, i.e. any memory that was allocated for the SNMP agent during initialization is freed.


Macros

A number of SNMP configuration parameters must be defined prior to starting the agent. These parameters include trap configuration parameters, SNMP port and communities information for SNMP v1/v2c configuration. If the SNMPv3 agent is built as explained above, then additional parameters related to five tables must be also defined. The default values are provided for ALL parameters. However, if the user decides to change some or all configuration parameters, he/she can do so via Configuration API functions defined in the next section.


The default values for the configuration parameters are contained in the trcfg.h and trregstr.h modules.


SNMP protocol recommends UDP port 161 as a port on which the agent listens to the requests. The following line in trcfg.h defines the SNMP default port:

#define TM_SNMP_DEF_PORT 161


However, for the security or other reasons, the user might want to set the SNMP port to a different value. To do so, he/she must use the function tfSetSnmpPort() defined in the next section.


Note Note: If you set this port to the value other than default, the manager(s)

communicating with the agent must be aware of the new port value. Most managers use port 161 as a default.


Warning Warning: The tfSetSnmpPort() function may be called ONLY prior to starting the agent, and NEVER called while the agent is running.


SNMP protocol does not specify a number of communities an SNMP agent might use for the message authentication, nor does it specify that different communities are to be used for retrieval and modification requests. This agent defines a maximum number of 'read' and 'write' communities and a maximum length of the human readable community string in trregstr.h:

#define TM_SNMP_MAX_NUM_READ_COMMUNITIES  5
#define TM_SNMP_MAX_NUM_WRITE_COMMUNITIES 5
#define TM_SNMP_MAX_COMMUNITY_LEN         24


Note that no Configuration API function is provided for changing these maximum numbers. The defined values are large enough to accommodate any needs. However, if the need arises to increase these values, the the user should simply redefine them in trregstr.h and rebuild the agent.


By default, the agent starts with one 'read' community and one 'write' community. They are defined in trcfg.h as:

#define TM_SNMP_READ_COMMUNITY          "public"
#define TM_SNMP_WRITE_COMMUNITY         "private"


The user can add, delete, or modify the community names by using tfAddCommunity(), tfDeleteCommunity() and tfModifyCommunity() defined in the next section. The only limitation is, if only one community is left in the list, the user is not allowed to delete it.


SNMP protocol does not specify a number of trap sinks (the network entities to which the agent sends the traps) or their IP addresses. This agent defines a maximum number of trap sinks in trregstr.h as follows:

#define TM_SNMP_MAX_NUM_TRAP_SINKS      5


Note, that, as in case of communities, this number is not changeable via Configuration API, only through manual modification and rebuilding the agent.


The trap message contains the fields which are defined in trcfg.h:

#define TM_SNMP_TRAP_DEST_ADDR          "192.168.1.2"
#define TM_SNMP_TRAP_DEF_PORT           162
#define TM_SNMP_TRAP_COMMUNITY          "trap comm"

and trregstr.h:

#define TM_DEFAULT_ENTERPRISE_NUMBER    32925
#define TM_DEFAULT_ENTERPRISE_LENGTH    8


The user can add, delete, or modify the trap information by using tfAddTrapEntry(), tfDeleteTrapEntry() and tfModifyTrapEntry() defined in the next section. The only limitation is, if only one trap entry is left in the list, the user is not allowed to delete it.

The enterprise entries in trregstr.h are only relevant for SNMPv1 traps.


By default, the agent starts with one trap entry.

The SNMP MIB-II system group, implementation of which is mandatory for all agents, contains seven objects. The default values for all objects except sysUpTime are defined in trcfg.h:

const char tvSnmpSysDescription[] = "Treck SNMP Agent";
const oid tvSnmpSysObjid[] = { 1, 3, 6, 1, 4, 1, TM_DEFAULT_ENTERPRISE_NUMBER, 1 };
const ttPktLen tvSnmpSysObjidLen = sizeof (tvSnmpSysObjid) / sizeof (oid);
const char tvSnmpSysContact[] = "Treck HQ";
const char tvSnmpSysName[] = "Treck, Inc.";
const char tvSnmpSysLocation[] = "Cincinnati, OH, USA";
const tt16Bit tvSnmpSysServices = 72;


Three objects, sysContact, sysName and sysLocation contain access clauses of read-write, i.e. their instances can be changed via SNMP requests, hence the Configuration API functions for their modifications are not provided. The other three members, sysDescription, sysObjectID and sysServices, contain access clauses of read-only, and can not be modified through SNMP requests. The modification functions, tfModifySysDescr(), tfModifySysObjId() and tfModifySysServices() can be used to modify these objects instances, and are described in the next section.


SNMPv3 Initialization

Overview

The SNMPv3 framework consists of 11 tables defined in the USM (User-Based Security Model) MIB (RFC 2574), the VACM (View-Based Access Control Model) MIB (RFC 2575), the community MIB (RFC 2576), the target MIB (RFC 2573) and the notification MIB (RFC 2573).

  • usmUserTable
  • vacmContextTable
  • vacmSecurityToGroupTable
  • vacmAccessTable
  • vacmViewTreeFamilyTable
  • snmpCommunityTable
  • snmpTargetAddrTable
  • snmpTargetParamsTable
  • snmpNotifyTable
  • snmpNotifyFilterTable
  • snmpNotifyFilterProfileTable


Though most of the objects in these tables contain access clauses of read-create, and therefore their instances can be modified via SNMP SET requests, the Configuration API functions for creation (modification) and deletion of entries in these tables are provided for the user convenience. These functions can be called either before starting the agent or while the agent is running.


Upon starting, the agent checks the values of the pointers

  • snmpUsmUserEntryStart
  • snmpVacmContextEntryStart
  • snmpVacmSec2GroupEntryStart
  • snmpVacmAccessEntryStart
  • snmpVacmViewTreeFamilyEntryStart
  • snmpCommunityTableEntryStart
  • snmpTargetAddrTableEntryStart
  • snmpTargetParamsTableEntryStart
  • snmpNotifyTableEntryStart
  • snmpNotifyFilterProfileTableEntryStart
  • snmpNotifyFilterTableEntryStart

contained in snmpInitTables within ttSnmpd, defined in trregstr.h. If any of the pointers is non-zero, the agent concludes the corresponding table is already initialized and skips default initialization. Otherwise, the agent initializes the corresponding table entries to their default values, defined in trv3init.c. The entries defined in those tables must be ordered in lexicographic order the way they would be ordered when walking the MIB.


usmUserTable

The usmUserTable contains SNMPv3 USM Users as defined in RFC 2574.


Data Structure

typedef struct tsSnmpUsmInit
{
    char        suiName[32];
    int         suiNameLen;
    char        suiSecurityName[32];
    int         suiSecurityNameLen;
    oid         suiCloneFromOid[32];
    int         suiCloneFromLen;
    oid         suiAuthProtocol[32];
    int         suiAuthProtocolLen;
    char        suiAuthKeyChange[32];
    int         suiAuthKeyChangeLen;
    char        suiOwnAuthKeyChange[32];
    int         suiOwnAuthKeyChangeLen;
    oid         suiPrivProtocol[32];
    int         suiPrivProtocolLen;
    char        suiPrivKeyChange[32];
    int         suiPrivKeyChangeLen;
    char        suiOwnPrivKeyChange[32];
    int         suiOwnPrivKeyChangeLen;
    char        suiUuPublic[32];
    int         suiPublicLen;
    int         suiStorageType;
    ttS32Bit    suiStatus;
} ttSnmpUsmInit;


Initialization Table

This table must be sorted by suiNameLen and suiName.

const ttSnmpUsmInit tvSnmpUsmInit[] =
{
    {   "initial", 7, "initial", 7,
        {1,3,6,1,4,1,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
        , 8 * sizeof (oid),
        {TM_SNMP_USM_MD5AUTH_PROTOCOL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0}
        , TM_SNMP_USM_PROTOCOLS_LEN * sizeof (oid), "auth_key", 8, "", 0,
        {TM_SNMP_USM_DESPRIV_PROTOCOL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        0,0,0,0,0,0,0,0}
        , TM_SNMP_USM_PROTOCOLS_LEN * sizeof (oid),
        "priv_key", 8, "", 0, "private", 7,
        TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE
    },
    {   "initial1", 8, "initial1", 8,
        {1,3,6,1,4,1,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        8 * sizeof (oid),
        {TM_SNMP_USM_NOAUTH_PROTOCOL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0},
        TM_SNMP_USM_PROTOCOLS_LEN * sizeof (oid),
        "auth key", 8, "", 0,
        {TM_SNMP_USM_NOPRIV_PROTOCOL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0},
        TM_SNMP_USM_PROTOCOLS_LEN * sizeof (oid),
        "", 0, "", 0, "private", 7,
        TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE
    },
    {   "initial2", 8, "initial2", 8,
        {1,3,6,1,4,1,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        8 * sizeof (oid),
        {TM_SNMP_USM_MD5AUTH_PROTOCOL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0},
        TM_SNMP_USM_PROTOCOLS_LEN * sizeof (oid),
        "auth_key", 8, "", 0,
        {TM_SNMP_USM_NOPRIV_PROTOCOL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
         0,0,0,0,0,0,0,0},
        TM_SNMP_USM_PROTOCOLS_LEN * sizeof (oid),
        "", 0, "", 0, "private", 7,
        TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE
    },
/* This row must stay at the end */
    {   "", 0, "", 0, {0}, 0, {0}, 0, "", 0, "", 0, {0}, 0,
        "", 0, "", 0, "", 0, -1, 0
    }
};

This table defines three users:

  • User "initial" is a user configured with "authPriv" authentication level using MD5 for authentication and DES for privacy. Its authentication password is "auth_key", its privacy password is "priv_key".
  • User "initial1" is a user configured with "noAuthNoPriv" authentication level.
  • User "initial2" is a user configured with "authNoPriv" authentication level using MD5 for authentication. Its authentication password is "auth_key".


vacmContextTable

This table (RFC 2574) defines the SNMP contexts supported by the agent. A SNMPv3 request is always handled within a particular SNMP context (included in the packet header). A different set of users and groups can be defined for different SNMP contexts. Most applications will run the agent with only one context, the default "" (empty string).


Data Structure

typedef struct tsSnmpVacmContextInit
{
    char        svciName[32];
    int         svciNameLen;
} ttSnmpVacmContextInit;


Initialization Table

This table must be sorted by svciNameLen and svciName.

const ttSnmpVacmContextInit tvSnmpVacmContextInit[] =
{
    {"", 0},
    {"context_1", 9},
    {"context_2", 9},
    {"", -1}
};

This table defines three contexts:

  1. "" (the default context)
  2. "context_1"
  3. "context_2"


vacmSecurityToGroupTable

This table defined in RFC 2575 is used to map users of the usmUserTable with groups of the vacmAccessTable. Once the packet is correctly authenticated and eventually decrypted using the information contained in the usmUserTable, the user read/right permissions contained in the vacmAccessTable are located by consulting the vacmSecurityToGroupTable.


Data Structure

typedef struct tsSnmpVacmSec2GroupInit
{
    int         svsgModel;
    char        svsgName[32];
    int         svsgNameLen;
    char        svsgGroupName[32];
    int         svsgGroupNameLen;
    int         svsgStorageType;
    ttS32Bit    svsgStatus;
} ttSnmpVacmSec2GroupInit;


Initialization Table

This table must be sorted by svsgModel, svsgNameLen, and svciName.

const ttSnmpVacmSec2GroupInit tvSnmpVacmSec2GroupInit[] =
{
    {TM_SNMP_SECMODEL_V1, "publicuser", 10, "group_1", 7,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
    {TM_SNMP_SECMODEL_V1, "privateuser", 11, "group_2", 7,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
    {TM_SNMP_SECMODEL_V2C, "publicuser", 10, "group_1", 7,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
    {TM_SNMP_SECMODEL_V2C, "privateuser", 11, "group_2", 7,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
    {TM_SNMP_SECMODEL_USM, "initial", 7, "group_2", 7,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
    {TM_SNMP_SECMODEL_USM, "tom", 3, "group_2", 7,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
    {TM_SNMP_SECMODEL_USM, "initial1", 8, "group_1", 7,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
    {TM_SNMP_SECMODEL_USM, "initial2", 8, "group_2", 7,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
    {TM_SNMP_SECMODEL_USM, "publicuser", 10, "group_1", 7,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
    {TM_SNMP_SECMODEL_USM, "privateuser", 11, "group_2", 7,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
/* This row must stay at the end */
    {-1, "", 0, "", 0, -1, 0}
};

This table defines six users:

  • User "publicuser" is bound to group "group_1" for all security models (V1, V2c, and USM)
  • User "privateuser" is bound to group "group_2" for all security models (V1, V2c, and USM)
  • User "initial" is bound to group "group_2" for USM
  • User "tom" is bound to group "group_2" for USM
  • User "initial1" is bound to group "group_1" for USM
  • User "initial2" is bound to group "group_2" for USM


vacmAccessTable

This table contains VACM groups as defined in RFC 2575. A group consists of a set of access rights defined with mib-views.


Data Structure

typedef struct tsSnmpVacmAccessInit
{
    char        svaiGroupName[32];
    int         svaiGroupNameLen;
    char        svaiPrefix[32];
    int         svaiPrefixLen;
    int         svaiModel;
    int         svaiLevel;
    int         svaiMatch;
    char        svaiReadName[32];
    int         svaiReadNameLen;
    char        svaiWriteName[32];
    int         svaiWriteNameLen;
    char        svaiNotifyName[32];
    int         svaiNotifyNameLen;
    int         svaiStorageType;
    int         svaiStatus;
} ttSnmpVacmAccessInit;


Initialization Table

This table must be sorted by svaiPrefixLen, svaiPrefix, svaiModel, and svaiLevel.

const ttSnmpVacmAccessInit tvSnmpVacmAccessInit[] =
{
    {"group_1", 7, "", 0,
     TM_SNMP_SECMODEL_V1, TM_SNMP_SECLEVEL_NOAUTHNOPRIV, 1,
     "allmib", 6, "none", 4, "notify view", 11,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
    {"group_1", 7, "", 0,
     TM_SNMP_SECMODEL_V2C, TM_SNMP_SECLEVEL_NOAUTHNOPRIV, 1,
     "allmib", 6, "none", 4, "notify view", 11,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
    {"group_1", 7, "", 0,
     TM_SNMP_SECMODEL_USM, TM_SNMP_SECLEVEL_NOAUTHNOPRIV, 1,
     "allmib", 6, "none", 4, "notify view", 11,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
    {"group_2", 7, "", 0,
     TM_SNMP_SECMODEL_V1, TM_SNMP_SECLEVEL_NOAUTHNOPRIV, 1,
     "allmib", 6, "allmib", 6, "notify view", 11,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
    {"group_2", 7, "", 0,
     TM_SNMP_SECMODEL_V2C, TM_SNMP_SECLEVEL_NOAUTHNOPRIV, 1,
     "allmib", 6, "allmib", 6, "notify view", 11,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
    {"group_2", 7, "", 0,
     TM_SNMP_SECMODEL_USM, TM_SNMP_SECLEVEL_NOAUTHNOPRIV, 1,
     "allmib", 6, "allmib", 6, "notify view", 11,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
/* This row must stay at the end */
    {"", 0, "", 0, -1, 0, 0, "", 0, "", 0, "", 0, 0, 0}
};

This table defines two groups:

  • Users who belong to the group "group_1" can read (GET/GETNEXT) the objects of the MIBs defined in the mib-view "allmib" and can write (SET) the objects of the MIBs defined in the mib-view "none".
  • Users who belong to the group "group_2" can read (GET/GETNEXT) the objects of the MIBs defined in the mib-view "allmib" and can write (SET) the objects of the MIBs defined in the mib-view "allmib".


vacmViewTreeFamilyTable

This table (RFC 2575) contains mib-views. A mib-view is a set of MIB sub-trees, either included or excluded (svviType) from the MIB. A group, a user or a community are bound to several mib views (for read, write, etc...). An SNMP request is processed only if the object requested OID is included in the mib-view bound to the group.


Data Structure

typedef struct tsSnmpVacmVtfInit
{
    char        svviName[32];
    int         svviNameLen;
    oid         svviSubtree[32];
    int         svviSubtreeLen;
    tt8Bit      svviMask[2];
    char        svviPad[2];         /* pad to 32-bit address boundary */
    int         svviMaskLen;
    int         svviType;           /* included/excluded */
    int         svviStorageType;
    ttS32Bit    svviStatus;
} ttSnmpVacmVtfInit;


Initialization Table

This table must be sorted by svviNameLen and svviName.

const ttSnmpVacmVtfInit tvSnmpVacmVtfInit[] =
{
    {"mib2", 4,
     {1,3,6,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
     6 * sizeof (oid), {0xFC, 0x00}, {0x00}, 2,
     TM_SNMP_VACM_VIEW_INCLUDED,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
    {"none", 4,
     {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
     1 * sizeof (oid), {0x00, 0x00}, {0x00}, 2,
     TM_SNMP_VACM_VIEW_EXCLUDED,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
    {"allmib", 6,
     {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
     1 * sizeof (oid), {0x00, 0x00}, {0x00}, 2,
     TM_SNMP_VACM_VIEW_INCLUDED,
     TM_SNMP_STORAGETYPE_PERMANENT, TM_SNMP_ROWSTATUS_ACTIVE},
 
/* This row must stay at the end */
    {"", 0, {0}, 0, {0x00}, {0x00}, 0, 0, -1, 1}
};

This table defines three views:

  • "mib2" - A view containing all objects of the MIB2 group (1.3.6.1.2.1)
  • "none" - A view excluding all possible objects of the ISO group (1)
  • "allmib" - A view that contains all possible objects of the ISO group (1)


snmpCommunityTable

This table (RFC 2576) defines a way to use the View-based access control model (preliminary defined for SNMPv3) for SNMPv1 and SNMPv2c requests. It maps a v1 or v2 community to a SNMPv3 user. The same access rights that apply to the USM user apply to the community. The equivalent user need not exist in the usmUserTable but must be referenced in the vacmSecurityToGroupTable.


Data Structure

typedef struct tsSnmpCommunityTableInit
{
    char        commIndex[32];     /* community identifier                  */
    tt32Bit     commIndexLen;
    char        commName[32];      /* community name                        */
    tt32Bit     commNameLen;
    char        commSecName[32];   /* the user the community is mapped to.  */
    tt32Bit     commSecNameLen;
    int         commStorageType;
    int         commStatus;
} ttSnmpCommunityTableInit;


Initialization Table

This table must be sorted by commIndexLen and commIndex.

const ttSnmpCommunityTableInit tvSnmpCommunityTableInit[] =
{
    {"privatecom", 10, "private", 7, "privateuser", 11,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
    {"publiccom",   9, "public",  6, "publicuser",  10,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
/* This row must stay at the end */
    {"", 0, "", 0, "", 0, -1, 0}
};

This table defines two communities:

  • "privatecom" - This maps the community name "private" to the v3 user "privateuser".
  • "publiccom" - This maps the community name "public" to the v3 user "publicuser".

When a V1 or V2c packet arrives with the community name set to "private", the agent will search in the vacmSecurityToGroupTable for an entry corresponding to "privateuser" with security model set to V1 or V2c and will apply the access rights associated with the user and the group it belongs to (looking at the vacmAccessTable).


snmpNotifyTable

This table (RFC 2573) defines an SNMP notification (trap).


Data Structure

typedef struct ttSnmpNotifyTableInit
{
    char        snmpNotifyName[32];
    tt32Bit     snmpNotifyNameLen;
    char        snmpNotifyTag[32];
    tt32Bit     snmpNotifyTagLen;
    tt32Bit     snmpNotifyType;
    int         snmpNotifyStorageType;
    int         snmpNotifyStatus;
} ttSnmpNotifyTableInit;


Initialization Table

This table must be sorted by snmpNotifyName.

const ttSnmpNotifyTableInit tvSnmpNotifyTableInit[] =
{
    {"defaultnotification", 19, "defaultnotification", 19,
     TM_SNMP_NOTIFYTYPE_TRAP,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
/* This row must stay at the end */
    {"", 0, "", 0, 0, -1, 0}
};

This table defines a trap identified by "defaultnotification". The destination host and trap parameters will be defined in the snmpTargetAddrTable as the entry "defaultnotification".


snmpNotifyFilterTable

The notifyFilterTable (RFC 2573) contains a list of sub-trees used to filter outgoing notifications the same way mib-views are used to filter incoming SNMP requests.


Data Structure

typedef struct tsSnmpNotifyFilterTableInit
{
    char        snmpNotifyFilterProfileName[32];
    tt32Bit     snmpNotifyFilterProfileNameLen;
    oid         snmpNotifyFilterSubtree[32];
    tt32Bit     snmpNotifyFilterSubtreeLen;
    char        snmpNotifyFilterMask[32];
    tt32Bit     snmpNotifyFilterMaskLen;
    tt32Bit     snmpNotifyFilterType;
    int         snmpNotifyFilterStorageType;
    int         snmpNotifyFilterowStatus;
} ttSnmpNotifyFilterTableInit;


Initialization Table

This table must be sorted by snmpNotifyNameLen and snmpNotifyName.

const ttSnmpNotifyFilterTableInit tvSnmpNotifyFilterTableInit[] =
{
    {"public profile", 14,
     {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
     1 * sizeof(oid), {0x00, 0x00}, 2, TM_SNMP_VACM_VIEW_INCLUDED,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
/* This row must stay at the end */
    {"", 0, {0}, 0, "", 0, 0, -1, 0}
};

This table creates a profile named "public profile" which includes all possible objects of the ISO group (1).


snmpTargetAddrTable

This table (RFC 2473) contains a list of transport addresses to be used in the generation of the SNMP notification.


Data Structure

typedef struct tsSnmpTargetAddrTableInit
{
    char        snmpTargetAddrName[32];
    tt32Bit     snmpTargetAddrNameLen;
    tt32Bit     snmpTargetAddrTDomain;
    char        snmpTargetAddr[64];
    tt32Bit     snmpTargetAddrPort;
    tt32Bit     snmpTargetAddrTimeout;
    tt32Bit     snmpTargetRetryCount;
    char        snmpTargetTagList[32];
    tt32Bit     snmpTargetTagListLen;
    char        snmpTargetAddrParams[32];
    tt32Bit     snmpTargetAddrParamsLen;
    int         snmpTargetAddrStorageType;
    int         snmpTargetAddrRowStatus;
} ttSnmpTargetAddrTableInit;


Initialization Table

This table must be sorted by targetAddrName and targetAddrTDomain.

const ttSnmpTargetAddrTableInit tvSnmpTargetAddrTableInit[] =
{
    {"target1", 7, AF_INET, "172.16.0.99", 162, 0, 0,
     "defaultnotification", 19, "paramv1", 7,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
    {"target2", 7, AF_INET, "172.16.0.99", 162, 0, 0,
     "defaultnotification", 19, "paramv2", 7,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
    {"target3", 7, AF_INET, "172.16.0.99", 162, 0, 0,
     "defaultnotification", 19, "paramv3", 7,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
/* This row must stay at the end */
    {"", 0, 0, "", 0, 0, 0, "", 0, "", 0, -1, 0}
};

This table defines three targets. All three targets have an IPv4 address of 172.16.0.99 and a port of 162. The targets differ in that they each refer to a different row of the snmpTargetParamsTable ("paramv1", "paramv2", and "paramv3") which is used when generating a message to the target.


snmpNotifyFilterProfileTable

This table (RFC 2473) associates a notification filter profile with a particular set of target parameters.


Data Structure

typedef struct tsSnmpNotifyFilterProfileTableInit
{
    char        snmpNotifyTargetParamsName[32];
    tt32Bit     snmpNotifyTargetParamsNameLen;
    char        snmpNotifyFilterProfileName[32];
    tt32Bit     snmpNotifyFilterProfileNameLen;
    int         snmpNotifyFilterProfileStorType;
    int         snmpNotifyFilterProfileRowStatus;
} ttSnmpNotifyFilterProfileTableInit;


Initialization Table

const ttSnmpNotifyFilterProfileTableInit tvSnmpNotifyFilterProfileTableInit[] =
{
    {"paramv1", 7, "public profile", 14,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
    {"paramv2", 7, "public profile", 14,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
    {"paramv3", 7, "public profile", 14,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
/* This row must stay at the end */
    {"", 0, "", 0, -1, 0}
};

This table provides a mapping between the targetParamsName ("paramv1", "paramv2", "paramv3") and the profile "public profile" defined in the snmpNotifyFilterTable.


snmpTargetParamsTable

The notification targets are defined in the snmpTargetAddrTable (RFC 2473). The snmpTargetParamsTable provides additional information required to generate a notification and send it to a specific target.


Data Structure

typedef struct tsSnmpTargetParamsTableInit
{
    char        snmpTargetParamsName[32];
    tt32Bit     snmpTargetParamsNameLen;
    tt32Bit     snmpTargetParamsMPModel;
    tt32Bit     snmpTargetParamsSecurityModel;
    char        snmpTargetParamsSecurityName[32];
    tt32Bit     snmpTargetParamsSecurityNameLen;
    tt32Bit     snmpTargetParamsSecurityLevel;
    int         snmpTargetParamsStorageType;
    int         snmpTargetParamsRowStatus;
} ttSnmpTargetParamsTableInit;


Initialization Table

This table must be sorted by snmpTargetParamsName.

const ttSnmpTargetParamsTableInit tvSnmpTargetParamsTableInit[] =
{
    {"paramv1", 7,
     TM_SNMP_MPMODEL_V1, TM_SNMP_SECMODEL_V1,
     "public", 6, TM_SNMP_SECLEVEL_AUTHNOPRIV,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
    {"paramv2", 7,
     TM_SNMP_MPMODEL_V2C, TM_SNMP_SECMODEL_V1,
     "public", 6, TM_SNMP_SECLEVEL_AUTHNOPRIV,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
    {"paramv3", 7,
     TM_SNMP_MPMODEL_V3, TM_SNMP_SECMODEL_V1,
     "public", 6, TM_SNMP_SECLEVEL_AUTHNOPRIV,
     TM_SNMP_STORAGETYPE_NONVOLATILE, TM_SNMP_ROWSTATUS_ACTIVE},
/* This row must stay at the end */
    {"", 0, 0, 0, "", 0, 0, -1, 0}
};

This table specifies the parameters to use when sending notifications using the specified snmpTargetParamsName.

  • "paramv1" - Use SNMPv1 and the community name "public"
  • "paramv2" - Use SNMPv2c and the community name "public"
  • "paramv3" - Use SNMPv3 and the community name "public"
Warning Warning: Currently when the Treck SNMP Agent sends an SNMPv3 trap, it only uses the global SNMPv3 Trap Username as specified by either the compile-time macro TM_SNMPV3_DEFAULT_TRAP_USERNAME or by calling the tfSnmpV3SetTrapOptions()API.
Warning Warning: The global SNMPv3 Trap Username must exist in the USM user table or else the trap will not be sent. The only exception to this is if sending of unencrypted traps has been allowed via the tfSnmpV3SetTrapOptions() API.
Warning Warning: Currently the snmpTargetParamsSecurityLevel is ignored. We use the highest available model according to the entry in the USM user table. That is, if the authenticaiton and privacy methods are valid, then we use authPriv. If the privacy method is not valid, but the authentication method is, then we use authNoPriv. If neither methods are valid, then we use noAuthNoPriv.


MIB Compiler

The main purpose for any MIB compiler is to verify the syntax and validity of the MIB. MIBs are written in accordance with the ASN.1 rules (somewhat, it's rather a subset of ASN.1) and involve very strong typing, as is the case with all formal languages. A developer writing a new MIB would be well advised to run it through the parser and eliminate all improper constructs, before using or publishing it. All public MIBs undergo such testing before being published. Treck SNMP MIB compiler is based on libsmi (http://www.ibr.cs.tu-bs.de/projects/sming/). Libsmi is an industry standard distribution widely used and recognized. It was developed by SNMP and SMI experts. The core of the libsmi distribution is a library that allows management applications to access SMI MIB module definitions. On top of this library, there are tools to check, analyze, dump, convert, and compare MIB definitions. The Treck SNMP mib compiler has been integrated to one of these tools: smidump.


Location

The MIB Compiler tools is located in the /snmpd/mibcomp folder of the distribution as an archive named 'mibcomp_win32.zip'. Inside of the archive is a directory named bin which has the smidump.exe MIB Compiler executable.


Setup

The MIB Compiler requires an environment variable to be set in order to find and process dependent MIBs. The environment variable is SMIPATH and should be set to the smi/mibs/ietf folder also located in the archive.


Processing a Custom MIB

In order to process a custom MIB, the MIB must be placed in the smi/mibs/ietf folder. The MIB file must be named according to the MIB module name. The MIB module name is the name preceding the DEFINITIONS ::= BEGIN statement in the MIB definition.


Once the MIB is in the smi/mibs/ietf folder, you may process the MIB by running the smidump.exe command with the following syntax:

smidump.exe -f Treck [Treck-options] MIBNAME

or

smidump.exe -f TreckLegacy [Treck-options] MIBNAME

You can use TreckLegacy format instead of the Treck format if you wish to not include the table management code in the generated output. This is typically only useful for users who have processed custom MIBs with older versions of the Treck MIB Compiler that did not include the table management functionality.


More run-time options can be viewed via the help menu:

smidump.exe -h

or

smidump.exe --help


Function Reference


Table of Contents