// /** // * File: EncodingRules.cs // * Author: haraldwolff // * // * This file and it's content is copyrighted by the Author and / or copyright holder. // * Any use wihtout proper permission is illegal and may lead to legal actions. // * // * // **/ using System; using System.IO; using System.Net; using System.Collections.Generic; namespace ln.snmp { public enum IdentifierClass : int { UNIVERSAL = 0, APPLICATION = 1, CONTEXT = 2, PRIVATE = 3 } public struct Identifier { public IdentifierClass IdentifierClass; public bool Constructed; public ulong Number; public Identifier(IdentifierClass identifierClass, bool constructed, ulong number) { IdentifierClass = identifierClass; Constructed = constructed; Number = number; } public bool Is(IdentifierClass identifierClass, bool constructed, ulong number) { return ((IdentifierClass == identifierClass) && (Constructed == constructed) && (Number == number)); } public byte Firstbyte { get { return (byte)( ((int)IdentifierClass << 6) | (Constructed ? 0x20 : 0x00) | (int)((Number < 31) ? Number : 0x1F) ); } } public override string ToString() { return String.Format("[ASN.1 Type Class={0} Constructed={1} Number={2} FirstByte=0x{3,2:X}]",IdentifierClass,Constructed,Number,Firstbyte); } } public static class BasicEncodingRules { public static Identifier ReadIdentifier(Stream stream) { Identifier identifier = new Identifier(); int b = stream.ReadByte(); identifier.IdentifierClass = (IdentifierClass)((b >> 6) & 0x03); identifier.Constructed = (b & 0x20) != 0; identifier.Number = (ulong)(b & 0x1F); if (identifier.Number == 0x1F) { identifier.Number = 0; do { b = stream.ReadByte(); if (b == -1) throw new EndOfStreamException(); identifier.Number <<= 7; identifier.Number |= ((uint)(b & 0x7F)); } while ((b & 0x80) == 0x80); } return identifier; } public static void WriteIdentifier(Stream stream,Identifier identifier) { if (identifier.Number < 31) { byte bid = (byte)( ((int)identifier.IdentifierClass << 6) | ( identifier.Constructed ? 0x20 : 0x00) | (int)identifier.Number ); stream.WriteByte(bid); } else { byte bid = (byte)( ((int)identifier.IdentifierClass << 6) | (identifier.Constructed ? 0x20 : 0x00) | (int)0x1F ); stream.WriteByte(bid); byte[] n = EncodeInteger((long)identifier.Number); stream.Write(n, 0, n.Length); } } public static int ReadLength(Stream stream) { int b = stream.ReadByte(); if ((b & 0x80) == 0) { return b; } b &= 0x7F; int length = 0; for (int n=0;n 0 && bytes[n] == 0; n--) { } n++; byte[] finalbytes = new byte[n]; Array.Copy(bytes, finalbytes, n); byte bl = (byte)(0x80 | finalbytes.Length); stream.WriteByte(bl); stream.Write(finalbytes, 0, finalbytes.Length); } } public static byte[] EncodeInteger(long i) { byte[] bits = BitConverter.GetBytes(i); int n = bits.Length; while ( (n > 1) && ( ((bits[n-1] == 0xFF) && ((bits[n - 2] & 0x80) == 0x80)) || ((bits[n-1] == 0x00) && ((bits[n - 2] & 0x80) == 0x00)) ) ) { n--; } if (n == 8) { Array.Reverse(bits); return bits; } else { byte[] encodedbits = new byte[n]; Array.Copy(bits, encodedbits, n); Array.Reverse(encodedbits); return encodedbits; } } public static long DecodeInteger(byte[] bits) { byte[] decodedbits = bits; if (bits.Length < 8) { decodedbits = new byte[8]; Array.Copy(bits, decodedbits, bits.Length); byte fill = (byte)(((bits[bits.Length - 1] & 0x80) == 0x80) ? 0xFF : 0x00); for (int n=bits.Length;n<8;n++) { decodedbits[n] = fill; } } return BitConverter.ToInt64(decodedbits,0); } public static int[] DecodeOID(byte[] bytes) { List oid = new List(); MemoryStream memoryStream = new MemoryStream(bytes); int b = memoryStream.ReadByte(); int e = 0; oid.Add(b / 40); oid.Add(b % 40); while (memoryStream.Position < memoryStream.Length) { e = 0; do { b = memoryStream.ReadByte(); e <<= 7; e |= (ushort)(b & 0x7F); if ((b & 0x80) == 0x00) { oid.Add(e); e = 0; } } while ((b & 0x80) == 0x80); } return oid.ToArray(); } public static byte[] EncodeOID(int[] oid) { MemoryStream memoryStream = new MemoryStream(); byte pseudo = (byte)( (oid[0] * 40) + oid[1] ); memoryStream.WriteByte(pseudo); for (int n = 2; n < oid.Length; n++) { int e = oid[n]; if (e < 128) { memoryStream.WriteByte((byte)e); } else { List bytes = new List(); bytes.Add((byte)(e & 0x7f)); while (e > 127) { e >>= 7; bytes.Add((byte)(0x80 | (e & 0x7f))); } bytes.Reverse(); memoryStream.Write(bytes.ToArray(), 0, bytes.Count); } } return memoryStream.ToArray(); } } }