Commit b7799fc9 authored by Brickner_cp's avatar Brickner_cp

IPv6

parent 14169c2a
...@@ -73,10 +73,10 @@ namespace PcapDotNet.Packets.Test ...@@ -73,10 +73,10 @@ namespace PcapDotNet.Packets.Test
// Ethernet // Ethernet
Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLengthValue, packet.Ethernet.PayloadLength, "PayloadLength"); Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLengthValue, packet.Ethernet.PayloadLength, "PayloadLength");
// Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer"); Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer");
// IpV6 // IpV6
// Assert.AreEqual(ipV6Layer, packet.Ethernet.IpV6.ExtractLayer(), "IP Layer"); Assert.AreEqual(ipV6Layer, packet.Ethernet.IpV6.ExtractLayer(), "IP Layer");
/* /*
if (packet.Ethernet.IpV6.NextHeader == IpV4Protocol.Tcp) if (packet.Ethernet.IpV6.NextHeader == IpV4Protocol.Tcp)
Assert.IsInstanceOfType(packet.Ethernet.IpV6.Transport, typeof(TcpDatagram)); Assert.IsInstanceOfType(packet.Ethernet.IpV6.Transport, typeof(TcpDatagram));
......
...@@ -45,15 +45,18 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -45,15 +45,18 @@ namespace PcapDotNet.Packets.TestUtils
IpV6ExtensionHeader[] headers = new IpV6ExtensionHeader[count]; IpV6ExtensionHeader[] headers = new IpV6ExtensionHeader[count];
for (int i = headers.Length - 1; i >= 0; --i) for (int i = headers.Length - 1; i >= 0; --i)
{ {
headers[i] = random.NextIpV6ExtensionHeader(nextHeader); headers[i] = random.NextIpV6ExtensionHeader(nextHeader, i == headers.Length - 1);
nextHeader = headers[i].Protocol; nextHeader = headers[i].Protocol;
} }
return new IpV6ExtensionHeaders(headers); return new IpV6ExtensionHeaders(headers);
} }
public static IpV6ExtensionHeader NextIpV6ExtensionHeader(this Random random, IpV4Protocol nextHeader) public static IpV6ExtensionHeader NextIpV6ExtensionHeader(this Random random, IpV4Protocol nextHeader, bool isEncapsulatingSecurityPayloadPossible)
{ {
IpV4Protocol extensionHeaderType = random.NextValue(IpV6ExtensionHeader.ExtensionHeaders); IpV4Protocol extensionHeaderType =
random.NextValue(
IpV6ExtensionHeader.ExtensionHeaders.Where(extensionHeader => isEncapsulatingSecurityPayloadPossible ||
extensionHeader != IpV4Protocol.EncapsulatingSecurityPayload).ToList());
switch (extensionHeaderType) switch (extensionHeaderType)
{ {
case IpV4Protocol.IpV6HopByHopOption: // 0 case IpV4Protocol.IpV6HopByHopOption: // 0
...@@ -84,7 +87,8 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -84,7 +87,8 @@ namespace PcapDotNet.Packets.TestUtils
random.NextBool(), random.NextUInt()); random.NextBool(), random.NextUInt());
case IpV4Protocol.IpV6Opts: // 60 case IpV4Protocol.IpV6Opts: // 60
return new IpV6ExtensionHeaderDestinationOptions(nextHeader, random.NextIpV6Options()); IpV6Options options = random.NextIpV6Options();
return new IpV6ExtensionHeaderDestinationOptions(nextHeader, options);
case IpV4Protocol.MobilityHeader: // 135 case IpV4Protocol.MobilityHeader: // 135
return random.NextIpV6ExtensionHeaderMobility(nextHeader); return random.NextIpV6ExtensionHeaderMobility(nextHeader);
......
...@@ -105,16 +105,9 @@ namespace PcapDotNet.Packets.Ip ...@@ -105,16 +105,9 @@ namespace PcapDotNet.Packets.Ip
IsValid = isValid; IsValid = isValid;
if (length.HasValue) if (length.HasValue)
{
BytesLength = length.Value; BytesLength = length.Value;
}
else else
{ BytesLength = CalculateBytesLength(SumBytesLength(OptionsCollection));
BytesLength = SumBytesLength(OptionsCollection);
if (BytesLength % 4 != 0)
BytesLength = (BytesLength / 4 + 1) * 4;
}
} }
internal static int SumBytesLength(IEnumerable<T> options) internal static int SumBytesLength(IEnumerable<T> options)
...@@ -122,6 +115,8 @@ namespace PcapDotNet.Packets.Ip ...@@ -122,6 +115,8 @@ namespace PcapDotNet.Packets.Ip
return options.Sum(option => option.Length); return options.Sum(option => option.Length);
} }
internal abstract int CalculateBytesLength(int optionsLength);
private readonly ReadOnlyCollection<T> _options; private readonly ReadOnlyCollection<T> _options;
} }
} }
\ No newline at end of file
...@@ -18,7 +18,14 @@ namespace PcapDotNet.Packets.Ip ...@@ -18,7 +18,14 @@ namespace PcapDotNet.Packets.Ip
if (BytesLength > maximumBytesLength) if (BytesLength > maximumBytesLength)
throw new ArgumentException("given options take " + BytesLength + " bytes and maximum number of bytes for options is " + maximumBytesLength, "options"); throw new ArgumentException("given options take " + BytesLength + " bytes and maximum number of bytes for options is " + maximumBytesLength, "options");
} }
internal override sealed int CalculateBytesLength(int optionsLength)
{
if (optionsLength % 4 == 0)
return optionsLength;
return (optionsLength / 4 + 1) * 4;
}
private V4Options(Tuple<IList<T>, bool> optionsAndIsValid, int? length) private V4Options(Tuple<IList<T>, bool> optionsAndIsValid, int? length)
: this(optionsAndIsValid.Item1, optionsAndIsValid.Item2, length) : this(optionsAndIsValid.Item1, optionsAndIsValid.Item2, length)
{ {
......
...@@ -44,13 +44,13 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -44,13 +44,13 @@ namespace PcapDotNet.Packets.IpV6
private static class Offset private static class Offset
{ {
public const int Version = 0; public const int Version = 0;
public const int TrafficClass = 0; public const int TrafficClass = Version;
public const int FlowLabel = 1; public const int FlowLabel = TrafficClass + 1;
public const int PayloadLength = 4; public const int PayloadLength = FlowLabel + 3;
public const int NextHeader = 6; public const int NextHeader = PayloadLength + sizeof(ushort);
public const int HopLimit = 7; public const int HopLimit = NextHeader + sizeof(byte);
public const int SourceAddress = 8; public const int SourceAddress = HopLimit + sizeof(byte);
public const int DestinationAddress = 24; public const int DestinationAddress = SourceAddress + IpV6Address.SizeOf;
} }
private static class Mask private static class Mask
...@@ -172,6 +172,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -172,6 +172,7 @@ namespace PcapDotNet.Packets.IpV6
return; return;
} }
_extensionHeaders = new IpV6ExtensionHeaders(Subsegment(HeaderLength, RealPayloadLength), NextHeader); _extensionHeaders = new IpV6ExtensionHeaders(Subsegment(HeaderLength, RealPayloadLength), NextHeader);
_isValid = _isValid && _extensionHeaders.IsValid;
/* /*
int extendedHeaderLength = HeaderLength; int extendedHeaderLength = HeaderLength;
IpV4Protocol? nextHeader = NextHeader; IpV4Protocol? nextHeader = NextHeader;
...@@ -236,7 +237,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -236,7 +237,7 @@ namespace PcapDotNet.Packets.IpV6
byte trafficClass, int flowLabel, ushort payloadLength, IpV4Protocol nextHeader, byte hopLimit, byte trafficClass, int flowLabel, ushort payloadLength, IpV4Protocol nextHeader, byte hopLimit,
IpV6Address source, IpV6Address currentDestination, IpV6ExtensionHeaders extensionHeaders) IpV6Address source, IpV6Address currentDestination, IpV6ExtensionHeaders extensionHeaders)
{ {
buffer.Write(offset + Offset.Version, (uint)(((((DefaultVersion << Shift.Version) << 8) | trafficClass) << 16) | flowLabel), Endianity.Big); buffer.Write(offset + Offset.Version, (uint)((((DefaultVersion << 8) | trafficClass) << 20) | flowLabel), Endianity.Big);
buffer.Write(offset + Offset.PayloadLength, payloadLength, Endianity.Big); buffer.Write(offset + Offset.PayloadLength, payloadLength, Endianity.Big);
buffer.Write(offset + Offset.NextHeader, (byte)nextHeader); buffer.Write(offset + Offset.NextHeader, (byte)nextHeader);
buffer.Write(offset + Offset.HopLimit, hopLimit); buffer.Write(offset + Offset.HopLimit, hopLimit);
...@@ -253,7 +254,6 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -253,7 +254,6 @@ namespace PcapDotNet.Packets.IpV6
} }
private IpV6ExtensionHeaders _extensionHeaders; private IpV6ExtensionHeaders _extensionHeaders;
private int _extensionHeadersLength;
private bool _isValid; private bool _isValid;
} }
} }
...@@ -33,6 +33,14 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -33,6 +33,14 @@ namespace PcapDotNet.Packets.IpV6
public const int MinimumLength = 8; public const int MinimumLength = 8;
public override sealed bool Equals(IpV6ExtensionHeader other)
{
return other != null &&
Protocol == other.Protocol && NextHeader == other.NextHeader && EqualsData(other);
}
internal abstract bool EqualsData(IpV6ExtensionHeader other);
internal IpV6ExtensionHeaderStandard(IpV4Protocol nextHeader) internal IpV6ExtensionHeaderStandard(IpV4Protocol nextHeader)
: base(nextHeader) : base(nextHeader)
{ {
...@@ -49,7 +57,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -49,7 +57,7 @@ namespace PcapDotNet.Packets.IpV6
internal abstract void WriteData(byte[] buffer, int offset); internal abstract void WriteData(byte[] buffer, int offset);
public override sealed int Length { get { return MinimumLength + DataLength; } } public override sealed int Length { get { return Offset.Data + DataLength; } }
internal abstract int DataLength { get; } internal abstract int DataLength { get; }
internal static bool IsStandard(IpV4Protocol nextHeader) internal static bool IsStandard(IpV4Protocol nextHeader)
{ {
...@@ -132,7 +140,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -132,7 +140,7 @@ namespace PcapDotNet.Packets.IpV6
/// <summary> /// <summary>
/// RFC 2460. /// RFC 2460.
/// </summary> /// </summary>
public abstract class IpV6ExtensionHeader public abstract class IpV6ExtensionHeader : IEquatable<IpV6ExtensionHeader>
{ {
public abstract IpV4Protocol Protocol { get; } public abstract IpV4Protocol Protocol { get; }
...@@ -145,6 +153,15 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -145,6 +153,15 @@ namespace PcapDotNet.Packets.IpV6
get { return _extensionHeaders; } get { return _extensionHeaders; }
} }
public abstract bool IsValid { get; }
public override sealed bool Equals(object obj)
{
return Equals(obj as IpV6ExtensionHeader);
}
public abstract bool Equals(IpV6ExtensionHeader other);
internal static bool IsExtensionHeader(IpV4Protocol nextHeader) internal static bool IsExtensionHeader(IpV4Protocol nextHeader)
{ {
if (IpV6ExtensionHeaderStandard.IsStandard(nextHeader)) if (IpV6ExtensionHeaderStandard.IsStandard(nextHeader))
...@@ -301,7 +318,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -301,7 +318,7 @@ namespace PcapDotNet.Packets.IpV6
data = data.Subsegment(numBytesRead, data.Length - numBytesRead); data = data.Subsegment(numBytesRead, data.Length - numBytesRead);
} }
Headers = headers.AsReadOnly(); Headers = headers.AsReadOnly();
IsValid = (!nextHeader.HasValue || !IpV6ExtensionHeader.IsExtensionHeader(nextHeader.Value)); IsValid = (!nextHeader.HasValue || !IpV6ExtensionHeader.IsExtensionHeader(nextHeader.Value)) && headers.All(header => header.IsValid);
} }
private static readonly IpV6ExtensionHeaders _empty = new IpV6ExtensionHeaders(); private static readonly IpV6ExtensionHeaders _empty = new IpV6ExtensionHeaders();
......
...@@ -20,7 +20,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -20,7 +20,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+--------------------------------------+ /// +-----+--------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderAuthentication : IpV6ExtensionHeader public class IpV6ExtensionHeaderAuthentication : IpV6ExtensionHeader, IEquatable<IpV6ExtensionHeaderAuthentication>
{ {
private static class Offset private static class Offset
{ {
...@@ -100,7 +100,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -100,7 +100,7 @@ namespace PcapDotNet.Packets.IpV6
} }
IpV4Protocol nextHeader = (IpV4Protocol)extensionHeaderData[Offset.NextHeader]; IpV4Protocol nextHeader = (IpV4Protocol)extensionHeaderData[Offset.NextHeader];
int payloadLength = (extensionHeaderData[Offset.PayloadLength] + 2) * 4; int payloadLength = (extensionHeaderData[Offset.PayloadLength] + 2) * 4;
if (extensionHeaderData.Length < Offset.AuthenticationData + payloadLength) if (extensionHeaderData.Length < payloadLength || payloadLength < MinimumLength)
{ {
numBytesRead = 0; numBytesRead = 0;
return null; return null;
...@@ -137,6 +137,23 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -137,6 +137,23 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumLength + AuthenticationData.Length; } get { return MinimumLength + AuthenticationData.Length; }
} }
public override bool IsValid
{
get { return true; }
}
public override bool Equals(IpV6ExtensionHeader other)
{
return Equals(other as IpV6ExtensionHeaderAuthentication);
}
public bool Equals(IpV6ExtensionHeaderAuthentication other)
{
return other != null &&
NextHeader == other.NextHeader && SecurityParametersIndex == other.SecurityParametersIndex && SequenceNumber == other.SequenceNumber &&
AuthenticationData.Equals(other.AuthenticationData);
}
internal override void Write(byte[] buffer, ref int offset) internal override void Write(byte[] buffer, ref int offset)
{ {
buffer.Write(offset + Offset.NextHeader, (byte)NextHeader); buffer.Write(offset + Offset.NextHeader, (byte)NextHeader);
......
using System;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6 namespace PcapDotNet.Packets.IpV6
......
using System;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6 namespace PcapDotNet.Packets.IpV6
...@@ -45,7 +46,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -45,7 +46,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+--------------------------+ /// +-----+--------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderEncapsulatingSecurityPayload : IpV6ExtensionHeader public sealed class IpV6ExtensionHeaderEncapsulatingSecurityPayload : IpV6ExtensionHeader, IEquatable<IpV6ExtensionHeaderEncapsulatingSecurityPayload>
{ {
private static class Offset private static class Offset
{ {
...@@ -74,6 +75,23 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -74,6 +75,23 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumLength + EncryptedDataAndAuthenticationData.Length; } get { return MinimumLength + EncryptedDataAndAuthenticationData.Length; }
} }
public override bool IsValid
{
get { return true; }
}
public override bool Equals(IpV6ExtensionHeader other)
{
return Equals(other as IpV6ExtensionHeaderEncapsulatingSecurityPayload);
}
public bool Equals(IpV6ExtensionHeaderEncapsulatingSecurityPayload other)
{
return other != null &&
SecurityParametersIndex == other.SecurityParametersIndex && SequenceNumber == other.SequenceNumber &&
EncryptedDataAndAuthenticationData.Equals(other.EncryptedDataAndAuthenticationData);
}
/// <summary> /// <summary>
/// <para> /// <para>
/// The SPI is an arbitrary 32-bit value that, in combination with the destination IP address and security protocol (ESP), /// The SPI is an arbitrary 32-bit value that, in combination with the destination IP address and security protocol (ESP),
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
...@@ -75,6 +76,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -75,6 +76,11 @@ namespace PcapDotNet.Packets.IpV6
get { return IpV4Protocol.FragmentHeaderForIpV6; } get { return IpV4Protocol.FragmentHeaderForIpV6; }
} }
public override bool IsValid
{
get { return true; }
}
internal override int DataLength internal override int DataLength
{ {
get { return ExtensionHeaderDataLength; } get { return ExtensionHeaderDataLength; }
...@@ -92,6 +98,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -92,6 +98,11 @@ namespace PcapDotNet.Packets.IpV6
return new IpV6ExtensionHeaderFragmentData(nextHeader, fragmentOffset, moreFragments, identification); return new IpV6ExtensionHeaderFragmentData(nextHeader, fragmentOffset, moreFragments, identification);
} }
internal override bool EqualsData(IpV6ExtensionHeader other)
{
return EqualsData(other as IpV6ExtensionHeaderFragmentData);
}
internal override void WriteData(byte[] buffer, int offset) internal override void WriteData(byte[] buffer, int offset)
{ {
ushort fragmentOffsetAndMoreFragments = (ushort)(FragmentOffset << DataShift.FragmentOffset); ushort fragmentOffsetAndMoreFragments = (ushort)(FragmentOffset << DataShift.FragmentOffset);
...@@ -101,6 +112,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -101,6 +112,12 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(offset + DataOffset.FragmentOffset, fragmentOffsetAndMoreFragments, Endianity.Big); buffer.Write(offset + DataOffset.FragmentOffset, fragmentOffsetAndMoreFragments, Endianity.Big);
buffer.Write(offset + DataOffset.Identification, Identification, Endianity.Big); buffer.Write(offset + DataOffset.Identification, Identification, Endianity.Big);
} }
private bool EqualsData(IpV6ExtensionHeaderFragmentData other)
{
return other != null &&
FragmentOffset == other.FragmentOffset && MoreFragments == other.MoreFragments && Identification == other.Identification;
}
} }
public enum IpV6MobilityHeaderType : byte public enum IpV6MobilityHeaderType : byte
...@@ -221,10 +238,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -221,10 +238,16 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public abstract class IpV6ExtensionHeaderMobility : IpV6ExtensionHeaderStandard public abstract class IpV6ExtensionHeaderMobility : IpV6ExtensionHeaderStandard
{ {
public override IpV4Protocol Protocol public override sealed IpV4Protocol Protocol
{ {
get { return IpV4Protocol.MobilityHeader; } get { return IpV4Protocol.MobilityHeader; }
} }
public override sealed bool IsValid
{
get { return MobilityOptions.IsValid && Length % 8 == 0; }
}
private static class DataOffset private static class DataOffset
{ {
public const int MobilityHeaderType = 0; public const int MobilityHeaderType = 0;
...@@ -241,13 +264,6 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -241,13 +264,6 @@ namespace PcapDotNet.Packets.IpV6
MobilityOptions = mobilityOptions; MobilityOptions = mobilityOptions;
} }
internal override sealed int DataLength
{
get { return MinimumDataLength + MessageDataLength; }
}
internal abstract int MessageDataLength { get; }
/// <summary> /// <summary>
/// Identifies the particular mobility message in question. /// Identifies the particular mobility message in question.
/// An unrecognized MH Type field causes an error indication to be sent. /// An unrecognized MH Type field causes an error indication to be sent.
...@@ -367,6 +383,27 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -367,6 +383,27 @@ namespace PcapDotNet.Packets.IpV6
} }
internal abstract void WriteMessageData(byte[] buffer, int offset); internal abstract void WriteMessageData(byte[] buffer, int offset);
internal override sealed int DataLength
{
get { return MinimumDataLength + MessageDataLength; }
}
internal abstract int MessageDataLength { get; }
internal override sealed bool EqualsData(IpV6ExtensionHeader other)
{
return EqualsData(other as IpV6ExtensionHeaderMobility);
}
internal abstract bool EqualsMessageData(IpV6ExtensionHeaderMobility other);
private bool EqualsData(IpV6ExtensionHeaderMobility other)
{
return other != null &&
MobilityHeaderType == other.MobilityHeaderType && Checksum == other.Checksum && MobilityOptions.Equals(other.MobilityOptions) &&
EqualsMessageData(other);
}
} }
/// <summary> /// <summary>
...@@ -429,6 +466,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -429,6 +466,11 @@ namespace PcapDotNet.Packets.IpV6
{ {
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options); MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return other != null;
}
} }
/// <summary> /// <summary>
...@@ -455,7 +497,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -455,7 +497,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityHomeTestInit : IpV6ExtensionHeaderMobility public sealed class IpV6ExtensionHeaderMobilityHomeTestInit : IpV6ExtensionHeaderMobility
{ {
private static class MessageDataOffset private static class MessageDataOffset
{ {
...@@ -490,6 +532,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -490,6 +532,11 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityHomeTestInit);
}
internal static IpV6ExtensionHeaderMobilityHomeTestInit ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityHomeTestInit ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -505,6 +552,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -505,6 +552,12 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(offset + MessageDataOffset.HomeInitCookie, HomeInitCookie, Endianity.Big); buffer.Write(offset + MessageDataOffset.HomeInitCookie, HomeInitCookie, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options); MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
} }
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityHomeTestInit other)
{
return other != null &&
HomeInitCookie == other.HomeInitCookie;
}
} }
/// <summary> /// <summary>
...@@ -531,7 +584,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -531,7 +584,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityCareOfTestInit : IpV6ExtensionHeaderMobility public sealed class IpV6ExtensionHeaderMobilityCareOfTestInit : IpV6ExtensionHeaderMobility
{ {
private static class MessageDataOffset private static class MessageDataOffset
{ {
...@@ -566,6 +619,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -566,6 +619,11 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityCareOfTestInit);
}
internal static IpV6ExtensionHeaderMobilityCareOfTestInit ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityCareOfTestInit ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -581,6 +639,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -581,6 +639,12 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(offset + MessageDataOffset.CareOfInitCookie, CareOfInitCookie, Endianity.Big); buffer.Write(offset + MessageDataOffset.CareOfInitCookie, CareOfInitCookie, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options); MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
} }
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityCareOfTestInit other)
{
return other != null &&
CareOfInitCookie == other.CareOfInitCookie;
}
} }
/// <summary> /// <summary>
...@@ -612,7 +676,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -612,7 +676,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityHomeTest : IpV6ExtensionHeaderMobility public sealed class IpV6ExtensionHeaderMobilityHomeTest : IpV6ExtensionHeaderMobility
{ {
private static class MessageDataOffset private static class MessageDataOffset
{ {
...@@ -662,6 +726,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -662,6 +726,11 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityHomeTest);
}
internal static IpV6ExtensionHeaderMobilityHomeTest ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityHomeTest ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -681,6 +750,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -681,6 +750,12 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(offset + MessageDataOffset.HomeKeygenToken, HomeKeygenToken, Endianity.Big); buffer.Write(offset + MessageDataOffset.HomeKeygenToken, HomeKeygenToken, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options); MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
} }
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityHomeTest other)
{
return other != null &&
HomeNonceIndex == other.HomeNonceIndex && HomeInitCookie == other.HomeInitCookie && HomeKeygenToken == other.HomeKeygenToken;
}
} }
/// <summary> /// <summary>
...@@ -712,7 +787,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -712,7 +787,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityCareOfTest : IpV6ExtensionHeaderMobility public sealed class IpV6ExtensionHeaderMobilityCareOfTest : IpV6ExtensionHeaderMobility
{ {
private static class MessageDataOffset private static class MessageDataOffset
{ {
...@@ -762,6 +837,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -762,6 +837,11 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityCareOfTest);
}
internal static IpV6ExtensionHeaderMobilityCareOfTest ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityCareOfTest ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -781,6 +861,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -781,6 +861,12 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(offset + MessageDataOffset.CareOfKeygenToken, CareOfKeygenToken, Endianity.Big); buffer.Write(offset + MessageDataOffset.CareOfKeygenToken, CareOfKeygenToken, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options); MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
} }
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityCareOfTest other)
{
return other != null &&
CareOfNonceIndex == other.CareOfNonceIndex && CareOfInitCookie == other.CareOfInitCookie && CareOfKeygenToken == other.CareOfKeygenToken;
}
} }
/// <summary> /// <summary>
...@@ -887,6 +973,19 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -887,6 +973,19 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public ushort Lifetime { get; private set; } public ushort Lifetime { get; private set; }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityBindingUpdateBase);
}
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityBindingUpdateBase other)
{
return other != null &&
SequenceNumber == other.SequenceNumber && Acknowledge == other.Acknowledge && HomeRegistration == other.HomeRegistration &&
LinkLocalAddressCompatibility == other.LinkLocalAddressCompatibility &&
KeyManagementMobilityCapability == other.KeyManagementMobilityCapability && Lifetime == other.Lifetime;
}
internal override int MessageDataLength internal override int MessageDataLength
{ {
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
...@@ -962,7 +1061,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -962,7 +1061,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+-----------------------------------------------+ /// +-----+-----------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityBindingUpdate : IpV6ExtensionHeaderMobilityBindingUpdateBase public sealed class IpV6ExtensionHeaderMobilityBindingUpdate : IpV6ExtensionHeaderMobilityBindingUpdateBase
{ {
public IpV6ExtensionHeaderMobilityBindingUpdate(IpV4Protocol nextHeader, ushort checksum, ushort sequenceNumber, bool acknowledge, bool homeRegistration, public IpV6ExtensionHeaderMobilityBindingUpdate(IpV4Protocol nextHeader, ushort checksum, ushort sequenceNumber, bool acknowledge, bool homeRegistration,
bool linkLocalAddressCompatibility, bool keyManagementMobilityCapability, ushort lifetime, bool linkLocalAddressCompatibility, bool keyManagementMobilityCapability, ushort lifetime,
...@@ -1382,6 +1481,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1382,6 +1481,11 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityBindingAcknowledgementBase);
}
internal static bool ParseMessageDataFields(DataSegment messageData, out IpV6BindingAcknowledgementStatus status, internal static bool ParseMessageDataFields(DataSegment messageData, out IpV6BindingAcknowledgementStatus status,
out bool keyManagementMobilityCapability, out ushort sequenceNumber, out ushort lifetime, out bool keyManagementMobilityCapability, out ushort sequenceNumber, out ushort lifetime,
out IpV6MobilityOptions options) out IpV6MobilityOptions options)
...@@ -1415,6 +1519,13 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1415,6 +1519,13 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(offset + MessageDataOffset.Lifetime, Lifetime, Endianity.Big); buffer.Write(offset + MessageDataOffset.Lifetime, Lifetime, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options); MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
} }
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityBindingAcknowledgementBase other)
{
return other != null &&
Status == other.Status && KeyManagementMobilityCapability == other.KeyManagementMobilityCapability && SequenceNumber == other.SequenceNumber &&
Lifetime == other.Lifetime;
}
} }
/// <summary> /// <summary>
...@@ -1440,7 +1551,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1440,7 +1551,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityBindingAcknowledgement : IpV6ExtensionHeaderMobilityBindingAcknowledgementBase public sealed class IpV6ExtensionHeaderMobilityBindingAcknowledgement : IpV6ExtensionHeaderMobilityBindingAcknowledgementBase
{ {
public IpV6ExtensionHeaderMobilityBindingAcknowledgement(IpV4Protocol nextHeader, ushort checksum, IpV6BindingAcknowledgementStatus status, public IpV6ExtensionHeaderMobilityBindingAcknowledgement(IpV4Protocol nextHeader, ushort checksum, IpV6BindingAcknowledgementStatus status,
bool keyManagementMobilityCapability, ushort sequenceNumber, ushort lifetime, bool keyManagementMobilityCapability, ushort sequenceNumber, ushort lifetime,
...@@ -1514,7 +1625,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1514,7 +1625,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityBindingError : IpV6ExtensionHeaderMobility public sealed class IpV6ExtensionHeaderMobilityBindingError : IpV6ExtensionHeaderMobility
{ {
private static class MessageDataOffset private static class MessageDataOffset
{ {
...@@ -1558,6 +1669,17 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1558,6 +1669,17 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityBindingError);
}
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityBindingError other)
{
return other != null &&
Status == other.Status && HomeAddress == other.HomeAddress;
}
internal static IpV6ExtensionHeaderMobilityBindingError ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityBindingError ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -1712,7 +1834,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1712,7 +1834,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityFastNeighborAdvertisement : IpV6ExtensionHeaderMobility public sealed class IpV6ExtensionHeaderMobilityFastNeighborAdvertisement : IpV6ExtensionHeaderMobility
{ {
private static class MessageDataOffset private static class MessageDataOffset
{ {
...@@ -1740,6 +1862,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1740,6 +1862,11 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return other != null;
}
internal static IpV6ExtensionHeaderMobilityFastNeighborAdvertisement ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityFastNeighborAdvertisement ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -1772,7 +1899,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1772,7 +1899,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityExperimental : IpV6ExtensionHeaderMobility public sealed class IpV6ExtensionHeaderMobilityExperimental : IpV6ExtensionHeaderMobility
{ {
public IpV6ExtensionHeaderMobilityExperimental(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) public IpV6ExtensionHeaderMobilityExperimental(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
: base(nextHeader, checksum, IpV6MobilityOptions.None) : base(nextHeader, checksum, IpV6MobilityOptions.None)
...@@ -1799,6 +1926,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1799,6 +1926,11 @@ namespace PcapDotNet.Packets.IpV6
get { return MessageData.Length; } get { return MessageData.Length; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityExperimental);
}
internal static IpV6ExtensionHeaderMobilityExperimental ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityExperimental ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
return new IpV6ExtensionHeaderMobilityExperimental(nextHeader, checksum, messageData); return new IpV6ExtensionHeaderMobilityExperimental(nextHeader, checksum, messageData);
...@@ -1808,6 +1940,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1808,6 +1940,12 @@ namespace PcapDotNet.Packets.IpV6
{ {
MessageData.Write(buffer, offset); MessageData.Write(buffer, offset);
} }
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityExperimental other)
{
return other != null &&
MessageData.Equals(other.MessageData);
}
} }
/// <summary> /// <summary>
...@@ -1832,7 +1970,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1832,7 +1970,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+------------------------------------------+ /// +-----+------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage : IpV6ExtensionHeaderMobility public sealed class IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage : IpV6ExtensionHeaderMobility
{ {
private static class MessageDataOffset private static class MessageDataOffset
{ {
...@@ -1873,6 +2011,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1873,6 +2011,11 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + HomeAgentAddresses.Count * IpV6Address.SizeOf + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + HomeAgentAddresses.Count * IpV6Address.SizeOf + MobilityOptions.BytesLength; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage);
}
internal static IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -1899,6 +2042,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1899,6 +2042,12 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(offset + MessageDataOffset.HomeAgentAddresses + i * IpV6Address.SizeOf, HomeAgentAddresses[i], Endianity.Big); buffer.Write(offset + MessageDataOffset.HomeAgentAddresses + i * IpV6Address.SizeOf, HomeAgentAddresses[i], Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.HomeAgentAddresses + HomeAgentAddresses.Count * IpV6Address.SizeOf); MobilityOptions.Write(buffer, offset + MessageDataOffset.HomeAgentAddresses + HomeAgentAddresses.Count * IpV6Address.SizeOf);
} }
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage other)
{
return other != null &&
HomeAgentAddresses.SequenceEqual(other.HomeAgentAddresses);
}
} }
/// <summary> /// <summary>
...@@ -1923,7 +2072,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1923,7 +2072,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+------------------------------------------+ /// +-----+------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityHeartbeatMessage : IpV6ExtensionHeaderMobility public sealed class IpV6ExtensionHeaderMobilityHeartbeatMessage : IpV6ExtensionHeaderMobility
{ {
private static class MessageDataOffset private static class MessageDataOffset
{ {
...@@ -1981,6 +2130,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1981,6 +2130,11 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityHeartbeatMessage);
}
internal static IpV6ExtensionHeaderMobilityHeartbeatMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityHeartbeatMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -2000,11 +2154,18 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2000,11 +2154,18 @@ namespace PcapDotNet.Packets.IpV6
isUnsolicitedHeartbeatResponseAndIsResponse |= MessageDataMask.IsUnsolicitedHeartbeatResponse; isUnsolicitedHeartbeatResponseAndIsResponse |= MessageDataMask.IsUnsolicitedHeartbeatResponse;
if (IsResponse) if (IsResponse)
isUnsolicitedHeartbeatResponseAndIsResponse |= MessageDataMask.IsResponse; isUnsolicitedHeartbeatResponseAndIsResponse |= MessageDataMask.IsResponse;
buffer.Write(MessageDataOffset.IsUnsolicitedHeartbeatResponse, isUnsolicitedHeartbeatResponseAndIsResponse); buffer.Write(offset + MessageDataOffset.IsUnsolicitedHeartbeatResponse, isUnsolicitedHeartbeatResponseAndIsResponse);
buffer.Write(offset + MessageDataOffset.SequenceNumber, SequenceNumber, Endianity.Big); buffer.Write(offset + MessageDataOffset.SequenceNumber, SequenceNumber, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.MobilityOptions); MobilityOptions.Write(buffer, offset + MessageDataOffset.MobilityOptions);
} }
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityHeartbeatMessage other)
{
return other != null &&
IsUnsolicitedHeartbeatResponse == other.IsUnsolicitedHeartbeatResponse && IsResponse == other.IsResponse &&
SequenceNumber == other.SequenceNumber;
}
} }
public enum IpV6HandoverInitiateMessageCode : byte public enum IpV6HandoverInitiateMessageCode : byte
...@@ -2034,7 +2195,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2034,7 +2195,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+--------------------------------------------+ /// +-----+--------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityHandoverInitiateMessage : IpV6ExtensionHeaderMobility public sealed class IpV6ExtensionHeaderMobilityHandoverInitiateMessage : IpV6ExtensionHeaderMobility
{ {
private static class MessageDataOffset private static class MessageDataOffset
{ {
...@@ -2101,6 +2262,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2101,6 +2262,11 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityHandoverInitiateMessage);
}
internal static IpV6ExtensionHeaderMobilityHandoverInitiateMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityHandoverInitiateMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -2129,6 +2295,13 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2129,6 +2295,13 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(offset + MessageDataOffset.Code, (byte)Code); buffer.Write(offset + MessageDataOffset.Code, (byte)Code);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options); MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
} }
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityHandoverInitiateMessage other)
{
return other != null &&
SequenceNumber == other.SequenceNumber && AssignedAddressConfiguration == other.AssignedAddressConfiguration && Buffer == other.Buffer &&
Code == other.Code;
}
} }
public enum IpV6MobilityHandoverAcknowledgeCode : byte public enum IpV6MobilityHandoverAcknowledgeCode : byte
...@@ -2195,7 +2368,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2195,7 +2368,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage : IpV6ExtensionHeaderMobility public sealed class IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage : IpV6ExtensionHeaderMobility
{ {
private static class MessageDataOffset private static class MessageDataOffset
{ {
...@@ -2239,6 +2412,17 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2239,6 +2412,17 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage);
}
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage other)
{
return other != null &&
SequenceNumber == other.SequenceNumber && Code == other.Code;
}
internal static IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -2378,6 +2562,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2378,6 +2562,11 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
} }
internal override bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityBindingRevocationMessage);
}
internal static IpV6ExtensionHeaderMobilityBindingRevocationMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityBindingRevocationMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -2425,6 +2614,14 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2425,6 +2614,14 @@ namespace PcapDotNet.Packets.IpV6
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options); MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
} }
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityBindingRevocationMessage other)
{
return other != null &&
BindingRevocationType == other.BindingRevocationType && RevocationTriggerOrStatus == other.RevocationTriggerOrStatus &&
SequenceNumber == other.SequenceNumber && ProxyBinding == other.ProxyBinding &&
IpV4HomeAddressBindingOnly == other.IpV4HomeAddressBindingOnly && Global == other.Global;
}
} }
/// <summary> /// <summary>
...@@ -2507,12 +2704,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2507,12 +2704,12 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---+---+---+-------------------------------+ /// +-----+---+---+---+-------------------------------+
/// | 80 | P | V | G | Reserved | /// | 80 | P | V | G | Reserved |
/// +-----+---+---+---+-------------------------------+ /// +-----+---+---+---+-------------------------------+
/// | 96 | Mobility options | /// | 96 | Mobility Options |
/// | ... | | /// | ... | |
/// +-----+-------------------------------------------+ /// +-----+-------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityBindingRevocationIndicationMessage : IpV6ExtensionHeaderMobilityBindingRevocationMessage public sealed class IpV6ExtensionHeaderMobilityBindingRevocationIndicationMessage : IpV6ExtensionHeaderMobilityBindingRevocationMessage
{ {
public IpV6ExtensionHeaderMobilityBindingRevocationIndicationMessage(IpV4Protocol nextHeader, ushort checksum, public IpV6ExtensionHeaderMobilityBindingRevocationIndicationMessage(IpV4Protocol nextHeader, ushort checksum,
Ipv6MobilityBindingRevocationTrigger revocationTrigger, ushort sequenceNumber, Ipv6MobilityBindingRevocationTrigger revocationTrigger, ushort sequenceNumber,
...@@ -2719,6 +2916,13 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2719,6 +2916,13 @@ namespace PcapDotNet.Packets.IpV6
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; } get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
} }
internal override sealed bool EqualsMessageData(IpV6ExtensionHeaderMobility other)
{
return EqualsMessageData(other as IpV6ExtensionHeaderMobilityLocalizedRouting);
}
internal abstract bool EqualsMessageDataLocalizedRoutingExtraFields(IpV6ExtensionHeaderMobilityLocalizedRouting other);
internal static bool ParseMessageDataToFields(DataSegment messageData, out ushort sequenceNumber, out ushort lifetime, out IpV6MobilityOptions options) internal static bool ParseMessageDataToFields(DataSegment messageData, out ushort sequenceNumber, out ushort lifetime, out IpV6MobilityOptions options)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -2741,6 +2945,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2741,6 +2945,12 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(offset + MessageDataOffset.Lifetime, Lifetime, Endianity.Big); buffer.Write(offset + MessageDataOffset.Lifetime, Lifetime, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options); MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
} }
private bool EqualsMessageData(IpV6ExtensionHeaderMobilityLocalizedRouting other)
{
return other != null &&
SequenceNumber == other.SequenceNumber && Lifetime == other.Lifetime && EqualsMessageDataLocalizedRoutingExtraFields(other);
}
} }
/// <summary> /// <summary>
...@@ -2766,7 +2976,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2766,7 +2976,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityLocalizedRoutingInitiation : IpV6ExtensionHeaderMobilityLocalizedRouting public sealed class IpV6ExtensionHeaderMobilityLocalizedRoutingInitiation : IpV6ExtensionHeaderMobilityLocalizedRouting
{ {
public IpV6ExtensionHeaderMobilityLocalizedRoutingInitiation(IpV4Protocol nextHeader, ushort checksum, ushort sequenceNumber, public IpV6ExtensionHeaderMobilityLocalizedRoutingInitiation(IpV4Protocol nextHeader, ushort checksum, ushort sequenceNumber,
ushort lifetime, IpV6MobilityOptions options) ushort lifetime, IpV6MobilityOptions options)
...@@ -2793,6 +3003,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2793,6 +3003,11 @@ namespace PcapDotNet.Packets.IpV6
return new IpV6ExtensionHeaderMobilityLocalizedRoutingInitiation(nextHeader, checksum, sequenceNumber, lifetime, options); return new IpV6ExtensionHeaderMobilityLocalizedRoutingInitiation(nextHeader, checksum, sequenceNumber, lifetime, options);
} }
internal override bool EqualsMessageDataLocalizedRoutingExtraFields(IpV6ExtensionHeaderMobilityLocalizedRouting other)
{
return true;
}
} }
/// <summary> /// <summary>
...@@ -2818,7 +3033,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2818,7 +3033,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+----------------------------------------+ /// +-----+----------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderMobilityLocalizedRoutingAcknowledgement : IpV6ExtensionHeaderMobilityLocalizedRouting public sealed class IpV6ExtensionHeaderMobilityLocalizedRoutingAcknowledgement : IpV6ExtensionHeaderMobilityLocalizedRouting
{ {
private static class MessageDataOffset private static class MessageDataOffset
{ {
...@@ -2865,5 +3080,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2865,5 +3080,16 @@ namespace PcapDotNet.Packets.IpV6
return new IpV6ExtensionHeaderMobilityLocalizedRoutingAcknowledgement(nextHeader, checksum, sequenceNumber, unsolicited, lifetime, options); return new IpV6ExtensionHeaderMobilityLocalizedRoutingAcknowledgement(nextHeader, checksum, sequenceNumber, unsolicited, lifetime, options);
} }
internal override bool EqualsMessageDataLocalizedRoutingExtraFields(IpV6ExtensionHeaderMobilityLocalizedRouting other)
{
return EqualsMessageDataLocalizedRoutingExtraFields(other as IpV6ExtensionHeaderMobilityLocalizedRoutingAcknowledgement);
}
private bool EqualsMessageDataLocalizedRoutingExtraFields(IpV6ExtensionHeaderMobilityLocalizedRoutingAcknowledgement other)
{
return other != null &&
Unsolicited == other.Unsolicited;
}
} }
} }
\ No newline at end of file
using System;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6 namespace PcapDotNet.Packets.IpV6
...@@ -19,11 +20,21 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -19,11 +20,21 @@ namespace PcapDotNet.Packets.IpV6
{ {
public IpV6Options Options { get; private set; } public IpV6Options Options { get; private set; }
public override sealed bool IsValid
{
get { return Options.IsValid; }
}
internal override sealed int DataLength internal override sealed int DataLength
{ {
get { return Options.BytesLength; } get { return Options.BytesLength; }
} }
internal override sealed bool EqualsData(IpV6ExtensionHeader other)
{
return EqualsData(other as IpV6ExtensionHeaderOptions);
}
internal override void WriteData(byte[] buffer, int offset) internal override void WriteData(byte[] buffer, int offset)
{ {
Options.Write(buffer, offset); Options.Write(buffer, offset);
...@@ -32,7 +43,15 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -32,7 +43,15 @@ namespace PcapDotNet.Packets.IpV6
internal IpV6ExtensionHeaderOptions(IpV4Protocol nextHeader, IpV6Options options) internal IpV6ExtensionHeaderOptions(IpV4Protocol nextHeader, IpV6Options options)
: base(nextHeader) : base(nextHeader)
{ {
if (options.BytesLength % 8 != 6)
throw new ArgumentException("Options length in bytes must be an integral product of 8 + 6.", "options");
Options = options; Options = options;
} }
private bool EqualsData(IpV6ExtensionHeaderOptions other)
{
return other != null &&
Options.Equals(other.Options);
}
} }
} }
\ No newline at end of file
...@@ -26,7 +26,10 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -26,7 +26,10 @@ namespace PcapDotNet.Packets.IpV6
public const int DataMinimumLength = DataOffset.TypeSpecificData; public const int DataMinimumLength = DataOffset.TypeSpecificData;
internal abstract int RoutingDataLength { get; } public override bool IsValid
{
get { return true; }
}
/// <summary> /// <summary>
/// Identifier of a particular Routing header variant. /// Identifier of a particular Routing header variant.
...@@ -54,6 +57,15 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -54,6 +57,15 @@ namespace PcapDotNet.Packets.IpV6
get { return DataMinimumLength + RoutingDataLength; } get { return DataMinimumLength + RoutingDataLength; }
} }
internal abstract int RoutingDataLength { get; }
internal override sealed bool EqualsData(IpV6ExtensionHeader other)
{
return EqualsData(other as IpV6ExtensionHeaderRouting);
}
internal abstract bool EqualsRoutingData(IpV6ExtensionHeaderRouting other);
internal static IpV6ExtensionHeaderRouting ParseData(IpV4Protocol nextHeader, DataSegment data) internal static IpV6ExtensionHeaderRouting ParseData(IpV4Protocol nextHeader, DataSegment data)
{ {
if (data.Length < DataMinimumLength) if (data.Length < DataMinimumLength)
...@@ -89,5 +101,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -89,5 +101,11 @@ namespace PcapDotNet.Packets.IpV6
} }
internal abstract void WriteRoutingData(byte[] buffer, int offset); internal abstract void WriteRoutingData(byte[] buffer, int offset);
private bool EqualsData(IpV6ExtensionHeaderRouting other)
{
return other != null &&
RoutingType == other.RoutingType && SegmentsLeft == other.SegmentsLeft && EqualsRoutingData(other);
}
} }
} }
\ No newline at end of file
...@@ -19,7 +19,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -19,7 +19,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+----------------------------------------------------------------------+ /// +-----+----------------------------------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderRoutingHomeAddress : IpV6ExtensionHeaderRouting public sealed class IpV6ExtensionHeaderRoutingHomeAddress : IpV6ExtensionHeaderRouting
{ {
private static class RoutingDataOffset private static class RoutingDataOffset
{ {
...@@ -58,9 +58,20 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -58,9 +58,20 @@ namespace PcapDotNet.Packets.IpV6
return new IpV6ExtensionHeaderRoutingHomeAddress(nextHeader, segmentsLeft, homeAddress); return new IpV6ExtensionHeaderRoutingHomeAddress(nextHeader, segmentsLeft, homeAddress);
} }
internal override bool EqualsRoutingData(IpV6ExtensionHeaderRouting other)
{
return EqualsRoutingData(other as IpV6ExtensionHeaderRoutingHomeAddress);
}
internal override void WriteRoutingData(byte[] buffer, int offset) internal override void WriteRoutingData(byte[] buffer, int offset)
{ {
buffer.Write(offset + RoutingDataOffset.HomeAddress, HomeAddress, Endianity.Big); buffer.Write(offset + RoutingDataOffset.HomeAddress, HomeAddress, Endianity.Big);
} }
private bool EqualsRoutingData(IpV6ExtensionHeaderRoutingHomeAddress other)
{
return other != null &&
HomeAddress.Equals(other.HomeAddress);
}
} }
} }
\ No newline at end of file
...@@ -34,7 +34,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -34,7 +34,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+------------------------------------------------------------------------+ /// +-----+------------------------------------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderRoutingRpl : IpV6ExtensionHeaderRouting public sealed class IpV6ExtensionHeaderRoutingRpl : IpV6ExtensionHeaderRouting
{ {
private static class RoutingDataOffset private static class RoutingDataOffset
{ {
...@@ -170,6 +170,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -170,6 +170,11 @@ namespace PcapDotNet.Packets.IpV6
addresses); addresses);
} }
internal override bool EqualsRoutingData(IpV6ExtensionHeaderRouting other)
{
return EqualsRoutingData(other as IpV6ExtensionHeaderRoutingRpl);
}
internal override void WriteRoutingData(byte[] buffer, int offset) internal override void WriteRoutingData(byte[] buffer, int offset)
{ {
buffer.Write(offset + RoutingDataOffset.CommonPrefixLengthForNonLastAddresses, buffer.Write(offset + RoutingDataOffset.CommonPrefixLengthForNonLastAddresses,
...@@ -189,5 +194,13 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -189,5 +194,13 @@ namespace PcapDotNet.Packets.IpV6
addressBytes.SubSegment(CommonPrefixLengthForLastAddress, IpV6Address.SizeOf - CommonPrefixLengthForLastAddress).Write(buffer, ref addressOffset); addressBytes.SubSegment(CommonPrefixLengthForLastAddress, IpV6Address.SizeOf - CommonPrefixLengthForLastAddress).Write(buffer, ref addressOffset);
} }
} }
private bool EqualsRoutingData(IpV6ExtensionHeaderRoutingRpl other)
{
return other != null &&
CommonPrefixLengthForNonLastAddresses == other.CommonPrefixLengthForNonLastAddresses &&
CommonPrefixLengthForLastAddress == other.CommonPrefixLengthForLastAddress && PadSize == other.PadSize &&
Addresses.SequenceEqual(other.Addresses);
}
} }
} }
\ No newline at end of file
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
...@@ -35,7 +36,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -35,7 +36,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+----------------------------------------------------------------------+ /// +-----+----------------------------------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderRoutingSourceRoute : IpV6ExtensionHeaderRouting public sealed class IpV6ExtensionHeaderRoutingSourceRoute : IpV6ExtensionHeaderRouting
{ {
private static class RoutingDataOffset private static class RoutingDataOffset
{ {
...@@ -78,10 +79,21 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -78,10 +79,21 @@ namespace PcapDotNet.Packets.IpV6
return new IpV6ExtensionHeaderRoutingSourceRoute(nextHeader, segmentsLeft, addresses); return new IpV6ExtensionHeaderRoutingSourceRoute(nextHeader, segmentsLeft, addresses);
} }
internal override bool EqualsRoutingData(IpV6ExtensionHeaderRouting other)
{
return EqualsRoutingData(other as IpV6ExtensionHeaderRoutingSourceRoute);
}
internal override void WriteRoutingData(byte[] buffer, int offset) internal override void WriteRoutingData(byte[] buffer, int offset)
{ {
for (int i = 0; i != Addresses.Count; ++i) for (int i = 0; i != Addresses.Count; ++i)
buffer.Write(offset + RoutingDataOffset.Addresses + i * IpV6Address.SizeOf, Addresses[i], Endianity.Big); buffer.Write(offset + RoutingDataOffset.Addresses + i * IpV6Address.SizeOf, Addresses[i], Endianity.Big);
} }
private bool EqualsRoutingData(IpV6ExtensionHeaderRoutingSourceRoute other)
{
return other != null &&
Addresses.SequenceEqual(other.Addresses);
}
} }
} }
\ No newline at end of file
...@@ -101,10 +101,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -101,10 +101,12 @@ namespace PcapDotNet.Packets.IpV6
nextHeader = ipV4NextLayer.PreviousLayerProtocol; nextHeader = ipV4NextLayer.PreviousLayerProtocol;
} }
else else
{
nextHeader = NextHeader.Value; nextHeader = NextHeader.Value;
}
IpV6Datagram.WriteHeader(buffer, offset, IpV6Datagram.WriteHeader(buffer, offset,
TrafficClass, FlowLabel, (ushort)payloadLength, nextHeader, HopLimit, Source, CurrentDestination, ExtensionHeaders); TrafficClass, FlowLabel, (ushort)(payloadLength + ExtensionHeaders.Sum(header => header.Length)), nextHeader, HopLimit, Source, CurrentDestination, ExtensionHeaders);
} }
/// <summary> /// <summary>
......
...@@ -42,7 +42,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -42,7 +42,7 @@ namespace PcapDotNet.Packets.IpV6
public IpV6OptionRoutingProtocolLowPowerAndLossyNetworks(bool down, bool rankError, bool forwardingError, byte rplInstanceId, ushort senderRank, public IpV6OptionRoutingProtocolLowPowerAndLossyNetworks(bool down, bool rankError, bool forwardingError, byte rplInstanceId, ushort senderRank,
DataSegment subTlvs) DataSegment subTlvs)
: base(IpV6OptionType.EndpointIdentification) : base(IpV6OptionType.RplOption)
{ {
Down = down; Down = down;
RankError = rankError; RankError = rankError;
......
...@@ -3938,14 +3938,14 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -3938,14 +3938,14 @@ namespace PcapDotNet.Packets.IpV6
/// <summary> /// <summary>
/// RFC 6089. /// RFC 6089.
/// </summary> /// </summary>
public class IpV6FlowIdentificationSubOptions : Options<IpV6FlowIdentificationSubOption> public class IpV6FlowIdentificationSubOptions : V6Options<IpV6FlowIdentificationSubOption>
{ {
/// <summary> /// <summary>
/// Creates options from a list of options. /// Creates options from a list of options.
/// </summary> /// </summary>
/// <param name="options">The list of options.</param> /// <param name="options">The list of options.</param>
public IpV6FlowIdentificationSubOptions(IList<IpV6FlowIdentificationSubOption> options) public IpV6FlowIdentificationSubOptions(IList<IpV6FlowIdentificationSubOption> options)
: base(options, true, null) : base(options, true)
{ {
} }
...@@ -3964,7 +3964,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -3964,7 +3964,7 @@ namespace PcapDotNet.Packets.IpV6
} }
private IpV6FlowIdentificationSubOptions(Tuple<IList<IpV6FlowIdentificationSubOption>, bool> optionsAndIsValid) private IpV6FlowIdentificationSubOptions(Tuple<IList<IpV6FlowIdentificationSubOption>, bool> optionsAndIsValid)
: base(optionsAndIsValid.Item1, optionsAndIsValid.Item2, null) : base(optionsAndIsValid.Item1, optionsAndIsValid.Item2)
{ {
} }
...@@ -4955,14 +4955,14 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -4955,14 +4955,14 @@ namespace PcapDotNet.Packets.IpV6
/// <summary> /// <summary>
/// RFC 6757. /// RFC 6757.
/// </summary> /// </summary>
public class IpV6AccessNetworkIdentifierSubOptions : Options<IpV6AccessNetworkIdentifierSubOption> public class IpV6AccessNetworkIdentifierSubOptions : V6Options<IpV6AccessNetworkIdentifierSubOption>
{ {
/// <summary> /// <summary>
/// Creates options from a list of options. /// Creates options from a list of options.
/// </summary> /// </summary>
/// <param name="options">The list of options.</param> /// <param name="options">The list of options.</param>
public IpV6AccessNetworkIdentifierSubOptions(IList<IpV6AccessNetworkIdentifierSubOption> options) public IpV6AccessNetworkIdentifierSubOptions(IList<IpV6AccessNetworkIdentifierSubOption> options)
: base(options, true, null) : base(options, true)
{ {
} }
...@@ -4981,7 +4981,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -4981,7 +4981,7 @@ namespace PcapDotNet.Packets.IpV6
} }
private IpV6AccessNetworkIdentifierSubOptions(Tuple<IList<IpV6AccessNetworkIdentifierSubOption>, bool> optionsAndIsValid) private IpV6AccessNetworkIdentifierSubOptions(Tuple<IList<IpV6AccessNetworkIdentifierSubOption>, bool> optionsAndIsValid)
: base(optionsAndIsValid.Item1, optionsAndIsValid.Item2, null) : base(optionsAndIsValid.Item1, optionsAndIsValid.Item2)
{ {
} }
......
...@@ -12,22 +12,38 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -12,22 +12,38 @@ namespace PcapDotNet.Packets.IpV6
IpV6Option CreateInstance(DataSegment data); IpV6Option CreateInstance(DataSegment data);
} }
public class IpV6Options : Options<IpV6Option> public sealed class IpV6Options : Options<IpV6Option>
{ {
public IpV6Options(IList<IpV6Option> options) public IpV6Options(IList<IpV6Option> options)
: base(options, true, null) : base(AddPadding(options), true, null)
{ {
} }
public IpV6Options(IEnumerable<IpV6Option> options)
: this(options.ToList())
{
}
public IpV6Options(DataSegment data) : this(Read(data)) public IpV6Options(DataSegment data)
: this(Read(data))
{ {
} }
private IpV6Options(Tuple<IList<IpV6Option>, bool> optionsAndIsValid) : base(optionsAndIsValid.Item1, optionsAndIsValid.Item2, null) private IpV6Options(Tuple<IList<IpV6Option>, bool> optionsAndIsValid)
: base(AddPadding(optionsAndIsValid.Item1), optionsAndIsValid.Item2, null)
{ {
} }
private static IList<IpV6Option> AddPadding(IList<IpV6Option> options)
{
int optionsLength = options.Sum(option => option.Length);
if (optionsLength % 8 == 6)
return options;
int paddingLength = (14 - optionsLength % 8) % 8;
return options.Concat(paddingLength == 1 ? (IpV6Option)new IpV6OptionPad1() : new IpV6OptionPadN(paddingLength - 2)).ToArray();
}
public static Tuple<IList<IpV6Option>, bool> Read(DataSegment data) public static Tuple<IList<IpV6Option>, bool> Read(DataSegment data)
{ {
int offset = 0; int offset = 0;
...@@ -68,6 +84,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -68,6 +84,11 @@ namespace PcapDotNet.Packets.IpV6
return new Tuple<IList<IpV6Option>, bool>(options, isValid); return new Tuple<IList<IpV6Option>, bool>(options, isValid);
} }
internal override int CalculateBytesLength(int optionsLength)
{
return optionsLength;
}
private static IpV6Option CreateOption(IpV6OptionType optionType, DataSegment data) private static IpV6Option CreateOption(IpV6OptionType optionType, DataSegment data)
{ {
IIpV6OptionComplexFactory factory; IIpV6OptionComplexFactory factory;
...@@ -102,14 +123,27 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -102,14 +123,27 @@ namespace PcapDotNet.Packets.IpV6
} }
} }
public class IpV6MobilityOptions : Options<IpV6MobilityOption> public abstract class V6Options<T> : Options<T> where T : Option
{
public V6Options(IList<T> options, bool isValid)
: base(options, isValid, null)
{
}
internal override sealed int CalculateBytesLength(int optionsLength)
{
return optionsLength;
}
}
public class IpV6MobilityOptions : V6Options<IpV6MobilityOption>
{ {
/// <summary> /// <summary>
/// Creates options from a list of options. /// Creates options from a list of options.
/// </summary> /// </summary>
/// <param name="options">The list of options.</param> /// <param name="options">The list of options.</param>
public IpV6MobilityOptions(IList<IpV6MobilityOption> options) public IpV6MobilityOptions(IList<IpV6MobilityOption> options)
: base(options, true, null) : base(options, true)
{ {
} }
...@@ -128,7 +162,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -128,7 +162,7 @@ namespace PcapDotNet.Packets.IpV6
} }
private IpV6MobilityOptions(Tuple<IList<IpV6MobilityOption>, bool> optionsAndIsValid) private IpV6MobilityOptions(Tuple<IList<IpV6MobilityOption>, bool> optionsAndIsValid)
: base(optionsAndIsValid.Item1, optionsAndIsValid.Item2, null) : base(optionsAndIsValid.Item1, optionsAndIsValid.Item2)
{ {
} }
......
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