Initial commit

master
Harald Wolff 2019-03-04 06:50:05 +01:00
commit b8e9ba6e9a
14 changed files with 851 additions and 0 deletions

41
.gitignore vendored 100644
View File

@ -0,0 +1,41 @@
# Autosave files
*~
# build
[Oo]bj/
[Bb]in/
packages/
TestResults/
# globs
Makefile.in
*.DS_Store
*.sln.cache
*.suo
*.cache
*.pidb
*.userprefs
*.usertasks
config.log
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.user
*.tar.gz
tarballs/
test-results/
Thumbs.db
.vs/
# Mac bundle stuff
*.dmg
*.app
# resharper
*_Resharper.*
*.Resharper
# dotCover
*.dotCover

View File

@ -0,0 +1,240 @@
// /**
// * 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 override string ToString()
{
return String.Format("[ASN.1 Type Class={0} Constructed={1} Number={2}]",IdentifierClass,Constructed,Number);
}
}
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 = EncodeInteger(length);
byte bl = (byte)(0x80 | bytes.Length);
stream.WriteByte(bl);
stream.Write(bytes, 0, bytes.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();
}
}
}

View File

@ -0,0 +1,35 @@
// /**
// * File: AssemblyInfo.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.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("ln.snmp")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("${AuthorCopyright}")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

32
SNMPClient.cs 100644
View File

@ -0,0 +1,32 @@
// /**
// * File: MyClass.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.Collections.Generic;
using Lextm.SharpSnmpLib;
namespace ln.snmp
{
public abstract class SNMPClient
{
public SNMPClient()
{
}
public abstract List<Variable> Walk(ObjectIdentifier baseOID);
public abstract List<Variable> Get(List<ObjectIdentifier> baseOID);
public virtual Variable Get(ObjectIdentifier oid)
{
return Get(new List<ObjectIdentifier>(new ObjectIdentifier[] { oid }))[0];
}
}
}

56
ln.snmp.csproj 100644
View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C7A43B82-55F2-4092-8DBE-6BE29CBF079D}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>ln.snmp</RootNamespace>
<AssemblyName>ln.snmp</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="SharpSnmpLib">
<HintPath>..\packages\Lextm.SharpSnmpLib.11.1.0\lib\net452\SharpSnmpLib.dll</HintPath>
</Reference>
<Reference Include="System.Configuration" />
</ItemGroup>
<ItemGroup>
<Compile Include="SNMPClient.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="types\Variable.cs" />
<Compile Include="BasicEncodingRules.cs" />
<Compile Include="types\Sequence.cs" />
<Compile Include="types\PDU.cs" />
<Compile Include="types\Integer.cs" />
<Compile Include="types\NullValue.cs" />
<Compile Include="types\Boolean.cs" />
<Compile Include="types\OctetString.cs" />
<Compile Include="types\ObjectIdentifier.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="types\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

4
packages.config 100644
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Lextm.SharpSnmpLib" version="11.1.0" targetFramework="net47" />
</packages>

33
types/Boolean.cs 100644
View File

@ -0,0 +1,33 @@
// /**
// * File: Boolean.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;
namespace ln.snmp.types
{
public class Boolean : Variable
{
public bool BooleanValue { get; set; }
public Boolean()
: base(new Identifier(IdentifierClass.UNIVERSAL, false, 1))
{
}
public override byte[] Bytes
{
get => BooleanValue ? new byte[] { 0xFF } : new byte[] { 0x00 };
set => BooleanValue = value[0] == 0 ? false : true;
}
public override object Value
{
get => BooleanValue;
set => BooleanValue = (bool)value;
}
}
}

36
types/Integer.cs 100644
View File

@ -0,0 +1,36 @@
// /**
// * File: Integer.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;
namespace ln.snmp.types
{
public class Integer : Variable
{
public long LongValue { get; set; }
public Integer()
:base(new Identifier(IdentifierClass.UNIVERSAL, false, 0x02))
{
}
public Integer(long value)
:this()
{
LongValue = value;
}
public override byte[] Bytes
{
get => BasicEncodingRules.EncodeInteger(LongValue);
set => LongValue = BasicEncodingRules.DecodeInteger(value);
}
public override object Value { get => LongValue; set => LongValue = (long)value; }
}
}

33
types/NullValue.cs 100644
View File

@ -0,0 +1,33 @@
// /**
// * File: NullValue.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;
namespace ln.snmp.types
{
public class NullValue : Variable
{
public static NullValue Instance = new NullValue();
byte[] value = new byte[0];
private NullValue()
:base(new Identifier(IdentifierClass.UNIVERSAL,false,0x05))
{
}
public override byte[] Bytes { get => value;
set
{
if (value.Length > 0)
throw new NotImplementedException();
}
}
public override object Value { get => null; set => throw new NotImplementedException(); }
}
}

View File

@ -0,0 +1,48 @@
// /**
// * File: ObjectIdentifier.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.Linq;
namespace ln.snmp.types
{
public class ObjectIdentifier : Variable
{
public int[] OIDValue { get; set; }
public ObjectIdentifier()
:base(new Identifier(IdentifierClass.UNIVERSAL,false,6))
{
}
public ObjectIdentifier(int[] oid)
: this()
{
OIDValue = oid;
}
public ObjectIdentifier(string oid)
: this()
{
int[] ioid = oid.Split(new char[] { '.' }, StringSplitOptions.None).Select((x)=> int.Parse(x)).ToArray();
OIDValue = ioid;
}
public override byte[] Bytes
{
get => BasicEncodingRules.EncodeOID(OIDValue);
set => OIDValue = BasicEncodingRules.DecodeOID(value);
}
public override object Value
{
get => OIDValue;
set => OIDValue = value as int[];
}
}
}

View File

@ -0,0 +1,38 @@
// /**
// * File: OctetString.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.Text;
namespace ln.snmp.types
{
public class OctetString : Variable
{
public string StringValue { get; set; }
public OctetString()
:base(new Identifier(IdentifierClass.UNIVERSAL, false, 4))
{
}
public OctetString(String text)
:this()
{
StringValue = text;
}
public override byte[] Bytes {
get => Encoding.UTF8.GetBytes(StringValue);
set => StringValue = Encoding.UTF8.GetString(value);
}
public override object Value {
get => StringValue;
set => StringValue = value as string;
}
}
}

71
types/PDU.cs 100644
View File

@ -0,0 +1,71 @@
// /**
// * File: PDU.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;
namespace ln.snmp.types
{
public class PDU : AbstractSequence
{
public Integer RequestID { get; private set; }
public Integer Error { get; private set; }
public Integer ErrorIndex { get; private set; }
public Sequence VarBinds { get; private set; }
private Variable[] items;
public PDU(Identifier identifier)
:base(identifier)
{
RequestID = new Integer(1); // Environment.TickCount
Error = new Integer();
ErrorIndex = new Integer();
VarBinds = new Sequence();
items = new Variable[] { RequestID, Error, ErrorIndex, VarBinds };
}
public override Variable[] Items => items;
public override void Add(Variable item)
{
VarBinds.Add(item);
}
public override void Remove(Variable item)
{
VarBinds.Remove(item);
}
public override byte[] Bytes
{
set
{
MemoryStream bytes = new MemoryStream(value);
RequestID = Variable.Read(bytes) as Integer;
Error = Variable.Read(bytes) as Integer;
ErrorIndex = Variable.Read(bytes) as Integer;
VarBinds = Variable.Read(bytes) as Sequence;
}
}
}
public class GetRequest : PDU
{
public GetRequest() : base(new Identifier(IdentifierClass.CONTEXT,true,0x00))
{
}
}
}

97
types/Sequence.cs 100644
View File

@ -0,0 +1,97 @@
// /**
// * File: Sequence.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.Collections.Generic;
using System.Linq;
using System.IO;
namespace ln.snmp.types
{
public class Sequence : AbstractSequence
{
private List<Variable> items = new List<Variable>();
public Sequence()
:base(new Identifier(IdentifierClass.UNIVERSAL,true,0x10))
{ }
public Sequence(IEnumerable<Variable> variables)
:this()
{
foreach (Variable variable in variables)
Add(variable);
}
public override Variable[] Items => items.ToArray();
public override void Add(Variable item)
{
this.items.Add(item);
}
public override void Remove(Variable item)
{
this.items.Remove(item);
}
public override void Remove(int n)
{
this.items.RemoveAt(n);
}
}
public abstract class AbstractSequence : Variable
{
protected AbstractSequence(Identifier identifier)
:base(identifier)
{
}
/* Items */
public abstract Variable[] Items { get; }
public abstract void Add(Variable item);
public abstract void Remove(Variable item);
public virtual void Remove(int n)
{
Remove(Items[n]);
}
public virtual void RemoveAll()
{
foreach (Variable item in Items)
Remove(item);
}
/* SNMP Variable */
public override object Value {
get => Items;
set => throw new NotImplementedException();
}
public override byte[] Bytes
{
get
{
MemoryStream payload = new MemoryStream();
foreach (Variable item in Items)
{
item.Write(payload);
}
return payload.ToArray();
}
set
{
MemoryStream bytes = new MemoryStream(value);
while (bytes.Position < bytes.Length)
{
Add(Variable.Read(bytes));
}
}
}
}
}

87
types/Variable.cs 100644
View File

@ -0,0 +1,87 @@
// /**
// * File: Variable.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;
namespace ln.snmp.types
{
public abstract class Variable
{
public Identifier Identifier { get; private set; }
public Variable(Identifier identifier)
{
Identifier = identifier;
}
public abstract byte[] Bytes { get; set; }
public abstract object Value { get; set; }
public virtual void Write(Stream stream)
{
byte[] payload = Bytes;
BasicEncodingRules.WriteIdentifier(stream,Identifier);
BasicEncodingRules.WriteLength(stream, payload.Length);
stream.Write(payload, 0, payload.Length);
}
public static Variable Read(Stream stream)
{
Variable variable = null;
Identifier identifier = BasicEncodingRules.ReadIdentifier(stream);
int length = BasicEncodingRules.ReadLength(stream);
byte[] payload = new byte[length];
stream.Read(payload, 0, length);
variable = FromIdentifier(identifier);
variable.Bytes = payload;
return variable;
}
public static void Write(Stream stream,Variable variable)
{
variable.Write(stream);
}
public static Variable FromIdentifier(Identifier identifier)
{
if (identifier.IdentifierClass == IdentifierClass.UNIVERSAL)
{
switch (identifier.Number)
{
case 0x02:
return new Integer();
case 0x04:
return new OctetString();
case 0x05:
return NullValue.Instance;
case 0x06:
return new ObjectIdentifier();
case 0x10:
return new Sequence();
}
} else if (identifier.IdentifierClass == IdentifierClass.CONTEXT)
{
switch (identifier.Number)
{
case 0x00:
return new GetRequest();
}
}
throw new NotSupportedException(String.Format("Unsupported ASN Type: {0}",identifier));
}
}
}