Commit cdb913a5 authored by Brickner_cp's avatar Brickner_cp

GRE

parent b9e2fbb1
...@@ -142,6 +142,14 @@ namespace PcapDotNet.Core.Test ...@@ -142,6 +142,14 @@ namespace PcapDotNet.Core.Test
ethernetLayer.EtherType = EthernetType.None; ethernetLayer.EtherType = EthernetType.None;
ipV4Layer.Protocol = null; ipV4Layer.Protocol = null;
GreLayer greLayer = random.NextGreLayer(); GreLayer greLayer = random.NextGreLayer();
// GreLayer greLayer = new GreLayer
// {
// AcknowledgmentSequenceNumber = 10,
// ProtocolType = EthernetType.AppleTalk,
// //EthernetType.PointToPointProtocol,
// Key = 0,
// Version = GreVersion.EnhancedGre,
// };
// IEnumerable<ILayer> grePayloadLayers = random.NextIcmpPayloadLayers(icmpLayer); // IEnumerable<ILayer> grePayloadLayers = random.NextIcmpPayloadLayers(icmpLayer);
return PacketBuilder.Build(packetTimestamp, new ILayer[] {ethernetLayer, ipV4Layer, greLayer}); return PacketBuilder.Build(packetTimestamp, new ILayer[] {ethernetLayer, ipV4Layer, greLayer});
...@@ -173,7 +181,7 @@ namespace PcapDotNet.Core.Test ...@@ -173,7 +181,7 @@ namespace PcapDotNet.Core.Test
private static void ComparePacketsToWireshark(IEnumerable<Packet> packets) private static void ComparePacketsToWireshark(IEnumerable<Packet> packets)
{ {
string pcapFilename = Path.GetTempPath() + "temp.pcap"; string pcapFilename = Path.GetTempPath() + "temp." + new Random().NextUShort() + ".pcap";
PacketDumpFile.Dump(pcapFilename, new PcapDataLink(DataLinkKind.Ethernet), PacketDevice.DefaultSnapshotLength, packets); PacketDumpFile.Dump(pcapFilename, new PcapDataLink(DataLinkKind.Ethernet), PacketDevice.DefaultSnapshotLength, packets);
// List<Packet> packetsList = new List<Packet>(); // List<Packet> packetsList = new List<Packet>();
// new OfflinePacketDevice(pcapFilename).Open().ReceivePackets(1000, packetsList.Add); // new OfflinePacketDevice(pcapFilename).Open().ReceivePackets(1000, packetsList.Add);
...@@ -851,31 +859,52 @@ namespace PcapDotNet.Core.Test ...@@ -851,31 +859,52 @@ namespace PcapDotNet.Core.Test
if (field.Show().StartsWith("Flags and version: ")) if (field.Show().StartsWith("Flags and version: "))
{ {
XElement[] innerFields = field.Fields().ToArray(); XElement[] innerFields = field.Fields().ToArray();
Assert.AreEqual(8, innerFields.Length); bool isEnhanced = greDatagram.ProtocolType == EthernetType.PointToPointProtocol;
Assert.AreEqual(isEnhanced ? 9 : 8, innerFields.Length, "innerFields.Length");
foreach (var innerField in innerFields) foreach (var innerField in innerFields)
{ {
innerField.AssertName(""); innerField.AssertName("");
} }
innerFields[0].AssertShow(string.Format("{0}... .... .... .... = {1}", greDatagram.ChecksumPresent.ToInt(), int currentInnerFieldIndex = 0;
innerFields[currentInnerFieldIndex++].AssertShow(string.Format("{0}... .... .... .... = {1}", greDatagram.ChecksumPresent.ToInt(),
(greDatagram.ChecksumPresent ? "Checksum" : "No checksum"))); (greDatagram.ChecksumPresent ? "Checksum" : "No checksum")));
innerFields[1].AssertShow(string.Format(".{0}.. .... .... .... = {1}", greDatagram.RoutingPresent.ToInt(), innerFields[currentInnerFieldIndex++].AssertShow(string.Format(".{0}.. .... .... .... = {1}", greDatagram.RoutingPresent.ToInt(),
(greDatagram.RoutingPresent ? "Routing" : "No routing"))); (greDatagram.RoutingPresent ? "Routing" : "No routing")));
innerFields[2].AssertShow(string.Format("..{0}. .... .... .... = {1}", greDatagram.KeyPresent.ToInt(), innerFields[currentInnerFieldIndex++].AssertShow(string.Format("..{0}. .... .... .... = {1}", greDatagram.KeyPresent.ToInt(),
(greDatagram.KeyPresent ? "Key" : "No key"))); (greDatagram.KeyPresent ? "Key" : "No key")));
innerFields[3].AssertShow(string.Format("...{0} .... .... .... = {1}", greDatagram.SequenceNumberPresent.ToInt(), innerFields[currentInnerFieldIndex++].AssertShow(string.Format("...{0} .... .... .... = {1}", greDatagram.SequenceNumberPresent.ToInt(),
(greDatagram.SequenceNumberPresent ? "Sequence number" : "No sequence number"))); (greDatagram.SequenceNumberPresent ? "Sequence number" : "No sequence number")));
innerFields[4].AssertShow(string.Format(".... {0}... .... .... = {1}", greDatagram.StrictSourceRoute.ToInt(), innerFields[currentInnerFieldIndex++].AssertShow(string.Format(".... {0}... .... .... = {1}", greDatagram.StrictSourceRoute.ToInt(),
(greDatagram.StrictSourceRoute ? "Strict source route" : "No strict source route"))); (greDatagram.StrictSourceRoute ? "Strict source route" : "No strict source route")));
innerFields[5].AssertShow(string.Format(".... .{0} .... .... = Recursion control: {1}", innerFields[currentInnerFieldIndex++].AssertShow(string.Format(".... .{0} .... .... = Recursion control: {1}",
greDatagram.RecursionControl.ToBits().Skip(5).Select(b => b.ToInt()). greDatagram.RecursionControl.ToBits().Skip(5).Select(b => b.ToInt()).
SequenceToString(), SequenceToString(),
greDatagram.RecursionControl)); greDatagram.RecursionControl));
innerFields[6].AssertShow(string.Format(".... .... {0}... = Flags: {1}", if (isEnhanced)
greDatagram.Flags.ToBits().Skip(3).Select(b => b.ToInt()).SequenceToString(). {
Insert(4, " "), innerFields[currentInnerFieldIndex++].AssertShow(string.Format(".... .... {0}... .... = {1}",
greDatagram.Flags)); greDatagram.AcknowledgmentSequenceNumberPresent.ToInt(),
innerFields[7].AssertShow(string.Format(".... .... .... .{0} = Version: {1}", (greDatagram.AcknowledgmentSequenceNumberPresent
? "Acknowledgment number"
: "No acknowledgment number")));
innerFields[currentInnerFieldIndex++].AssertShow(string.Format(".... .... .{0}... = Flags: {1}",
greDatagram.Flags.ToBits().Skip(3).Take(4).Select(b => b.ToInt()).
SequenceToString().
Insert(3, " "),
greDatagram.Flags));
}
else
{
byte fullFlags = (byte)(greDatagram.Flags | (greDatagram.AcknowledgmentSequenceNumberPresent ? 0x10 : 0x00));
innerFields[currentInnerFieldIndex++].AssertShow(string.Format(".... .... {0}... = Flags: {1}",
fullFlags.ToBits().Skip(3).Select(b => b.ToInt()).
SequenceToString().
Insert(4, " "),
fullFlags));
}
innerFields[currentInnerFieldIndex++].AssertShow(string.Format(".... .... .... .{0} = Version: {1}",
((byte)greDatagram.Version).ToBits().Skip(5).Select(b => b.ToInt()). ((byte)greDatagram.Version).ToBits().Skip(5).Select(b => b.ToInt()).
SequenceToString(), SequenceToString(),
(byte)greDatagram.Version)); (byte)greDatagram.Version));
...@@ -888,10 +917,22 @@ namespace PcapDotNet.Core.Test ...@@ -888,10 +917,22 @@ namespace PcapDotNet.Core.Test
{ {
field.AssertValue(greDatagram.RoutingOffset); field.AssertValue(greDatagram.RoutingOffset);
} }
else if (field.Show().StartsWith("Payload length: "))
{
field.AssertValue(greDatagram.KeyPayloadLength);
}
else if (field.Show().StartsWith("Call ID: "))
{
field.AssertValue(greDatagram.KeyCallId);
}
else if (field.Show().StartsWith("Sequence number: ")) else if (field.Show().StartsWith("Sequence number: "))
{ {
field.AssertValue(greDatagram.SequenceNumber); field.AssertValue(greDatagram.SequenceNumber);
} }
else if (field.Show().StartsWith("Acknowledgement number: "))
{
field.AssertValue(greDatagram.AcknowledgmentSequenceNumber);
}
else if (field.Show().StartsWith("Address family: ")) else if (field.Show().StartsWith("Address family: "))
{ {
++currentEntry; ++currentEntry;
......
...@@ -583,72 +583,85 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -583,72 +583,85 @@ namespace PcapDotNet.Packets.TestUtils
// GRE // GRE
public static GreLayer NextGreLayer(this Random random) public static GreLayer NextGreLayer(this Random random)
{ {
GreVersion version = random.NextEnum<GreVersion>();
bool isChecksum = random.NextBool(); bool isChecksum = random.NextBool();
bool isRouting = random.NextBool();
GreSourceRouteEntry[] routing = null; GreSourceRouteEntry[] routing = null;
ushort? routingOffset = null; ushort? routingOffset = null;
bool strictSourceRoute = false; bool strictSourceRoute = false;
if (isRouting) EthernetType protocolType = random.NextEnum(EthernetType.None);
uint? key = random.NextBool() ? (uint?)random.NextUInt() : null;
if (version == GreVersion.Gre)
{ {
strictSourceRoute = random.NextBool();
routing = new GreSourceRouteEntry[random.Next(5)];
GreSourceRouteEntryAddressFamily family;
if (random.NextBool()) if (random.NextBool())
family = random.NextEnum(GreSourceRouteEntryAddressFamily.None);
else
family = (GreSourceRouteEntryAddressFamily)random.NextUShort();
for (int i = 0; i != routing.Length; ++i)
{ {
switch (family) strictSourceRoute = random.NextBool();
routing = new GreSourceRouteEntry[random.Next(5)];
GreSourceRouteEntryAddressFamily family;
if (random.NextBool())
family = random.NextEnum(GreSourceRouteEntryAddressFamily.None);
else
family = (GreSourceRouteEntryAddressFamily)random.NextUShort();
for (int i = 0; i != routing.Length; ++i)
{ {
case GreSourceRouteEntryAddressFamily.AsSourceRoute: switch (family)
{ {
ushort[] asNumbers = new ushort[random.Next(1, 5)]; case GreSourceRouteEntryAddressFamily.AsSourceRoute:
for (int j = 0; j != asNumbers.Length; ++j) {
asNumbers[j] = random.NextUShort(); ushort[] asNumbers = new ushort[random.Next(1, 5)];
routing[i] = new GreSourceRouteEntryAs(asNumbers.AsReadOnly(), random.Next(asNumbers.Length + 1)); for (int j = 0; j != asNumbers.Length; ++j)
break; asNumbers[j] = random.NextUShort();
} routing[i] = new GreSourceRouteEntryAs(asNumbers.AsReadOnly(), random.Next(asNumbers.Length + 1));
break;
}
case GreSourceRouteEntryAddressFamily.IpSourceRoute: case GreSourceRouteEntryAddressFamily.IpSourceRoute:
{ {
IpV4Address[] ips = new IpV4Address[random.Next(1, 5)]; IpV4Address[] ips = new IpV4Address[random.Next(1, 5)];
for (int j = 0; j != ips.Length; ++j) for (int j = 0; j != ips.Length; ++j)
ips[j] = random.NextIpV4Address(); ips[j] = random.NextIpV4Address();
routing[i] = new GreSourceRouteEntryIp(ips.AsReadOnly(), random.Next(ips.Length + 1)); routing[i] = new GreSourceRouteEntryIp(ips.AsReadOnly(), random.Next(ips.Length + 1));
break; break;
} }
default: default:
{ {
int dataLength = random.Next(1, 100); int dataLength = random.Next(1, 100);
routing[i] = new GreSourceRouteEntryUnknown(family, random.NextDatagram(dataLength), random.Next(dataLength + 1)); routing[i] = new GreSourceRouteEntryUnknown(family, random.NextDatagram(dataLength), random.Next(dataLength + 1));
break; break;
}
} }
}
}
routingOffset = 0;
if (!routing.IsEmpty())
{
int routingIndex = random.Next(routing.Length);
for (int i = 0; i != routingIndex; ++i)
routingOffset += (ushort)routing[i].Length;
}
} }
routingOffset = 0; }
if (!routing.IsEmpty()) else
{ {
int routingIndex = random.Next(routing.Length); protocolType = EthernetType.PointToPointProtocol;
for (int i = 0; i != routingIndex; ++i) isChecksum = false;
routingOffset += (ushort)routing[i].Length; key = random.NextUInt();
}
} }
return new GreLayer return new GreLayer
{ {
Version = random.NextEnum<GreVersion>(), Version = version,
ProtocolType = random.NextEnum(EthernetType.None), ProtocolType = protocolType,
ChecksumPresent = isChecksum, ChecksumPresent = isChecksum,
Checksum = isChecksum && random.NextBool() ? (ushort?)random.NextUShort() : null, Checksum = isChecksum && random.NextBool() ? (ushort?)random.NextUShort() : null,
Key = random.NextBool() ? (uint?)random.NextUInt() : null, Key = key,
SequenceNumber = random.NextBool() ? (uint?)random.NextUInt() : null, SequenceNumber = random.NextBool() ? (uint?)random.NextUInt() : null,
AcknowledgmentSequenceNumber = version == GreVersion.EnhancedGre && random.NextBool() ? (uint?)random.NextUInt() : null,
RecursionControl = random.NextByte(8), RecursionControl = random.NextByte(8),
Flags = random.NextByte(32), // Flags = random.NextByte(32),
Routing = routing == null ? null : routing.AsReadOnly(), Routing = routing == null ? null : routing.AsReadOnly(),
RoutingOffset = routingOffset, RoutingOffset = routingOffset,
StrictSourceRoute = strictSourceRoute, StrictSourceRoute = strictSourceRoute,
......
...@@ -51,6 +51,10 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -51,6 +51,10 @@ namespace PcapDotNet.Packets.Ethernet
/// </summary> /// </summary>
MacControl = 0x8808, MacControl = 0x8808,
/// <summary> /// <summary>
/// PPP, Point-to-Point Protocol
/// </summary>
PointToPointProtocol = 0x880B,
/// <summary>
/// CobraNet /// CobraNet
/// </summary> /// </summary>
CobraNet = 0x8819, CobraNet = 0x8819,
......
...@@ -11,19 +11,21 @@ namespace PcapDotNet.Packets.Gre ...@@ -11,19 +11,21 @@ namespace PcapDotNet.Packets.Gre
/// <summary> /// <summary>
/// RFC 1701, RFC 1702, RFC 2637, RFC 2784. /// RFC 1701, RFC 1702, RFC 2637, RFC 2784.
/// <pre> /// <pre>
/// +-----+---+---+---+---+---+-------+-------+---------+-------------------+ /// +-----+---+---+---+---+---+-------+---+-------+---------+-------------------+
/// | Bit | 0 | 1 | 2 | 3 | 4 | 5-7 | 8-12 | 13-15 | 16-31 | /// | Bit | 0 | 1 | 2 | 3 | 4 | 5-7 | 8 | 9-12 | 13-15 | 16-31 |
/// +-----+---+-----------+---+-------+-------+---------+-------------------+ /// +-----+---+-----------+---+-------+---+-------+---------+-------------------+
/// | 0 | C | R | K | S | s | Recur | Flags | Version | Protocol Type | /// | 0 | C | R | K | S | s | Recur | A | Flags | Version | Protocol Type |
/// +-----+---+-----------+---+-------+-------+---------+-------------------+ /// +-----+---+-----------+---+-------+---+-------+---------+-------------------+
/// | 32 | Checksum (optional) | Offset (optional) | /// | 32 | Checksum (optional) | Offset (optional) |
/// +-----+---------------------------------------------+-------------------+ /// +-----+-------------------------------------------------+-------------------+
/// | 32 | Key (optional) | /// | 32 | Key (optional) |
/// +-----+-----------------------------------------------------------------+ /// +-----+---------------------------------------------------------------------+
/// | 32 | Sequence Number (optional) | /// | 32 | Sequence Number (optional) |
/// +-----+-----------------------------------------------------------------+ /// +-----+---------------------------------------------------------------------+
/// | 32 | Routing (optional) | /// | 32 | Acknowledgment Number (optional) |
/// +-----+-----------------------------------------------------------------+ /// +-----+---------------------------------------------------------------------+
/// | 32 | Routing (optional) |
/// +-----+---------------------------------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class GreDatagram : Datagram public class GreDatagram : Datagram
...@@ -36,6 +38,7 @@ namespace PcapDotNet.Packets.Gre ...@@ -36,6 +38,7 @@ namespace PcapDotNet.Packets.Gre
public const int SequenceNumberPresent = 0; public const int SequenceNumberPresent = 0;
public const int StrictSourceRoute = 0; public const int StrictSourceRoute = 0;
public const int RecursionControl = 0; public const int RecursionControl = 0;
public const int AcknowledgmentSequenceNumberPresent = 1;
public const int Flags = 1; public const int Flags = 1;
public const int Version = 1; public const int Version = 1;
public const int ProtocolType = 2; public const int ProtocolType = 2;
...@@ -51,7 +54,8 @@ namespace PcapDotNet.Packets.Gre ...@@ -51,7 +54,8 @@ namespace PcapDotNet.Packets.Gre
public const byte SequenceNumberPresent = 0x10; public const byte SequenceNumberPresent = 0x10;
public const byte StrictSourceRoute = 0x08; public const byte StrictSourceRoute = 0x08;
public const byte RecursionControl = 0x07; public const byte RecursionControl = 0x07;
public const byte Flags = 0xF8; public const byte AcknowledgmentSequenceNumberPresent = 0x80;
public const byte Flags = 0x78;
public const byte Version = 0x07; public const byte Version = 0x07;
} }
...@@ -66,7 +70,7 @@ namespace PcapDotNet.Packets.Gre ...@@ -66,7 +70,7 @@ namespace PcapDotNet.Packets.Gre
{ {
get get
{ {
return GetHeaderLength(ChecksumPresent, KeyPresent, SequenceNumberPresent, Routing); return GetHeaderLength(ChecksumPresent, KeyPresent, SequenceNumberPresent, AcknowledgmentSequenceNumberPresent, Routing);
} }
} }
...@@ -124,6 +128,17 @@ namespace PcapDotNet.Packets.Gre ...@@ -124,6 +128,17 @@ namespace PcapDotNet.Packets.Gre
get { return (byte)(this[Offset.RecursionControl] & Mask.RecursionControl); } get { return (byte)(this[Offset.RecursionControl] & Mask.RecursionControl); }
} }
/// <summary>
/// Set to one (1) if packet contains Acknowledgment Number to be used for acknowledging previously transmitted data.
/// </summary>
public bool AcknowledgmentSequenceNumberPresent
{
get { return (this[Offset.AcknowledgmentSequenceNumberPresent] & Mask.AcknowledgmentSequenceNumberPresent) == Mask.AcknowledgmentSequenceNumberPresent; }
}
/// <summary>
/// Must be set to zero (0).
/// </summary>
public byte Flags public byte Flags
{ {
get { return (byte)((this[Offset.Flags] & Mask.Flags) >> Shift.Flags); } get { return (byte)((this[Offset.Flags] & Mask.Flags) >> Shift.Flags); }
...@@ -208,6 +223,16 @@ namespace PcapDotNet.Packets.Gre ...@@ -208,6 +223,16 @@ namespace PcapDotNet.Packets.Gre
get { return ReadUInt(OffsetKey, Endianity.Big); } get { return ReadUInt(OffsetKey, Endianity.Big); }
} }
public ushort KeyPayloadLength
{
get { return ReadUShort(OffsetKeyPayloadLength, Endianity.Big); }
}
public ushort KeyCallId
{
get { return ReadUShort(OffsetKeyCallId, Endianity.Big); }
}
/// <summary> /// <summary>
/// The Sequence Number field contains an unsigned 32 bit integer which is inserted by the encapsulator. /// The Sequence Number field contains an unsigned 32 bit integer which is inserted by the encapsulator.
/// It may be used by the receiver to establish the order in which packets have been transmitted from the encapsulator to the receiver. /// It may be used by the receiver to establish the order in which packets have been transmitted from the encapsulator to the receiver.
...@@ -217,6 +242,15 @@ namespace PcapDotNet.Packets.Gre ...@@ -217,6 +242,15 @@ namespace PcapDotNet.Packets.Gre
get { return ReadUInt(OffsetSequenceNumber, Endianity.Big); } get { return ReadUInt(OffsetSequenceNumber, Endianity.Big); }
} }
/// <summary>
/// Contains the sequence number of the highest numbered GRE packet received by the sending peer for this user session.
/// Present if A bit (Bit 8) is one (1).
/// </summary>
public uint AcknowledgmentSequenceNumber
{
get { return ReadUInt(OffsetAcknowledgmentSequenceNumber, Endianity.Big); }
}
/// <summary> /// <summary>
/// The Routing field is optional and is present only if the Routing Present bit is set to 1. /// The Routing field is optional and is present only if the Routing Present bit is set to 1.
/// The Routing field is a list of Source Route Entries (SREs). /// The Routing field is a list of Source Route Entries (SREs).
...@@ -254,24 +288,28 @@ namespace PcapDotNet.Packets.Gre ...@@ -254,24 +288,28 @@ namespace PcapDotNet.Packets.Gre
public override ILayer ExtractLayer() public override ILayer ExtractLayer()
{ {
return new GreLayer return new GreLayer
{ {
Version = Version, Version = Version,
ProtocolType = ProtocolType, ProtocolType = ProtocolType,
RecursionControl = RecursionControl, RecursionControl = RecursionControl,
Flags = Flags, Flags = Flags,
ChecksumPresent = ChecksumPresent, ChecksumPresent = ChecksumPresent,
Checksum = ChecksumPresent ? (ushort?)Checksum : null, Checksum = ChecksumPresent ? (ushort?)Checksum : null,
Key = KeyPresent ? (uint?)Key : null, Key = KeyPresent ? (uint?)Key : null,
SequenceNumber = SequenceNumberPresent ? (uint?)SequenceNumber : null, SequenceNumber = SequenceNumberPresent ? (uint?)SequenceNumber : null,
Routing = RoutingPresent ? Routing : null, AcknowledgmentSequenceNumber = AcknowledgmentSequenceNumberPresent ? (uint?)AcknowledgmentSequenceNumber : null,
RoutingOffset = RoutingPresent ? (ushort?)RoutingOffset : null, Routing = RoutingPresent ? Routing : null,
StrictSourceRoute = StrictSourceRoute, RoutingOffset = RoutingPresent ? (ushort?)RoutingOffset : null,
}; StrictSourceRoute = StrictSourceRoute,
};
} }
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
return (Length >= HeaderMinimumLength && Length >= HeaderLength && IsValidRouting && (!ChecksumPresent || IsChecksumCorrect)); return (Length >= HeaderMinimumLength && Length >= HeaderLength &&
IsValidRouting && Flags == 0 &&
(Version == GreVersion.EnhancedGre || Version == GreVersion.Gre && !AcknowledgmentSequenceNumberPresent) &&
(!ChecksumPresent || IsChecksumCorrect));
} }
internal GreDatagram(byte[] buffer, int offset, int length) internal GreDatagram(byte[] buffer, int offset, int length)
...@@ -279,18 +317,19 @@ namespace PcapDotNet.Packets.Gre ...@@ -279,18 +317,19 @@ namespace PcapDotNet.Packets.Gre
{ {
} }
internal static int GetHeaderLength(bool isChecksumPresent, bool isKeyPresent, bool isSequenceNumberPresent, IEnumerable<GreSourceRouteEntry> routing) internal static int GetHeaderLength(bool isChecksumPresent, bool isKeyPresent, bool isSequenceNumberPresent, bool isAcknowledgmentSequenceNumberPresent, IEnumerable<GreSourceRouteEntry> routing)
{ {
return HeaderMinimumLength + return HeaderMinimumLength +
(isChecksumPresent || routing != null ? sizeof(ushort) + sizeof(ushort) : 0) + (isChecksumPresent || routing != null ? sizeof(ushort) + sizeof(ushort) : 0) +
(isKeyPresent ? sizeof(uint) : 0) + (isKeyPresent ? sizeof(uint) : 0) +
(isSequenceNumberPresent ? sizeof(uint) : 0) + (isSequenceNumberPresent ? sizeof(uint) : 0) +
(isAcknowledgmentSequenceNumberPresent ? sizeof(uint) : 0) +
(routing != null ? routing.Sum(entry => entry.Length) + GreSourceRouteEntry.HeaderLength : 0); (routing != null ? routing.Sum(entry => entry.Length) + GreSourceRouteEntry.HeaderLength : 0);
} }
internal static void WriteHeader(byte[] buffer, int offset, internal static void WriteHeader(byte[] buffer, int offset,
byte recursionControl, byte flags, GreVersion version, EthernetType protocolType, byte recursionControl, byte flags, GreVersion version, EthernetType protocolType,
bool checksumPresent, uint? key, uint? sequenceNumber, bool checksumPresent, uint? key, uint? sequenceNumber, uint? acknowledgmentSequenceNumber,
ReadOnlyCollection<GreSourceRouteEntry> routing, ushort? routingOffset, bool strictSourceRoute) ReadOnlyCollection<GreSourceRouteEntry> routing, ushort? routingOffset, bool strictSourceRoute)
{ {
buffer.Write(offset + Offset.ChecksumPresent, buffer.Write(offset + Offset.ChecksumPresent,
...@@ -301,7 +340,9 @@ namespace PcapDotNet.Packets.Gre ...@@ -301,7 +340,9 @@ namespace PcapDotNet.Packets.Gre
(strictSourceRoute ? Mask.StrictSourceRoute : (byte)0) | (strictSourceRoute ? Mask.StrictSourceRoute : (byte)0) |
(recursionControl & Mask.RecursionControl))); (recursionControl & Mask.RecursionControl)));
buffer.Write(offset + Offset.Flags, (byte)(((flags << Shift.Flags) & Mask.Flags) | ((byte)version & Mask.Version))); buffer.Write(offset + Offset.Flags, (byte)((acknowledgmentSequenceNumber != null ? Mask.AcknowledgmentSequenceNumberPresent : (byte)0) |
((flags << Shift.Flags) & Mask.Flags) |
((byte)version & Mask.Version)));
buffer.Write(offset + Offset.ProtocolType, (ushort)protocolType, Endianity.Big); buffer.Write(offset + Offset.ProtocolType, (ushort)protocolType, Endianity.Big);
...@@ -320,6 +361,9 @@ namespace PcapDotNet.Packets.Gre ...@@ -320,6 +361,9 @@ namespace PcapDotNet.Packets.Gre
if (sequenceNumber != null) if (sequenceNumber != null)
buffer.Write(ref offset, sequenceNumber.Value, Endianity.Big); buffer.Write(ref offset, sequenceNumber.Value, Endianity.Big);
if (acknowledgmentSequenceNumber != null)
buffer.Write(ref offset, acknowledgmentSequenceNumber.Value, Endianity.Big);
if (routing != null) if (routing != null)
{ {
foreach (GreSourceRouteEntry entry in routing) foreach (GreSourceRouteEntry entry in routing)
...@@ -342,16 +386,31 @@ namespace PcapDotNet.Packets.Gre ...@@ -342,16 +386,31 @@ namespace PcapDotNet.Packets.Gre
get { return HeaderMinimumLength + ((ChecksumPresent || RoutingPresent) ? sizeof(ushort) + sizeof(ushort) : 0); } get { return HeaderMinimumLength + ((ChecksumPresent || RoutingPresent) ? sizeof(ushort) + sizeof(ushort) : 0); }
} }
private int OffsetKeyPayloadLength
{
get { return OffsetKey; }
}
private int OffsetKeyCallId
{
get { return OffsetKey + sizeof(ushort); }
}
private int OffsetSequenceNumber private int OffsetSequenceNumber
{ {
get { return OffsetKey + (KeyPresent ? sizeof(uint) : 0); } get { return OffsetKey + (KeyPresent ? sizeof(uint) : 0); }
} }
private int OffsetRouting private int OffsetAcknowledgmentSequenceNumber
{ {
get { return OffsetSequenceNumber + (SequenceNumberPresent ? sizeof(uint) : 0); } get { return OffsetSequenceNumber + (SequenceNumberPresent ? sizeof(uint) : 0); }
} }
private int OffsetRouting
{
get { return OffsetAcknowledgmentSequenceNumber + (AcknowledgmentSequenceNumberPresent ? sizeof(uint) : 0); }
}
private void TryParseRouting() private void TryParseRouting()
{ {
if (_routing != null || !RoutingPresent) if (_routing != null || !RoutingPresent)
......
...@@ -16,6 +16,7 @@ namespace PcapDotNet.Packets.Gre ...@@ -16,6 +16,7 @@ namespace PcapDotNet.Packets.Gre
public ushort? Checksum { get; set; } public ushort? Checksum { get; set; }
public uint? Key { get; set; } public uint? Key { get; set; }
public uint? SequenceNumber { get; set; } public uint? SequenceNumber { get; set; }
public uint? AcknowledgmentSequenceNumber { get; set; }
public ushort? RoutingOffset { 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 bool StrictSourceRoute { get; set; }
...@@ -24,13 +25,13 @@ namespace PcapDotNet.Packets.Gre ...@@ -24,13 +25,13 @@ namespace PcapDotNet.Packets.Gre
{ {
get get
{ {
return GreDatagram.GetHeaderLength(ChecksumPresent, Key != null, SequenceNumber != null, Routing); return GreDatagram.GetHeaderLength(ChecksumPresent, Key != null, SequenceNumber != null, AcknowledgmentSequenceNumber != 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, RecursionControl, Flags, Version, ProtocolType, ChecksumPresent, Key, SequenceNumber, Routing, RoutingOffset, StrictSourceRoute); GreDatagram.WriteHeader(buffer, offset, RecursionControl, Flags, Version, ProtocolType, ChecksumPresent, Key, SequenceNumber, AcknowledgmentSequenceNumber, Routing, RoutingOffset, StrictSourceRoute);
} }
public override void Finalize(byte[] buffer, int offset, int payloadLength, ILayer nextLayer) public override void Finalize(byte[] buffer, int offset, int payloadLength, ILayer nextLayer)
...@@ -50,6 +51,7 @@ namespace PcapDotNet.Packets.Gre ...@@ -50,6 +51,7 @@ namespace PcapDotNet.Packets.Gre
(Checksum == null ? other.Checksum == null : Checksum.Equals(other.Checksum)) && (Checksum == null ? other.Checksum == null : Checksum.Equals(other.Checksum)) &&
(Key == null ? other.Key == null : Key.Equals(other.Key)) && (Key == null ? other.Key == null : Key.Equals(other.Key)) &&
(SequenceNumber == null ? other.SequenceNumber == null : SequenceNumber.Equals(other.SequenceNumber)) && (SequenceNumber == null ? other.SequenceNumber == null : SequenceNumber.Equals(other.SequenceNumber)) &&
(AcknowledgmentSequenceNumber == null ? other.AcknowledgmentSequenceNumber == null : AcknowledgmentSequenceNumber.Equals(other.AcknowledgmentSequenceNumber)) &&
(RoutingOffset == null ? other.RoutingOffset == null : RoutingOffset.Equals(other.RoutingOffset)) && (RoutingOffset == null ? other.RoutingOffset == null : RoutingOffset.Equals(other.RoutingOffset)) &&
(Routing == null ? other.Routing == null : Routing.SequenceEqual(other.Routing)) && (Routing == null ? other.Routing == null : Routing.SequenceEqual(other.Routing)) &&
StrictSourceRoute.Equals(other.StrictSourceRoute); StrictSourceRoute.Equals(other.StrictSourceRoute);
......
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