|
|
|||||||||||||||||||||||||
|
SNMP Tools GPW log2sql SNMP query (C#) Sniffer (C#) PING / Trace (C#) |
|
SNMP packet structure// Author: Toomas Kaljus
// http://www.digigrupp.com namespace DG { public enum SnmpType { Boolean = 0x01, Integer = 0x02, BitString = 0x03, OctetString = 0x04, Null = 0x05, ObjectIdentifier = 0x06, Sequence = 0x30, IPAddress = 0x40, Counter32 = 0x41, Gauge = 0x42, TimeTicks = 0x43, Opaque = 0x44, NetAddress = 0x45, Counter64 = 0x46, UInt32 = 0x47, GetRequestPDU = 0xa0, GetNextRequestPDU = 0xa1, GetResponsePDU = 0xa2, SetRequestPDU = 0xa3, TrapPDUv1 = 0xa4, GetBulkRequest = 0xa5, InformRequest = 0xa6, TrapPDUv2 = 0xa7 } public class SNMPPacket { public long Version; public string Community; public SnmpType PacketType; public long RequestID; public long Error; public long Index; public string ObjectID; public SnmpType ValueType; public object Value; public SNMPPacket() : base() { } // commonly used snmp type constants public SNMPPacket(ref byte[] Packet) : base() { try { int Pos = 0; GetSNMPSequence(ref Packet, ref Pos, (byte)SnmpType.Sequence); Version = GetSNMPInteger(ref Packet, ref Pos); Community = GetSNMPString(ref Packet, ref Pos); GetSNMPSequence(ref Packet, ref Pos, (byte)SnmpType.GetResponsePDU); RequestID = GetSNMPInteger(ref Packet, ref Pos); Error = GetSNMPInteger(ref Packet, ref Pos); Index = GetSNMPInteger(ref Packet, ref Pos); GetSNMPSequence(ref Packet, ref Pos, (byte)SnmpType.Sequence); GetSNMPSequence(ref Packet, ref Pos, (byte)SnmpType.Sequence); ObjectID = GetSNMPObjectID(ref Packet, ref Pos); ValueType = 0; Value = null; if (Error == 0) { // extract first data component (usually there only is one) ValueType = (SnmpType)Packet[Pos]; switch (ValueType) { case SnmpType.Boolean: Value = GetSNMPInteger(ref Packet, ref Pos, (byte)ValueType); break; case SnmpType.Integer: Value = GetSNMPInteger(ref Packet, ref Pos); break; case SnmpType.OctetString: Value = GetSNMPString(ref Packet, ref Pos); break; case SnmpType.Null: Value = GetSNMPNull(ref Packet, ref Pos); break; case SnmpType.ObjectIdentifier: Value = GetSNMPObjectID(ref Packet, ref Pos); break; case SnmpType.IPAddress: Value = GetSNMPIPAddress(ref Packet, ref Pos); break; case SnmpType.Counter32: Value = GetSNMPInteger(ref Packet, ref Pos, (byte)ValueType); break; case SnmpType.Gauge: Value = GetSNMPInteger(ref Packet, ref Pos, (byte)ValueType); break; case SnmpType.TimeTicks: Value = new System.TimeSpan((long)GetSNMPInteger(ref Packet, ref Pos, (byte)ValueType) * 100000); break; case SnmpType.Opaque: Value = GetSNMPInteger(ref Packet, ref Pos, (byte)ValueType); break; case SnmpType.NetAddress: Value = GetSNMPInteger(ref Packet, ref Pos, (byte)ValueType); break; case SnmpType.Counter64: Value = GetSNMPInteger(ref Packet, ref Pos, (byte)ValueType); break; case SnmpType.UInt32: Value = GetSNMPInteger(ref Packet, ref Pos, (byte)ValueType); break; default: Value = GetSNMPBinary(ref Packet, ref Pos); break; } //GetSNMPNull(ref Packet, ref Pos); } } catch { } } public byte[] GetBytes() { if (RequestID == 0) RequestID = 1; // create components for request Packet byte[] _Version = SNMPInteger(Version); byte[] _Community = SNMPString(Community); byte[] _RequestID = SNMPInteger(RequestID); byte[] _Error = SNMPInteger(Error); byte[] _Index = SNMPInteger(Index); byte[] _ObjectID = SNMPObjectID(ObjectID); byte[] _EndMarker = SNMPNull(); byte[] Packet = new byte[8 + _Version.Length + _Community.Length + _RequestID.Length + _Error.Length + _Index.Length + _ObjectID.Length + _EndMarker.Length]; byte[] _ASN1Header = SNMPSequence(0x30, Packet.Length - 2); int RequestLength = 6 + _RequestID.Length + _Error.Length + _Index.Length + _ObjectID.Length; byte[] _RequestHeader = SNMPSequence((int)PacketType, RequestLength); int VarBindListLength = 4 + _ObjectID.Length; byte[] _VarBindList = SNMPSequence(0x30, VarBindListLength); int VarBindLength = 2 + _ObjectID.Length; byte[] _VarBind = SNMPSequence(0x30, VarBindLength); // combine components to request Packet int Pos = 0; System.Buffer.BlockCopy(_ASN1Header, 0, Packet, Pos, _ASN1Header.Length); Pos += _ASN1Header.Length; System.Buffer.BlockCopy(_Version, 0, Packet, Pos, _Version.Length); Pos += _Version.Length; System.Buffer.BlockCopy(_Community, 0, Packet, Pos, _Community.Length); Pos += _Community.Length; System.Buffer.BlockCopy(_RequestHeader, 0, Packet, Pos, _RequestHeader.Length); Pos += _RequestHeader.Length; System.Buffer.BlockCopy(_RequestID, 0, Packet, Pos, _RequestID.Length); Pos += _RequestID.Length; System.Buffer.BlockCopy(_Error, 0, Packet, Pos, _Error.Length); Pos += _Error.Length; System.Buffer.BlockCopy(_Index, 0, Packet, Pos, _Index.Length); Pos += _Index.Length; System.Buffer.BlockCopy(_VarBindList, 0, Packet, Pos, _VarBindList.Length); Pos += _VarBindList.Length; System.Buffer.BlockCopy(_VarBind, 0, Packet, Pos, _VarBind.Length); Pos += _VarBind.Length; System.Buffer.BlockCopy(_ObjectID, 0, Packet, Pos, _ObjectID.Length); Pos += _ObjectID.Length; System.Buffer.BlockCopy(_EndMarker, 0, Packet, Pos, _EndMarker.Length); Pos += _EndMarker.Length; return Packet; } // add variable length in front of byte list private void AddSNMPLength(ref System.Collections.ArrayList B, int Len) { int Pos = 0; B.Insert(Pos++, (byte)(Len & 0xFF)); Len >>= 8; while (Len != 0) { B.Insert(Pos++, (byte)(Len & 0xFF)); Len >>= 8; } if (Pos > 1) B.Insert(0, (byte)(B.Count | 0x80)); } // create snmp integer private byte[] SNMPInteger(long Val) { System.Collections.ArrayList B = new System.Collections.ArrayList(); do { B.Insert(0, (byte)(Val & 0xFF)); Val >>= 8; } while (Val != 0); AddSNMPLength(ref B, B.Count); byte[] Result = new byte[1 + B.Count]; int Pos = 0; Result[Pos++] = (byte)SnmpType.Integer; for (int i=0; i<B.Count; i++) Result[Pos++] = (byte)B[i]; return Result; } // create snmp octet string private byte[] SNMPString(string Val) { System.Collections.ArrayList B = new System.Collections.ArrayList(); AddSNMPLength(ref B, Val.Length); byte[] Result = new byte[1 + B.Count + Val.Length]; int Pos = 0; Result[Pos++] = (byte)SnmpType.OctetString; for (int i=0; i<B.Count; i++) Result[Pos++] = (byte)B[i]; System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Val), 0, Result, Pos, Val.Length); return Result; } // create snmp null private byte[] SNMPNull() { byte[] Result = new byte[2]; Result[0] = (byte)SnmpType.Null; Result[1] = 0x00; // length is zero return Result; } // create snmp OID private byte[] SNMPObjectID(string Val) { if (Val.StartsWith("1.3")) Val = "43" + Val.Substring(3); System.Collections.ArrayList B = new System.Collections.ArrayList(); string[] A = Val.Split('.'); int Len = 0; for (int i=0; i<A.Length; i++) { int V = System.Convert.ToInt32(A[i]); B.Insert(Len, (byte)(V & 0x7F)); V >>= 7; while(V != 0) { B.Insert(Len, (byte)(V & 0x7F | 0x80)); V >>= 7; } Len = B.Count; } AddSNMPLength(ref B, B.Count); byte[] Result = new byte[1 + B.Count]; int Pos = 0; Result[Pos++] = (byte)SnmpType.ObjectIdentifier; for (int i=0; i<B.Count; i++) Result[Pos++] = (byte)B[i]; return Result; } // create snmp sequence header private byte[] SNMPSequence(long Tag, int Len) { System.Collections.ArrayList B = new System.Collections.ArrayList(); AddSNMPLength(ref B, Len); byte[] Result = new byte[1 + B.Count]; int Pos = 0; Result[Pos++] = (byte)Tag; for (int i=0; i<B.Count; i++) Result[Pos++] = (byte)B[i]; return Result; } // get snmp variable length private int GetSNMPLength(ref byte[] Packet, ref int Pos) { int Len = Packet[Pos++]; if (Len > 128) { int L = Len & 0x7F; Len = 0; for (int i=0; i<L; i++) Len = (Len << 8) + Packet[Pos++]; } return Len; } // get snmp integer private long GetSNMPInteger(ref byte[] Packet, ref int Pos) { if (Packet[Pos++] != (byte)SnmpType.Integer) throw new System.Exception("ASN.1 Integer expected."); int Len = GetSNMPLength(ref Packet, ref Pos); long Val = 0; for (int i=0; i<Len; i++) Val = (Val << 8) + Packet[Pos++]; return Val; } // get snmp variable as integer (used for booleans, integers of all sizes, counters, etc.) private long GetSNMPInteger(ref byte[] Packet, ref int Pos, int Tag) { if (Packet[Pos++] != Tag) throw new System.Exception("ASN.1 Integer " + System.String.Format("0x{0:x}", Tag) + " expected."); int Len = GetSNMPLength(ref Packet, ref Pos); long Val = 0; for (int i=0; i<Len; i++) Val = (Val << 8) + Packet[Pos++]; return Val; } // get snmp octet string (detect dates and numeric mac addresses) private string GetSNMPString(ref byte[] Packet, ref int Pos) { if (Packet[Pos++] != (byte)SnmpType.OctetString) throw new System.Exception("ASN.1 String expected."); int Len = GetSNMPLength(ref Packet, ref Pos); // detect date/time try { int y = (Packet[Pos] * 256) + Packet[Pos + 1]; int m = Packet[Pos + 2]; int d = Packet[Pos + 3]; if ((y < 2020) && (y > 1990) && (m < 13) && (d < 32)) { int h = Packet[Pos + 4]; int n = Packet[Pos + 5]; int s = Packet[Pos + 6]; int t = Packet[Pos + 7]; string DateResult = y + "-" + ((m < 10) ? "0" : "") + m + "-" + ((d < 10) ? "0" : "") + d + " " + ((h < 10) ? "0" : "") + h + ":" + ((n < 10) ? "0" : "") + n + ":" + ((s < 10) ? "0" : "") + s + "." + t; Pos += Len; return DateResult; } } catch { } // detect numbers string Result = ""; if (Len <= 8) for (int l=Pos; l<Pos+Len-1; l++) if (Packet[l] < 32) { Result = System.BitConverter.ToString(Packet, Pos, Len); break; } if (Result == "") Result = System.Text.Encoding.ASCII.GetString(Packet, Pos, Len); Pos += Len; return Result; } // get snmp null private string GetSNMPNull(ref byte[] Packet, ref int Pos) { if (Packet[Pos++] != (byte)SnmpType.Null) throw new System.Exception("ASN.1 Null expected."); Pos++; return ""; } // get snmp OID private string GetSNMPObjectID(ref byte[] Packet, ref int Pos) { if (Packet[Pos++] != (byte)SnmpType.ObjectIdentifier) throw new System.Exception("ASN.1 ObjectID expected."); int Len = GetSNMPLength(ref Packet, ref Pos); string Result = ""; for (int i = Pos; i < Pos + Len; i++) { int Val = 0; int V; do { V = Packet[i]; Val = (Val << 7) + (V & 0x7F); if (V > 127) i++; else break; } while(true); if (Result != "") Result += "."; Result += Val; } if (Result.StartsWith("43")) Result = "1.3" + Result.Substring(2); Pos += Len; return Result; } // get snmp sequence length (used for Sequence, GetResponsePDU, etc) private int GetSNMPSequence(ref byte[] Packet, ref int Pos, int Tag) { if (Packet[Pos++] != (byte)Tag) throw new System.Exception("ASN.1 " + System.String.Format("0x{0:x}", Tag) + " expected."); return GetSNMPLength(ref Packet, ref Pos); } // get snmp ipaddress private string GetSNMPIPAddress(ref byte[] Packet, ref int Pos) { if (Packet[Pos++] != (byte)SnmpType.IPAddress) throw new System.Exception("ASN.1 IPAddress expected."); int Len = GetSNMPLength(ref Packet, ref Pos); string Result = ""; for (int i=0; i<Len; i++) { if (Result != "") Result += "."; Result += Packet[Pos++]; } return Result; } // get binary snmp data (used for unknown data types) private string GetSNMPBinary(ref byte[] Packet, ref int Pos) { Pos++; int Len = GetSNMPLength(ref Packet, ref Pos); string Result = System.BitConverter.ToString(Packet, Pos, Len); Pos += Len; return Result; } } } |
|||||||||||||||||||||||
Copyright © 2003-2007 Digi Grupp OÜ
|
|||||||||||||||||||||||||