An SNMP Library for .NET Framework Version 0.2


This document forms part of the documentationset for the accompanying software and describes the usable interfacesexposed by snmp.dll and mib.dll.

Snmp.dll is a C# class library for the .NETframework. It has been developed on the Windows platform and may beuseful on others also. In contains two namespaces, X690 and Snmp.

The X690 namespace contains an implementationof the Basic Encoding Rules (BER) of Abstract Syntax Notation 1 (ASN.1)as specified by international standards (ISO's code for this standardin X.690) and used within Snmp. Snmp is specified in an InternetStandard, and uses a logical Management Information Base (MIB).Implementation of at least the mib-2 (RFC1213) is mandatory for allcomputer systems connected to the Internet. For recent developments seeRFC2570. It is notable that more recent SNMP-related protocols (such asRFC2741) do not use BER.

Mib.dll is a C# class library that handles thetranslation of MIB object identifiers (OID) such as 1.3.6.1.2.1.1.4.0to readable names such as "system.sysContact.0". It also collects thehelp strings from the system mib files (on windows systems these are inthe system folder, usually c:\windows\system32.) It contains onenamespace, RFC1157. Later versions of this toolkit will extend theseaspects to allow for some validation of MIB values.

The distribution includes some simple applications that show these libraries in use.

Getting Started with Snmp.dll and Mib.dll

The simplest possible call on the Snmpprotocol is to GET a single MIB entry such as "system.sysContact.0"from an agent (host) such as "localhost" with community "public". Thetraditional snmputil.exe would do this using the command

snmputil get ict-main-s.msroot.student.paisley.ac.uk public system.sysContact.0

To do this programmatically, proceed as follows:

RFC1157.Mgmt mib = new RFC1157.Mgmt();
ManagerSession sess=new ManagerSession("localhost","public");
ManagerItem mi=new ManagerItem(sess,mib.OID("mgmt.mib-2.system.sysContact.0"));
Console.WriteLine(mi.Value.ToString());

This code is explained as follows.

1. You will need a an instance of Mgmt() to encode and decode IODs:

new RFC1157.Mgmt()

Store the returned value in a RFC1157.Mgmtvariable, mib, say. This constructor takes some time at present, as itreads all the mib definitions it finds in the system folder.

2. Create a ManagerSession to the chosen agent and community by

new ManagerSession("localhost","public")

Store the returned value in a ManagerSession variable, sess, say.

3. Translate the given OID into a uint[]:

uint[] oid = mib.OID("mgmt.mib-2.system.sysContact.0");

The prefix mgmt.mib-2 is added to provide auniform starting point for the numerous mibs you will find on yoursystem. A typical Windows-2000 system has 20 mibs defined. All of themibs begin "iso.dod.internet." followed by such things as "mgmt.mib-2".

4. Create a ManagerItem to obtain the result:

new ManagerItem(sess,oid)

Store the returned value in a ManagerItem variable, mi, say.

5. Now mi.Oid contains the actual OID returned(which can be converted to a string using mib.OID() again), andmi.Value the actual value object. You can call ToString on this valueto obtain a readable version.

You can also retrieve a SubTree by using the GET/.GETNEXT combination.

More advanced use of the classes

Snmp

As a first step, it is a good idea to Close aManagerSession that is no longer in use. This will happen automaticallyif the object becomes inaccessible (goes out of scope).

It is possible to request a number of managedobjects in a single PDU, by using the VarBind and Get methods ofManagerSession: sess.Get(VarBind(oid1),VarBind(oid2)�). The returnedvalue is a sequence of Variable Bindings, according to the SNMPstandard. That is, if we set

Universal[] results = sess.Get(�);

Then each of results[0], results[1]etc is a variable binding. If we set

Universal varbind = results[k];

Then varbind[0] contains the OID which can beextracted as (uint[])(varbind[0].Value) , and varbind[1] contains thevalue. This is again a Universal, whose Value property can be cast intowhatever form the OID's value uses.

If you want to construct a SetRequest, you canwrite code very similar to the Get method: just place the value(s) inthe vbinds, and use the SetRequestPDU instead of GetRequestPDU.

ASN.1

ASN.1 provides a way of defining objects in aplatform-independent way. It is less commonly used today for newprotocols, but many existing protocols are defined using ASN.1. If youwant to extend the BER libraries here to cover another protocol, themachinery is as follows. You should provide constructors to create BERdata for each of the objects in the protocol. Then you extend thedecoding machinery for BER to build structures containing BER data fromthe encoded data stream.

Universal can be used as a base class forbuilding other BER encodings (e.g. Application, Context-Specific, orPrivate) for ASN.1 applications. For example, suppose we were to buildApplication types for the Foo protocol.

First we need to sort out the types that the Foo protocol uses: something like

 

public enum FooType { something=0xA1, � // application specific, construct, .. }
public enum FooTag : BERTag
{
public FooTag(FooType t): base((byte)t) {}
public FooTag() {}
public FooTag(byte t): base(t) {}
public FooTag(Stream s): base(s) {}
public override string ToString() { return ((FooType)ToByte()).ToString(); }
}
We would declare
public class FooBER : Universal
{ // make creators for your types, placing the coding in byte array b.
public FooBER(something x) // for creating byte array b from your data
{ type = new FooTag(FooType.something); // set the right type coding
e = true;
b = .. // set the byte[] b to contain the encoded version
}

// now support the machinery to decode your objects from streams
protected override BERtag CreateTag(Stream s) { return new FooTag(s); }
protected override Universal Creator(Stream s) { return new FooBER(s); }
protected override Universal[] Creators(int n) { return new FooBER[n]; }
public FooBER(Stream s) : base(s) {}
protected virtual bool ValueOf(uint n)
{ // use Universal's type property to work out what to do
switch((FooType)(type.ToByte()))
{ // set up a suitable value in val from the binary data in b.
case FooType.something:
val = MakeASomethingFrom(b,n); break;

default: // maybe some Universal type
return base.ValueOf(n);
}
return true;
}
// finally provide a protected default constructor
protected FooBER() {}
}

Most Commented Articles :

Twitter Digg Delicious Stumbleupon Technorati Facebook Email

No comments yet... Be the first to leave a reply!