ln.snmp/BasicEncodingRules.cs

267 lines
7.5 KiB
C#

// /**
// * 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<b;n++)
{
length <<= 8;
length |= stream.ReadByte();
}
return length;
}
public static void WriteLength(Stream stream,int length)
{
if (length < 128)
{
stream.WriteByte((byte)length);
}
else
{
byte[] bytes = BitConverter.GetBytes(length);
int n;
for (n = 3; 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<int> oid = new List<int>();
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<byte> bytes = new List<byte>();
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();
}
}
}