Commit a17e9ecf authored by Brickner_cp's avatar Brickner_cp

--no commit message

--no commit message
parent 88526433
......@@ -25,6 +25,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
......@@ -49,7 +50,16 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Datagram.cs" />
<Compile Include="DataLink.cs" />
<Compile Include="DataLinkKind.cs" />
<Compile Include="EthernetDatagram.cs" />
<Compile Include="EthernetType.cs" />
<Compile Include="IDataLink.cs" />
<Compile Include="MacAddress.cs" />
<Compile Include="MoreByteArray.cs" />
<Compile Include="Packet.cs" />
<Compile Include="PacketBuilder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
......
namespace BPacket
{
public struct DataLink : IDataLink
{
public DataLink(DataLinkKind kind)
{
_kind = kind;
}
public DataLinkKind Kind
{
get { return _kind; }
}
private readonly DataLinkKind _kind;
}
}
\ No newline at end of file
namespace BPacket
{
public enum DataLinkKind
{
Ethernet
}
}
\ No newline at end of file
namespace BPacket
{
public class Datagram
{
public Datagram(byte[] buffer, int offset, int length)
{
_buffer = buffer;
_startOffset = offset;
_length = length;
}
public static Datagram Empty
{
get { return _empty; }
}
public int Length
{
get { return _length; }
}
internal void Write(byte[] buffer, int offset)
{
System.Buffer.BlockCopy(_buffer, StartOffset, buffer, offset, Length);
}
protected byte[] Buffer
{
get { return _buffer; }
}
protected int StartOffset
{
get { return _startOffset; }
}
protected ushort ReadUShort(int offset, Endianity endianity)
{
return _buffer.ReadUShort(StartOffset + offset, endianity);
}
private static Datagram _empty = new Datagram(new byte[0], 0, 0);
private byte[] _buffer;
private int _startOffset;
private int _length;
}
}
\ No newline at end of file
namespace BPacket
{
/// <summary>
/// +------+-----------------+------------+------------------+
/// | Byte | 0-5 | 6-11 | 12-13 |
/// +------+-----------------+------------+------------------+
/// | 0 | MAC Destination | MAC Source | EtherType/Length |
/// +------+-----------------+------------+------------------+
/// | 14 | Data |
/// +------+-------------------------------------------------+
/// </summary>
public class EthernetDatagram : Datagram
{
private class Offset
{
public const int Destination = 0;
public const int Source = 6;
public const int EtherTypeLength = 12;
}
internal const int HeaderLength = 14;
public EthernetDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length)
{
}
public MacAddress Source
{
get
{
return new MacAddress(Buffer, StartOffset + Offset.Source);
}
}
public MacAddress Destination
{
get
{
return new MacAddress(Buffer, StartOffset + Offset.Destination);
}
}
public EthernetType EtherType
{
get
{
return (EthernetType)ReadUShort(Offset.EtherTypeLength, Endianity.Big);
}
}
internal static void WriteHeader(byte[] buffer, int offset, MacAddress ethernetSource, MacAddress ethernetDestination, EthernetType ethernetType)
{
ethernetSource.Write(buffer, offset + Offset.Source);
ethernetDestination.Write(buffer, offset + Offset.Destination);
ethernetDestination.Write(buffer, offset + Offset.Destination);
buffer.Write(offset + Offset.EtherTypeLength, (ushort)ethernetType, Endianity.Big);
}
}
}
\ No newline at end of file
namespace BPacket
{
public enum EthernetType : ushort
{
IpV4 = 0x0800,
Arp = 0x0806,
Ieee802_1Q = 0x8100,
IpV6 = 0x86DD
}
}
\ No newline at end of file
namespace BPacket
{
public interface IDataLink
{
DataLinkKind Kind { get; }
}
}
\ No newline at end of file
using System;
namespace BPacket
{
public struct MacAddress
{
public MacAddress(byte[] buffer, int offset)
{
_b1 = buffer[offset++];
_b2 = buffer[offset++];
_b3 = buffer[offset++];
_b4 = buffer[offset++];
_b5 = buffer[offset++];
_b6 = buffer[offset];
}
public MacAddress(string address)
{
string[] hexes = address.Split(':');
if (hexes.Length != 6)
throw new ArgumentException("Failed parsing " + address + " as mac address. Expected 6 hexes and got " + hexes.Length + " hexes", "address");
_b1 = Convert.ToByte(hexes[0], 16);
_b2 = Convert.ToByte(hexes[1], 16);
_b3 = Convert.ToByte(hexes[2], 16);
_b4 = Convert.ToByte(hexes[3], 16);
_b5 = Convert.ToByte(hexes[4], 16);
_b6 = Convert.ToByte(hexes[5], 16);
}
public override string ToString()
{
return string.Format("{0:X2}:{1:X2}:{2:X2}:{3:X2}:{4:X2}:{5:X2}", _b1, _b2, _b3, _b4, _b5, _b6);
}
internal void Write(byte[] buffer, int offset)
{
buffer[offset++] = _b1;
buffer[offset++] = _b2;
buffer[offset++] = _b3;
buffer[offset++] = _b4;
buffer[offset++] = _b5;
buffer[offset] = _b6;
}
private readonly byte _b1;
private readonly byte _b2;
private readonly byte _b3;
private readonly byte _b4;
private readonly byte _b5;
private readonly byte _b6;
}
}
\ No newline at end of file
using System;
using System.Net;
namespace BPacket
{
public enum Endianity : byte
{
Small,
Big
}
public static class MoreByteArray
{
public static short ReadShort(this byte[] buffer, int offset, Endianity endianity)
{
short value = ReadShort(buffer, offset);
if (IsWrongEndianity(endianity))
value = IPAddress.HostToNetworkOrder(value);
return value;
}
public static ushort ReadUShort(this byte[] buffer, int offset, Endianity endianity)
{
return (ushort)ReadShort(buffer, offset, endianity);
}
public static void Write(this byte[] buffer, int offset, short value, Endianity endianity)
{
if (IsWrongEndianity(endianity))
value = IPAddress.HostToNetworkOrder(value);
Write(buffer, offset, value);
}
public static void Write(this byte[] buffer, int offset, ushort value, Endianity endianity)
{
Write(buffer, offset, (short)value, endianity);
}
private static bool IsWrongEndianity(Endianity endianity)
{
return (BitConverter.IsLittleEndian == (endianity == Endianity.Big));
}
private static short ReadShort(byte[] buffer, int offset)
{
unsafe
{
fixed (byte* ptr = &buffer[offset])
{
return *((short*)ptr);
}
}
}
private static void Write(byte[] buffer, int offset, short value)
{
unsafe
{
fixed (byte* ptr = &buffer[offset])
{
*((short*)ptr) = value;
}
}
}
}
}
\ No newline at end of file
......@@ -7,10 +7,11 @@ namespace BPacket
{
public class Packet
{
public Packet(byte[] data, DateTime timestamp)
public Packet(byte[] data, DateTime timestamp, IDataLink dataLink)
{
_data = data;
_timestamp = timestamp;
_dataLink = dataLink;
}
public int Length
......@@ -23,6 +24,11 @@ namespace BPacket
get { return _timestamp; }
}
public IDataLink DataLink
{
get { return _dataLink; }
}
public byte[] Buffer
{
get { return _data; }
......@@ -30,5 +36,6 @@ namespace BPacket
private readonly byte[] _data;
private readonly DateTime _timestamp;
private readonly IDataLink _dataLink;
}
}
using System;
namespace BPacket
{
public static class PacketBuilder
{
public static Packet Ethernet(DateTime timestamp, MacAddress ethernetSource, MacAddress ethernetDestination, EthernetType ethernetType, Datagram etherentPayload)
{
byte[] buffer = new byte[EthernetDatagram.HeaderLength + etherentPayload.Length];
EthernetDatagram.WriteHeader(buffer, 0, ethernetSource, ethernetDestination, ethernetType);
etherentPayload.Write(buffer, EthernetDatagram.HeaderLength);
return new Packet(buffer, timestamp, new DataLink(DataLinkKind.Ethernet));
}
}
}
\ No newline at end of file
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace PcapDotNet.Core.Test
{
public static class MoreAssert
{
public static void IsBiggerOrEqual<T>(T expectedMinimum, T actual) where T : IComparable<T>
{
if (expectedMinimum.CompareTo(actual) > 0)
throw new AssertFailedException("Assert.IsBiggerOrEqual failed. Expected minimum: <" + expectedMinimum +
"> Actual: <" + actual + ">.");
}
public static void IsSmallerOrEqual<T>(T expectedMaximum, T actual) where T : IComparable<T>
{
if (expectedMaximum.CompareTo(actual) < 0)
throw new AssertFailedException("Assert.IsSmallerOrEqual failed. Expected maximum: <" + expectedMaximum +
"> Actual: <" + actual + ">.");
}
public static void IsInRange<T>(T expectedMinimum, T expectedMaximum, T actual) where T : IComparable<T>
{
IsBiggerOrEqual(expectedMinimum, actual);
IsSmallerOrEqual(expectedMaximum, actual);
}
}
}
\ No newline at end of file
......@@ -42,10 +42,16 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="MoreAssert.cs" />
<Compile Include="PcapLiveDeviceTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PcapLibTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BPacket\BPacket.csproj">
<Project>{8A184AF5-E46C-482C-81A3-76D8CE290104}</Project>
<Name>BPacket</Name>
</ProjectReference>
<ProjectReference Include="..\PcapDotNet.Core\WinPCapDotNet.Core.vcproj">
<Project>{89C63BE1-AF9A-472E-B256-A4F56B1655A7}</Project>
<Name>PcapDotNet.Core</Name>
......
using System;
using System.Text;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
......@@ -8,7 +7,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace PcapDotNet.Core.Test
{
/// <summary>
/// Summary description for UnitTest1
/// Summary description for PcapLibTests
/// </summary>
[TestClass]
public class PcapLibTests
......
using System;
using System.Threading;
using BPacket;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace PcapDotNet.Core.Test
{
/// <summary>
/// Summary description for PcapLibTests
/// </summary>
[TestClass]
public class PcapLiveDeviceTests
{
public PcapLiveDeviceTests()
{
//
// TODO: Add constructor logic here
//
}
private TestContext testContextInstance;
/// <summary>
///Gets or sets the test context which provides
///information about and functionality for the current test run.
///</summary>
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
#region Additional test attributes
//
// You can use the following additional attributes as you write your tests:
//
// Use ClassInitialize to run code before running the first test in the class
// [ClassInitialize()]
// public static void MyClassInitialize(TestContext testContext) { }
//
// Use ClassCleanup to run code after all tests in a class have run
// [ClassCleanup()]
// public static void MyClassCleanup() { }
//
// Use TestInitialize to run code before running each test
// [TestInitialize()]
// public void MyTestInitialize() { }
//
// Use TestCleanup to run code after each test has run
// [TestCleanup()]
// public void MyTestCleanup() { }
//
#endregion
[TestMethod]
public void SendAndReceievePacketTest()
{
const string sourceMac = "11:22:33:44:55:66";
const string dstMac = "77:88:99:AA:BB:CC";
IPcapDevice device = PcapLiveDevice.AllLocalMachine[0];
using (PcapDeviceHandler deviceHandler = device.Open())
{
Assert.AreEqual(DataLinkKind.Ethernet, deviceHandler.DataLink.Kind);
deviceHandler.SetFilter("ether src " + sourceMac + " and ether dst " + dstMac);
Packet sentPacket = PacketBuilder.Ethernet(DateTime.Now,
new MacAddress(sourceMac),
new MacAddress(dstMac),
EthernetType.IpV4,
new Datagram(new byte[10], 0, 10));
DateTime startSendingTime = DateTime.Now;
for (int i = 0; i != 10; ++i)
deviceHandler.SendPacket(sentPacket);
DateTime endSendingTime = DateTime.Now;
Thread.Sleep(TimeSpan.FromSeconds(5));
Packet packet;
DeviceHandlerResult result = deviceHandler.GetPacket(out packet);
Assert.AreEqual(DeviceHandlerResult.Ok, result);
Assert.AreEqual(sentPacket.Length, packet.Length);
MoreAssert.IsInRange(startSendingTime, endSendingTime + TimeSpan.FromSeconds(2), packet.Timestamp);
}
}
}
}
\ No newline at end of file
......@@ -6,6 +6,7 @@
#include "Pcap.h"
using namespace System;
using namespace BPacket;
using namespace PcapDotNet::Core;
PcapDataLink::PcapDataLink(int value)
......@@ -23,6 +24,18 @@ PcapDataLink::PcapDataLink(String^ name)
_value = value;
}
DataLinkKind PcapDataLink::Kind::get()
{
switch (Value)
{
case 1:
return DataLinkKind::Ethernet;
default:
throw gcnew NotSupportedException("PcapDataLink " + Value.ToString() + " - " + ToString() + " is unsupported");
}
}
int PcapDataLink::Value::get()
{
return _value;
......@@ -49,5 +62,5 @@ String^ PcapDataLink::Description::get()
String^ PcapDataLink::ToString()
{
return Name;
return Name + " (" + Description + ")";
}
......@@ -2,12 +2,17 @@
namespace PcapDotNet { namespace Core
{
public value class PcapDataLink
public value class PcapDataLink : BPacket::IDataLink
{
public:
PcapDataLink(int value);
PcapDataLink(System::String^ name);
virtual property BPacket::DataLinkKind Kind
{
BPacket::DataLinkKind get();
}
property int Value
{
int get();
......
......@@ -150,7 +150,7 @@ DeviceHandlerResult PcapDeviceHandler::GetPacket([Out] Packet^% packet)
return result;
}
packet = CreatePacket(*packetHeader, packetData);
packet = CreatePacket(*packetHeader, packetData, DataLink);
return result;
}
......@@ -158,7 +158,7 @@ DeviceHandlerResult PcapDeviceHandler::GetSomePackets(int maxPackets, HandlePack
{
AssertMode(DeviceHandlerMode::Capture);
PacketHandler^ packetHandler = gcnew PacketHandler(callBack);
PacketHandler^ packetHandler = gcnew PacketHandler(callBack, DataLink);
HandlerDelegate^ packetHandlerDelegate = gcnew HandlerDelegate(packetHandler, &PacketHandler::Handle);
pcap_handler functionPointer = (pcap_handler)Marshal::GetFunctionPointerForDelegate(packetHandlerDelegate).ToPointer();
......@@ -178,7 +178,7 @@ DeviceHandlerResult PcapDeviceHandler::GetPackets(int numPackets, HandlePacket^
{
AssertMode(DeviceHandlerMode::Capture);
PacketHandler^ packetHandler = gcnew PacketHandler(callBack);
PacketHandler^ packetHandler = gcnew PacketHandler(callBack, DataLink);
HandlerDelegate^ packetHandlerDelegate = gcnew HandlerDelegate(packetHandler, &PacketHandler::Handle);
pcap_handler functionPointer = (pcap_handler)Marshal::GetFunctionPointerForDelegate(packetHandlerDelegate).ToPointer();
......@@ -211,7 +211,9 @@ DeviceHandlerResult PcapDeviceHandler::GetNextStatistics([Out] PcapSampleStatist
void PcapDeviceHandler::SendPacket(Packet^ packet)
{
pin_ptr<Byte> unamangedPacketBytes = &packet->Buffer[0];
pin_ptr<Byte> unamangedPacketBytes;
if (packet->Length != 0)
unamangedPacketBytes = &packet->Buffer[0];
if (pcap_sendpacket(_pcapDescriptor, unamangedPacketBytes, packet->Length) != 0)
throw BuildInvalidOperation("Failed writing to device");
}
......@@ -255,13 +257,13 @@ pcap_t* PcapDeviceHandler::Descriptor::get()
}
// static
Packet^ PcapDeviceHandler::CreatePacket(const pcap_pkthdr& packetHeader, const unsigned char* packetData)
Packet^ PcapDeviceHandler::CreatePacket(const pcap_pkthdr& packetHeader, const unsigned char* packetData, IDataLink^ dataLink)
{
DateTime timestamp;
Timestamp::PcapTimestampToDateTime(packetHeader.ts, timestamp);
array<Byte>^ managedPacketData = MarshalingServices::UnamangedToManagedByteArray(packetData, 0, packetHeader.caplen);
return gcnew Packet(managedPacketData, timestamp);
return gcnew Packet(managedPacketData, timestamp, dataLink);
}
// static
......@@ -312,7 +314,7 @@ InvalidOperationException^ PcapDeviceHandler::BuildInvalidOperation(System::Stri
void PcapDeviceHandler::PacketHandler::Handle(unsigned char *user, const struct pcap_pkthdr *packetHeader, const unsigned char *packetData)
{
_callBack->Invoke(CreatePacket(*packetHeader, packetData));
_callBack->Invoke(CreatePacket(*packetHeader, packetData, _dataLink));
}
void PcapDeviceHandler::StatisticsHandler::Handle(unsigned char *user, const struct pcap_pkthdr *packetHeader, const unsigned char *packetData)
......
......@@ -105,7 +105,7 @@ namespace PcapDotNet { namespace Core
}
private:
static BPacket::Packet^ CreatePacket(const pcap_pkthdr& packetHeader, const unsigned char* packetData);
static BPacket::Packet^ CreatePacket(const pcap_pkthdr& packetHeader, const unsigned char* packetData, BPacket::IDataLink^ dataLink);
static PcapSampleStatistics^ PcapDeviceHandler::CreateStatistics(const pcap_pkthdr& packetHeader, const unsigned char* packetData);
DeviceHandlerResult RunPcapNextEx(pcap_pkthdr** packetHeader, const unsigned char** packetData);
......@@ -125,14 +125,16 @@ namespace PcapDotNet { namespace Core
ref class PacketHandler
{
public:
PacketHandler(HandlePacket^ callBack)
PacketHandler(HandlePacket^ callBack, PcapDataLink dataLink)
{
_callBack = callBack;
_dataLink = dataLink;
}
void Handle(unsigned char *user, const struct pcap_pkthdr *packetHeader, const unsigned char *packetData);
HandlePacket^ _callBack;
PcapDataLink _dataLink;
};
ref class StatisticsHandler
......
......@@ -9,15 +9,6 @@ using namespace System;
using namespace PcapDotNet::Core;
using namespace BPacket;
PcapDumpFile::PcapDumpFile(pcap_t* pcapDescriptor, System::String^ filename)
{
_filename = filename;
std::string unmanagedString = MarshalingServices::ManagedToUnmanagedString(_filename);
_pcapDumper = pcap_dump_open(pcapDescriptor, unmanagedString.c_str());
if (_pcapDumper == NULL)
throw gcnew InvalidOperationException("Error opening output file " + filename + " Error: " + PcapError::GetErrorMessage(pcapDescriptor));
}
void PcapDumpFile::Dump(Packet^ packet)
{
pcap_pkthdr header;
......@@ -45,4 +36,15 @@ long PcapDumpFile::Position::get()
PcapDumpFile::~PcapDumpFile()
{
pcap_dump_close(_pcapDumper);
}
\ No newline at end of file
}
// internal
PcapDumpFile::PcapDumpFile(pcap_t* pcapDescriptor, System::String^ filename)
{
_filename = filename;
std::string unmanagedString = MarshalingServices::ManagedToUnmanagedString(_filename);
_pcapDumper = pcap_dump_open(pcapDescriptor, unmanagedString.c_str());
if (_pcapDumper == NULL)
throw gcnew InvalidOperationException("Error opening output file " + filename + " Error: " + PcapError::GetErrorMessage(pcapDescriptor));
}
......@@ -7,8 +7,6 @@ namespace PcapDotNet { namespace Core
public ref class PcapDumpFile : System::IDisposable
{
public:
PcapDumpFile(pcap_t* pcapDescriptor, System::String^ filename);
void Dump(BPacket::Packet^ packet);
void Flush();
......@@ -20,6 +18,9 @@ namespace PcapDotNet { namespace Core
~PcapDumpFile();
internal:
PcapDumpFile(pcap_t* pcapDescriptor, System::String^ filename);
private:
pcap_dumper_t* _pcapDumper;
System::String^ _filename;
......
......@@ -7,14 +7,15 @@ using namespace PcapDotNet::Core;
// static
void Timestamp::PcapTimestampToDateTime(const timeval& pcapTimestamp, [System::Runtime::InteropServices::Out] System::DateTime% dateTime)
{
dateTime = DateTime(1970,1,1).Add(TimeSpan::FromSeconds(pcapTimestamp.tv_sec) +
TimeSpan::FromMilliseconds(((double)pcapTimestamp.tv_usec) / 1000));
dateTime = DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind::Utc);
dateTime = dateTime.Add(TimeSpan::FromSeconds(pcapTimestamp.tv_sec) + TimeSpan::FromMilliseconds(((double)pcapTimestamp.tv_usec) / 1000));
dateTime = dateTime.ToLocalTime();
}
// static
void Timestamp::DateTimeToPcapTimestamp(System::DateTime dateTime, timeval& pcapTimestamp)
{
TimeSpan timespan = dateTime - DateTime(1970,1,1);
TimeSpan timespan = dateTime - DateTime(1970,1,1, 0, 0, 0, DateTimeKind::Utc);
pcapTimestamp.tv_sec = (long)timespan.TotalSeconds;
pcapTimestamp.tv_usec = (long)(timespan.Milliseconds * 1000);
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment