Simple SNMP

image_pdfimage_print
   

/*
C# Network Programming 
by Richard Blum

Publisher: Sybex 
ISBN: 0782141765
*/
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;


public class SimpleSNMP
{
   public static void Main(string[] argv)
   {
      int commlength, miblength, datatype, datalength, datastart;
      int uptime = 0;
      string output;
      SNMP conn = new SNMP();
      byte[] response = new byte[1024];

      Console.WriteLine("Device SNMP information:");

      // Send sysName SNMP request
      response = conn.get("get", argv[0], argv[1], "1.3.6.1.2.1.1.5.0");
      if (response[0] == 0xff)
      {
         Console.WriteLine("No response from {0}", argv[0]);
         return;
      }

      // If response, get the community name and MIB lengths
      commlength = Convert.ToInt16(response[6]);
      miblength = Convert.ToInt16(response[23 + commlength]);

      // Extract the MIB data from the SNMP response
      datatype = Convert.ToInt16(response[24 + commlength + miblength]);
      datalength = Convert.ToInt16(response[25 + commlength + miblength]);
      datastart = 26 + commlength + miblength;
      output = Encoding.ASCII.GetString(response, datastart, datalength);
      Console.WriteLine("  sysName - Datatype: {0}, Value: {1}",
              datatype, output);

      // Send a sysLocation SNMP request
      response = conn.get("get", argv[0], argv[1], "1.3.6.1.2.1.1.6.0");
      if (response[0] == 0xff)
      {
         Console.WriteLine("No response from {0}", argv[0]);
         return;
      }

      // If response, get the community name and MIB lengths
      commlength = Convert.ToInt16(response[6]);
      miblength = Convert.ToInt16(response[23 + commlength]);

      // Extract the MIB data from the SNMP response
      datatype = Convert.ToInt16(response[24 + commlength + miblength]);
      datalength = Convert.ToInt16(response[25 + commlength + miblength]);
      datastart = 26 + commlength + miblength;
      output = Encoding.ASCII.GetString(response, datastart, datalength);
      Console.WriteLine("  sysLocation - Datatype: {0}, Value: {1}", datatype, output);

      // Send a sysContact SNMP request
      response = conn.get("get", argv[0], argv[1], "1.3.6.1.2.1.1.4.0");
      if (response[0] == 0xff)
      {
         Console.WriteLine("No response from {0}", argv[0]);
         return;
      }

      // Get the community and MIB lengths
      commlength = Convert.ToInt16(response[6]);
      miblength = Convert.ToInt16(response[23 + commlength]);

      // Extract the MIB data from the SNMP response
      datatype = Convert.ToInt16(response[24 + commlength + miblength]);
      datalength = Convert.ToInt16(response[25 + commlength + miblength]);
      datastart = 26 + commlength + miblength;
      output = Encoding.ASCII.GetString(response, datastart, datalength);
      Console.WriteLine("  sysContact - Datatype: {0}, Value: {1}",
              datatype, output);
      
      // Send a SysUptime SNMP request
      response = conn.get("get", argv[0], argv[1], "1.3.6.1.2.1.1.3.0");
      if (response[0] == 0xff)
      {
         Console.WriteLine("No response from {0}", argv[0]);
         return;
      }

      // Get the community and MIB lengths of the response
      commlength = Convert.ToInt16(response[6]);
      miblength = Convert.ToInt16(response[23 + commlength]);

      // Extract the MIB data from the SNMp response
      datatype = Convert.ToInt16(response[24 + commlength + miblength]);
      datalength = Convert.ToInt16(response[25 + commlength + miblength]);
      datastart = 26 + commlength + miblength;

      // The sysUptime value may by a multi-byte integer
      // Each byte read must be shifted to the higher byte order
      while(datalength > 0)
      {
         uptime = (uptime << 8) + response&#91;datastart++&#93;;
         datalength--;
      }
      Console.WriteLine("  sysUptime - Datatype: {0}, Value: {1}",
             datatype, uptime);

   }
}


class SNMP
{
   public SNMP()
   {

   }

   public byte&#91;&#93; get(string request, string host, string community, string mibstring)
   {
      byte&#91;&#93; packet = new byte&#91;1024&#93;;
      byte&#91;&#93; mib = new byte&#91;1024&#93;;
      int snmplen;
      int comlen = community.Length;
      string&#91;&#93; mibvals = mibstring.Split(&#039;.&#039;);
      int miblen = mibvals.Length;
      int cnt = 0, temp, i;
      int orgmiblen = miblen;
      int pos = 0;

      // Convert the string MIB into a byte array of integer values
      // Unfortunately, values over 128 require multiple bytes
      // which also increases the MIB length
      for (i = 0; i < orgmiblen; i++)
      {
         temp = Convert.ToInt16(mibvals&#91;i&#93;);
         if (temp > 127)
         {
            mib[cnt] = Convert.ToByte(128 + (temp / 128));
            mib[cnt + 1] = Convert.ToByte(temp - ((temp / 128) * 128));
            cnt += 2;
            miblen++;
         } else
         {
            mib[cnt] = Convert.ToByte(temp);
            cnt++;
         }
      }
      snmplen = 29 + comlen + miblen - 1;  //Length of entire SNMP packet

      //The SNMP sequence start
      packet[pos++] = 0x30; //Sequence start
      packet[pos++] = Convert.ToByte(snmplen - 2);  //sequence size

      //SNMP version
      packet[pos++] = 0x02; //Integer type
      packet[pos++] = 0x01; //length
      packet[pos++] = 0x00; //SNMP version 1

      //Community name
      packet[pos++] = 0x04; // String type
      packet[pos++] = Convert.ToByte(comlen); //length
      //Convert community name to byte array
      byte[] data = Encoding.ASCII.GetBytes(community);
      for (i = 0; i < data.Length; i++)
      {
         packet&#91;pos++&#93; = data&#91;i&#93;;
      }

      //Add GetRequest or GetNextRequest value
      if (request == "get")
         packet&#91;pos++&#93; = 0xA0;
      else
         packet&#91;pos++&#93; = 0xA1;

      packet&#91;pos++&#93; = Convert.ToByte(20 + miblen - 1); //Size of total MIB

      //Request ID
      packet&#91;pos++&#93; = 0x02; //Integer type
      packet&#91;pos++&#93; = 0x04; //length
      packet&#91;pos++&#93; = 0x00; //SNMP request ID
      packet&#91;pos++&#93; = 0x00;
      packet&#91;pos++&#93; = 0x00;
      packet&#91;pos++&#93; = 0x01;

      //Error status
      packet&#91;pos++&#93; = 0x02; //Integer type
      packet&#91;pos++&#93; = 0x01; //length
      packet&#91;pos++&#93; = 0x00; //SNMP error status

      //Error index
      packet&#91;pos++&#93; = 0x02; //Integer type
      packet&#91;pos++&#93; = 0x01; //length
      packet&#91;pos++&#93; = 0x00; //SNMP error index

      //Start of variable bindings
      packet&#91;pos++&#93; = 0x30; //Start of variable bindings sequence

      packet&#91;pos++&#93; = Convert.ToByte(6 + miblen - 1); // Size of variable binding

      packet&#91;pos++&#93; = 0x30; //Start of first variable bindings sequence
      packet&#91;pos++&#93; = Convert.ToByte(6 + miblen - 1 - 2); // size
      packet&#91;pos++&#93; = 0x06; //Object type
      packet&#91;pos++&#93; = Convert.ToByte(miblen - 1); //length

      //Start of MIB
      packet&#91;pos++&#93; = 0x2b;
      //Place MIB array in packet
      for(i = 2; i < miblen; i++)
         packet&#91;pos++&#93; = Convert.ToByte(mib&#91;i&#93;);
      packet&#91;pos++&#93; = 0x05; //Null object value
      packet&#91;pos++&#93; = 0x00; //Null

      //Send packet to destination
      Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
                       ProtocolType.Udp);
      sock.SetSocketOption(SocketOptionLevel.Socket,
                      SocketOptionName.ReceiveTimeout, 5000);
      IPHostEntry ihe = Dns.Resolve(host);
      IPEndPoint iep = new IPEndPoint(ihe.AddressList&#91;0&#93;, 161);
      EndPoint ep = (EndPoint)iep;
      sock.SendTo(packet, snmplen, SocketFlags.None, iep);

      //Receive response from packet
      try
      {
         int recv = sock.ReceiveFrom(packet, ref ep);
      } catch (SocketException)
      {
         packet&#91;0&#93; = 0xff;
      }
      return packet;
   }

   public string getnextMIB(byte&#91;&#93; mibin)
   {
      string output = "1.3";
      int commlength = mibin&#91;6&#93;;
      int mibstart = 6 + commlength + 17; //find the start of the mib section
      //The MIB length is the length defined in the SNMP packet
     // minus 1 to remove the ending .0, which is not used
      int miblength = mibin&#91;mibstart&#93; - 1;
      mibstart += 2; //skip over the length and 0x2b values
      int mibvalue;

      for(int i = mibstart; i < mibstart + miblength; i++)
      {
         mibvalue = Convert.ToInt16(mibin&#91;i&#93;);
         if (mibvalue > 128)
         {
            mibvalue = (mibvalue/128)*128 + Convert.ToInt16(mibin[i+1]);
            //ERROR here, it should be mibvalue = (mibvalue-128)*128 + Convert.ToInt16(mibin[i+1]);
            //for mib values greater than 128, the math is not adding up correctly   
            
            i++;
         }
         output += "." + mibvalue;
      }
      return output;
   }
}


           
          


This entry was posted in C# Network. Bookmark the permalink.