Commit 2da3e5e9 authored by Brickner_cp's avatar Brickner_cp

--no commit message

--no commit message
parent a21627ba
...@@ -650,7 +650,13 @@ namespace PcapDotNet.Core.Test ...@@ -650,7 +650,13 @@ namespace PcapDotNet.Core.Test
PacketCommunicator communicator = device.Open(); PacketCommunicator communicator = device.Open();
try try
{ {
Assert.AreEqual(new PacketTotalStatistics(0, 0, 0, 0), communicator.TotalStatistics); PacketTotalStatistics totalStatistics = communicator.TotalStatistics;
Assert.AreEqual(totalStatistics, totalStatistics);
Assert.AreNotEqual(null, totalStatistics);
Assert.AreEqual(0, totalStatistics.PacketsCaptured);
Assert.AreEqual(0, totalStatistics.PacketsDroppedByDriver);
Assert.AreEqual(0, totalStatistics.PacketsDroppedByInterface);
Assert.AreEqual(0, totalStatistics.PacketsReceived);
communicator.SetKernelBufferSize(2 * 1024 * 1024); // 2 MB instead of 1 communicator.SetKernelBufferSize(2 * 1024 * 1024); // 2 MB instead of 1
communicator.SetKernelMinimumBytesToCopy(10); // 10 bytes minimum to copy communicator.SetKernelMinimumBytesToCopy(10); // 10 bytes minimum to copy
communicator.SetSamplingMethod(new SamplingMethodNone()); communicator.SetSamplingMethod(new SamplingMethodNone());
......
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace PcapDotNet.Core.Test
{
/// <summary>
/// Summary description for PacketTotalStatisticsTests
/// </summary>
[TestClass]
public class PacketTotalStatisticsTests
{
public PacketTotalStatisticsTests()
{
//
// 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 Test()
{
Assert.IsNotNull(new PacketTotalStatistics(1,2,3,4).ToString());
Assert.IsFalse(new PacketTotalStatistics(1,2,3,4).Equals(null));
}
}
}
\ No newline at end of file
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
<Compile Include="PacketHandler.cs" /> <Compile Include="PacketHandler.cs" />
<Compile Include="PacketSendQueueTests.cs" /> <Compile Include="PacketSendQueueTests.cs" />
<Compile Include="OfflinePacketDeviceTests.cs" /> <Compile Include="OfflinePacketDeviceTests.cs" />
<Compile Include="PacketTotalStatisticsTests.cs" />
<Compile Include="PcapDataLinkTests.cs" /> <Compile Include="PcapDataLinkTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PcapLibTests.cs" /> <Compile Include="PcapLibTests.cs" />
......
...@@ -5,15 +5,71 @@ ...@@ -5,15 +5,71 @@
namespace PcapDotNet { namespace Core namespace PcapDotNet { namespace Core
{ {
/// <summary>
/// A packet filter, converting a high level filtering expression (see <see href="http://www.winpcap.org/docs/docs_40_2/html/group__language.html">WinPcap Filtering expression syntax</see>) in a program that can be interpreted by the kernel-level filtering engine.
/// The user must dispose instances of this class to deallocate resources.
/// </summary>
public ref class BerkeleyPacketFilter : System::IDisposable public ref class BerkeleyPacketFilter : System::IDisposable
{ {
public: public:
/// <summary>
/// Compile a packet filter without the need of opening an adapter.
/// This constructor converts a high level filtering expression (see <see href="http://www.winpcap.org/docs/docs_40_2/html/group__language.html">WinPcap Filtering expression syntax</see>) in a program that can be interpreted by the kernel-level filtering engine.
/// </summary>
/// <param name="filterValue">A high level filtering expression (see <see href="http://www.winpcap.org/docs/docs_40_2/html/group__language.html">WinPcap Filtering expression syntax</see>)</param>
/// <param name="snapshotLength">Length of the packet that has to be retained of the communicator this filter will be applied on.</param>
/// <param name="kind">The link layer of an adapter that this filter will apply upon.</param>
/// <param name="netmask">Specifies the IPv4 netmask of the network on which packets are being captured; it is used only when checking for IPv4 broadcast addresses in the filter program. If the netmask of the network on which packets are being captured isn't known to the program, or if packets are being captured on the Linux "any" pseudo-interface that can capture on more than one network, null can be supplied; tests for IPv4 broadcast addreses won't be done correctly, but all other tests in the filter program will be OK.</param>
/// <exception cref="System::ArgumentException">Indicates an error. Probably caused by bad syntax.</exception>
/// <remarks>
/// If the purpose of this filter is to apply it on a communicator and not to test packets in memory, it would be simpler to call to PacketCommunicator.CreateFilter() or to directly call PacketCommunicator.SetFilter().
/// </remarks>
BerkeleyPacketFilter(System::String^ filterValue, int snapshotLength, Packets::DataLinkKind kind, IpV4SocketAddress^ netmask); BerkeleyPacketFilter(System::String^ filterValue, int snapshotLength, Packets::DataLinkKind kind, IpV4SocketAddress^ netmask);
/// <summary>
/// Compile a packet filter without the need of opening an adapter.
/// This constructor converts a high level filtering expression (see <see href="http://www.winpcap.org/docs/docs_40_2/html/group__language.html">WinPcap Filtering expression syntax</see>) in a program that can be interpreted by the kernel-level filtering engine.
/// Assumes the netmask of the network on which packets are being captured isn't known to the program, or that packets are being captured on the Linux "any" pseudo-interface that can capture on more than one network.
/// Tests for IPv4 broadcast addreses won't be done correctly, but all other tests in the filter program will be OK.
/// </summary>
/// <param name="filterValue">A high level filtering expression (see <see href="http://www.winpcap.org/docs/docs_40_2/html/group__language.html">WinPcap Filtering expression syntax</see>)</param>
/// <param name="snapshotLength">Length of the packet that has to be retained of the communicator this filter will be applied on.</param>
/// <param name="kind">The link layer of an adapter that this filter will apply upon.</param>
/// <exception cref="System::ArgumentException">Indicates an error. Probably caused by bad syntax.</exception>
/// <remarks>
/// If the purpose of this filter is to apply it on a communicator and not to test packets in memory, it would be simpler to call to PacketCommunicator.CreateFilter() or to directly call PacketCommunicator.SetFilter().
/// </remarks>
BerkeleyPacketFilter(System::String^ filterValue, int snapshotLength, Packets::DataLinkKind kind); BerkeleyPacketFilter(System::String^ filterValue, int snapshotLength, Packets::DataLinkKind kind);
/// <summary>
/// Returns if a given filter applies to an offline packet.
/// This method is used to apply a filter to a packet that is currently in memory.
/// This process does not need to open an adapter; we need just to create the proper filter (by settings parameters like the snapshot length, or the link-layer type) by means of the Pcap.
/// The current API of libpcap does not allow to receive a packet and to filter the packet after it has been received. However, this can be useful in case you want to filter packets in the application, instead of into the receiving process. This function allows you to do the job.
/// </summary>
/// <param name="snapshotLength">The length of the bytes that are currently available into the packet if the packet satisfies the filter, 0 otherwise.</param>
/// <param name="packet">The packet that has to be filtered.</param>
/// <returns>
/// True iff the given packet satisfies the filter.
/// </returns>
bool Test([System::Runtime::InteropServices::Out] int% snapshotLength, Packets::Packet^ packet); bool Test([System::Runtime::InteropServices::Out] int% snapshotLength, Packets::Packet^ packet);
/// <summary>
/// Returns if a given filter applies to an offline packet.
/// This method is used to apply a filter to a packet that is currently in memory.
/// This process does not need to open an adapter; we need just to create the proper filter (by settings parameters like the snapshot length, or the link-layer type) by means of the Pcap.
/// The current API of libpcap does not allow to receive a packet and to filter the packet after it has been received. However, this can be useful in case you want to filter packets in the application, instead of into the receiving process. This function allows you to do the job.
/// </summary>
/// <param name="packet">The packet that has to be filtered.</param>
/// <returns>
/// True iff the given packet satisfies the filter.
/// </returns>
bool Test(Packets::Packet^ packet); bool Test(Packets::Packet^ packet);
/// <summary>
/// Free a filter.
/// Used to free up allocated memory when that BPF program is no longer needed, for example after it has been made the filter program for a packet communicator by a call to PacketCommunicator.SetFilter().
/// </summary>
~BerkeleyPacketFilter(); // IDisposable ~BerkeleyPacketFilter(); // IDisposable
internal: internal:
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
namespace PcapDotNet { namespace Core namespace PcapDotNet { namespace Core
{ {
/// <summary> /// <summary>
/// Represents an a live or offline interface. /// Represents a live or offline interface.
/// </summary> /// </summary>
public interface class IPacketDevice public interface class IPacketDevice
{ {
...@@ -22,7 +22,7 @@ namespace PcapDotNet { namespace Core ...@@ -22,7 +22,7 @@ namespace PcapDotNet { namespace Core
property System::String^ Description { System::String^ get(); }; property System::String^ Description { System::String^ get(); };
/// <summary> /// <summary>
/// interface flags. Currently the only possible flag is Loopback, that is set if the interface is a loopback interface. /// Interface flags. Currently the only possible flag is Loopback, that is set if the interface is a loopback interface.
/// </summary> /// </summary>
property DeviceAttributes^ Attributes { DeviceAttributes^ get(); }; property DeviceAttributes^ Attributes { DeviceAttributes^ get(); };
...@@ -37,9 +37,9 @@ namespace PcapDotNet { namespace Core ...@@ -37,9 +37,9 @@ namespace PcapDotNet { namespace Core
/// <summary> /// <summary>
/// Open a generic source in order to capture / send (WinPcap only) traffic. /// Open a generic source in order to capture / send (WinPcap only) traffic.
/// </summary> /// </summary>
/// <param name="snapshotLength">length of the packet that has to be retained. For each packet received by the filter, only the first 'snapshotLength' bytes are stored in the buffer and passed to the user application. For instance, snaplen equal to 100 means that only the first 100 bytes of each packet are stored.</param> /// <param name="snapshotLength">Length of the packet that has to be retained. For each packet received by the filter, only the first 'snapshotLength' bytes are stored in the buffer and passed to the user application. For instance, snaplen equal to 100 means that only the first 100 bytes of each packet are stored.</param>
/// <param name="attributes">keeps several flags that can be needed for capturing packets.</param> /// <param name="attributes">Keeps several flags that can be needed for capturing packets.</param>
/// <param name="readTimeout">read timeout in milliseconds. The read timeout is used to arrange that the read not necessarily return immediately when a packet is seen, but that it waits for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. Not all platforms support a read timeout; on platforms that don't, the read timeout is ignored.</param> /// <param name="readTimeout">Read timeout in milliseconds. The read timeout is used to arrange that the read not necessarily return immediately when a packet is seen, but that it waits for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. Not all platforms support a read timeout; on platforms that don't, the read timeout is ignored.</param>
/// <exception cref="System::InvalidOperationException">Thrown on failure.</exception> /// <exception cref="System::InvalidOperationException">Thrown on failure.</exception>
PacketCommunicator^ Open(int snapshotLength, PacketDeviceOpenAttributes attributes, int readTimeout); PacketCommunicator^ Open(int snapshotLength, PacketDeviceOpenAttributes attributes, int readTimeout);
......
...@@ -11,17 +11,12 @@ IpV4Address IpV4SocketAddress::Address::get() ...@@ -11,17 +11,12 @@ IpV4Address IpV4SocketAddress::Address::get()
return _address; return _address;
} }
String^ IpV4SocketAddress::AddressString::get()
{
return Address.ToString();
}
String^ IpV4SocketAddress::ToString() String^ IpV4SocketAddress::ToString()
{ {
StringBuilder^ result = gcnew StringBuilder(); StringBuilder^ result = gcnew StringBuilder();
result->Append(SocketAddress::ToString()); result->Append(SocketAddress::ToString());
result->Append(" "); result->Append(" ");
result->Append(AddressString); result->Append(Address);
return result->ToString(); return result->ToString();
} }
......
...@@ -5,19 +5,20 @@ ...@@ -5,19 +5,20 @@
namespace PcapDotNet { namespace Core namespace PcapDotNet { namespace Core
{ {
/// <summary>
/// An internet protocol version 4 address for a device.
/// </summary>
public ref class IpV4SocketAddress : SocketAddress public ref class IpV4SocketAddress : SocketAddress
{ {
public: public:
/// <summary>
/// The ip version 4 address.
/// </summary>
property Packets::IpV4Address Address property Packets::IpV4Address Address
{ {
Packets::IpV4Address get(); Packets::IpV4Address get();
} }
property System::String^ AddressString
{
System::String^ get();
}
virtual System::String^ ToString() override; virtual System::String^ ToString() override;
internal: internal:
......
...@@ -16,13 +16,7 @@ PacketTotalStatistics^ LivePacketCommunicator::TotalStatistics::get() ...@@ -16,13 +16,7 @@ PacketTotalStatistics^ LivePacketCommunicator::TotalStatistics::get()
if (statistics == NULL) if (statistics == NULL)
throw BuildInvalidOperation("Failed getting total statistics"); throw BuildInvalidOperation("Failed getting total statistics");
unsigned int packetsReceived = statistics->ps_recv; return gcnew PacketTotalStatistics(*statistics, statisticsSize);
unsigned int packetsDroppedByDriver = statistics->ps_drop;
unsigned int packetsDroppedByInterface = statistics->ps_ifdrop;
unsigned int packetsCaptured = (statisticsSize >= 16
? *(reinterpret_cast<int*>(statistics) + 3)
: 0);
return gcnew PacketTotalStatistics(packetsReceived, packetsDroppedByDriver, packetsDroppedByInterface, packetsCaptured);
} }
void LivePacketCommunicator::Transmit(PacketSendBuffer^ sendBuffer, bool isSync) void LivePacketCommunicator::Transmit(PacketSendBuffer^ sendBuffer, bool isSync)
......
...@@ -4,29 +4,64 @@ ...@@ -4,29 +4,64 @@
namespace PcapDotNet { namespace Core namespace PcapDotNet { namespace Core
{ {
/// <summary>
/// A live interface.
/// </summary>
public ref class LivePacketDevice : PacketDevice public ref class LivePacketDevice : PacketDevice
{ {
public: public:
/// <summary>
/// Create a list of local machine network devices that can be opened with Open().
/// Platform independent.
/// </summary>
/// <returns>
/// A readonly collection of LivePacketDevices.
/// </returns>
/// <exception cref="System::InvalidOperationException">
/// Thrown if some errors occurred.
/// An error could be due to several reasons:
/// <list type="bullet">
/// <item>libpcap/WinPcap was not installed on the local/remote host.</item>
/// <item>The user does not have enough privileges to list the devices.</item>
/// <item>A network problem.</item>
/// <item>other errors (not enough memory and others).</item>
/// </list>
/// </exception>
/// <remarks>
/// There may be network devices that cannot be opened with Open() by the process calling AllLocalMachine, because, for example, that process might not have sufficient privileges to open them for capturing; if so, those devices will not appear on the list.
/// </remarks>
static property System::Collections::ObjectModel::ReadOnlyCollection<LivePacketDevice^>^ AllLocalMachine static property System::Collections::ObjectModel::ReadOnlyCollection<LivePacketDevice^>^ AllLocalMachine
{ {
System::Collections::ObjectModel::ReadOnlyCollection<LivePacketDevice^>^ get(); System::Collections::ObjectModel::ReadOnlyCollection<LivePacketDevice^>^ get();
} }
/// <summary>
/// A string giving a name for the device.
/// </summary>
virtual property System::String^ Name virtual property System::String^ Name
{ {
System::String^ get() override; System::String^ get() override;
} }
/// <summary>
/// if not null, a string giving a human-readable description of the device.
/// </summary>
virtual property System::String^ Description virtual property System::String^ Description
{ {
System::String^ get() override; System::String^ get() override;
} }
/// <summary>
/// Interface flags. Currently the only possible flag is Loopback, that is set if the interface is a loopback interface.
/// </summary>
virtual property DeviceAttributes^ Attributes virtual property DeviceAttributes^ Attributes
{ {
DeviceAttributes^ get() override; DeviceAttributes^ get() override;
} }
/// <summary>
/// List of addresses for the interface.
/// </summary>
virtual property System::Collections::ObjectModel::ReadOnlyCollection<DeviceAddress^>^ Addresses virtual property System::Collections::ObjectModel::ReadOnlyCollection<DeviceAddress^>^ Addresses
{ {
System::Collections::ObjectModel::ReadOnlyCollection<DeviceAddress^>^ get() override; System::Collections::ObjectModel::ReadOnlyCollection<DeviceAddress^>^ get() override;
...@@ -35,9 +70,10 @@ namespace PcapDotNet { namespace Core ...@@ -35,9 +70,10 @@ namespace PcapDotNet { namespace Core
/// <summary> /// <summary>
/// Open a generic source in order to capture / send (WinPcap only) traffic. /// Open a generic source in order to capture / send (WinPcap only) traffic.
/// </summary> /// </summary>
/// <param name="snapshotLength">length of the packet that has to be retained. For each packet received by the filter, only the first 'snapshotLength' bytes are stored in the buffer and passed to the user application. For instance, snaplen equal to 100 means that only the first 100 bytes of each packet are stored.</param> /// <param name="snapshotLength">Length of the packet that has to be retained. For each packet received by the filter, only the first 'snapshotLength' bytes are stored in the buffer and passed to the user application. For instance, snaplen equal to 100 means that only the first 100 bytes of each packet are stored.</param>
/// <param name="attributes">keeps several flags that can be needed for capturing packets.</param> /// <param name="attributes">Keeps several flags that can be needed for capturing packets.</param>
/// <param name="readTimeout">read timeout in milliseconds. The read timeout is used to arrange that the read not necessarily return immediately when a packet is seen, but that it waits for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. Not all platforms support a read timeout; on platforms that don't, the read timeout is ignored.</param> /// <param name="readTimeout">Read timeout in milliseconds. The read timeout is used to arrange that the read not necessarily return immediately when a packet is seen, but that it waits for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. Not all platforms support a read timeout; on platforms that don't, the read timeout is ignored.</param>
/// <exception cref="System::InvalidOperationException">Thrown on failure.</exception>
virtual PacketCommunicator^ Open(int snapshotLength, PacketDeviceOpenAttributes attributes, int readTimeout) override; virtual PacketCommunicator^ Open(int snapshotLength, PacketDeviceOpenAttributes attributes, int readTimeout) override;
private: private:
......
...@@ -4,31 +4,58 @@ ...@@ -4,31 +4,58 @@
namespace PcapDotNet { namespace Core namespace PcapDotNet { namespace Core
{ {
/// <summary>
/// An offline interface - a pcap file to read packets from.
/// </summary>
public ref class OfflinePacketDevice : PacketDevice public ref class OfflinePacketDevice : PacketDevice
{ {
public: public:
/// <summary>
/// Creates a device object from a pcap file.
/// The device can opened to read packets from.
/// </summary>
/// <param name="fileName">The name of the pcap file.</param>
OfflinePacketDevice(System::String^ fileName); OfflinePacketDevice(System::String^ fileName);
/// <summary>
/// A string giving a name for the device.
/// </summary>
virtual property System::String^ Name virtual property System::String^ Name
{ {
System::String^ get() override; System::String^ get() override;
} }
/// <summary>
/// if not null, a string giving a human-readable description of the device.
/// </summary>
virtual property System::String^ Description virtual property System::String^ Description
{ {
System::String^ get() override; System::String^ get() override;
} }
/// <summary>
/// Interface flags. Currently the only possible flag is Loopback, that is set if the interface is a loopback interface.
/// </summary>
virtual property DeviceAttributes^ Attributes virtual property DeviceAttributes^ Attributes
{ {
DeviceAttributes^ get() override; DeviceAttributes^ get() override;
} }
/// <summary>
/// List of addresses for the interface.
/// </summary>
virtual property System::Collections::ObjectModel::ReadOnlyCollection<DeviceAddress^>^ Addresses virtual property System::Collections::ObjectModel::ReadOnlyCollection<DeviceAddress^>^ Addresses
{ {
System::Collections::ObjectModel::ReadOnlyCollection<DeviceAddress^>^ get() override; System::Collections::ObjectModel::ReadOnlyCollection<DeviceAddress^>^ get() override;
} }
/// <summary>
/// Open a generic source in order to capture / send (WinPcap only) traffic.
/// </summary>
/// <param name="snapshotLength">length of the packet that has to be retained. For each packet received by the filter, only the first 'snapshotLength' bytes are stored in the buffer and passed to the user application. For instance, snaplen equal to 100 means that only the first 100 bytes of each packet are stored.</param>
/// <param name="attributes">Keeps several flags that can be needed for capturing packets.</param>
/// <param name="readTimeout">Read timeout in milliseconds. The read timeout is used to arrange that the read not necessarily return immediately when a packet is seen, but that it waits for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. Not all platforms support a read timeout; on platforms that don't, the read timeout is ignored.</param>
/// <exception cref="System::InvalidOperationException">Thrown on failure.</exception>
virtual PacketCommunicator^ Open(int snapshotLength, PacketDeviceOpenAttributes attributes, int readTimeout) override; virtual PacketCommunicator^ Open(int snapshotLength, PacketDeviceOpenAttributes attributes, int readTimeout) override;
private: private:
......
...@@ -221,7 +221,7 @@ PacketCommunicatorReceiveResult PacketCommunicator::ReceiveStatistics([Out] Pack ...@@ -221,7 +221,7 @@ PacketCommunicatorReceiveResult PacketCommunicator::ReceiveStatistics([Out] Pack
if (result != PacketCommunicatorReceiveResult::Ok) if (result != PacketCommunicatorReceiveResult::Ok)
throw gcnew InvalidOperationException("Got result " + result.ToString() + " in statistics mode"); throw gcnew InvalidOperationException("Got result " + result.ToString() + " in statistics mode");
statistics = CreateStatistics(*packetHeader, packetData); statistics = gcnew PacketSampleStatistics(*packetHeader, packetData);
return result; return result;
} }
...@@ -299,18 +299,6 @@ Packet^ PacketCommunicator::CreatePacket(const pcap_pkthdr& packetHeader, const ...@@ -299,18 +299,6 @@ Packet^ PacketCommunicator::CreatePacket(const pcap_pkthdr& packetHeader, const
return gcnew Packet(managedPacketData, timestamp, dataLink); return gcnew Packet(managedPacketData, timestamp, dataLink);
} }
// static
PacketSampleStatistics^ PacketCommunicator::CreateStatistics(const pcap_pkthdr& packetHeader, const unsigned char* packetData)
{
DateTime timestamp;
Timestamp::PcapTimestampToDateTime(packetHeader.ts, timestamp);
unsigned long acceptedPackets = *reinterpret_cast<const unsigned long*>(packetData);
unsigned long acceptedBytes = *reinterpret_cast<const unsigned long*>(packetData + 8);
return gcnew PacketSampleStatistics(timestamp, acceptedPackets, acceptedBytes);
}
PacketCommunicatorReceiveResult PacketCommunicator::RunPcapNextEx(pcap_pkthdr** packetHeader, const unsigned char** packetData) PacketCommunicatorReceiveResult PacketCommunicator::RunPcapNextEx(pcap_pkthdr** packetHeader, const unsigned char** packetData)
{ {
int result = pcap_next_ex(_pcapDescriptor, packetHeader, packetData); int result = pcap_next_ex(_pcapDescriptor, packetHeader, packetData);
...@@ -358,5 +346,5 @@ int PacketCommunicator::PacketHandler::PacketCounter::get() ...@@ -358,5 +346,5 @@ int PacketCommunicator::PacketHandler::PacketCounter::get()
void PacketCommunicator::StatisticsHandler::Handle(unsigned char *user, const struct pcap_pkthdr *packetHeader, const unsigned char *packetData) void PacketCommunicator::StatisticsHandler::Handle(unsigned char *user, const struct pcap_pkthdr *packetHeader, const unsigned char *packetData)
{ {
_callback->Invoke(CreateStatistics(*packetHeader, packetData)); _callback->Invoke(gcnew PacketSampleStatistics(*packetHeader, packetData));
} }
\ No newline at end of file
...@@ -374,7 +374,6 @@ namespace PcapDotNet { namespace Core ...@@ -374,7 +374,6 @@ namespace PcapDotNet { namespace Core
private: private:
static Packets::Packet^ CreatePacket(const pcap_pkthdr& packetHeader, const unsigned char* packetData, Packets::IDataLink^ dataLink); static Packets::Packet^ CreatePacket(const pcap_pkthdr& packetHeader, const unsigned char* packetData, Packets::IDataLink^ dataLink);
static PacketSampleStatistics^ PacketCommunicator::CreateStatistics(const pcap_pkthdr& packetHeader, const unsigned char* packetData);
PacketCommunicatorReceiveResult RunPcapNextEx(pcap_pkthdr** packetHeader, const unsigned char** packetData); PacketCommunicatorReceiveResult RunPcapNextEx(pcap_pkthdr** packetHeader, const unsigned char** packetData);
......
...@@ -4,33 +4,62 @@ ...@@ -4,33 +4,62 @@
namespace PcapDotNet { namespace Core namespace PcapDotNet { namespace Core
{ {
/// <summary>
/// The base class of a live or offline interface.
/// </summary>
public ref class PacketDevice abstract : IPacketDevice public ref class PacketDevice abstract : IPacketDevice
{ {
public: public:
literal int DefaultSnapshotLength = 65536; /// <summary>
/// This snapshort length value should be sufficient, on most if not all networks, to capture all the data available from the packet.
/// </summary>
literal int DefaultSnapshotLength = 65535;
/// <summary>
/// A string giving a name for the device.
/// </summary>
virtual property System::String^ Name virtual property System::String^ Name
{ {
System::String^ get() = 0; System::String^ get() = 0;
} }
/// <summary>
/// if not null, a string giving a human-readable description of the device.
/// </summary>
virtual property System::String^ Description virtual property System::String^ Description
{ {
System::String^ get() = 0; System::String^ get() = 0;
} }
/// <summary>
/// Interface flags. Currently the only possible flag is Loopback, that is set if the interface is a loopback interface.
/// </summary>
virtual property DeviceAttributes^ Attributes virtual property DeviceAttributes^ Attributes
{ {
DeviceAttributes^ get() = 0; DeviceAttributes^ get() = 0;
} }
/// <summary>
/// List of addresses for the interface.
/// </summary>
virtual property System::Collections::ObjectModel::ReadOnlyCollection<DeviceAddress^>^ Addresses virtual property System::Collections::ObjectModel::ReadOnlyCollection<DeviceAddress^>^ Addresses
{ {
System::Collections::ObjectModel::ReadOnlyCollection<DeviceAddress^>^ get() = 0; System::Collections::ObjectModel::ReadOnlyCollection<DeviceAddress^>^ get() = 0;
} }
/// <summary>
/// Open a generic source in order to capture / send (WinPcap only) traffic.
/// </summary>
/// <param name="snapshotLength">Length of the packet that has to be retained. For each packet received by the filter, only the first 'snapshotLength' bytes are stored in the buffer and passed to the user application. For instance, snaplen equal to 100 means that only the first 100 bytes of each packet are stored.</param>
/// <param name="attributes">Keeps several flags that can be needed for capturing packets.</param>
/// <param name="readTimeout">Read timeout in milliseconds. The read timeout is used to arrange that the read not necessarily return immediately when a packet is seen, but that it waits for some amount of time to allow more packets to arrive and to read multiple packets from the OS kernel in one operation. Not all platforms support a read timeout; on platforms that don't, the read timeout is ignored.</param>
/// <exception cref="System::InvalidOperationException">Thrown on failure.</exception>
virtual PacketCommunicator^ Open(int snapshotLength, PacketDeviceOpenAttributes attributes, int readTimeout) = 0; virtual PacketCommunicator^ Open(int snapshotLength, PacketDeviceOpenAttributes attributes, int readTimeout) = 0;
/// <summary>
/// Open a generic source in order to capture / send (WinPcap only) traffic.
/// Uses maxmimum snapshotLength (65536), promiscuous mode and 1 second read timeout.
/// </summary>
virtual PacketCommunicator^ Open(); virtual PacketCommunicator^ Open();
protected: protected:
......
...@@ -4,18 +4,38 @@ ...@@ -4,18 +4,38 @@
namespace PcapDotNet { namespace Core namespace PcapDotNet { namespace Core
{ {
/// <summary>
/// A file to write packets.
/// </summary>
public ref class PacketDumpFile : System::IDisposable public ref class PacketDumpFile : System::IDisposable
{ {
public: public:
/// <summary>
/// Save a packet to disk.
/// Outputs a packet to the "savefile" opened with PacketCommunicator.OpenDump().
/// </summary>
/// <param name="packet">The packet to write to disk.</param>
void Dump(Packets::Packet^ packet); void Dump(Packets::Packet^ packet);
/// <summary>
/// Flushes the output buffer to the ``savefile,'' so that any packets written with Dump() but not yet written to the ``savefile'' will be written.
/// </summary>
/// <exception cref="System::InvalidOperationException">Thrown on error.</exception>
void Flush(); void Flush();
/// <summary>
/// Return the file position for a "savefile".
/// Returns the current file position for the "savefile", representing the number of bytes written by PacketCommunicator.OpenDump() and Dump().
/// </summary>
/// <exception cref="System::InvalidOperationException">Thrown on error.</exception>
property long Position property long Position
{ {
long get(); long get();
} }
/// <summary>
/// Closes a savefile.
/// </summary>
~PacketDumpFile(); ~PacketDumpFile();
internal: internal:
......
#include "PacketSampleStatistics.h" #include "PacketSampleStatistics.h"
#include "Timestamp.h"
#include "Pcap.h"
using namespace System; using namespace System;
using namespace PcapDotNet::Core; using namespace PcapDotNet::Core;
PacketSampleStatistics::PacketSampleStatistics(DateTime timestamp, unsigned long acceptedPackets, unsigned long acceptedBytes)
{
_timestamp = timestamp;
_acceptedPackets = acceptedPackets;
_acceptedBytes = acceptedBytes;
}
DateTime PacketSampleStatistics::Timestamp::get() DateTime PacketSampleStatistics::Timestamp::get()
{ {
return _timestamp; return _timestamp;
...@@ -27,4 +22,14 @@ unsigned long PacketSampleStatistics::AcceptedBytes::get() ...@@ -27,4 +22,14 @@ unsigned long PacketSampleStatistics::AcceptedBytes::get()
System::String^ PacketSampleStatistics::ToString() System::String^ PacketSampleStatistics::ToString()
{ {
return _timestamp + ": " + AcceptedPackets + " packets. " + AcceptedBytes + " bytes."; return _timestamp + ": " + AcceptedPackets + " packets. " + AcceptedBytes + " bytes.";
}
// Internal
PacketSampleStatistics::PacketSampleStatistics(const pcap_pkthdr& packetHeader, const unsigned char* packetData)
{
PcapDotNet::Core::Timestamp::PcapTimestampToDateTime(packetHeader.ts, _timestamp);
_acceptedPackets = *reinterpret_cast<const unsigned long*>(packetData);
_acceptedBytes = *reinterpret_cast<const unsigned long*>(packetData + 8);
} }
\ No newline at end of file
#pragma once #pragma once
#include "PcapDeclarations.h"
namespace PcapDotNet { namespace Core namespace PcapDotNet { namespace Core
{ {
/// <summary>
/// Represents a statistics value when running in statistics mode.
/// </summary>
public ref class PacketSampleStatistics public ref class PacketSampleStatistics
{ {
public: public:
PacketSampleStatistics(System::DateTime timestamp, unsigned long acceptedPackets, unsigned long acceptedBytes); /// <summary>
/// The time the statistics was received.
/// </summary>
property System::DateTime Timestamp property System::DateTime Timestamp
{ {
System::DateTime get(); System::DateTime get();
} }
/// <summary>
/// The number of packets received during the last interval.
/// </summary>
property unsigned long AcceptedPackets property unsigned long AcceptedPackets
{ {
unsigned long get(); unsigned long get();
} }
/// <summary>
/// The number of bytes received during the last interval.
/// </summary>
property unsigned long AcceptedBytes property unsigned long AcceptedBytes
{ {
unsigned long get(); unsigned long get();
...@@ -24,6 +36,9 @@ namespace PcapDotNet { namespace Core ...@@ -24,6 +36,9 @@ namespace PcapDotNet { namespace Core
virtual System::String^ ToString() override; virtual System::String^ ToString() override;
internal:
PacketSampleStatistics(const pcap_pkthdr& packetHeader, const unsigned char* packetData);
private: private:
System::DateTime _timestamp; System::DateTime _timestamp;
unsigned long _acceptedPackets; unsigned long _acceptedPackets;
......
...@@ -4,13 +4,30 @@ ...@@ -4,13 +4,30 @@
namespace PcapDotNet { namespace Core namespace PcapDotNet { namespace Core
{ {
/// <summary>
/// Represents a buffer of packets to be sent.
/// Note that transmitting a send buffer is much more efficient than performing a series of Send(), because the send buffer is buffered at kernel level drastically decreasing the number of context switches.
/// </summary>
public ref class PacketSendBuffer : System::IDisposable public ref class PacketSendBuffer : System::IDisposable
{ {
public: public:
/// <summary>
/// This function allocates a send buffer, i.e. a buffer containing a set of raw packets that will be transimtted on the network with PacketCommunicator.Transmit().
/// </summary>
/// <param name="capacity">The size, in bytes, of the buffer, therefore it determines the maximum amount of data that the buffer will contain.</param>
PacketSendBuffer(unsigned int capacity); PacketSendBuffer(unsigned int capacity);
/// <summary>
/// Adds a raw packet at the end of the send buffer.
/// 'Raw packet' means that the sending application will have to include the protocol headers, since every packet is sent to the network 'as is'. The CRC of the packets needs not to be calculated, because it will be transparently added by the network interface.
/// </summary>
/// <param name="packet">The packet to be added to the buffer</param>
/// <exception cref="System::InvalidOperationException">Thrown on failure.</exception>
void Enqueue(Packets::Packet^ packet); void Enqueue(Packets::Packet^ packet);
/// <summary>
/// Deletes a send buffer and frees all the memory associated with it.
/// </summary>
~PacketSendBuffer(); ~PacketSendBuffer();
internal: internal:
......
#include "PacketTotalStatistics.h" #include "PacketTotalStatistics.h"
#include "Pcap.h"
using namespace System; using namespace System;
using namespace System::Text; using namespace System::Text;
using namespace PcapDotNet::Core; using namespace PcapDotNet::Core;
PacketTotalStatistics::PacketTotalStatistics(unsigned int packetsReceived, unsigned int packetsDroppedByDriver, unsigned int packetsDroppedByInterface, unsigned int packetsCaptured)
{
_packetsReceived = packetsReceived;
_packetsDroppedByDriver = packetsDroppedByDriver;
_packetsDroppedByInterface = packetsDroppedByInterface;
_packetsCaptured = packetsCaptured;
}
unsigned int PacketTotalStatistics::PacketsReceived::get() unsigned int PacketTotalStatistics::PacketsReceived::get()
{ {
return _packetsReceived; return _packetsReceived;
...@@ -73,4 +66,15 @@ String^ PacketTotalStatistics::ToString() ...@@ -73,4 +66,15 @@ String^ PacketTotalStatistics::ToString()
stringBuilder->Append(PacketsCaptured); stringBuilder->Append(PacketsCaptured);
stringBuilder->Append("."); stringBuilder->Append(".");
return stringBuilder->ToString(); return stringBuilder->ToString();
}
// Internal
PacketTotalStatistics::PacketTotalStatistics(const pcap_stat& statistics, int statisticsSize)
{
_packetsReceived = statistics.ps_recv;
_packetsDroppedByDriver = statistics.ps_drop;
_packetsDroppedByInterface = statistics.ps_ifdrop;
_packetsCaptured = (statisticsSize >= 16
? *(reinterpret_cast<const int*>(&statistics) + 3)
: 0);
} }
\ No newline at end of file
#pragma once #pragma once
#include "PcapDeclarations.h"
namespace PcapDotNet { namespace Core namespace PcapDotNet { namespace Core
{ {
/// <summary>
/// Statistics on capture from the start of the run.
/// </summary>
public ref class PacketTotalStatistics : System::IEquatable<PacketTotalStatistics^> public ref class PacketTotalStatistics : System::IEquatable<PacketTotalStatistics^>
{ {
public: public:
PacketTotalStatistics(unsigned int packetsReceived, unsigned int packetsDroppedByDriver, unsigned int packetsDroppedByInterface, unsigned int packetsCaptured); /// <summary>
/// Number of packets transited on the network.
/// </summary>
property unsigned int PacketsReceived property unsigned int PacketsReceived
{ {
unsigned int get(); unsigned int get();
} }
/// <summary>
/// Number of packets dropped by the driver.
/// </summary>
property unsigned int PacketsDroppedByDriver property unsigned int PacketsDroppedByDriver
{ {
unsigned int get(); unsigned int get();
} }
/// <summary>
/// number of packets dropped by the interface.
/// </summary>
property unsigned int PacketsDroppedByInterface property unsigned int PacketsDroppedByInterface
{ {
unsigned int get(); unsigned int get();
} }
/// <summary>
/// Win32 specific. Number of packets captured, i.e number of packets that are accepted by the filter, that find place in the kernel buffer and therefore that actually reach the application.
/// </summary>
property unsigned int PacketsCaptured property unsigned int PacketsCaptured
{ {
unsigned int get(); unsigned int get();
...@@ -34,6 +49,9 @@ namespace PcapDotNet { namespace Core ...@@ -34,6 +49,9 @@ namespace PcapDotNet { namespace Core
virtual System::String^ ToString() override; virtual System::String^ ToString() override;
internal:
PacketTotalStatistics(const pcap_stat& statistics, int statisticsSize);
private: private:
unsigned int _packetsReceived; unsigned int _packetsReceived;
unsigned int _packetsDroppedByDriver; unsigned int _packetsDroppedByDriver;
......
...@@ -2,28 +2,57 @@ ...@@ -2,28 +2,57 @@
namespace PcapDotNet { namespace Core namespace PcapDotNet { namespace Core
{ {
/// <summary>
/// A packet communicator datalink.
/// </summary>
public value class PcapDataLink : Packets::IDataLink, System::IEquatable<PcapDataLink> public value class PcapDataLink : Packets::IDataLink, System::IEquatable<PcapDataLink>
{ {
public: public:
/// <summary>
/// Create the datalink from one of the well defined datalink kinds.
/// </summary>
/// <param name="kind">The kind of datalink to create.</param>
PcapDataLink(Packets::DataLinkKind kind); PcapDataLink(Packets::DataLinkKind kind);
/// <summary>
/// Create the datalink from an int value (pcap value).
/// </summary>
/// <param name="value">The pcap value of the datalink.</param>
PcapDataLink(int value); PcapDataLink(int value);
/// <summary>
/// Create the datalink its name.
/// </summary>
/// <param name="name">The name of the pcap datalink.</param>
PcapDataLink(System::String^ name); PcapDataLink(System::String^ name);
/// <summary>
/// The kind of the datalink.
/// </summary>
virtual property Packets::DataLinkKind Kind virtual property Packets::DataLinkKind Kind
{ {
Packets::DataLinkKind get(); Packets::DataLinkKind get();
} }
/// <summary>
/// The pcap value of the datalink.
/// </summary>
property int Value property int Value
{ {
int get(); int get();
} }
/// <summary>
/// The name of the datalink.
/// </summary>
property System::String^ Name property System::String^ Name
{ {
System::String^ get(); System::String^ get();
} }
/// <summary>
/// The description of the datalink.
/// </summary>
property System::String^ Description property System::String^ Description
{ {
System::String^ get(); System::String^ get();
......
...@@ -6,6 +6,7 @@ struct pcap_rmtauth; ...@@ -6,6 +6,7 @@ struct pcap_rmtauth;
struct pcap_send_queue; struct pcap_send_queue;
struct sockaddr; struct sockaddr;
struct timeval; struct timeval;
struct pcap_stat;
typedef struct pcap_addr pcap_addr_t; typedef struct pcap_addr pcap_addr_t;
typedef struct pcap_dumper pcap_dumper_t; typedef struct pcap_dumper pcap_dumper_t;
......
...@@ -2,9 +2,15 @@ ...@@ -2,9 +2,15 @@
namespace PcapDotNet { namespace Core namespace PcapDotNet { namespace Core
{ {
/// <summary>
/// This class holds methods for general pcap library functionality.
/// </summary>
public ref class PcapLibrary sealed public ref class PcapLibrary sealed
{ {
public: public:
/// <summary>
/// The Pcap library version.
/// </summary>
static property System::String^ Version static property System::String^ Version
{ {
System::String^ get(); System::String^ get();
......
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