Commit e6ce2bec authored by Brickner_cp's avatar Brickner_cp

GRE

parent 1f35830f
...@@ -80,7 +80,7 @@ namespace PcapDotNet.Packets.Test ...@@ -80,7 +80,7 @@ namespace PcapDotNet.Packets.Test
Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer"); Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer");
// IPv4 // IPv4
ipV4Layer.Protocol = IpV4Protocol.InternetControlMessageProtocol; ipV4Layer.Protocol = IpV4Protocol.Gre;
ipV4Layer.HeaderChecksum = ((IpV4Layer)packet.Ethernet.IpV4.ExtractLayer()).HeaderChecksum; ipV4Layer.HeaderChecksum = ((IpV4Layer)packet.Ethernet.IpV4.ExtractLayer()).HeaderChecksum;
Assert.AreEqual(ipV4Layer, packet.Ethernet.IpV4.ExtractLayer()); Assert.AreEqual(ipV4Layer, packet.Ethernet.IpV4.ExtractLayer());
ipV4Layer.HeaderChecksum = null; ipV4Layer.HeaderChecksum = null;
......
...@@ -58,27 +58,10 @@ namespace PcapDotNet.Packets.Gre ...@@ -58,27 +58,10 @@ namespace PcapDotNet.Packets.Gre
{ {
get get
{ {
return OffsetRouting + (RoutingPresent return GetHeaderLength(ChecksumPresent, KeyPresent, SequenceNumberPresent, Routing);
? Routing.Sum(entry => entry.Length) + GreSourceRouteEntry.HeaderLength // Routing and Routing termination
: 0);
} }
} }
private int OffsetKey
{
get{return HeaderMinimumLength + ((ChecksumPresent || RoutingPresent) ? sizeof(ushort) + sizeof(ushort) : 0);}
}
private int OffsetSequenceNumber
{
get { return OffsetKey + (KeyPresent ? sizeof(uint) : 0); }
}
private int OffsetRouting
{
get { return OffsetSequenceNumber + (SequenceNumberPresent ? sizeof(uint) : 0); }
}
/// <summary> /// <summary>
/// If the Checksum Present bit is set to 1, then the Checksum field is present and contains valid information. /// If the Checksum Present bit is set to 1, then the Checksum field is present and contains valid information.
/// If either the Checksum Present bit or the Routing Present bit are set, BOTH the Checksum and Offset fields are present in the GRE packet. /// If either the Checksum Present bit or the Routing Present bit are set, BOTH the Checksum and Offset fields are present in the GRE packet.
...@@ -124,7 +107,6 @@ namespace PcapDotNet.Packets.Gre ...@@ -124,7 +107,6 @@ namespace PcapDotNet.Packets.Gre
get { return (this[Offset.StrictSourceRoute] & Mask.StrictSourceRoute) == Mask.StrictSourceRoute; } get { return (this[Offset.StrictSourceRoute] & Mask.StrictSourceRoute) == Mask.StrictSourceRoute; }
} }
/// <summary> /// <summary>
/// Recursion control contains a three bit unsigned integer which contains the number of additional encapsulations which are permissible. /// Recursion control contains a three bit unsigned integer which contains the number of additional encapsulations which are permissible.
/// This SHOULD default to zero. /// This SHOULD default to zero.
...@@ -210,7 +192,7 @@ namespace PcapDotNet.Packets.Gre ...@@ -210,7 +192,7 @@ namespace PcapDotNet.Packets.Gre
{ {
get get
{ {
if (_routing == null) if (_routing == null && RoutingPresent)
{ {
List<GreSourceRouteEntry> entries = new List<GreSourceRouteEntry>(); List<GreSourceRouteEntry> entries = new List<GreSourceRouteEntry>();
int entryOffset = StartOffset + OffsetRouting; int entryOffset = StartOffset + OffsetRouting;
...@@ -249,7 +231,19 @@ namespace PcapDotNet.Packets.Gre ...@@ -249,7 +231,19 @@ namespace PcapDotNet.Packets.Gre
public override ILayer ExtractLayer() public override ILayer ExtractLayer()
{ {
throw new NotImplementedException(); return new GreLayer
{
Version = Version,
ProtocolType = ProtocolType,
RecursionControl = RecursionControl,
ChecksumPresent = ChecksumPresent,
Checksum = ChecksumPresent ? (ushort?)Checksum : null,
Key = KeyPresent ? (uint?)Key : null,
SequenceNumber = SequenceNumberPresent ? (uint?)SequenceNumber : null,
Routing = RoutingPresent ? Routing : null,
RoutingOffset = RoutingPresent ? (ushort?)RoutingOffset : null,
StrictSourceRoute = StrictSourceRoute,
};
} }
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
...@@ -263,9 +257,80 @@ namespace PcapDotNet.Packets.Gre ...@@ -263,9 +257,80 @@ namespace PcapDotNet.Packets.Gre
{ {
} }
internal static void WriteHeader(byte[] buffer, int offset) internal static int GetHeaderLength(bool isChecksumPresent, bool isKeyPresent, bool isSequenceNumberPresent, IEnumerable<GreSourceRouteEntry> routing)
{ {
throw new NotImplementedException(); return HeaderMinimumLength +
(isChecksumPresent || routing != null ? sizeof(ushort) + sizeof(ushort) : 0) +
(isKeyPresent ? sizeof(uint) : 0) +
(isSequenceNumberPresent ? sizeof(uint) : 0) +
(routing != null ? routing.Sum(entry => entry.Length) + GreSourceRouteEntry.HeaderLength : 0);
}
internal static void WriteHeader(byte[] buffer, int offset,
byte recursionControl, GreVersion version, EthernetType protocolType,
bool checksumPresent, uint? key, uint? sequenceNumber,
ReadOnlyCollection<GreSourceRouteEntry> routing, ushort? routingOffset, bool strictSourceRoute)
{
buffer.Write(offset + Offset.ChecksumPresent,
(byte)((checksumPresent ? Mask.ChecksumPresent : (byte)0) |
(routing != null ? Mask.RoutingPresent : (byte)0) |
(key != null ? Mask.KeyPresent : (byte)0) |
(sequenceNumber != null ? Mask.SequenceNumberPresent : (byte)0) |
(strictSourceRoute ? Mask.StrictSourceRoute : (byte)0) |
(recursionControl & Mask.RecursionControl)));
buffer.Write(offset + Offset.Version, (byte)((byte)version & Mask.Version));
buffer.Write(offset + Offset.ProtocolType, (ushort)protocolType, Endianity.Big);
offset += Offset.RoutingOffset;
if (routingOffset != null)
buffer.Write(ref offset, routingOffset.Value, Endianity.Big);
if (key != null)
buffer.Write(ref offset, key.Value, Endianity.Big);
if (sequenceNumber != null)
buffer.Write(ref offset, sequenceNumber.Value, Endianity.Big);
if (routing != null)
{
foreach (GreSourceRouteEntry entry in routing)
entry.Write(buffer, ref offset);
buffer.Write(ref offset, (uint)0, Endianity.Big);
}
}
internal static void WriteChecksum(byte[] buffer, int offset, int length, ushort? checksum)
{
ushort checksumValue = checksum == null
? CalculateChecksum(buffer, offset, length)
: checksum.Value;
buffer.Write(offset + Offset.Checksum, checksumValue, Endianity.Big);
}
private int OffsetKey
{
get { return HeaderMinimumLength + ((ChecksumPresent || RoutingPresent) ? sizeof(ushort) + sizeof(ushort) : 0); }
}
private int OffsetSequenceNumber
{
get { return OffsetKey + (KeyPresent ? sizeof(uint) : 0); }
}
private int OffsetRouting
{
get { return OffsetSequenceNumber + (SequenceNumberPresent ? sizeof(uint) : 0); }
}
private static ushort CalculateChecksum(byte[] buffer, int offset, int length)
{
uint sum = Sum16Bits(buffer, offset, Math.Min(Offset.Checksum, length)) +
Sum16Bits(buffer, offset + Offset.Checksum + sizeof(ushort), length - Offset.Checksum - sizeof(ushort));
return Sum16BitsToChecksum(sum);
} }
private IpV4Datagram _ipV4; private IpV4Datagram _ipV4;
...@@ -273,12 +338,26 @@ namespace PcapDotNet.Packets.Gre ...@@ -273,12 +338,26 @@ namespace PcapDotNet.Packets.Gre
private bool _isValidRouting = true; private bool _isValidRouting = true;
} }
/// <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 public abstract class GreSourceRouteEntry
{ {
public abstract GreSourceRouteEntryAddressFamily AddressFamily { get; }
public const int HeaderLength = 4; public const int HeaderLength = 4;
private static class Offset private static class Offset
{ {
public const int AddressFamily = 0;
public const int SreOffset = 2; public const int SreOffset = 2;
public const int SreLength = 3; public const int SreLength = 3;
} }
...@@ -290,6 +369,9 @@ namespace PcapDotNet.Packets.Gre ...@@ -290,6 +369,9 @@ namespace PcapDotNet.Packets.Gre
public abstract int PayloadLength { get; } public abstract int PayloadLength { get; }
protected abstract byte OffsetInPayload { get; }
protected abstract void WriteRoutingInformation(byte[] buffer, int offset);
internal static bool TryReadEntry(byte[] buffer, ref int offset, int length, out GreSourceRouteEntry entry) internal static bool TryReadEntry(byte[] buffer, ref int offset, int length, out GreSourceRouteEntry entry)
{ {
entry = null; entry = null;
...@@ -321,6 +403,14 @@ namespace PcapDotNet.Packets.Gre ...@@ -321,6 +403,14 @@ namespace PcapDotNet.Packets.Gre
return true; return true;
} }
internal void Write(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.AddressFamily, (ushort)AddressFamily, Endianity.Big);
buffer.Write(offset + Offset.SreOffset, OffsetInPayload);
buffer.Write(offset + Offset.SreLength, Length, Endianity.Big);
WriteRoutingInformation(buffer, offset + HeaderLength);
}
private static bool TryReadEntry(byte[] buffer, int payloadOffset, int payloadLength, GreSourceRouteEntryAddressFamily addressFamily, int offsetInPayload, out GreSourceRouteEntry entry) private static bool TryReadEntry(byte[] buffer, int payloadOffset, int payloadLength, GreSourceRouteEntryAddressFamily addressFamily, int offsetInPayload, out GreSourceRouteEntry entry)
{ {
entry = null; entry = null;
...@@ -352,7 +442,7 @@ namespace PcapDotNet.Packets.Gre ...@@ -352,7 +442,7 @@ namespace PcapDotNet.Packets.Gre
default: default:
Datagram data = new Datagram(buffer, payloadOffset, payloadLength); Datagram data = new Datagram(buffer, payloadOffset, payloadLength);
entry = new GreSourceRouteEntryUnknown(data, offsetInPayload); entry = new GreSourceRouteEntryUnknown(addressFamily, data, offsetInPayload);
return true; return true;
} }
} }
...@@ -360,11 +450,22 @@ namespace PcapDotNet.Packets.Gre ...@@ -360,11 +450,22 @@ namespace PcapDotNet.Packets.Gre
public class GreSourceRouteEntryIp : GreSourceRouteEntry public class GreSourceRouteEntryIp : GreSourceRouteEntry
{ {
public override GreSourceRouteEntryAddressFamily AddressFamily
{
get { return GreSourceRouteEntryAddressFamily.IpSourceRoute; }
}
public override int PayloadLength public override int PayloadLength
{ {
get { return IpV4Address.SizeOf; } get { return IpV4Address.SizeOf; }
} }
protected override void WriteRoutingInformation(byte[] buffer, int offset)
{
foreach (IpV4Address address in Addresses)
buffer.Write(ref offset, address, Endianity.Big);
}
public ReadOnlyCollection<IpV4Address> Addresses public ReadOnlyCollection<IpV4Address> Addresses
{ {
get { return _addresses; } get { return _addresses; }
...@@ -380,6 +481,11 @@ namespace PcapDotNet.Packets.Gre ...@@ -380,6 +481,11 @@ namespace PcapDotNet.Packets.Gre
get { return Addresses[NextAddressIndex]; } get { return Addresses[NextAddressIndex]; }
} }
protected override byte OffsetInPayload
{
get { return (byte)(NextAddressIndex * IpV4Address.SizeOf); }
}
internal GreSourceRouteEntryIp(IpV4Address[] addresses, int nextAddressIndex) internal GreSourceRouteEntryIp(IpV4Address[] addresses, int nextAddressIndex)
{ {
_addresses = new ReadOnlyCollection<IpV4Address>(addresses); _addresses = new ReadOnlyCollection<IpV4Address>(addresses);
...@@ -392,6 +498,11 @@ namespace PcapDotNet.Packets.Gre ...@@ -392,6 +498,11 @@ namespace PcapDotNet.Packets.Gre
public class GreSourceRouteEntryAs : GreSourceRouteEntry public class GreSourceRouteEntryAs : GreSourceRouteEntry
{ {
public override GreSourceRouteEntryAddressFamily AddressFamily
{
get { return GreSourceRouteEntryAddressFamily.AsSourceRoute; }
}
public override int PayloadLength public override int PayloadLength
{ {
get { return sizeof(ushort); } get { return sizeof(ushort); }
...@@ -412,6 +523,17 @@ namespace PcapDotNet.Packets.Gre ...@@ -412,6 +523,17 @@ namespace PcapDotNet.Packets.Gre
get { return AsNumbers[NextAsNumberIndex]; } get { return AsNumbers[NextAsNumberIndex]; }
} }
protected override byte OffsetInPayload
{
get { return (byte)(NextAsNumberIndex * sizeof(ushort)); }
}
protected override void WriteRoutingInformation(byte[] buffer, int offset)
{
foreach (ushort asNumber in AsNumbers)
buffer.Write(ref offset, asNumber, Endianity.Big);
}
internal GreSourceRouteEntryAs(ushort[] asNumbers, int nextAsNumberIndex) internal GreSourceRouteEntryAs(ushort[] asNumbers, int nextAsNumberIndex)
{ {
_asNumbers = new ReadOnlyCollection<ushort>(asNumbers); _asNumbers = new ReadOnlyCollection<ushort>(asNumbers);
...@@ -424,6 +546,11 @@ namespace PcapDotNet.Packets.Gre ...@@ -424,6 +546,11 @@ namespace PcapDotNet.Packets.Gre
public class GreSourceRouteEntryUnknown : GreSourceRouteEntry public class GreSourceRouteEntryUnknown : GreSourceRouteEntry
{ {
public override GreSourceRouteEntryAddressFamily AddressFamily
{
get { return _addressFamily; }
}
public override int PayloadLength public override int PayloadLength
{ {
get { return Data.Length; } get { return Data.Length; }
...@@ -439,12 +566,24 @@ namespace PcapDotNet.Packets.Gre ...@@ -439,12 +566,24 @@ namespace PcapDotNet.Packets.Gre
get { return _offset; } get { return _offset; }
} }
internal GreSourceRouteEntryUnknown(Datagram data, int offset) protected override byte OffsetInPayload
{
get { return (byte)Offset; }
}
protected override void WriteRoutingInformation(byte[] buffer, int offset)
{
buffer.Write(offset, Data);
}
internal GreSourceRouteEntryUnknown(GreSourceRouteEntryAddressFamily addressFamily, Datagram data, int offset)
{ {
_addressFamily = addressFamily;
_data = data; _data = data;
_offset = offset; _offset = offset;
} }
private readonly GreSourceRouteEntryAddressFamily _addressFamily;
private readonly Datagram _data; private readonly Datagram _data;
private readonly int _offset; private readonly int _offset;
} }
......
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq;
using PcapDotNet.Packets.Ethernet; using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Gre namespace PcapDotNet.Packets.Gre
{ {
public class GreLayer : Layer public class GreLayer : Layer, IIpV4NextLayer, IEquatable<GreLayer>
{ {
public byte RecursionControl { get; set; }
public GreVersion Version { get; set; } public GreVersion Version { get; set; }
public EthernetType ProtocolType { get; set; } public EthernetType ProtocolType { get; set; }
public byte RecursionControl { get; set; }
public bool ChecksumPresent { get; set; }
public ushort? Checksum { get; set; } public ushort? Checksum { get; set; }
public ushort? RoutingOffset { get; set; }
public uint? Key { get; set; } public uint? Key { get; set; }
public uint? SequenceNumber { get; set; } public uint? SequenceNumber { get; set; }
public ushort? RoutingOffset { get; set; }
public ReadOnlyCollection<GreSourceRouteEntry> Routing { get; set; } public ReadOnlyCollection<GreSourceRouteEntry> Routing { get; set; }
public bool StrictSourceRoute { get; set; }
public override int Length public override int Length
{ {
get { throw new NotImplementedException(); } get
{
return GreDatagram.GetHeaderLength(ChecksumPresent, Key != null, SequenceNumber != null, Routing);
}
} }
public override void Write(byte[] buffer, int offset, int payloadLength, ILayer previousLayer, ILayer nextLayer) public override void Write(byte[] buffer, int offset, int payloadLength, ILayer previousLayer, ILayer nextLayer)
{ {
GreDatagram.WriteHeader(buffer, offset); GreDatagram.WriteHeader(buffer, offset, RecursionControl, Version, ProtocolType, ChecksumPresent, Key, SequenceNumber, Routing, RoutingOffset, StrictSourceRoute);
}
public override void Finalize(byte[] buffer, int offset, int payloadLength, ILayer nextLayer)
{
if (ChecksumPresent)
GreDatagram.WriteChecksum(buffer, offset, Length + payloadLength, Checksum);
}
public bool Equals(GreLayer other)
{
return other != null &&
Version.Equals(other.Version) &&
ProtocolType.Equals(other.ProtocolType) &&
RecursionControl.Equals(other.RecursionControl) &&
ChecksumPresent.Equals(other.ChecksumPresent) &&
(Checksum == null ? other.Checksum == null : Checksum.Equals(other.Checksum)) &&
(Key == null ? other.Key == null : Key.Equals(other.Key)) &&
(SequenceNumber == null ? other.SequenceNumber == null : SequenceNumber.Equals(other.SequenceNumber)) &&
(RoutingOffset == null ? other.RoutingOffset == null : RoutingOffset.Equals(other.RoutingOffset)) &&
(Routing == null ? other.Routing == null : Routing.SequenceEqual(other.Routing)) &&
StrictSourceRoute.Equals(other.StrictSourceRoute);
} }
public override bool Equals(Layer other) public override bool Equals(Layer other)
{ {
throw new NotImplementedException(); return Equals(other as GreLayer);
}
public IpV4Protocol PreviousLayerProtocol
{
get { return IpV4Protocol.Gre; }
} }
} }
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment