Commit 834ddc5a authored by Brickner_cp's avatar Brickner_cp

GRE

Code Coverage 96.16%
parent 690d4a9b
using System;
using System.Globalization;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Base.Test
{
......@@ -60,21 +62,18 @@ namespace PcapDotNet.Base.Test
[TestMethod]
public void UInt128Test()
{
// Random random = new Random();
// for (int i = 0; i != 1000; ++i)
// {
// UInt48 value = random.NextUInt48();
//
// Assert.AreEqual(value, value);
// Assert.IsTrue(value == value);
// Assert.IsFalse(value != value);
// Assert.IsNotNull(value.GetHashCode());
//
// if (value < uint.MaxValue)
// Assert.AreEqual(value, uint.Parse(value.ToString()));
//
// Assert.AreEqual((byte)value, (byte)(value % 256));
// }
Random random = new Random();
for (int i = 0; i != 1000; ++i)
{
UInt128 value = random.NextUInt128();
Assert.AreEqual(value, value);
Assert.IsTrue(value == value);
Assert.IsFalse(value != value);
Assert.IsNotNull(value.GetHashCode());
Assert.AreEqual(value, UInt128.Parse(value.ToString("X32"), NumberStyles.HexNumber, CultureInfo.InvariantCulture));
Assert.AreEqual(value >> 64, UInt128.Parse(((ulong)(value >> 64)).ToString("X16"), NumberStyles.HexNumber, CultureInfo.InvariantCulture));
}
}
[TestMethod]
......
......@@ -243,6 +243,13 @@ namespace PcapDotNet.Core.Test
{
OpenOfflineDevice(10, _random.NextEthernetPacket(100), TimeSpan.Zero, "??");
}
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void EmptyNameTest()
{
OpenOfflineDevice(10, _random.NextEthernetPacket(100), TimeSpan.Zero, string.Empty);
}
private static void TestGetSomePackets(int numPacketsToSend, int numPacketsToGet, int numPacketsToBreakLoop,
PacketCommunicatorReceiveResult expectedResult, int expectedNumPackets,
......
......@@ -151,7 +151,7 @@ namespace PcapDotNet.Core.Test
// Version = GreVersion.EnhancedGre,
// };
// IEnumerable<ILayer> grePayloadLayers = random.NextIcmpPayloadLayers(icmpLayer);
return PacketBuilder.Build(packetTimestamp, new ILayer[] {ethernetLayer, ipV4Layer, greLayer});
return PacketBuilder.Build(packetTimestamp, ethernetLayer, ipV4Layer, greLayer, payloadLayer);
case PacketType.Udp:
ethernetLayer.EtherType = EthernetType.None;
......@@ -181,7 +181,7 @@ namespace PcapDotNet.Core.Test
private static void ComparePacketsToWireshark(IEnumerable<Packet> packets)
{
string pcapFilename = Path.GetTempPath() + "temp." + new Random().NextUShort() + ".pcap";
string pcapFilename = Path.GetTempPath() + "temp." + new Random().NextByte() + ".pcap";
PacketDumpFile.Dump(pcapFilename, new PcapDataLink(DataLinkKind.Ethernet), PacketDevice.DefaultSnapshotLength, packets);
// List<Packet> packetsList = new List<Packet>();
// new OfflinePacketDevice(pcapFilename).Open().ReceivePackets(1000, packetsList.Add);
......@@ -191,8 +191,8 @@ namespace PcapDotNet.Core.Test
string documentFilename = pcapFilename + ".pdml";
using (Process process = new Process())
{
process.StartInfo = new ProcessStartInfo()
{
process.StartInfo = new ProcessStartInfo
{
FileName = WiresharkTsharkPath,
Arguments = "-o udp.check_checksum:TRUE " +
"-o tcp.relative_sequence_numbers:FALSE " +
......@@ -970,6 +970,15 @@ namespace PcapDotNet.Core.Test
field.AssertShowHex(greDatagram.Key);
break;
case "data":
case "data.data":
field.AssertValue(greDatagram.Payload);
break;
case "data.len":
field.AssertShowDecimal(greDatagram.Payload.Length);
break;
default:
Assert.Fail("Invalid field name: " + field.Name());
break;
......
......@@ -63,6 +63,7 @@ namespace PcapDotNet.Packets.Test
Packet packet = new PacketBuilder(ethernetLayer, payloadLayer).Build(DateTime.Now);
// Ethernet
Assert.IsTrue(packet.IsValid, "IsValid");
Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLength, packet.Ethernet.PayloadLength, "PayloadLength");
Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer");
Assert.AreEqual(ethernetLayer.GetHashCode(), packet.Ethernet.ExtractLayer().GetHashCode(), "Ethernet Layer Hash Code");
......
......@@ -71,8 +71,9 @@ namespace PcapDotNet.Packets.Test
for (int i = 0; i != 100; ++i)
{
GreLayer greLayer = random.NextGreLayer();
PayloadLayer payloadLayer = random.NextPayloadLayer(random.Next(100));
PacketBuilder packetBuilder = new PacketBuilder(ethernetLayer, ipV4Layer, greLayer);
PacketBuilder packetBuilder = new PacketBuilder(ethernetLayer, ipV4Layer, greLayer, payloadLayer);
Packet packet = packetBuilder.Build(DateTime.Now);
if (greLayer.Checksum == null)
......@@ -89,7 +90,7 @@ namespace PcapDotNet.Packets.Test
ipV4Layer.HeaderChecksum = null;
Assert.AreEqual(ipV4Layer.Length, packet.Ethernet.IpV4.HeaderLength);
Assert.IsTrue(packet.Ethernet.IpV4.IsHeaderChecksumCorrect);
Assert.AreEqual(ipV4Layer.Length + greLayer.Length,
Assert.AreEqual(ipV4Layer.Length + greLayer.Length + payloadLayer.Length,
packet.Ethernet.IpV4.TotalLength);
Assert.AreEqual(IpV4Datagram.DefaultVersion, packet.Ethernet.IpV4.Version);
......@@ -102,6 +103,14 @@ namespace PcapDotNet.Packets.Test
greLayer.Checksum = actualGre.Checksum;
}
Assert.AreEqual(greLayer, actualGreLayer, "Layer");
if (actualGreLayer.Key != null)
actualGreLayer.SetKey(actualGreLayer.KeyPayloadLength.Value, actualGreLayer.KeyCallId.Value);
else
{
Assert.IsNull(actualGreLayer.KeyPayloadLength);
Assert.IsNull(actualGreLayer.KeyCallId);
}
Assert.AreEqual(greLayer, actualGreLayer, "Layer");
Assert.AreNotEqual(random.NextGreLayer(), actualGreLayer, "Not Layer");
Assert.AreEqual(greLayer.Length, actualGre.HeaderLength);
Assert.IsTrue(actualGre.KeyPresent ^ (greLayer.Key == null));
......
......@@ -149,7 +149,7 @@ namespace PcapDotNet.Packets
/// The original buffer that holds all the data for the datagram.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
protected byte[] Buffer
internal byte[] Buffer
{
get { return _buffer; }
}
......@@ -157,7 +157,7 @@ namespace PcapDotNet.Packets
/// <summary>
/// The offset of the first byte of the datagram in the buffer.
/// </summary>
protected int StartOffset
internal int StartOffset
{
get { return _startOffset; }
}
......
......@@ -39,19 +39,6 @@ namespace PcapDotNet.Packets.Ethernet
get { return _broadcastAddress; }
}
/// <summary>
/// The Ethernet payload.
/// </summary>
public Datagram Payload
{
get
{
if (_payload == null && Length >= HeaderLength)
_payload = new Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength);
return _payload;
}
}
/// <summary>
/// The Ethernet payload length in bytes.
/// </summary>
......@@ -100,17 +87,20 @@ namespace PcapDotNet.Packets.Ethernet
};
}
/// <summary>
/// The Ethernet payload.
/// </summary>
public Datagram Payload
{
get { return PayloadDatagrams.Payload; }
}
/// <summary>
/// The Ethernet payload as an IPv4 datagram.
/// </summary>
public IpV4Datagram IpV4
{
get
{
if (_ipV4 == null && Length >= HeaderLength)
_ipV4 = new IpV4Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength);
return _ipV4;
}
get { return PayloadDatagrams.IpV4; }
}
/// <summary>
......@@ -118,12 +108,7 @@ namespace PcapDotNet.Packets.Ethernet
/// </summary>
public ArpDatagram Arp
{
get
{
if (_arp == null && Length >= HeaderLength)
_arp = ArpDatagram.CreateInstance(Buffer, StartOffset + HeaderLength, Length - HeaderLength);
return _arp;
}
get { return PayloadDatagrams.Arp; }
}
internal EthernetDatagram(byte[] buffer, int offset, int length)
......@@ -146,22 +131,24 @@ namespace PcapDotNet.Packets.Ethernet
if (Length < HeaderLength)
return false;
switch (EtherType)
{
case EthernetType.Arp:
return Arp.IsValid;
case EthernetType.IpV4:
return IpV4.IsValid;
return PayloadDatagrams.Get(EtherType).IsValid;
}
default:
return true;
private EthernetPayloadDatagrams PayloadDatagrams
{
get
{
if (_payloadDatagrams == null)
{
_payloadDatagrams = new EthernetPayloadDatagrams(Length >= HeaderLength
? new Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength)
: null);
}
return _payloadDatagrams;
}
}
private static readonly MacAddress _broadcastAddress = new MacAddress("FF:FF:FF:FF:FF:FF");
private Datagram _payload;
private IpV4Datagram _ipV4;
private ArpDatagram _arp;
private EthernetPayloadDatagrams _payloadDatagrams;
}
}
\ No newline at end of file
using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Ethernet
{
internal class EthernetPayloadDatagrams
{
public EthernetPayloadDatagrams(Datagram payload)
{
_payload = payload;
}
public Datagram Get(EthernetType ethernetType)
{
switch (ethernetType)
{
case EthernetType.Arp:
return Arp;
case EthernetType.IpV4:
return IpV4;
default:
return Payload;
}
}
/// <summary>
/// The Ethernet payload as an IPv4 datagram.
/// </summary>
public IpV4Datagram IpV4
{
get
{
if (_ipV4 == null && _payload != null)
_ipV4 = new IpV4Datagram(_payload.Buffer, _payload.StartOffset, _payload.Length);
return _ipV4;
}
}
/// <summary>
/// The Ethernet payload as an ARP datagram.
/// </summary>
public ArpDatagram Arp
{
get
{
if (_arp == null && _payload != null)
_arp = ArpDatagram.CreateInstance(_payload.Buffer, _payload.StartOffset, _payload.Length);
return _arp;
}
}
/// <summary>
/// The Ethernet payload.
/// </summary>
public Datagram Payload
{
get { return _payload; }
}
private readonly Datagram _payload;
private IpV4Datagram _ipV4;
private ArpDatagram _arp;
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4;
......@@ -275,16 +275,6 @@ namespace PcapDotNet.Packets.Gre
}
}
public IpV4Datagram IpV4
{
get
{
if (_ipV4 == null && Length >= HeaderLength)
_ipV4 = new IpV4Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength);
return _ipV4;
}
}
public override ILayer ExtractLayer()
{
return new GreLayer
......@@ -304,12 +294,38 @@ namespace PcapDotNet.Packets.Gre
};
}
/// <summary>
/// The Ethernet payload.
/// </summary>
public Datagram Payload
{
get { return PayloadDatagrams.Payload; }
}
/// <summary>
/// The Ethernet payload as an IPv4 datagram.
/// </summary>
public IpV4Datagram IpV4
{
get { return PayloadDatagrams.IpV4; }
}
/// <summary>
/// The Ethernet payload as an ARP datagram.
/// </summary>
public ArpDatagram Arp
{
get { return PayloadDatagrams.Arp; }
}
protected override bool CalculateIsValid()
{
return (Length >= HeaderMinimumLength && Length >= HeaderLength &&
IsValidRouting && Flags == 0 &&
(Version == GreVersion.EnhancedGre || Version == GreVersion.Gre && !AcknowledgmentSequenceNumberPresent) &&
(!ChecksumPresent || IsChecksumCorrect));
return (Length >= HeaderMinimumLength && Length >= HeaderLength &&
IsValidRouting && Flags == 0 &&
(Version == GreVersion.EnhancedGre || Version == GreVersion.Gre && !AcknowledgmentSequenceNumberPresent) &&
(!ChecksumPresent || IsChecksumCorrect) &&
PayloadDatagrams.Get(ProtocolType).IsValid);
}
internal GreDatagram(byte[] buffer, int offset, int length)
......@@ -464,316 +480,24 @@ namespace PcapDotNet.Packets.Gre
}
}
private IpV4Datagram _ipV4;
private ReadOnlyCollection<GreSourceRouteEntry> _routing;
private bool _isValidRouting = true;
private bool? _isChecksumCorrect;
private int? _activeSourceRouteEntryIndex;
}
/// <summary>
/// <pre>
/// +-----+----------------+------------+------------+
/// | Bit | 0-15 | 16-23 | 24-31 |
/// +-----+----------------+------------+------------+
/// | 0 | Address Family | SRE Offset | SRE Length |
/// +-----+----------------+------------+------------+
/// | 32 | Routing Information ... |
/// +-----+------------------------------------------+
/// </pre>
/// </summary>
public abstract class GreSourceRouteEntry : IEquatable<GreSourceRouteEntry>
{
public abstract GreSourceRouteEntryAddressFamily AddressFamily { get; }
public const int HeaderLength = 4;
private static class Offset
{
public const int AddressFamily = 0;
public const int SreOffset = 2;
public const int SreLength = 3;
}
public int Length
{
get { return HeaderLength + PayloadLength; }
}
public abstract byte PayloadOffset { get; }
public abstract byte PayloadLength { get; }
public bool Equals(GreSourceRouteEntry other)
{
return other != null &&
AddressFamily == other.AddressFamily &&
Length == other.Length &&
PayloadOffset == other.PayloadOffset &&
EqualsPayloads(other);
}
public override bool Equals(object obj)
{
return Equals(obj as GreSourceRouteEntry);
}
protected abstract bool EqualsPayloads(GreSourceRouteEntry other);
protected abstract void WritePayload(byte[] buffer, int offset);
internal static bool TryReadEntry(byte[] buffer, ref int offset, int length, out GreSourceRouteEntry entry)
{
entry = null;
if (length < HeaderLength)
return false;
// Address Family
GreSourceRouteEntryAddressFamily addressFamily = (GreSourceRouteEntryAddressFamily)buffer.ReadUShort(offset + Offset.AddressFamily, Endianity.Big);
// SRE Length
byte sreLength = buffer[offset + Offset.SreLength];
if (sreLength == 0)
return addressFamily == GreSourceRouteEntryAddressFamily.None;
if (HeaderLength + sreLength > length)
return false;
// SRE Offset
byte sreOffset = buffer[offset + Offset.SreOffset];
if (sreOffset > sreLength)
return false;
// Entry
if (!TryReadEntry(buffer, offset + HeaderLength, sreLength, addressFamily, sreOffset, out entry))
return false;
// Change offset
offset += entry.Length;
return true;
}
internal void Write(byte[] buffer, ref int offset)
private EthernetPayloadDatagrams PayloadDatagrams
{
buffer.Write(offset + Offset.AddressFamily, (ushort)AddressFamily, Endianity.Big);
buffer.Write(offset + Offset.SreOffset, PayloadOffset);
buffer.Write(offset + Offset.SreLength, (byte)PayloadLength);
WritePayload(buffer, offset + HeaderLength);
offset += Length;
}
private static bool TryReadEntry(byte[] buffer, int payloadOffset, int payloadLength, GreSourceRouteEntryAddressFamily addressFamily, int offsetInPayload, out GreSourceRouteEntry entry)
{
entry = null;
switch (addressFamily)
get
{
case GreSourceRouteEntryAddressFamily.IpSourceRoute:
if (offsetInPayload % IpV4Address.SizeOf != 0 || payloadLength % IpV4Address.SizeOf != 0)
return false;
int numAddresses = payloadLength / IpV4Address.SizeOf;
IpV4Address[] addresses = new IpV4Address[numAddresses];
for (int i = 0; i != numAddresses; ++i)
addresses[i] = buffer.ReadIpV4Address(payloadOffset + i * IpV4Address.SizeOf, Endianity.Big);
entry = new GreSourceRouteEntryIp(addresses, offsetInPayload / IpV4Address.SizeOf);
return true;
case GreSourceRouteEntryAddressFamily.AsSourceRoute:
if (offsetInPayload % sizeof(ushort) != 0 || payloadLength % sizeof(ushort) != 0)
return false;
int numAsNumbers = payloadLength / sizeof(ushort);
ushort[] asNumbers = new ushort[numAsNumbers];
for (int i = 0; i != numAsNumbers; ++i)
asNumbers[i] = buffer.ReadUShort(payloadOffset + i * sizeof(ushort), Endianity.Big);
entry = new GreSourceRouteEntryAs(asNumbers, offsetInPayload / sizeof(ushort));
return true;
default:
Datagram data = new Datagram(buffer, payloadOffset, payloadLength);
entry = new GreSourceRouteEntryUnknown(addressFamily, data, offsetInPayload);
return true;
if (_payloadDatagrams == null)
{
_payloadDatagrams = new EthernetPayloadDatagrams(Length >= HeaderLength
? new Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength)
: null);
}
return _payloadDatagrams;
}
}
}
public class GreSourceRouteEntryIp : GreSourceRouteEntry
{
public GreSourceRouteEntryIp(ReadOnlyCollection<IpV4Address> addresses, int nextAddressIndex)
{
_addresses = addresses;
_nextAddressIndex = nextAddressIndex;
}
public override GreSourceRouteEntryAddressFamily AddressFamily
{
get { return GreSourceRouteEntryAddressFamily.IpSourceRoute; }
}
public override byte PayloadLength
{
get { return (byte)(Addresses.Count * IpV4Address.SizeOf); }
}
public override byte PayloadOffset
{
get { return (byte)(NextAddressIndex * IpV4Address.SizeOf); }
}
protected override bool EqualsPayloads(GreSourceRouteEntry other)
{
return Addresses.SequenceEqual(((GreSourceRouteEntryIp)other).Addresses);
}
protected override void WritePayload(byte[] buffer, int offset)
{
foreach (IpV4Address address in Addresses)
buffer.Write(ref offset, address, Endianity.Big);
}
public ReadOnlyCollection<IpV4Address> Addresses
{
get { return _addresses; }
}
public int NextAddressIndex
{
get { return _nextAddressIndex; }
}
public IpV4Address NextAddress
{
get { return Addresses[NextAddressIndex]; }
}
internal GreSourceRouteEntryIp(IpV4Address[] addresses, int nextAddressIndex)
:this(addresses.AsReadOnly(), nextAddressIndex)
{
}
private readonly ReadOnlyCollection<IpV4Address> _addresses;
private readonly int _nextAddressIndex;
}
public class GreSourceRouteEntryAs : GreSourceRouteEntry
{
public GreSourceRouteEntryAs(ReadOnlyCollection<ushort> asNumbers, int nextAsNumberIndex)
{
_asNumbers = asNumbers;
_nextAsNumberIndex = nextAsNumberIndex;
}
public override GreSourceRouteEntryAddressFamily AddressFamily
{
get { return GreSourceRouteEntryAddressFamily.AsSourceRoute; }
}
public override byte PayloadLength
{
get { return (byte)(AsNumbers.Count * sizeof(ushort)); }
}
public override byte PayloadOffset
{
get { return (byte)(NextAsNumberIndex * sizeof(ushort)); }
}
protected override bool EqualsPayloads(GreSourceRouteEntry other)
{
return AsNumbers.SequenceEqual(((GreSourceRouteEntryAs)other).AsNumbers);
}
public ReadOnlyCollection<ushort> AsNumbers
{
get { return _asNumbers; }
}
public int NextAsNumberIndex
{
get { return _nextAsNumberIndex; }
}
public ushort NextAsNumber
{
get { return AsNumbers[NextAsNumberIndex]; }
}
protected override void WritePayload(byte[] buffer, int offset)
{
foreach (ushort asNumber in AsNumbers)
buffer.Write(ref offset, asNumber, Endianity.Big);
}
internal GreSourceRouteEntryAs(ushort[] asNumbers, int nextAsNumberIndex)
: this(asNumbers.AsReadOnly(), nextAsNumberIndex)
{
}
private readonly ReadOnlyCollection<ushort> _asNumbers;
private readonly int _nextAsNumberIndex;
}
public class GreSourceRouteEntryUnknown : GreSourceRouteEntry
{
public GreSourceRouteEntryUnknown(GreSourceRouteEntryAddressFamily addressFamily, Datagram data, int offset)
{
_addressFamily = addressFamily;
_data = data;
_offset = offset;
}
public override GreSourceRouteEntryAddressFamily AddressFamily
{
get { return _addressFamily; }
}
public override byte PayloadLength
{
get { return (byte)Data.Length; }
}
public override byte PayloadOffset
{
get { return (byte)_offset; }
}
public Datagram Data
{
get { return _data; }
}
protected override bool EqualsPayloads(GreSourceRouteEntry other)
{
return Data.Equals(((GreSourceRouteEntryUnknown)other).Data);
}
protected override void WritePayload(byte[] buffer, int offset)
{
buffer.Write(offset, Data);
}
private readonly GreSourceRouteEntryAddressFamily _addressFamily;
private readonly Datagram _data;
private readonly int _offset;
}
public enum GreSourceRouteEntryAddressFamily : ushort
{
None = 0x0000,
IpSourceRoute = 0x0800,
AsSourceRoute = 0xfffe,
}
public enum GreVersion : byte
{
/// <summary>
/// RFC 2784
/// </summary>
Gre = 0x00,
/// <summary>
/// RFC 2637
/// </summary>
EnhancedGre = 0x01
private EthernetPayloadDatagrams _payloadDatagrams;
private ReadOnlyCollection<GreSourceRouteEntry> _routing;
private bool _isValidRouting = true;
private bool? _isChecksumCorrect;
private int? _activeSourceRouteEntryIndex;
}
}
\ No newline at end of file
......@@ -15,6 +15,8 @@ namespace PcapDotNet.Packets.Gre
public bool ChecksumPresent { get; set; }
public ushort? Checksum { get; set; }
public uint? Key { get; set; }
public ushort? KeyPayloadLength { get { return Key == null ? null : (ushort?)((Key & 0xFFFF0000) >> 16); } }
public ushort? KeyCallId { get { return Key == null ? null : (ushort?)(Key & 0x0000FFFF); } }
public void SetKey(ushort keyPayloadLength, ushort keyCallId)
{
Key = (uint)((keyPayloadLength << 16) | keyCallId);
......
using System;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Gre
{
/// <summary>
/// <pre>
/// +-----+----------------+------------+------------+
/// | Bit | 0-15 | 16-23 | 24-31 |
/// +-----+----------------+------------+------------+
/// | 0 | Address Family | SRE Offset | SRE Length |
/// +-----+----------------+------------+------------+
/// | 32 | Routing Information ... |
/// +-----+------------------------------------------+
/// </pre>
/// </summary>
public abstract class GreSourceRouteEntry : IEquatable<GreSourceRouteEntry>
{
public abstract GreSourceRouteEntryAddressFamily AddressFamily { get; }
public const int HeaderLength = 4;
private static class Offset
{
public const int AddressFamily = 0;
public const int SreOffset = 2;
public const int SreLength = 3;
}
public int Length
{
get { return HeaderLength + PayloadLength; }
}
public abstract byte PayloadOffset { get; }
public abstract byte PayloadLength { get; }
public bool Equals(GreSourceRouteEntry other)
{
return other != null &&
AddressFamily == other.AddressFamily &&
Length == other.Length &&
PayloadOffset == other.PayloadOffset &&
EqualsPayloads(other);
}
public override bool Equals(object obj)
{
return Equals(obj as GreSourceRouteEntry);
}
protected abstract bool EqualsPayloads(GreSourceRouteEntry other);
protected abstract void WritePayload(byte[] buffer, int offset);
internal static bool TryReadEntry(byte[] buffer, ref int offset, int length, out GreSourceRouteEntry entry)
{
entry = null;
if (length < HeaderLength)
return false;
// Address Family
GreSourceRouteEntryAddressFamily addressFamily = (GreSourceRouteEntryAddressFamily)buffer.ReadUShort(offset + Offset.AddressFamily, Endianity.Big);
// SRE Length
byte sreLength = buffer[offset + Offset.SreLength];
if (sreLength == 0)
return addressFamily == GreSourceRouteEntryAddressFamily.None;
if (HeaderLength + sreLength > length)
return false;
// SRE Offset
byte sreOffset = buffer[offset + Offset.SreOffset];
if (sreOffset > sreLength)
return false;
// Entry
if (!TryReadEntry(buffer, offset + HeaderLength, sreLength, addressFamily, sreOffset, out entry))
return false;
// Change offset
offset += entry.Length;
return true;
}
internal void Write(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.AddressFamily, (ushort)AddressFamily, Endianity.Big);
buffer.Write(offset + Offset.SreOffset, PayloadOffset);
buffer.Write(offset + Offset.SreLength, (byte)PayloadLength);
WritePayload(buffer, offset + HeaderLength);
offset += Length;
}
private static bool TryReadEntry(byte[] buffer, int payloadOffset, int payloadLength, GreSourceRouteEntryAddressFamily addressFamily, int offsetInPayload, out GreSourceRouteEntry entry)
{
entry = null;
switch (addressFamily)
{
case GreSourceRouteEntryAddressFamily.IpSourceRoute:
if (offsetInPayload % IpV4Address.SizeOf != 0 || payloadLength % IpV4Address.SizeOf != 0)
return false;
int numAddresses = payloadLength / IpV4Address.SizeOf;
IpV4Address[] addresses = new IpV4Address[numAddresses];
for (int i = 0; i != numAddresses; ++i)
addresses[i] = buffer.ReadIpV4Address(payloadOffset + i * IpV4Address.SizeOf, Endianity.Big);
entry = new GreSourceRouteEntryIp(addresses, offsetInPayload / IpV4Address.SizeOf);
return true;
case GreSourceRouteEntryAddressFamily.AsSourceRoute:
if (offsetInPayload % sizeof(ushort) != 0 || payloadLength % sizeof(ushort) != 0)
return false;
int numAsNumbers = payloadLength / sizeof(ushort);
ushort[] asNumbers = new ushort[numAsNumbers];
for (int i = 0; i != numAsNumbers; ++i)
asNumbers[i] = buffer.ReadUShort(payloadOffset + i * sizeof(ushort), Endianity.Big);
entry = new GreSourceRouteEntryAs(asNumbers, offsetInPayload / sizeof(ushort));
return true;
default:
Datagram data = new Datagram(buffer, payloadOffset, payloadLength);
entry = new GreSourceRouteEntryUnknown(addressFamily, data, offsetInPayload);
return true;
}
}
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Gre
{
public enum GreSourceRouteEntryAddressFamily : ushort
{
None = 0x0000,
IpSourceRoute = 0x0800,
AsSourceRoute = 0xfffe,
}
}
\ No newline at end of file
using System.Collections.ObjectModel;
using System.Linq;
using PcapDotNet.Base;
namespace PcapDotNet.Packets.Gre
{
public class GreSourceRouteEntryAs : GreSourceRouteEntry
{
public GreSourceRouteEntryAs(ReadOnlyCollection<ushort> asNumbers, int nextAsNumberIndex)
{
_asNumbers = asNumbers;
_nextAsNumberIndex = nextAsNumberIndex;
}
public override GreSourceRouteEntryAddressFamily AddressFamily
{
get { return GreSourceRouteEntryAddressFamily.AsSourceRoute; }
}
public override byte PayloadLength
{
get { return (byte)(AsNumbers.Count * sizeof(ushort)); }
}
public override byte PayloadOffset
{
get { return (byte)(NextAsNumberIndex * sizeof(ushort)); }
}
protected override bool EqualsPayloads(GreSourceRouteEntry other)
{
return AsNumbers.SequenceEqual(((GreSourceRouteEntryAs)other).AsNumbers);
}
public ReadOnlyCollection<ushort> AsNumbers
{
get { return _asNumbers; }
}
public int NextAsNumberIndex
{
get { return _nextAsNumberIndex; }
}
public ushort NextAsNumber
{
get { return AsNumbers[NextAsNumberIndex]; }
}
protected override void WritePayload(byte[] buffer, int offset)
{
foreach (ushort asNumber in AsNumbers)
buffer.Write(ref offset, asNumber, Endianity.Big);
}
internal GreSourceRouteEntryAs(ushort[] asNumbers, int nextAsNumberIndex)
: this(asNumbers.AsReadOnly(), nextAsNumberIndex)
{
}
private readonly ReadOnlyCollection<ushort> _asNumbers;
private readonly int _nextAsNumberIndex;
}
}
\ No newline at end of file
using System.Collections.ObjectModel;
using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Gre
{
public class GreSourceRouteEntryIp : GreSourceRouteEntry
{
public GreSourceRouteEntryIp(ReadOnlyCollection<IpV4Address> addresses, int nextAddressIndex)
{
_addresses = addresses;
_nextAddressIndex = nextAddressIndex;
}
public override GreSourceRouteEntryAddressFamily AddressFamily
{
get { return GreSourceRouteEntryAddressFamily.IpSourceRoute; }
}
public override byte PayloadLength
{
get { return (byte)(Addresses.Count * IpV4Address.SizeOf); }
}
public override byte PayloadOffset
{
get { return (byte)(NextAddressIndex * IpV4Address.SizeOf); }
}
protected override bool EqualsPayloads(GreSourceRouteEntry other)
{
return Addresses.SequenceEqual(((GreSourceRouteEntryIp)other).Addresses);
}
protected override void WritePayload(byte[] buffer, int offset)
{
foreach (IpV4Address address in Addresses)
buffer.Write(ref offset, address, Endianity.Big);
}
public ReadOnlyCollection<IpV4Address> Addresses
{
get { return _addresses; }
}
public int NextAddressIndex
{
get { return _nextAddressIndex; }
}
public IpV4Address NextAddress
{
get { return Addresses[NextAddressIndex]; }
}
internal GreSourceRouteEntryIp(IpV4Address[] addresses, int nextAddressIndex)
:this(addresses.AsReadOnly(), nextAddressIndex)
{
}
private readonly ReadOnlyCollection<IpV4Address> _addresses;
private readonly int _nextAddressIndex;
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Gre
{
public class GreSourceRouteEntryUnknown : GreSourceRouteEntry
{
public GreSourceRouteEntryUnknown(GreSourceRouteEntryAddressFamily addressFamily, Datagram data, int offset)
{
_addressFamily = addressFamily;
_data = data;
_offset = offset;
}
public override GreSourceRouteEntryAddressFamily AddressFamily
{
get { return _addressFamily; }
}
public override byte PayloadLength
{
get { return (byte)Data.Length; }
}
public override byte PayloadOffset
{
get { return (byte)_offset; }
}
public Datagram Data
{
get { return _data; }
}
protected override bool EqualsPayloads(GreSourceRouteEntry other)
{
return Data.Equals(((GreSourceRouteEntryUnknown)other).Data);
}
protected override void WritePayload(byte[] buffer, int offset)
{
buffer.Write(offset, Data);
}
private readonly GreSourceRouteEntryAddressFamily _addressFamily;
private readonly Datagram _data;
private readonly int _offset;
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Gre
{
public enum GreVersion : byte
{
/// <summary>
/// RFC 2784
/// </summary>
Gre = 0x00,
/// <summary>
/// RFC 2637
/// </summary>
EnhancedGre = 0x01
}
}
\ No newline at end of file
......@@ -3,7 +3,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{8A184AF5-E46C-482C-81A3-76D8CE290104}</ProjectGuid>
<OutputType>Library</OutputType>
......@@ -70,11 +70,18 @@
<Compile Include="Endianity.cs" />
<Compile Include="Ethernet\EthernetLayer.cs" />
<Compile Include="Ethernet\EthernetDatagram.cs" />
<Compile Include="Ethernet\EthernetPayloadDatagrams.cs" />
<Compile Include="Ethernet\EthernetType.cs" />
<Compile Include="Ethernet\MacAddress.cs" />
<Compile Include="Arp\IArpPreviousLayer.cs" />
<Compile Include="Gre\GreDatagram.cs" />
<Compile Include="Gre\GreLayer.cs" />
<Compile Include="Gre\GreSourceRouteEntry.cs" />
<Compile Include="Gre\GreSourceRouteEntryAddressFamily.cs" />
<Compile Include="Gre\GreSourceRouteEntryAs.cs" />
<Compile Include="Gre\GreSourceRouteEntryIp.cs" />
<Compile Include="Gre\GreSourceRouteEntryUnknown.cs" />
<Compile Include="Gre\GreVersion.cs" />
<Compile Include="Icmp\IcmpAddressMaskReplyDatagram.cs" />
<Compile Include="Icmp\IcmpAddressMaskReplyLayer.cs" />
<Compile Include="Icmp\IcmpAddressMaskRequestLayer.cs" />
......
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