Commit d9ff3069 authored by Brickner_cp's avatar Brickner_cp

ARP.

Code Coverage 93.30%
parent 69229a7d
using System; using System;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
...@@ -93,6 +94,23 @@ namespace PcapDotNet.Base ...@@ -93,6 +94,23 @@ namespace PcapDotNet.Base
return sequence.SequenceToString(string.Empty); return sequence.SequenceToString(string.Empty);
} }
/// <summary>
/// Returns a hash code by xoring all the bytes.
/// Each byte is xored with the next 8 bits of the integer.
/// </summary>
/// <param name="sequence">The bytes to xor.</param>
/// <returns>The hash code resulted by xoring all the bytes.</returns>
public static string BytesSequenceToHexadecimalString(this IEnumerable<byte> sequence, string separator)
{
return sequence.Aggregate(string.Empty,
delegate(string result, byte value)
{
if (!string.IsNullOrEmpty(result))
result = result + separator;
return result + string.Format(CultureInfo.InvariantCulture, "{0:x2}", value);
});
}
/// <summary> /// <summary>
/// Creates a hash code by xoring the hash codes of the elements in the sequence. /// Creates a hash code by xoring the hash codes of the elements in the sequence.
/// </summary> /// </summary>
......
...@@ -8,6 +8,7 @@ using PcapDotNet.Core.Extensions; ...@@ -8,6 +8,7 @@ using PcapDotNet.Core.Extensions;
using PcapDotNet.Packets; using PcapDotNet.Packets;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Packets.TestUtils; using PcapDotNet.Packets.TestUtils;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Core.Test namespace PcapDotNet.Core.Test
{ {
......
...@@ -5,6 +5,7 @@ using System.Threading; ...@@ -5,6 +5,7 @@ using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Packets; using PcapDotNet.Packets;
using PcapDotNet.Packets.TestUtils; using PcapDotNet.Packets.TestUtils;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Core.Test namespace PcapDotNet.Core.Test
{ {
......
using System; using System;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Packets; using PcapDotNet.Packets;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Core.Test namespace PcapDotNet.Core.Test
{ {
......
...@@ -3,6 +3,7 @@ using System.Collections.Generic; ...@@ -3,6 +3,7 @@ using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Packets; using PcapDotNet.Packets;
using PcapDotNet.Packets.TestUtils; using PcapDotNet.Packets.TestUtils;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Core.Test namespace PcapDotNet.Core.Test
{ {
......
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BerkeleyPacketFilterTests.cs" /> <Compile Include="BerkeleyPacketFilterTests.cs" />
<Compile Include="MoreAssert.cs" />
<Compile Include="LivePacketDeviceTests.cs" /> <Compile Include="LivePacketDeviceTests.cs" />
<Compile Include="MoreIpV4Option.cs" /> <Compile Include="MoreIpV4Option.cs" />
<Compile Include="MoreTcpOption.cs" /> <Compile Include="MoreTcpOption.cs" />
......
...@@ -3,6 +3,7 @@ using System.Collections.Generic; ...@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Core.Test namespace PcapDotNet.Core.Test
{ {
......
...@@ -10,6 +10,7 @@ using System.Xml.Linq; ...@@ -10,6 +10,7 @@ using System.Xml.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets; using PcapDotNet.Packets;
using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.Ethernet; using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.TestUtils; using PcapDotNet.Packets.TestUtils;
...@@ -103,6 +104,7 @@ namespace PcapDotNet.Core.Test ...@@ -103,6 +104,7 @@ namespace PcapDotNet.Core.Test
private enum PacketType private enum PacketType
{ {
Ethernet, Ethernet,
Arp,
IpV4, IpV4,
Udp, Udp,
Tcp Tcp
...@@ -114,7 +116,6 @@ namespace PcapDotNet.Core.Test ...@@ -114,7 +116,6 @@ namespace PcapDotNet.Core.Test
for (int i = 0; i != numPackets; ++i) for (int i = 0; i != numPackets; ++i)
{ {
DateTime packetTimestamp = random.NextDateTime(PacketTimestamp.MinimumPacketTimestamp, PacketTimestamp.MaximumPacketTimestamp).ToUniversalTime().ToLocalTime(); DateTime packetTimestamp = random.NextDateTime(PacketTimestamp.MinimumPacketTimestamp, PacketTimestamp.MaximumPacketTimestamp).ToUniversalTime().ToLocalTime();
// switch (PacketType.Tcp)
switch (random.NextEnum<PacketType>()) switch (random.NextEnum<PacketType>())
{ {
case PacketType.Ethernet: case PacketType.Ethernet:
...@@ -123,6 +124,16 @@ namespace PcapDotNet.Core.Test ...@@ -123,6 +124,16 @@ namespace PcapDotNet.Core.Test
random.NextDatagram(random.Next(100))); random.NextDatagram(random.Next(100)));
break; break;
case PacketType.Arp:
byte hardwareAddressLength = random.NextByte();
byte protocolAddressLength = random.NextByte();
yield return PacketBuilder.EthernetArp(packetTimestamp,
random.NextMacAddress(),
random.NextEnum<EthernetType>(), random.NextEnum<ArpOperation>(),
random.NextBytes(hardwareAddressLength), random.NextBytes(protocolAddressLength),
random.NextBytes(hardwareAddressLength), random.NextBytes(protocolAddressLength));
break;
case PacketType.IpV4: case PacketType.IpV4:
yield return PacketBuilder.EthernetIpV4(packetTimestamp, yield return PacketBuilder.EthernetIpV4(packetTimestamp,
random.NextMacAddress(), random.NextMacAddress(), random.NextMacAddress(), random.NextMacAddress(),
...@@ -244,6 +255,14 @@ namespace PcapDotNet.Core.Test ...@@ -244,6 +255,14 @@ namespace PcapDotNet.Core.Test
CompareEtherent(layer, (EthernetDatagram)currentDatagram); CompareEtherent(layer, (EthernetDatagram)currentDatagram);
break; break;
case "arp":
PropertyInfo arpProperty = currentDatagram.GetType().GetProperty("Arp");
if (arpProperty == null)
break;
currentDatagram = arpProperty.GetValue(currentDatagram);
CompareArp(layer, (ArpDatagram)currentDatagram);
break;
case "ip": case "ip":
PropertyInfo ipV4Property = currentDatagram.GetType().GetProperty("IpV4"); PropertyInfo ipV4Property = currentDatagram.GetType().GetProperty("IpV4");
if (ipV4Property == null) if (ipV4Property == null)
...@@ -325,6 +344,55 @@ namespace PcapDotNet.Core.Test ...@@ -325,6 +344,55 @@ namespace PcapDotNet.Core.Test
} }
} }
private static void CompareArp(XElement arp, ArpDatagram arpDatagram)
{
foreach (var field in arp.Fields())
{
switch (field.Name())
{
case "arp.hw.type":
field.AssertShowHex((ushort)arpDatagram.HardwareType);
break;
case "arp.proto.type":
field.AssertShowHex((ushort)arpDatagram.ProtocolType);
break;
case "arp.hw.size":
field.AssertShowDecimal(arpDatagram.HardwareLength);
break;
case "arp.proto.size":
field.AssertShowDecimal(arpDatagram.ProtocolLength);
break;
case "arp.opcode":
field.AssertShowHex((ushort)arpDatagram.Operation);
break;
// case "arp.isgratuitous":
// field.AssertShowDecimal(false);
// break;
case "arp.src.hw":
field.AssertShow(arpDatagram.SenderHardwareAddress.BytesSequenceToHexadecimalString(":"));
break;
case "arp.src.proto":
field.AssertShow(arpDatagram.SenderProtocolAddress.BytesSequenceToHexadecimalString(":"));
break;
case "arp.dst.hw":
field.AssertShow(arpDatagram.TargetHardwareAddress.BytesSequenceToHexadecimalString(":"));
break;
case "arp.dst.proto":
field.AssertShow(arpDatagram.TargetProtocolAddress.BytesSequenceToHexadecimalString(":"));
break;
}
}
}
private static void CompareEthernetAddress(XElement element, MacAddress address) private static void CompareEthernetAddress(XElement element, MacAddress address)
{ {
foreach (var field in element.Fields()) foreach (var field in element.Fields())
......
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.TestUtils;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.Test
{
/// <summary>
/// Summary description for ArpTests
/// </summary>
[TestClass]
public class ArpTests
{
public ArpTests()
{
//
// TODO: Add constructor logic here
//
}
/// <summary>
///Gets or sets the test context which provides
///information about and functionality for the current test run.
///</summary>
public TestContext TestContext { get; set; }
#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 RandomArpTest()
{
Random random = new Random();
for (int i = 0; i != 1000; ++i)
{
MacAddress ethernetSource = random.NextMacAddress();
EthernetType ethernetType = random.NextEnum<EthernetType>();
ArpOperation arpOperation = random.NextEnum<ArpOperation>();
byte hardwareAddressLength = random.NextByte();
byte protocolAddressLength = random.NextByte();
byte[] arpSenderHardwareAddress = random.NextBytes(hardwareAddressLength);
byte[] arpSenderProtocolAddress = random.NextBytes(protocolAddressLength);
byte[] arpTargetHardwareAddress = random.NextBytes(hardwareAddressLength);
byte[] arpTargetProtocolAddress = random.NextBytes(protocolAddressLength);
Packet packet = PacketBuilder.EthernetArp(DateTime.Now,
ethernetSource,
ethernetType, arpOperation,
arpSenderHardwareAddress, arpSenderProtocolAddress,
arpTargetHardwareAddress, arpTargetProtocolAddress);
// Ethernet
Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLength, packet.Ethernet.PayloadLength, "PayloadLength");
Assert.AreEqual(ethernetSource, packet.Ethernet.Source, "Ethernet Source");
Assert.AreEqual(EthernetDatagram.BroadcastAddress, packet.Ethernet.Destination, "Ethernet Destination");
Assert.AreEqual(EthernetType.Arp, packet.Ethernet.EtherType, "Ethernet EtherType");
// Arp
Assert.AreEqual(ArpDatagram.HeaderBaseLength + 2 * hardwareAddressLength + 2 * protocolAddressLength, packet.Ethernet.Arp.Length, "Arp length");
Assert.AreEqual(ArpHardwareType.Ethernet, packet.Ethernet.Arp.HardwareType, "Arp hardware type");
Assert.AreEqual(ethernetType, packet.Ethernet.Arp.ProtocolType, "Arp protocol type");
Assert.AreEqual(hardwareAddressLength, packet.Ethernet.Arp.HardwareLength, "Arp hardware length");
Assert.AreEqual(protocolAddressLength, packet.Ethernet.Arp.ProtocolLength, "Arp protocol length");
Assert.AreEqual(arpOperation, packet.Ethernet.Arp.Operation, "Arp operation");
MoreAssert.AreSequenceEqual(arpSenderHardwareAddress, packet.Ethernet.Arp.SenderHardwareAddress, "Arp SenderHardwareAddress");
MoreAssert.AreSequenceEqual(arpSenderProtocolAddress, packet.Ethernet.Arp.SenderProtocolAddress, "Arp SenderProtocolAddress");
MoreAssert.AreSequenceEqual(arpTargetHardwareAddress, packet.Ethernet.Arp.TargetHardwareAddress, "Arp TargetHardwareAddress");
MoreAssert.AreSequenceEqual(arpTargetProtocolAddress, packet.Ethernet.Arp.TargetProtocolAddress, "Arp TargetProtocolAddress");
}
}
}
}
\ No newline at end of file
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ArpTests.cs" />
<Compile Include="DatagramTests.cs" /> <Compile Include="DatagramTests.cs" />
<Compile Include="DataLinkTests.cs" /> <Compile Include="DataLinkTests.cs" />
<Compile Include="EndianitiyTests.cs" /> <Compile Include="EndianitiyTests.cs" />
......
...@@ -115,6 +115,7 @@ namespace PcapDotNet.Packets.Test ...@@ -115,6 +115,7 @@ namespace PcapDotNet.Packets.Test
Assert.AreEqual(option, option); Assert.AreEqual(option, option);
Assert.AreEqual(option.GetHashCode(), option.GetHashCode()); Assert.AreEqual(option.GetHashCode(), option.GetHashCode());
Assert.IsFalse(string.IsNullOrEmpty(option.ToString())); Assert.IsFalse(string.IsNullOrEmpty(option.ToString()));
} }
Assert.AreEqual(tcpOptions, packet.Ethernet.IpV4.Tcp.Options, "Options"); Assert.AreEqual(tcpOptions, packet.Ethernet.IpV4.Tcp.Options, "Options");
Assert.AreEqual((tcpControlBits & TcpControlBits.Acknowledgment) == TcpControlBits.Acknowledgment, packet.Ethernet.IpV4.Tcp.IsAcknowledgment, "IsAcknowledgment"); Assert.AreEqual((tcpControlBits & TcpControlBits.Acknowledgment) == TcpControlBits.Acknowledgment, packet.Ethernet.IpV4.Tcp.IsAcknowledgment, "IsAcknowledgment");
......
using System;
using PcapDotNet.Packets.Ethernet;
namespace PcapDotNet.Packets.Arp
{
/// <summary>
/// The following is the packet structure used for ARP requests and replies.
/// On Ethernet networks, these packets use an EtherType of 0x0806, and are sent to the broadcast MAC address of FF:FF:FF:FF:FF:FF.
/// Note that the EtherType (0x0806) is used in the Ethernet header, and should not be used as the PTYPE of the ARP packet.
/// The ARP type (0x0806) should never be used in the PTYPE field of an ARP packet, since a hardware protocol address should never be linked to the ARP protocol.
/// Note that the packet structure shown in the table has SHA and THA as 48-bit fields and SPA and TPA as 32-bit fields but this is just for convenience
/// their actual lengths are determined by the hardware & protocol length fields.
/// <pre>
/// +-----+------------------------+------------------------+-----------------------------------------------+
/// | bit | 0-7 | 8-15 | 16-31 |
/// +-----+------------------------+------------------------+-----------------------------------------------+
/// | 0 | Hardware type (HTYPE) | Protocol type (PTYPE) |
/// +-----+------------------------+------------------------+-----------------------------------------------+
/// | 32 | Hardware length (HLEN) | Protocol length (PLEN) | Operation (OPER) |
/// +-----+------------------------+------------------------+-----------------------------------------------+
/// | 64 | Sender hardware address (SHA) (first 32 bits) |
/// +-----+-------------------------------------------------+-----------------------------------------------+
/// | 96 | Sender hardware address (SHA) (last 16 bits) | Sender protocol address (SPA) (first 16 bits) |
/// +-----+-------------------------------------------------+-----------------------------------------------+
/// | 128 | Sender protocol address (SPA) (last 16 bits) | Target hardware address (THA) (first 16 bits) |
/// +-----+-------------------------------------------------+-----------------------------------------------+
/// | 160 | Target hardware address (THA) (last 32 bits) |
/// +-----+-------------------------------------------------------------------------------------------------+
/// | 192 | Target protocol address (TPA) |
/// +-----+-------------------------------------------------------------------------------------------------+
/// </pre>
/// </summary>
public class ArpDatagram : Datagram
{
private static class Offset
{
public const int HardwareType = 0;
public const int ProtocolType = 2;
public const int HardwareLength = 4;
public const int ProtocolLength = 5;
public const int Operation = 6;
public const int SenderHardwareAddress = 8;
}
public const int HeaderBaseLength = 8;
/// <summary>
/// Each data link layer protocol is assigned a number used in this field.
/// </summary>
public ArpHardwareType HardwareType
{
get { return (ArpHardwareType)ReadUShort(Offset.HardwareType, Endianity.Big); }
}
/// <summary>
/// Each protocol is assigned a number used in this field.
/// </summary>
public EthernetType ProtocolType
{
get { return (EthernetType)ReadUShort(Offset.ProtocolType, Endianity.Big); }
}
/// <summary>
/// Length in bytes of a hardware address. Ethernet addresses are 6 bytes long.
/// </summary>
public byte HardwareLength
{
get { return this[Offset.HardwareLength]; }
}
/// <summary>
/// Length in bytes of a logical address. IPv4 address are 4 bytes long.
/// </summary>
public byte ProtocolLength
{
get { return this[Offset.ProtocolLength]; }
}
/// <summary>
/// Specifies the operation the sender is performing.
/// </summary>
public ArpOperation Operation
{
get { return (ArpOperation)ReadUShort(Offset.Operation, Endianity.Big); }
}
/// <summary>
/// Hardware address of the sender.
/// </summary>
public byte[] SenderHardwareAddress
{
get { return ReadBytes(Offset.SenderHardwareAddress, HardwareLength); }
}
/// <summary>
/// Protocol address of the sender.
/// </summary>
public byte[] SenderProtocolAddress
{
get { return ReadBytes(OffsetSenderProtocolAddress, ProtocolLength); }
}
/// <summary>
/// Hardware address of the intended receiver.
/// This field is ignored in requests.
/// </summary>
public byte[] TargetHardwareAddress
{
get { return ReadBytes(OffsetTargetHardwareAddress, HardwareLength); }
}
/// <summary>
/// Protocol address of the intended receiver.
/// </summary>
public byte[] TargetProtocolAddress
{
get { return ReadBytes(OffsetTargetProtocolAddress, ProtocolLength); }
}
internal ArpDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length)
{
}
internal static int GetHeaderLength(int hardwareLength, int protocolLength)
{
return HeaderBaseLength + 2 * hardwareLength + 2 * protocolLength;
}
internal static void WriteHeader(byte[] buffer, int offset,
ArpHardwareType hardwareType, EthernetType protocolType, ArpOperation operation,
byte[] senderHardwareAddress, byte[] senderProtocolAddress,
byte[] targetHardwareAddress, byte[] targetProtocolAddress)
{
buffer.Write(ref offset, (ushort)hardwareType, Endianity.Big);
buffer.Write(ref offset, (ushort)protocolType, Endianity.Big);
buffer.Write(ref offset, (byte)senderHardwareAddress.Length);
buffer.Write(ref offset, (byte)senderProtocolAddress.Length);
buffer.Write(ref offset, (ushort)operation, Endianity.Big);
buffer.Write(ref offset, senderHardwareAddress);
buffer.Write(ref offset, senderProtocolAddress);
buffer.Write(ref offset, targetHardwareAddress);
buffer.Write(ref offset, targetProtocolAddress);
}
private int OffsetSenderProtocolAddress
{
get { return Offset.SenderHardwareAddress + HardwareLength; }
}
private int OffsetTargetHardwareAddress
{
get { return OffsetSenderProtocolAddress + ProtocolLength; }
}
private int OffsetTargetProtocolAddress
{
get { return OffsetTargetHardwareAddress + HardwareLength; }
}
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Arp
{
public enum ArpHardwareType : ushort
{
/// <summary>
/// Ethernet (10Mb)
/// </summary>
Ethernet = 1,
/// <summary>
/// Experimental Ethernet (3Mb)
/// </summary>
ExperimentalEthernet = 2,
/// <summary>
/// Amateur Radio AX.25
/// </summary>
AmateurRadioAx25 = 3,
/// <summary>
/// Proteon ProNET Token Ring
/// </summary>
ProteonProNetTokenRing = 4,
/// <summary>
/// Chaos
/// </summary>
Chaos = 5,
/// <summary>
/// IEEE 802 Networks
/// </summary>
Ieee802Networks = 6,
/// <summary>
/// ARCNET
/// </summary>
Arcnet = 7,
/// <summary>
/// Hyperchannel
/// </summary>
Hyperchannel = 8,
/// <summary>
/// Lanstar
/// </summary>
Lanstar = 9,
/// <summary>
/// Autonet Short Address
/// </summary>
AutonetShortAddress = 10,
/// <summary>
/// LocalTalk
/// </summary>
LocalTalk = 11,
/// <summary>
/// LocalNet (IBM PCNet or SYTEK LocalNET)
/// </summary>
LocalNet = 12,
/// <summary>
/// Ultra link
/// </summary>
UltraLink = 13,
/// <summary>
/// SMDS
/// </summary>
Smds = 14,
/// <summary>
/// Frame Relay
/// </summary>
FrameRelay = 15,
/// <summary>
/// Asynchronous Transmission Mode (ATM)
/// </summary>
AsynchronousTransmissionMode16 = 16,
/// <summary>
/// HDLC
/// </summary>
Hdlc = 17,
/// <summary>
/// Fibre Channel
/// </summary>
FibreChannel = 18,
/// <summary>
/// Asynchronous Transmission Mode (ATM)
/// </summary>
AsynchronousTransmissionMode19 = 19,
/// <summary>
/// Serial Line
/// </summary>
SerialLine = 20,
/// <summary>
/// Asynchronous Transmission Mode (ATM)
/// </summary>
AsynchronousTransmissionMode21 = 21,
/// <summary>
/// MIL-STD-188-220
/// </summary>
MilStd188_220 = 22,
/// <summary>
/// Metricom
/// </summary>
Metricom = 23,
/// <summary>
/// IEEE 1394.1995
/// </summary>
Ieee1394_1995 = 24,
/// <summary>
/// MAPOS
/// </summary>
Mapos = 25,
/// <summary>
/// Twinaxial
/// </summary>
Twinaxial = 26,
/// <summary>
/// EUI-64
/// </summary>
Eui64 = 27,
/// <summary>
/// HIPARP
/// </summary>
Hiparp = 28,
/// <summary>
/// IP and ARP over ISO 7816-3
/// </summary>
IpAndArpOverIso7816_3 = 29,
/// <summary>
/// ARPSec
/// </summary>
ArpSec = 30,
/// <summary>
/// IPsec tunnel
/// </summary>
IpSecTunnel = 31,
/// <summary>
/// InfiniBand (TM)
/// </summary>
InfiniBand = 32,
/// <summary>
/// TIA-102 Project 25 Common Air Interface (CAI)
/// </summary>
Tia102Project25CommonAirInterface = 33,
/// <summary>
/// Wiegand Interface
/// </summary>
WiegandInterface = 34,
/// <summary>
/// Pure IP
/// </summary>
PureIp = 35,
/// <summary>
/// HW_EXP1
/// </summary>
Experimental1 = 36,
/// <summary>
/// HW_EXP2
/// </summary>
Experimental2 = 256,
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Arp
{
public enum ArpOperation : ushort
{
/// <summary>
/// [RFC826][RFC5227]
/// </summary>
Request = 1,
/// <summary>
/// [RFC826][RFC5227]
/// </summary>
Reply = 2,
/// <summary>
/// [RFC903]
/// </summary>
ReverseRequest = 3,
/// <summary>
/// [RFC903]
/// </summary>
ReverseReply = 4,
/// <summary>
/// [RFC1931]
/// </summary>
DynamicReverseRequest = 5,
/// <summary>
/// [RFC1931]
/// </summary>
DynamicReverseReply = 6,
/// <summary>
/// [RFC1931]
/// </summary>
DynamicReverseError = 7,
/// <summary>
/// [RFC1293]
/// </summary>
InverseRequest = 8,
/// <summary>
/// [RFC1293]
/// </summary>
InverseReply = 9,
/// <summary>
/// [RFC1577]
/// </summary>
NegativeAtmReply = 10,
//MARS-Request = 11
//MARS-Multi = 12
//MARS-MServ = 13
//MARS-Join = 14
//MARS-Leave = 15
//MARS-NAK = 16
//MARS-Unserv = 17
//MARS-SJoin = 18
//MARS-SLeave = 19
//MARS-Grouplist-Request= 20
//MARS-Grouplist-Reply = 21
//MARS-Redirect-Map = 22
/// <summary>
/// [RFC2176]
/// </summary>
MultipleAccessOverSonetOrSdhUnarp = 23,
/// <summary>
/// [RFC5494]
/// </summary>
Experimental1 = 24,
/// <summary>
/// [RFC5494]
/// </summary>
Experimental2 = 25
}
}
\ No newline at end of file
...@@ -152,6 +152,11 @@ namespace PcapDotNet.Packets ...@@ -152,6 +152,11 @@ namespace PcapDotNet.Packets
return true; return true;
} }
protected byte[] ReadBytes(int offset, int length)
{
return Buffer.ReadBytes(StartOffset + offset, length);
}
/// <summary> /// <summary>
/// Reads 2 bytes from a specific offset in the datagram as a ushort with a given endianity. /// Reads 2 bytes from a specific offset in the datagram as a ushort with a given endianity.
/// </summary> /// </summary>
......
using System; using System;
using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Ethernet namespace PcapDotNet.Packets.Ethernet
...@@ -30,6 +31,11 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -30,6 +31,11 @@ namespace PcapDotNet.Packets.Ethernet
/// </summary> /// </summary>
public const int HeaderLength = 14; public const int HeaderLength = 14;
public static MacAddress BroadcastAddress
{
get { return _broadcastAddress; }
}
/// <summary> /// <summary>
/// The Ethernet payload. /// The Ethernet payload.
/// </summary> /// </summary>
...@@ -92,6 +98,16 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -92,6 +98,16 @@ namespace PcapDotNet.Packets.Ethernet
} }
} }
public ArpDatagram Arp
{
get
{
if (_arp == null && Length >= HeaderLength)
_arp = new ArpDatagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength);
return _arp;
}
}
internal EthernetDatagram(byte[] buffer, int offset, int length) internal EthernetDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length) : base(buffer, offset, length)
{ {
...@@ -121,6 +137,8 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -121,6 +137,8 @@ namespace PcapDotNet.Packets.Ethernet
} }
} }
private static readonly MacAddress _broadcastAddress = new MacAddress("FF:FF:FF:FF:FF:FF");
private IpV4Datagram _ipV4; private IpV4Datagram _ipV4;
private ArpDatagram _arp;
} }
} }
\ No newline at end of file
using System; using System;
using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.Ethernet; using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.Transport; using PcapDotNet.Packets.Transport;
...@@ -29,6 +30,31 @@ namespace PcapDotNet.Packets ...@@ -29,6 +30,31 @@ namespace PcapDotNet.Packets
return new Packet(buffer, timestamp, new DataLink(DataLinkKind.Ethernet)); return new Packet(buffer, timestamp, new DataLink(DataLinkKind.Ethernet));
} }
public static Packet EthernetArp(DateTime timestamp,
MacAddress ethernetSource,
EthernetType arpProtocolType, ArpOperation arpOperation,
byte[] arpSenderHardwareAddress, byte[] arpSenderProtocolAddress,
byte[] arpTargetHardwareAddress, byte[] arpTargetProtocolAddress)
{
if (arpSenderHardwareAddress.Length != arpTargetHardwareAddress.Length)
{
throw new ArgumentException("Sender hardware address length is " + arpSenderHardwareAddress.Length + " bytes " +
"while target hardware address length is " + arpTargetHardwareAddress.Length + " bytes");
}
if (arpSenderProtocolAddress.Length != arpTargetProtocolAddress.Length)
{
throw new ArgumentException("Sender protocol address length is " + arpSenderProtocolAddress.Length + " bytes " +
"while target protocol address length is " + arpTargetProtocolAddress.Length + " bytes");
}
byte[] buffer = new byte[EthernetDatagram.HeaderLength + ArpDatagram.GetHeaderLength(arpSenderHardwareAddress.Length, arpSenderProtocolAddress.Length)];
EthernetDatagram.WriteHeader(buffer, 0, ethernetSource, EthernetDatagram.BroadcastAddress, EthernetType.Arp);
ArpDatagram.WriteHeader(buffer, EthernetDatagram.HeaderLength,
ArpHardwareType.Ethernet, arpProtocolType, arpOperation,
arpSenderHardwareAddress, arpSenderProtocolAddress, arpTargetHardwareAddress, arpTargetProtocolAddress);
return new Packet(buffer, timestamp, new DataLink(DataLinkKind.Ethernet));
}
/// <summary> /// <summary>
/// Builds an IPv4 over Ethernet packet. /// Builds an IPv4 over Ethernet packet.
/// </summary> /// </summary>
......
...@@ -60,6 +60,9 @@ ...@@ -60,6 +60,9 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Arp\ArpDatagram.cs" />
<Compile Include="Arp\ArpHardwareType.cs" />
<Compile Include="Arp\ArpOperation.cs" />
<Compile Include="Datagram.cs" /> <Compile Include="Datagram.cs" />
<Compile Include="DataLink.cs" /> <Compile Include="DataLink.cs" />
<Compile Include="DataLinkKind.cs" /> <Compile Include="DataLinkKind.cs" />
......
...@@ -58,6 +58,11 @@ namespace PcapDotNet.Packets.Transport ...@@ -58,6 +58,11 @@ namespace PcapDotNet.Packets.Transport
return Equals(other as TcpOptionConnectionCountBase); return Equals(other as TcpOptionConnectionCountBase);
} }
public override int GetHashCode()
{
return base.GetHashCode() ^ ConnectionCount.GetHashCode();
}
internal override void Write(byte[] buffer, ref int offset) internal override void Write(byte[] buffer, ref int offset)
{ {
base.Write(buffer, ref offset); base.Write(buffer, ref offset);
......
...@@ -90,6 +90,11 @@ namespace PcapDotNet.Packets.Transport ...@@ -90,6 +90,11 @@ namespace PcapDotNet.Packets.Transport
return Equals(other as TcpOptionEcho); return Equals(other as TcpOptionEcho);
} }
public override int GetHashCode()
{
return base.GetHashCode() ^ Info.GetHashCode();
}
/// <summary> /// <summary>
/// Tries to read the option from a buffer starting from the option value (after the type and length). /// Tries to read the option from a buffer starting from the option value (after the type and length).
/// </summary> /// </summary>
......
...@@ -97,6 +97,11 @@ namespace PcapDotNet.Packets.Transport ...@@ -97,6 +97,11 @@ namespace PcapDotNet.Packets.Transport
return Equals(other as TcpOptionEchoReply); return Equals(other as TcpOptionEchoReply);
} }
public override int GetHashCode()
{
return base.GetHashCode() ^ Info.GetHashCode();
}
/// <summary> /// <summary>
/// Tries to read the option from a buffer starting from the option value (after the type and length). /// Tries to read the option from a buffer starting from the option value (after the type and length).
/// </summary> /// </summary>
......
...@@ -2,6 +2,7 @@ using System; ...@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using PcapDotNet.Base;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -97,6 +98,11 @@ namespace PcapDotNet.Packets.Transport ...@@ -97,6 +98,11 @@ namespace PcapDotNet.Packets.Transport
return Equals(other as TcpOptionMd5Signature); return Equals(other as TcpOptionMd5Signature);
} }
public override int GetHashCode()
{
return base.GetHashCode() ^ Data.BytesSequenceGetHashCode();
}
/// <summary> /// <summary>
/// Tries to read the option from a buffer starting from the option value (after the type and length). /// Tries to read the option from a buffer starting from the option value (after the type and length).
/// </summary> /// </summary>
......
...@@ -103,6 +103,11 @@ namespace PcapDotNet.Packets.Transport ...@@ -103,6 +103,11 @@ namespace PcapDotNet.Packets.Transport
return Equals(other as TcpOptionPartialOrderServiceProfile); return Equals(other as TcpOptionPartialOrderServiceProfile);
} }
public override int GetHashCode()
{
return base.GetHashCode() ^ ((IsStart ? 1 : 0) << 1) ^ (IsEnd ? 1 : 0);
}
/// <summary> /// <summary>
/// Tries to read the option from a buffer starting from the option value (after the type and length). /// Tries to read the option from a buffer starting from the option value (after the type and length).
/// </summary> /// </summary>
......
...@@ -2,6 +2,7 @@ using System; ...@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using PcapDotNet.Base;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
...@@ -125,6 +126,11 @@ namespace PcapDotNet.Packets.Transport ...@@ -125,6 +126,11 @@ namespace PcapDotNet.Packets.Transport
return Equals(other as TcpOptionSelectiveAcknowledgment); return Equals(other as TcpOptionSelectiveAcknowledgment);
} }
public override int GetHashCode()
{
return base.GetHashCode() ^ Blocks.SequenceGetHashCode();
}
/// <summary> /// <summary>
/// Tries to read the option from a buffer starting from the option value (after the type and length). /// Tries to read the option from a buffer starting from the option value (after the type and length).
/// </summary> /// </summary>
......
...@@ -105,6 +105,11 @@ namespace PcapDotNet.Packets.Transport ...@@ -105,6 +105,11 @@ namespace PcapDotNet.Packets.Transport
return Equals(other as TcpOptionTimestamp); return Equals(other as TcpOptionTimestamp);
} }
public override int GetHashCode()
{
return base.GetHashCode() ^ TimestampEchoReply.GetHashCode();
}
/// <summary> /// <summary>
/// Tries to read the option from a buffer starting from the option value (after the type and length). /// Tries to read the option from a buffer starting from the option value (after the type and length).
/// </summary> /// </summary>
......
...@@ -5,9 +5,9 @@ using System.Text.RegularExpressions; ...@@ -5,9 +5,9 @@ using System.Text.RegularExpressions;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Base; using PcapDotNet.Base;
namespace PcapDotNet.Core.Test namespace PcapDotNet.TestUtils
{ {
internal static class MoreAssert public static class MoreAssert
{ {
public static void IsBigger<T>(T expectedMinimum, T actual) where T : IComparable<T> public static void IsBigger<T>(T expectedMinimum, T actual) where T : IComparable<T>
{ {
...@@ -63,11 +63,16 @@ namespace PcapDotNet.Core.Test ...@@ -63,11 +63,16 @@ namespace PcapDotNet.Core.Test
Assert.IsTrue(Regex.IsMatch(actualValue, expectedPattern), "Expected pattern: <" + expectedPattern + ">. Actual value: <" + actualValue + ">."); Assert.IsTrue(Regex.IsMatch(actualValue, expectedPattern), "Expected pattern: <" + expectedPattern + ">. Actual value: <" + actualValue + ">.");
} }
public static void AreSequenceEqual<T>(IEnumerable<T> expectedSequence, IEnumerable<T> actualSequence) public static void AreSequenceEqual<T>(IEnumerable<T> expectedSequence, IEnumerable<T> actualSequence, string message)
{ {
Assert.IsTrue(expectedSequence.SequenceEqual(actualSequence), Assert.IsTrue(expectedSequence.SequenceEqual(actualSequence),
"Expected sequence: <" + expectedSequence.SequenceToString(",") + ">. Actual sequence: <" + "Expected sequence: <" + expectedSequence.SequenceToString(",") + ">. Actual sequence: <" +
actualSequence.SequenceToString(",") + ">."); actualSequence.SequenceToString(",") + ">. " + message);
}
public static void AreSequenceEqual<T>(IEnumerable<T> expectedSequence, IEnumerable<T> actualSequence)
{
AreSequenceEqual(expectedSequence, actualSequence, string.Empty);
} }
} }
} }
\ No newline at end of file
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core"> <Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework> <RequiredTargetFramework>3.5</RequiredTargetFramework>
...@@ -49,6 +50,7 @@ ...@@ -49,6 +50,7 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="MoreAssert.cs" />
<Compile Include="MoreRandom.cs" /> <Compile Include="MoreRandom.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
......
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