267 lines
7.5 KiB
C#
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();
|
|
}
|
|
|
|
|
|
}
|
|
}
|