Commit b7799fc9 authored by Brickner_cp's avatar Brickner_cp

IPv6

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