Version: 4.9.4.0
Create custom SNMP Manager, Trap and Agent applications for monitoring and controlling network devices. 

Programming Primer

This primer describes many useful things you need to know about implementing SNMP managers and agents. Written for PowerSNMP for .NET 4.7. Note the definitions available below.

PowerSNMP is organized into 3 sub-systems

  1. Agent and Manager .NET components derive from SnmpBase for shared functionality. Integrates socket communications with thread management.
  2. SNMP message classes (GetMessage, GetBulkMessage, GetNextMessage, SetMessage, InformMessage, ReportMessage, Trap1Message, Trap2Message) derive from MessageBase. The Security class implements timeliness, authentication and encryption/decryption user-based security. By exposing properties and lists that correspond to PDU fields, the object model is familiar to knowlegable SNMP programmers and teaches SNMP terminology to the novice.
  3. MIB classes
    - Manager and Agent components can import MIB files at design-time. Source code is added to your project.
    - The MibNodes class can import MIB files at run-time to create dynamic MibNode definitions.
    - MibNode.Oid property associates a MIB definition with the IIDs found in PDUs.

SNMP Version 3 Supports User-Based Security

  • Authentication and privacy password keys are used to hash and encrypt/decrypt PDUs. They are used by agent and manager and are not sent over the wire.
  • Security class contains the configuration items needed for encoding.
  • AuthoritativeEngine.Users dictionary uses a username key to lookup passwords needed for decoding.
  • RequestMessage provides automatic discovery of the remote authoritative engine configuration.

Manager and Agent are the Core Components

  1. Manager
    - Send a request and receive the response. In code, create a new GetMessage, GetBulkMessage, GetNextMessage, SetMessage or InformMessage and initialize properties. GetResponse() encodes and sends the request, receives the response, decodes it and returns a ResponseMessage. GetResponseTaskAsync() does the same using more scalable, awaitable, asynchronous I/O.
    - Receive inform requests (from agents and managers) and traps (from agents).
  2. Agent
    - Receive requests from managers. A default ResponseMessage can be easily created. Send() encodes and sends the ResponseMessage.
    - Send traps to managers. In code, create a new Trap1Message or Trap2Message and initialize properties. Send() encodes and sends the trap.
    - Send an inform request to a manager and receive the response. In code, create a new InformMessage and initialize properties. GetResponse() encodes and sends the request, receives the response from the manager, decodes it and returns a ResponseMessage. GetResponseTaskAsync() does the same using more scalable, awaitable, asynchronous I/O.

Thread Management

Worker threads and/or asynchronous communications is necessary to develop robust applications.

  1. Manager
    - Send a request and receive the response. Start(ThreadStart) starts a worker thread where GetResponse() encodes and sends the request, receives the response, decodes it and returns a ResponseMessage. The Manager can send multiple requests in parallel (one thread per request), in serial (one thread for all requests performed sequentially), or any combination thereof. Alternatively, GetResponseTaskAsync() does the same using more scalable, awaitable, asynchronous I/O.
    - Receive inform requests (from agents and managers) and traps (from agents). Start(ManagerMessageReceived) starts receiving packets asynchronously. For inform requests, Send() is used to encode and send a ResponseMessage.
  2. Agent
    - Receive requests from managers. Start(AgentMessageReceived) starts receiving packets asynchronously. Send() is used to encode and send a ResponseMessage.
    - Send traps to managers. Send() can be used on any thread (inluding the UI thread) because encoding and sending a trap is immediate and no response need be received.
    - Send an inform request to a manager and receive the response. Start(ThreadStart) starts a worker thread where GetResponse() encodes and sends the request, receives the response, decodes it and returns a ResponseMessage.

Developing a Manager

  • Basic Manager (SNMPv1 or SNMPv2 without security)
    - Write a method that will send/receive your request(s). Try using code from the Manager sample application. Multiple requests can be accomplished in parallel or serially.
    - Start(ThreadStart) to execute your method on a worker thread. Alternatively, use the awaitable GetResponseTaskAsync() method to make the request without dedicating a thread.
  • Advanced Manager adds MIB, trap, inform support
    - MIB files can be loaded at design-time or run-time. They are used to build MibNode instances (that provide properties like Name, Description, Oid, Access, Usage, ValueType, etc.) to enhance business logic.
    - Write a method that will handle incoming trap and inform messages. Try using code from the Manager sample application.
    - Use Start(ManagerMessageReceived) to listen for traps and inform messages. Use Close() to stop listening.
  • Secure Manager uses SNMPv3 security
    - Set Security properties (username, passwords, etc.) and send requests per step 1 above. The Manager.Security.EngineCache cache optimizes performance.
    - To authenticate and decrypt SNMPv3 traps, add username/passwords to Manager.Security.TrapUsers.
    - To authenticate and decrypt SNMPv3 inform requests, add username/passwords to Manager.AuthoritativeEngine.Users.
    - Received PDUs are decoded using the username in the PDU to lookup the associated passwords in the AuthoritativeEngine.Users dictionary.

Developing an Agent

  • Basic Agent (SNMPv1 or SNMPv2 without security)
    - Write a method to handle manager requests. Try using code from the Agent sample application.
    - Populate Agent.Variables with MIB values. Use CreateDefaultResponse() to build the ResponseMessage. Use Send(ResponseMessage) to encode and send the response.
    - Use Start(AgentMessageReceived...) to listen for requests. Use Close() to stop listening.
  • Advanced Agent adds MIB and trap support
    - MIB files can be loaded at design-time or run-time. They are used to build MibNode instances (that provide properties like Name, Description, Oid, Access, Usage, ValueType, etc.) to enhance business logic.
    - Send traps using Send(Trap1Message) or Send(Trap2Message).
  • Secure Agent uses SNMPv3 security
    - Set Agent.AuthoritativeEngine.Id to desired EngineId if default is not suitable.
    - Add username/passwords to AuthoritativeEngine.Users dictionary.
    - Configure authorized SNMP managers with username/passwords.
    - Received PDUs will be decoded using the username in the PDU.
  • Special use can involve sending an inform request to a manager.
    - Write a method that will send the inform request. Try using code from the Agent sample.
    - Use Start(ThreadStart) to execute your method on a worker thread.

Definitions

Names marked with an asterisk are also PowerSNMP class names. Lowercase is used to indicate generic use (not a class name).

  • Agent*. Provides MIB access for all SNMP managers.
  • Agent Discovery. Refers to the dynamic discovery of SNMP agents on the network. A manager can broadcast a GetMessage to all computers on the network, but this is becoming less useful as agents that support SNMPv3 decline to respond to broadcast messages. Polling a series of addresses is another alternative, but most manager applications will probably want to persist a list of agents between session.
  • AuthoritativeEngine*. Stores EngineID, EngineTime, EngineBoots and username/passwords used for decoding. The authoritative engine is the "owner" of the SNMPv3 security protocol configuration.
  • Discovery. Technique used to discover the EngineId, EngineTime and EngineBoots of a remote Authoritative Engine. Transparent to the programmer, negotiating packets can be accessed using the Agent.Log and Manager.Log events.
  • GetBulkMessage*. Queries an agent for bulk IID values. ResponseMessage represents the response returned by the Agent.
  • GetMessage*. Queries an agent for specified IID values. ResponseMessage represents the response returned by the Agent.
  • GetNextMessage*. Queries an agent for IID values that immediately follow the IDs provided. ResponseMessage represents the response returned by the Agent.
  • ID. General identifier. OIDs and IIDs are IDs.
  • IID. Instance identifier that references the value of an OID instance. "1.3.6.1.6.3.15.1.1.3.0" is an IID. For static OIDs a ".0" is appended to create the IID. For table OIDs a row indexer is appended to create the IID (the row indexer is a unique value for each row in the table).
  • InformMessage*. Informs a manager of IID values. ResponseMessage represents the response returned by the Manager.
  • Manager*. Manages MIB data via agents. Can receive inform and trap notifications.
  • MIB. Management Information Base (data that is read and managed by managers via an agent).
  • MIB file. A structured document that defines OIDs. Often parsed by managers to provide contextual information to the user.
  • MIB tree. The MIB is often described as a tree graph consisting of OID nodes. An OID with no sub-node is a leaf and has one or more IIDs that reference its data. A static leaf is referenced by appending ".0" to the OID (there is only one value for this kind of leaf). The other kind of leaf is a table row instance, where a table column is designated as the indexer and that value is appended instead of "0".
  • OID. Object identifier. An OID as a class definition. "1.3.6.1.6.3.15.1.1.3" is an OID. Each digit, separated by periods, defines a node in the MIB tree.
  • Protocol Data Unit (PDU). The encoded bytes that represent an SNMP request, response, inform, report or trap.
  • RemoteEngines*. A dictionary of AuthoritativeEngine objects, using an IPEndPoint key, that caches security data and stores username/passwords needed for decoding.
  • ReportMessage*. Reports information to a manager (a special kind of ResponseMessage). Used during SNMPv3 discovery.
  • RequestMessage*. Base class for GetMessage, SetMessage, GetBulkMessage, GetNextMessage and InformMessage. These messages require a response.
  • ResponseMessage*. Class used to return variable values requested.
  • SetMessage*. Asks an agent to set IID values. ResponseMessage represents the response returned by the Agent that confirms the values were set.
  • Threading. A new worker thread is typically used when a request/response pair are sent/received. Socket.ReceiveFrom() efficiently sleeps until a ResponseMessage is received. This technique protects other application threads from processing delays associated with timeouts, and is recommended.
  • Trap1Message*. Notifies a manager of SNMPv1 errors (can include variables). No response required.
  • Trap2Message*. Notifies a manager of SNMPv2/3 errors (can include variables). No response required.
  • User Based Security. SNMPv3 supports this security model. EngineID and elapsed time are used to ensure timeliness (so packets cannot be replayed later). Optional authentication can be specified (a one-way hash ensures the packet has not been tampered with). Optional encryption can be specified (a shared key cypher encrypts the PDU).
  • Variable*. An IID/value pair. PDUs contain variables.

Summary

This primer relies on terminology and software constructs that some might consider advanced. Please start by compiling and running our Manager and Agent applications. Look these over and see how multi-threading is used to implement complex operations using very little code.