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 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