|
Comments
Did you read today's front page stories & breaking news?
SYS-CON.TV
|
SNMP .NET Interop with SNMP
.NET Interop with SNMP
By: James R. Thomas
Aug. 11, 2003 12:00 AM
In Part 1 of this series (DNDJ, Vol. 1, issue 5), I described the steps necessary to build a .NET interoperability library to communicate with the Windows SNMP stack. In this article I will build on that foundation by creating the necessary code to support an application capable of receiving and displaying SNMP traps, commonly called an SNMP trap handler. As in Part 1, I will just touch on the more interesting parts of the code and leave you to look at the code to get a complete picture. All of the code for both articles can be downloaded from www.sys-con.com/dotnet/sourcec.cfm.
What Is an SNMP Trap?
Why Are SNMP Traps Needed? For simplicity, the trap handler I create here will receive SNMP traps and display them on the console as text messages, but it would be relatively easy to add some logic to interpret the trap and send e-mail or pager alerts when specific conditions are detected.
WinSNMP and Traps
Community Strings SNMP agents also use community strings to identify trap contexts, so an application can look for traps with a specific community string. Okay, let's get down to business!
Establishing a WinSNMP Session
IntPtr SnmpCreate The key parameter here is the third, callback. This is defined as SnmpCallback, which is defined in our library as a delegate. WinSNMP will use this delegate to call back into our application each time it receives an SNMP trap. To enable this, we create a SnmpCallback delegate and pass it to this function. SnmpAPI.SnmpCallback SnmpCB = new SnmpAPI.SnmpCallback(OnSnmpMessage); OnSnmpMessage is the function that will be called with the trap information. It is defined with parameters identical to the declaration of the SnmpCallback delegate.
SNMPAPI_STATUS OnSnmpMessage(IntPtr session, We create the delegate by instantiating a new variable of type SnmpCallback and passing it a parameter reference to OnSnmpMessage. SnmpCallback SnmpCB = new SnmpAPI.SnmpCallback(OnSnmpMessage); Now we can pass the SnmpCB variable to SnmpCreateSession.
Registering to Receive Traps
SNMPAPI_STATUS SnmpRegister(IntPtr session, The parameters allow you to specify the source and destination address of the traps you want to receive, and also to filter them by content. As we will not be using these parameters, I will not go into great detail about them. We will set them all to zero, which tells WinSNMP to send us all traps from all sources.
Receiving the Traps The first step in decoding the trap information is to get it from WinSNMP. This is done by calling SnmpRecvMsg.
SNMPAPI_STATUS rc = SnmpAPI.SnmpRecvMsg(session, SnmpRecvMsg returns the trap information in four out parameters.
Decoding the Trap Information The source and destination entities (src and dest) are really just IP addresses. To convert them, we call SnmpEntityToStr.
SNMPAPI_STATUS rc = SnmpAPI.SnmpEntityToStr(dest, 1408, buffer); SnmpEntityToStr returns a string representation of the entity reference passed in. The returned string will be the IP address of the device sending the trap (src) and the IP address of the device the trap was sent to (dest). The buffer used in the above code is a work buffer. The creation of this buffer is explained later. Now we can move on to decoding the actual trap data. All SNMP data is transmitted in what is called a protocol data unit (PDU). You can think of a PDU as a container that holds the SNMP variables. In order to get at the variables in the trap, we need to extract them from the PDU using SnmpGetPduData function. SnmpGetPduData is declared as:
SnmpAPI.SnmpGetPduData(pdu,
This function will decode the PDU and return the individual data components
in the out parameters. Since we are dealing only with traps, we will ignore the id, status, and index parameters. The vbl parameter is the most important, as it contains all of the trap information sent by the SNMP device.
Displaying the Trap Information First, we must verify that the message we received is actually a trap. In our case this will always be so because we are working only with trap messages in this application. But in a more complicated SNMP application in which you would be sending and receiving SNMP messages as well as traps, you would need a way to tell the difference between a trap message and a message from a device sent in response to an SNMP GET command. The type parameter gives us this information, and we should check to see that it is set to the value SNMPAPI_PDU.SNMP_PDU_TRAP. This tells us it is a trap message. After we have determined that we have a trap message, we can start to display the trap information. First, we display a header message along with the trap id.
Console.WriteLine("Trap received..."); To display the SNMP variables in the vbl, we will need to do a bit more work.
Decoding the Variable Binding List Second, we need to iterate over each variable in the vbl, translate it, then write it to the console. To translate each variable, we need to call SnmpGetVb and pass it the vbl and the index of the variable we are interested in. It will return the name and value of the variable at that position.
SMIOID name = new SMIOID(); Note: The name and value parameters are passed as refs, so you need to initialize them first. The next step is to convert the variable name to a string. The variable name is an OID, so we convert it by calling SnmpOidToStr. SnmpOidToStr takes a reference to the OID and returns a string in the buffer specified by the buffer parameter. We must allocate this buffer ourselves but how big does it need to be? If we look at the WinSNMP documentation, we see that the largest an OID can be is 1408 bytes, so we allocate a buffer of this size. This might seem like an odd size, but it's not. SNMP uses UDP (User Datagram Protocol) for its transport protocol, and each SNMP message must fit into one UDP message. The standard MTU (Maximum Transmission Unit) on most networks is 1500 bytes, so, 1408 is what's left over when you subtract all the message headers needed to get one variable across the network. We allocate this buffer by calling the .NET marshaler. IntPtr buffer = Marshal.AllocHGlobal(1408); After we have the buffer, we can call SnmpOidToStr. SNMPAPI_STATUS rc = SnmpAPI.SnmpOidToStr(ref oid, 1408, buffer); This gives us a string in a global buffer allocated by the marshaler. But all we have is an opaque internal pointer to a buffer. We must convert it to a string type. For this, we call another .NET marshaler function, PtrToStringAnsi. string str = Marshal.PtrToStringAnsi(buffer); Now we have a string representation of the OID. Whew! All this work and we still haven't decoded the data. To convert the data to a displayable format, we need to first check the type of data that was sent in the variable. Each variable value in SNMP includes a type code to help determine the type of data the variable contains. We will use this type to determine how to convert the data to a string. Most of the conversions are straightforward, so I will refer you to the function in Listing 1 that performs the conversions. Most of the conversions are straightforward, but if you look at the string conversion for the SNMP type OCTET_STRING, you will see that in order to determine whether we have an ASCII string or a binary buffer we scan the buffer looking for binary characters. If all the characters are ASCII, we make it a string; If there are binary characters, we encode the buffer so it can be displayed. I chose to unencode it because it was quicker to call the ToBase64String function than to write a hex converter.
Running the Trap Handler Now you are ready to receive traps. An easy way to generate a couple of traps is to stop and start the SNMP service on the machine where the trap handler is running. Note that there are two SNMP services, one is called "SNMP Service", and the other is "SNMP Trap Service". You will want to stop "SNMP Service", then restart it. Once you've done this, you should see traps appear in the trap handler console, as shown in Figure 2.
Conclusion Reader Feedback: Page 1 of 1
SOA World Latest Stories
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||