Commit e6ce2bec authored by Brickner_cp's avatar Brickner_cp

GRE

parent 1f35830f
......@@ -80,7 +80,7 @@ namespace PcapDotNet.Packets.Test
Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer");
// IPv4
ipV4Layer.Protocol = IpV4Protocol.InternetControlMessageProtocol;
ipV4Layer.Protocol = IpV4Protocol.Gre;
ipV4Layer.HeaderChecksum = ((IpV4Layer)packet.Ethernet.IpV4.ExtractLayer()).HeaderChecksum;
Assert.AreEqual(ipV4Layer, packet.Ethernet.IpV4.ExtractLayer());
ipV4Layer.HeaderChecksum = null;
......
......@@ -58,27 +58,10 @@ namespace PcapDotNet.Packets.Gre
{
get
{
return OffsetRouting + (RoutingPresent
? Routing.Sum(entry => entry.Length) + GreSourceRouteEntry.HeaderLength // Routing and Routing termination
: 0);
return GetHeaderLength(ChecksumPresent, KeyPresent, SequenceNumberPresent, Routing);
}
}
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>
/// 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.
......@@ -124,7 +107,6 @@ namespace PcapDotNet.Packets.Gre
get { return (this[Offset.StrictSourceRoute] & Mask.StrictSourceRoute) == Mask.StrictSourceRoute; }
}
/// <summary>
/// Recursion control contains a three bit unsigned integer which contains the number of additional encapsulations which are permissible.
/// This SHOULD default to zero.
......@@ -210,7 +192,7 @@ namespace PcapDotNet.Packets.Gre
{
get
{
if (_routing == null)
if (_routing == null && RoutingPresent)
{
List<GreSourceRouteEntry> entries = new List<GreSourceRouteEntry>();
int entryOffset = StartOffset + OffsetRouting;
......@@ -249,7 +231,19 @@ namespace PcapDotNet.Packets.Gre
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()
......@@ -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;
......@@ -273,12 +338,26 @@ namespace PcapDotNet.Packets.Gre
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 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;
}
......@@ -290,6 +369,9 @@ namespace PcapDotNet.Packets.Gre
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)
{
entry = null;
......@@ -321,6 +403,14 @@ namespace PcapDotNet.Packets.Gre
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)
{
entry = null;
......@@ -352,7 +442,7 @@ namespace PcapDotNet.Packets.Gre
default:
Datagram data = new Datagram(buffer, payloadOffset, payloadLength);
entry = new GreSourceRouteEntryUnknown(data, offsetInPayload);
entry = new GreSourceRouteEntryUnknown(addressFamily, data, offsetInPayload);
return true;
}
}
......@@ -360,11 +450,22 @@ namespace PcapDotNet.Packets.Gre
public class GreSourceRouteEntryIp : GreSourceRouteEntry
{
public override GreSourceRouteEntryAddressFamily AddressFamily
{
get { return GreSourceRouteEntryAddressFamily.IpSourceRoute; }
}
public override int PayloadLength
{
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
{
get { return _addresses; }
......@@ -380,6 +481,11 @@ namespace PcapDotNet.Packets.Gre
get { return Addresses[NextAddressIndex]; }
}
protected override byte OffsetInPayload
{
get { return (byte)(NextAddressIndex * IpV4Address.SizeOf); }
}
internal GreSourceRouteEntryIp(IpV4Address[] addresses, int nextAddressIndex)
{
_addresses = new ReadOnlyCollection<IpV4Address>(addresses);
......@@ -392,6 +498,11 @@ namespace PcapDotNet.Packets.Gre
public class GreSourceRouteEntryAs : GreSourceRouteEntry
{
public override GreSourceRouteEntryAddressFamily AddressFamily
{
get { return GreSourceRouteEntryAddressFamily.AsSourceRoute; }
}
public override int PayloadLength
{
get { return sizeof(ushort); }
......@@ -412,6 +523,17 @@ namespace PcapDotNet.Packets.Gre
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)
{
_asNumbers = new ReadOnlyCollection<ushort>(asNumbers);
......@@ -424,6 +546,11 @@ namespace PcapDotNet.Packets.Gre
public class GreSourceRouteEntryUnknown : GreSourceRouteEntry
{
public override GreSourceRouteEntryAddressFamily AddressFamily
{
get { return _addressFamily; }
}
public override int PayloadLength
{
get { return Data.Length; }
......@@ -439,12 +566,24 @@ namespace PcapDotNet.Packets.Gre
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;
_offset = offset;
}
private readonly GreSourceRouteEntryAddressFamily _addressFamily;
private readonly Datagram _data;
private readonly int _offset;
}
......
using System;
using System.Collections.ObjectModel;
using System.Linq;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4;
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 EthernetType ProtocolType { get; set; }
public byte RecursionControl { get; set; }
public bool ChecksumPresent { get; set; }
public ushort? Checksum { get; set; }
public ushort? RoutingOffset { get; set; }
public uint? Key { get; set; }
public uint? SequenceNumber { get; set; }
public ushort? RoutingOffset { get; set; }
public ReadOnlyCollection<GreSourceRouteEntry> Routing { get; set; }
public bool StrictSourceRoute { get; set; }
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)
{
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)
{
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