Commit ea4bf9ef authored by Brickner_cp's avatar Brickner_cp

IPv6

parent 12713caf
using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.IpV6;
using PcapDotNet.Packets.TestUtils;
using PcapDotNet.Packets.Transport;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.Test
{
/// <summary>
/// Summary description for IpV6Tests
/// </summary>
[TestClass]
public class IpV6Tests
{
/// <summary>
/// Gets or sets the test context which provides
/// information about and functionality for the current test run.
/// </summary>
public TestContext TestContext { get; set; }
#region Additional test attributes
//
// You can use the following additional attributes as you write your tests:
//
// Use ClassInitialize to run code before running the first test in the class
// [ClassInitialize()]
// public static void MyClassInitialize(TestContext testContext) { }
//
// Use ClassCleanup to run code after all tests in a class have run
// [ClassCleanup()]
// public static void MyClassCleanup() { }
//
// Use TestInitialize to run code before running each test
// [TestInitialize()]
// public void MyTestInitialize() { }
//
// Use TestCleanup to run code after each test has run
// [TestCleanup()]
// public void MyTestCleanup() { }
//
#endregion
[TestMethod]
public void RandomIpV6Test()
{
MacAddress ethernetSource = new MacAddress("00:01:02:03:04:05");
MacAddress ethernetDestination = new MacAddress("A0:A1:A2:A3:A4:A5");
const EthernetType EthernetType = EthernetType.IpV6;
EthernetLayer ethernetLayer = new EthernetLayer
{
Source = ethernetSource,
Destination = ethernetDestination,
EtherType = EthernetType
};
Random random = new Random();
for (int i = 0; i != 1000; ++i)
{
IpV6Layer ipV6Layer = random.NextIpV6Layer();
PayloadLayer payloadLayer = random.NextPayloadLayer(random.NextInt(0, 50 * 1024));
Packet packet = PacketBuilder.Build(DateTime.Now, ethernetLayer, ipV6Layer, payloadLayer);
Assert.IsTrue(packet.IsValid, string.Format("IsValid ({0})", ipV6Layer.NextHeader));
// Ethernet
Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLengthValue, packet.Ethernet.PayloadLength, "PayloadLength");
Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer");
// IpV6
Assert.AreEqual(ipV6Layer, packet.Ethernet.IpV6.ExtractLayer(), "IP Layer");
/*
if (packet.Ethernet.IpV6.NextHeader == IpV4Protocol.Tcp)
Assert.IsInstanceOfType(packet.Ethernet.IpV6.Transport, typeof(TcpDatagram));
else if (packet.Ethernet.IpV6.NextHeader == IpV4Protocol.Udp)
Assert.IsInstanceOfType(packet.Ethernet.IpV6.Transport, typeof(UdpDatagram));
else
Assert.IsNull(packet.Ethernet.IpV6.Transport);
*/
// Assert.AreEqual(payloadLayer.Data, packet.Ethernet.IpV6.Payload, "IP Payload");
}
}
}
}
\ No newline at end of file
...@@ -81,6 +81,7 @@ ...@@ -81,6 +81,7 @@
<Compile Include="IgmpTests.cs" /> <Compile Include="IgmpTests.cs" />
<Compile Include="IpV4Tests.cs" /> <Compile Include="IpV4Tests.cs" />
<Compile Include="IpV6AddressTests.cs" /> <Compile Include="IpV6AddressTests.cs" />
<Compile Include="IpV6Tests.cs" />
<Compile Include="MacAddressTests.cs" /> <Compile Include="MacAddressTests.cs" />
<Compile Include="PacketBuilderTests.cs" /> <Compile Include="PacketBuilderTests.cs" />
<Compile Include="PacketTests.cs" /> <Compile Include="PacketTests.cs" />
......
...@@ -62,6 +62,11 @@ namespace PcapDotNet.Packets ...@@ -62,6 +62,11 @@ namespace PcapDotNet.Packets
return array.Compare(offset, other, otherOffset, count) == 0; return array.Compare(offset, other, otherOffset, count) == 0;
} }
public static DataSegment SubSegment(this byte[] array, int offset, int length)
{
return new DataSegment(array, offset, length);
}
/// <summary> /// <summary>
/// Returns the first offset in the array where the other array's range sequence of bytes can be found or the length of the array if no match exists. /// Returns the first offset in the array where the other array's range sequence of bytes can be found or the length of the array if no match exists.
/// </summary> /// </summary>
......
using PcapDotNet.Packets.Arp; using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.IpV6;
namespace PcapDotNet.Packets.Ethernet namespace PcapDotNet.Packets.Ethernet
{ {
...@@ -83,6 +84,14 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -83,6 +84,14 @@ namespace PcapDotNet.Packets.Ethernet
get { return PayloadDatagrams.IpV4; } get { return PayloadDatagrams.IpV4; }
} }
/// <summary>
/// The Ethernet payload as an IPv6 datagram.
/// </summary>
public IpV6Datagram IpV6
{
get { return PayloadDatagrams.IpV6; }
}
/// <summary> /// <summary>
/// The Ethernet payload as an ARP datagram. /// The Ethernet payload as an ARP datagram.
/// </summary> /// </summary>
......
using PcapDotNet.Packets.Arp; using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.IpV6;
namespace PcapDotNet.Packets.Ethernet namespace PcapDotNet.Packets.Ethernet
{ {
...@@ -17,6 +18,9 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -17,6 +18,9 @@ namespace PcapDotNet.Packets.Ethernet
case EthernetType.IpV4: case EthernetType.IpV4:
return IpV4; return IpV4;
case EthernetType.IpV6:
return IpV6;
case EthernetType.Arp: case EthernetType.Arp:
return Arp; return Arp;
...@@ -41,6 +45,19 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -41,6 +45,19 @@ namespace PcapDotNet.Packets.Ethernet
} }
} }
/// <summary>
/// The Ethernet payload as an IPv6 datagram.
/// </summary>
public IpV6Datagram IpV6
{
get
{
if (_ipV6 == null && _payload != null)
_ipV6 = new IpV6Datagram(_payload.Buffer, _payload.StartOffset, IpV6Datagram.GetTotalLength(_payload));
return _ipV6;
}
}
/// <summary> /// <summary>
/// The Ethernet payload as an ARP datagram. /// The Ethernet payload as an ARP datagram.
/// </summary> /// </summary>
...@@ -74,6 +91,7 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -74,6 +91,7 @@ namespace PcapDotNet.Packets.Ethernet
private readonly Datagram _payload; private readonly Datagram _payload;
private IpV4Datagram _ipV4; private IpV4Datagram _ipV4;
private IpV6Datagram _ipV6;
private ArpDatagram _arp; private ArpDatagram _arp;
private VLanTaggedFrameDatagram _vLanTaggedFrame; private VLanTaggedFrameDatagram _vLanTaggedFrame;
} }
......
...@@ -3,9 +3,9 @@ using PcapDotNet.Packets.IpV4; ...@@ -3,9 +3,9 @@ using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Ip namespace PcapDotNet.Packets.Ip
{ {
internal static class IpOptionQuickStartCommon public static class IpOptionQuickStartCommon
{ {
public const int DataLength = 6; internal const int DataLength = 6;
/// <summary> /// <summary>
/// The maximum value for the rate field. /// The maximum value for the rate field.
...@@ -26,7 +26,7 @@ namespace PcapDotNet.Packets.Ip ...@@ -26,7 +26,7 @@ namespace PcapDotNet.Packets.Ip
public const byte Rate = 0x0F; public const byte Rate = 0x0F;
} }
public static void AssertValidParameters(IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce) internal static void AssertValidParameters(IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce)
{ {
if (function != IpV4OptionQuickStartFunction.RateRequest && if (function != IpV4OptionQuickStartFunction.RateRequest &&
function != IpV4OptionQuickStartFunction.RateReport) function != IpV4OptionQuickStartFunction.RateReport)
...@@ -41,7 +41,7 @@ namespace PcapDotNet.Packets.Ip ...@@ -41,7 +41,7 @@ namespace PcapDotNet.Packets.Ip
throw new ArgumentException("nonce last two bits are reserved and must be zero", "nonce"); throw new ArgumentException("nonce last two bits are reserved and must be zero", "nonce");
} }
public static int CalcRateKbps(byte rate) internal static int CalcRateKbps(byte rate)
{ {
if (rate == 0) if (rate == 0)
return 0; return 0;
...@@ -49,7 +49,7 @@ namespace PcapDotNet.Packets.Ip ...@@ -49,7 +49,7 @@ namespace PcapDotNet.Packets.Ip
return 40*(1 << rate); return 40*(1 << rate);
} }
public static void ReadData(DataSegment data, out IpV4OptionQuickStartFunction function, out byte rate, out byte ttl, out uint nonce) internal static void ReadData(DataSegment data, out IpV4OptionQuickStartFunction function, out byte rate, out byte ttl, out uint nonce)
{ {
function = (IpV4OptionQuickStartFunction)(data[Offset.Function] & Mask.Function); function = (IpV4OptionQuickStartFunction)(data[Offset.Function] & Mask.Function);
rate = (byte)(data[Offset.Rate] & Mask.Rate); rate = (byte)(data[Offset.Rate] & Mask.Rate);
...@@ -57,7 +57,7 @@ namespace PcapDotNet.Packets.Ip ...@@ -57,7 +57,7 @@ namespace PcapDotNet.Packets.Ip
nonce = data.ReadUInt(Offset.Nonce, Endianity.Big); nonce = data.ReadUInt(Offset.Nonce, Endianity.Big);
} }
public static void WriteData(byte[] buffer, ref int offset, IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce) internal static void WriteData(byte[] buffer, ref int offset, IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce)
{ {
buffer[offset + Offset.Function] = (byte)(((byte)function & Mask.Function) | (rate & Mask.Rate)); buffer[offset + Offset.Function] = (byte)(((byte)function & Mask.Function) | (rate & Mask.Rate));
buffer[offset + Offset.Ttl] = ttl; buffer[offset + Offset.Ttl] = ttl;
......
...@@ -170,19 +170,22 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -170,19 +170,22 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
Il = 0x28, Il = 0x28,
/// <summary> /// <summary>
/// IPv6 RFC 2460 /// RFC 2460.
/// IPv6.
/// </summary> /// </summary>
IpV6 = 0x29, IpV6 = 0x29,
/// <summary> /// <summary>
/// Source Demand Routing Protocol /// Source Demand Routing Protocol.
/// </summary> /// </summary>
SourceDemandRoutingProtocol = 0x2A, SourceDemandRoutingProtocol = 0x2A,
/// <summary> /// <summary>
/// Routing Header for IPv6 RFC 2460 /// RFC 2460.
/// Routing Header for IPv6.
/// </summary> /// </summary>
IpV6Route = 0x2B, IpV6Route = 0x2B,
/// <summary> /// <summary>
/// Fragment Header for IPv6 RFC 2460 /// RFC 2460.
/// Fragment Header for IPv6.
/// </summary> /// </summary>
FragmentHeaderForIpV6 = 0x2C, FragmentHeaderForIpV6 = 0x2C,
/// <summary> /// <summary>
......
...@@ -39,6 +39,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -39,6 +39,8 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public const int HeaderLength = 40; public const int HeaderLength = 40;
public const int MaxFlowLabel = 0xFFFFF;
private static class Offset private static class Offset
{ {
public const int Version = 0; public const int Version = 0;
...@@ -107,7 +109,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -107,7 +109,12 @@ namespace PcapDotNet.Packets.IpV6
public ushort RealPayloadLength public ushort RealPayloadLength
{ {
get { return (ushort)Math.Min(PayloadLength, Length); } get
{
if (Length < HeaderLength)
return 0;
return (ushort)Math.Min(PayloadLength, Length - HeaderLength);
}
} }
/// <summary> /// <summary>
...@@ -144,7 +151,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -144,7 +151,7 @@ namespace PcapDotNet.Packets.IpV6
get { return ReadIpV6Address(Offset.DestinationAddress, Endianity.Big); } get { return ReadIpV6Address(Offset.DestinationAddress, Endianity.Big); }
} }
public ReadOnlyCollection<IpV6ExtensionHeader> ExtensionHeaders public IpV6ExtensionHeaders ExtensionHeaders
{ {
get get
{ {
...@@ -158,16 +165,17 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -158,16 +165,17 @@ namespace PcapDotNet.Packets.IpV6
if (_extensionHeaders != null) if (_extensionHeaders != null)
return; return;
List<IpV6ExtensionHeader> extensionHeaders = new List<IpV6ExtensionHeader>(); if (Length < HeaderLength)
if (HeaderLength > RealPayloadLength)
{ {
_isValid = false; _isValid = false;
_extensionHeaders = extensionHeaders.AsReadOnly(); _extensionHeaders = IpV6ExtensionHeaders.Empty;
return; return;
} }
_extensionHeaders = new IpV6ExtensionHeaders(Subsegment(HeaderLength, RealPayloadLength), NextHeader);
/*
int extendedHeaderLength = HeaderLength; int extendedHeaderLength = HeaderLength;
IpV4Protocol? nextHeader = NextHeader; IpV4Protocol? nextHeader = NextHeader;
while (extendedHeaderLength + 8 <= RealPayloadLength && nextHeader.HasValue && IsExtensionHeader(nextHeader.Value)) while (extendedHeaderLength + 8 <= RealPayloadLength && nextHeader.HasValue && IpV6ExtensionHeader.IsExtensionHeader(nextHeader.Value))
{ {
int numBytesRead; int numBytesRead;
IpV6ExtensionHeader extensionHeader = IpV6ExtensionHeader.CreateInstance(nextHeader.Value, IpV6ExtensionHeader extensionHeader = IpV6ExtensionHeader.CreateInstance(nextHeader.Value,
...@@ -178,27 +186,10 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -178,27 +186,10 @@ namespace PcapDotNet.Packets.IpV6
nextHeader = extensionHeader.NextHeader; nextHeader = extensionHeader.NextHeader;
extendedHeaderLength += numBytesRead; extendedHeaderLength += numBytesRead;
} }
_isValid = (!nextHeader.HasValue || !IsExtensionHeader(nextHeader.Value)) && (HeaderLength + _extensionHeadersLength == PayloadLength);
_extensionHeaders = extensionHeaders.AsReadOnly();
_extensionHeadersLength = extendedHeaderLength - HeaderLength; _extensionHeadersLength = extendedHeaderLength - HeaderLength;
} _extensionHeaders = extensionHeaders.AsReadOnly();
_isValid = (!nextHeader.HasValue || !IpV6ExtensionHeader.IsExtensionHeader(nextHeader.Value));
private static bool IsExtensionHeader(IpV4Protocol nextHeader) */
{
switch (nextHeader)
{
case IpV4Protocol.IpV6HopByHopOption: // 0
case IpV4Protocol.IpV6Route: // 43
case IpV4Protocol.FragmentHeaderForIpV6: // 44
case IpV4Protocol.EncapsulatingSecurityPayload: // 50
case IpV4Protocol.AuthenticationHeader: // 51
case IpV4Protocol.IpV6Opts: // 60
case IpV4Protocol.MobilityHeader: // 135
return true;
default:
return false;
}
} }
/// <summary> /// <summary>
...@@ -206,20 +197,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -206,20 +197,16 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public override ILayer ExtractLayer() public override ILayer ExtractLayer()
{ {
return null; return new IpV6Layer
// TODO: Implement. {
// return new IpV6Layer TrafficClass = TrafficClass,
// { FlowLabel = FlowLabel,
// Version = Version, NextHeader = NextHeader,
// TrafficClass = TrafficClass, HopLimit = HopLimit,
// FlowLabel = FlowLabel, Source = Source,
// PayloadLength = PayloadLength, CurrentDestination = CurrentDestination,
// NextHeader = NextHeader, ExtensionHeaders = ExtensionHeaders,
// HopLimit = HopLimit, };
// Source = Source,
// CurrentDestination = CurrentDestination,
// ExtensionHeaders = ExtensionHeaders,
// };
} }
...@@ -228,16 +215,34 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -228,16 +215,34 @@ namespace PcapDotNet.Packets.IpV6
{ {
} }
internal static int GetTotalLength(Datagram payload)
{
if (payload.Length <= HeaderLength)
return payload.Length;
int totalLength = HeaderLength;
IpV4Protocol? nextHeader = (IpV4Protocol)payload[Offset.NextHeader];
while (nextHeader.HasValue && IpV6ExtensionHeader.IsExtensionHeader(nextHeader.Value))
{
int extensionHeaderLength;
IpV6ExtensionHeader.GetNextNextHeaderAndLength(nextHeader.Value, payload.Subsegment(totalLength, payload.Length - totalLength), out nextHeader,
out extensionHeaderLength);
totalLength += extensionHeaderLength;
}
return totalLength;
}
internal static void WriteHeader(byte[] buffer, int offset, internal static void WriteHeader(byte[] buffer, int offset,
byte version, byte trafficClass, int flowLabel, ushort payloadLength, IpV4Protocol nextHeader, byte hopLimit, byte trafficClass, int flowLabel, ushort payloadLength, IpV4Protocol nextHeader, byte hopLimit,
IpV6Address source, IpV6Address currentDestination) IpV6Address source, IpV6Address currentDestination, IpV6ExtensionHeaders extensionHeaders)
{ {
buffer.Write(offset + Offset.Version, (uint)(((((version << Shift.Version) << 8) | trafficClass) << 16) | flowLabel), Endianity.Big); buffer.Write(offset + Offset.Version, (uint)(((((DefaultVersion << Shift.Version) << 8) | trafficClass) << 16) | 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);
buffer.Write(offset + Offset.SourceAddress, source, Endianity.Big); buffer.Write(offset + Offset.SourceAddress, source, Endianity.Big);
buffer.Write(offset + Offset.DestinationAddress, currentDestination, Endianity.Big); buffer.Write(offset + Offset.DestinationAddress, currentDestination, Endianity.Big);
extensionHeaders.Write(buffer, offset + HeaderLength);
} }
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
...@@ -246,68 +251,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -246,68 +251,8 @@ namespace PcapDotNet.Packets.IpV6
return _isValid; return _isValid;
} }
private ReadOnlyCollection<IpV6ExtensionHeader> _extensionHeaders; private IpV6ExtensionHeaders _extensionHeaders;
private int _extensionHeadersLength; private int _extensionHeadersLength;
private bool _isValid; private bool _isValid;
} }
/*
/// <summary>
/// RFC 2460.
/// +-----+-------------+-------------------------+--------------+---------------+
/// | Bit | 0-7 | 8-15 | 16-23 | 24-31 |
/// +-----+-------------+-------------------------+--------------+---------------+
/// | 0 | Next Header | Header Extension Length | Routing Type | Segments Left |
/// +-----+-------------+-------------------------+--------------+---------------+
/// | 32 | type-specific data |
/// | ... | |
/// +-----+----------------------------------------------------------------------+
/// </summary>
public class IpV6ExtensionHeaderRouting : IpV6ExtensionHeader
{
}
/// <summary>
/// RFC 2460.
/// +-----+-------------+----------+-----------------+----------+----+
/// | Bit | 0-7 | 8-15 | 16-28 | 29-30 | 31 |
/// +-----+-------------+----------+-----------------+----------+----+
/// | 0 | Next Header | Reserved | Fragment Offset | Reserved | M |
/// +-----+-------------+----------+-----------------+----------+----+
/// | 32 | Identification |
/// +-----+----------------------------------------------------------+
/// </summary>
public class IpV6ExtensionHeaderFragment : IpV6ExtensionHeader
{
}
/// <summary>
/// RFC 2460.
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | Options |
/// | ... | |
/// +-----+---------------------------------------+
/// </summary>
public class IpV6ExtensionHeaderDestinationOptions : IpV6ExtensionHeader
{
}
/// <summary>
/// RFC 2402.
/// </summary>
public class IpV6ExtensionHeaderAuthentication : IpV6ExtensionHeader
{
}
/// <summary>
/// RFC 2406.
/// </summary>
public class IpV6ExtensionHeaderEncapsulatingSecurityPayload : IpV6ExtensionHeader
{
}
*/
} }
...@@ -92,7 +92,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -92,7 +92,7 @@ namespace PcapDotNet.Packets.IpV6
return null; return null;
} }
IpV4Protocol nextHeader = (IpV4Protocol)extensionHeaderData[Offset.NextHeader]; IpV4Protocol nextHeader = (IpV4Protocol)extensionHeaderData[Offset.NextHeader];
byte payloadLength = extensionHeaderData[Offset.PayloadLength]; int payloadLength = (extensionHeaderData[Offset.PayloadLength] + 2) * 4;
if (extensionHeaderData.Length < Offset.AuthenticationData + payloadLength) if (extensionHeaderData.Length < Offset.AuthenticationData + payloadLength)
{ {
numBytesRead = 0; numBytesRead = 0;
...@@ -101,10 +101,44 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -101,10 +101,44 @@ namespace PcapDotNet.Packets.IpV6
uint securityParametersIndex = extensionHeaderData.ReadUInt(Offset.SecurityParametersIndex, Endianity.Big); uint securityParametersIndex = extensionHeaderData.ReadUInt(Offset.SecurityParametersIndex, Endianity.Big);
uint sequenceNumber = extensionHeaderData.ReadUInt(Offset.SequenceNumber, Endianity.Big); uint sequenceNumber = extensionHeaderData.ReadUInt(Offset.SequenceNumber, Endianity.Big);
DataSegment authenticationData = extensionHeaderData.Subsegment(Offset.AuthenticationData, payloadLength); DataSegment authenticationData = extensionHeaderData.Subsegment(Offset.AuthenticationData, payloadLength - Offset.AuthenticationData);
numBytesRead = Offset.AuthenticationData + payloadLength; numBytesRead = payloadLength;
return new IpV6ExtensionHeaderAuthentication(nextHeader, securityParametersIndex, sequenceNumber, authenticationData); return new IpV6ExtensionHeaderAuthentication(nextHeader, securityParametersIndex, sequenceNumber, authenticationData);
} }
public static void GetNextNextHeaderAndLength(DataSegment extensionHeader, out IpV4Protocol? nextNextHeader, out int extensionHeaderLength)
{
if (extensionHeader.Length < MinimumLength)
{
nextNextHeader = null;
extensionHeaderLength = extensionHeader.Length;
return;
}
nextNextHeader = (IpV4Protocol)extensionHeader[Offset.NextHeader];
extensionHeaderLength = extensionHeader[Offset.PayloadLength] * 4;
}
public override IpV4Protocol Protocol
{
get { return IpV4Protocol.AuthenticationHeader; }
}
public override int Length
{
get { return MinimumLength + AuthenticationData.Length; }
}
internal override void Write(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.NextHeader, (byte)NextHeader);
int length = Length;
buffer.Write(offset + Offset.PayloadLength, (byte)((length / 4) - 2));
buffer.Write(offset + Offset.SecurityParametersIndex, SecurityParametersIndex, Endianity.Big);
buffer.Write(offset + Offset.SequenceNumber, SequenceNumber, Endianity.Big);
AuthenticationData.Write(buffer, offset + Offset.AuthenticationData);
offset += length;
}
} }
} }
\ No newline at end of file
...@@ -22,6 +22,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -22,6 +22,11 @@ namespace PcapDotNet.Packets.IpV6
{ {
} }
public override IpV4Protocol Protocol
{
get { return IpV4Protocol.IpV6Opts; }
}
internal static IpV6ExtensionHeaderDestinationOptions ParseData(IpV4Protocol nextHeader, DataSegment data) internal static IpV6ExtensionHeaderDestinationOptions ParseData(IpV4Protocol nextHeader, DataSegment data)
{ {
IpV6Options options = new IpV6Options(data); IpV6Options options = new IpV6Options(data);
......
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6 namespace PcapDotNet.Packets.IpV6
{ {
/// <summary> /// <summary>
...@@ -62,6 +64,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -62,6 +64,16 @@ namespace PcapDotNet.Packets.IpV6
EncryptedDataAndAuthenticationData = encryptedDataAndAuthenticationData; EncryptedDataAndAuthenticationData = encryptedDataAndAuthenticationData;
} }
public override IpV4Protocol Protocol
{
get { return IpV4Protocol.EncapsulatingSecurityPayload; }
}
public override int Length
{
get { return MinimumLength + EncryptedDataAndAuthenticationData.Length; }
}
/// <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),
...@@ -132,6 +144,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -132,6 +144,12 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public DataSegment EncryptedDataAndAuthenticationData { get; private set; } public DataSegment EncryptedDataAndAuthenticationData { get; private set; }
internal static void GetNextNextHeaderAndLength(DataSegment extensionHeader, out IpV4Protocol? nextNextHeader, out int extensionHeaderLength)
{
nextNextHeader = null;
extensionHeaderLength = extensionHeader.Length;
}
internal static IpV6ExtensionHeaderEncapsulatingSecurityPayload CreateInstance(DataSegment extensionHeaderData, out int numBytesRead) internal static IpV6ExtensionHeaderEncapsulatingSecurityPayload CreateInstance(DataSegment extensionHeaderData, out int numBytesRead)
{ {
if (extensionHeaderData.Length < MinimumLength) if (extensionHeaderData.Length < MinimumLength)
...@@ -146,5 +164,13 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -146,5 +164,13 @@ namespace PcapDotNet.Packets.IpV6
return new IpV6ExtensionHeaderEncapsulatingSecurityPayload(securityParametersIndex, sequenceNumber, encryptedDataAndAuthenticationData); return new IpV6ExtensionHeaderEncapsulatingSecurityPayload(securityParametersIndex, sequenceNumber, encryptedDataAndAuthenticationData);
} }
internal override void Write(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.SecurityParametersIndex, SecurityParametersIndex, Endianity.Big);
buffer.Write(offset + Offset.SequenceNumber, SequenceNumber, Endianity.Big);
EncryptedDataAndAuthenticationData.Write(buffer, offset + Offset.PayloadData);
offset += Length;
}
} }
} }
\ No newline at end of file
...@@ -17,11 +17,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -17,11 +17,16 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public class IpV6ExtensionHeaderHopByHopOptions : IpV6ExtensionHeaderOptions public class IpV6ExtensionHeaderHopByHopOptions : IpV6ExtensionHeaderOptions
{ {
private IpV6ExtensionHeaderHopByHopOptions(IpV4Protocol nextHeader, IpV6Options options) public IpV6ExtensionHeaderHopByHopOptions(IpV4Protocol nextHeader, IpV6Options options)
: base(nextHeader, options) : base(nextHeader, options)
{ {
} }
public override IpV4Protocol Protocol
{
get { return IpV4Protocol.IpV6HopByHopOption; }
}
internal static IpV6ExtensionHeaderHopByHopOptions ParseData(IpV4Protocol nextHeader, DataSegment data) internal static IpV6ExtensionHeaderHopByHopOptions ParseData(IpV4Protocol nextHeader, DataSegment data)
{ {
IpV6Options options = new IpV6Options(data); IpV6Options options = new IpV6Options(data);
......
...@@ -15,10 +15,20 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -15,10 +15,20 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public abstract class IpV6ExtensionHeaderOptions : IpV6ExtensionHeader public abstract class IpV6ExtensionHeaderOptions : IpV6ExtensionHeaderStandard
{ {
public IpV6Options Options { get; private set; } public IpV6Options Options { get; private set; }
internal override sealed int DataLength
{
get { return Options.BytesLength; }
}
internal override void WriteData(byte[] buffer, int offset)
{
Options.Write(buffer, offset);
}
internal IpV6ExtensionHeaderOptions(IpV4Protocol nextHeader, IpV6Options options) internal IpV6ExtensionHeaderOptions(IpV4Protocol nextHeader, IpV6Options options)
: base(nextHeader) : base(nextHeader)
{ {
......
...@@ -15,7 +15,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -15,7 +15,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+----------------------------------------------------------------------+ /// +-----+----------------------------------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public abstract class IpV6ExtensionHeaderRouting : IpV6ExtensionHeader public abstract class IpV6ExtensionHeaderRouting : IpV6ExtensionHeaderStandard
{ {
private static class DataOffset private static class DataOffset
{ {
...@@ -26,6 +26,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -26,6 +26,8 @@ namespace PcapDotNet.Packets.IpV6
public const int DataMinimumLength = DataOffset.TypeSpecificData; public const int DataMinimumLength = DataOffset.TypeSpecificData;
internal abstract int RoutingDataLength { get; }
/// <summary> /// <summary>
/// Identifier of a particular Routing header variant. /// Identifier of a particular Routing header variant.
/// </summary> /// </summary>
...@@ -36,6 +38,22 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -36,6 +38,22 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public byte SegmentsLeft { get; private set; } public byte SegmentsLeft { get; private set; }
public override IpV4Protocol Protocol
{
get { return IpV4Protocol.IpV6Route; }
}
internal IpV6ExtensionHeaderRouting(IpV4Protocol nextHeader, byte segmentsLeft)
: base(nextHeader)
{
SegmentsLeft = segmentsLeft;
}
internal override sealed int DataLength
{
get { return DataMinimumLength + RoutingDataLength; }
}
internal static IpV6ExtensionHeaderRouting ParseData(IpV4Protocol nextHeader, DataSegment data) internal static IpV6ExtensionHeaderRouting ParseData(IpV4Protocol nextHeader, DataSegment data)
{ {
if (data.Length < DataMinimumLength) if (data.Length < DataMinimumLength)
...@@ -63,10 +81,13 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -63,10 +81,13 @@ namespace PcapDotNet.Packets.IpV6
} }
} }
internal IpV6ExtensionHeaderRouting(IpV4Protocol nextHeader, byte segmentsLeft) internal override sealed void WriteData(byte[] buffer, int offset)
: base(nextHeader)
{ {
SegmentsLeft = segmentsLeft; buffer.Write(offset + DataOffset.RoutingType, (byte)RoutingType);
buffer.Write(offset + DataOffset.SegmentsLeft, SegmentsLeft);
WriteRoutingData(buffer, offset + DataOffset.TypeSpecificData);
} }
internal abstract void WriteRoutingData(byte[] buffer, int offset);
} }
} }
\ No newline at end of file
...@@ -23,11 +23,10 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -23,11 +23,10 @@ namespace PcapDotNet.Packets.IpV6
{ {
private static class RoutingDataOffset private static class RoutingDataOffset
{ {
public const int Reserved = 0; public const int HomeAddress = sizeof(uint);
public const int HomeAddress = Reserved + sizeof(uint);
} }
public const int RoutingDataLength = RoutingDataOffset.HomeAddress + IpV6Address.SizeOf; public const int ConstRoutingDataLength = RoutingDataOffset.HomeAddress + IpV6Address.SizeOf;
public IpV6ExtensionHeaderRoutingHomeAddress(IpV4Protocol nextHeader, byte segmentsLeft, IpV6Address homeAddress) public IpV6ExtensionHeaderRoutingHomeAddress(IpV4Protocol nextHeader, byte segmentsLeft, IpV6Address homeAddress)
: base(nextHeader, segmentsLeft) : base(nextHeader, segmentsLeft)
...@@ -45,13 +44,23 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -45,13 +44,23 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public IpV6Address HomeAddress { get; private set; } public IpV6Address HomeAddress { get; private set; }
internal override int RoutingDataLength
{
get { return ConstRoutingDataLength; }
}
internal static IpV6ExtensionHeaderRoutingHomeAddress ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData) internal static IpV6ExtensionHeaderRoutingHomeAddress ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
{ {
if (routingData.Length != RoutingDataLength) if (routingData.Length != ConstRoutingDataLength)
return null; return null;
IpV6Address homeAddress = routingData.ReadIpV6Address(RoutingDataOffset.HomeAddress, Endianity.Big); IpV6Address homeAddress = routingData.ReadIpV6Address(RoutingDataOffset.HomeAddress, Endianity.Big);
return new IpV6ExtensionHeaderRoutingHomeAddress(nextHeader, segmentsLeft, homeAddress); return new IpV6ExtensionHeaderRoutingHomeAddress(nextHeader, segmentsLeft, homeAddress);
} }
internal override void WriteRoutingData(byte[] buffer, int offset)
{
buffer.Write(offset + RoutingDataOffset.HomeAddress, HomeAddress, Endianity.Big);
}
} }
} }
\ No newline at end of file
using System; using System;
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;
...@@ -14,7 +15,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -14,7 +15,7 @@ namespace PcapDotNet.Packets.IpV6
/// | 0 | Next Header | Header Extension Length | Routing Type | Segments Left | /// | 0 | Next Header | Header Extension Length | Routing Type | Segments Left |
/// +-----+-------+-------+------+------------------+--------------+---------------+ /// +-----+-------+-------+------+------------------+--------------+---------------+
/// | 32 | CmprI | CmprE | Pad | Reserved | /// | 32 | CmprI | CmprE | Pad | Reserved |
/// +-----+-------+-------+------+------------------+--------------+---------------+ /// +-----+-------+-------+------+-------------------------------------------------+
/// | 64 | Address[1] | /// | 64 | Address[1] |
/// | ... | | /// | ... | |
/// +-----+------------------------------------------------------------------------+ /// +-----+------------------------------------------------------------------------+
...@@ -110,6 +111,18 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -110,6 +111,18 @@ namespace PcapDotNet.Packets.IpV6
public ReadOnlyCollection<IpV6Address> Addresses { get; private set; } public ReadOnlyCollection<IpV6Address> Addresses { get; private set; }
internal override int RoutingDataLength
{
get
{
return RoutingDataMinimumLength +
(Addresses.Any()
? Addresses.Count * IpV6Address.SizeOf -
(Addresses.Count - 1) * CommonPrefixLengthForNonLastAddresses - CommonPrefixLengthForLastAddress
: 0) + PadSize;
}
}
internal static IpV6ExtensionHeaderRoutingRpl ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData) internal static IpV6ExtensionHeaderRoutingRpl ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
{ {
if (routingData.Length < RoutingDataMinimumLength) if (routingData.Length < RoutingDataMinimumLength)
...@@ -158,5 +171,25 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -158,5 +171,25 @@ namespace PcapDotNet.Packets.IpV6
return new IpV6ExtensionHeaderRoutingRpl(nextHeader, segmentsLeft, commonPrefixLengthForNonLastAddresses, commonPrefixLengthForLastAddress, padSize, return new IpV6ExtensionHeaderRoutingRpl(nextHeader, segmentsLeft, commonPrefixLengthForNonLastAddresses, commonPrefixLengthForLastAddress, padSize,
addresses); addresses);
} }
internal override void WriteRoutingData(byte[] buffer, int offset)
{
buffer.Write(offset + RoutingDataOffset.CommonPrefixLengthForNonLastAddresses,
(byte)((CommonPrefixLengthForNonLastAddresses << RoutingDataShift.CommonPrefixLengthForNonLastAddresses) |
CommonPrefixLengthForLastAddress));
buffer.Write(offset + RoutingDataOffset.PadSize, (byte)(PadSize << RoutingDataShift.PadSize));
if (Addresses.Any())
{
int addressOffset = offset + RoutingDataOffset.Addresses;
byte[] addressBytes = new byte[IpV6Address.SizeOf];
for (int i = 0; i != Addresses.Count - 1; ++i)
{
addressBytes.Write(0, Addresses[i], Endianity.Big);
addressBytes.SubSegment(CommonPrefixLengthForNonLastAddresses, IpV6Address.SizeOf - CommonPrefixLengthForNonLastAddresses).Write(buffer, ref addressOffset);
}
addressBytes.Write(0, Addresses[Addresses.Count - 1], Endianity.Big);
addressBytes.SubSegment(CommonPrefixLengthForLastAddress, IpV6Address.SizeOf - CommonPrefixLengthForLastAddress).Write(buffer, ref addressOffset);
}
}
} }
} }
\ No newline at end of file
...@@ -58,6 +58,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -58,6 +58,11 @@ namespace PcapDotNet.Packets.IpV6
public ReadOnlyCollection<IpV6Address> Addresses { get; private set; } public ReadOnlyCollection<IpV6Address> Addresses { get; private set; }
internal override int RoutingDataLength
{
get { return RoutingDataMinimumLength + Addresses.Count * IpV6Address.SizeOf; }
}
internal static IpV6ExtensionHeaderRoutingSourceRoute ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData) internal static IpV6ExtensionHeaderRoutingSourceRoute ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
{ {
if (routingData.Length < RoutingDataMinimumLength) if (routingData.Length < RoutingDataMinimumLength)
...@@ -72,5 +77,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -72,5 +77,11 @@ namespace PcapDotNet.Packets.IpV6
addresses[i] = routingData.ReadIpV6Address(RoutingDataOffset.Addresses + i * IpV6Address.SizeOf, Endianity.Big); addresses[i] = routingData.ReadIpV6Address(RoutingDataOffset.Addresses + i * IpV6Address.SizeOf, Endianity.Big);
return new IpV6ExtensionHeaderRoutingSourceRoute(nextHeader, segmentsLeft, addresses); return new IpV6ExtensionHeaderRoutingSourceRoute(nextHeader, segmentsLeft, addresses);
} }
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);
}
} }
} }
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6
{
/// <summary>
/// Represents IPv6 layer.
/// <seealso cref="IpV6Datagram"/>
/// </summary>
public sealed class IpV6Layer : Layer, IEthernetNextLayer, IIpV4NextLayer
{
/// <summary>
/// Creates an IPv6 layer with all zero values.
/// </summary>
public IpV6Layer()
{
ExtensionHeaders = IpV6ExtensionHeaders.Empty;
}
public byte TrafficClass { get; set; }
public int FlowLabel { get; set; }
/// <summary>
/// Identifies the type of header immediately following the IPv6 header.
/// Uses the same values as the IPv4 Protocol field.
/// null means that this value should be calculated according to the next layer.
/// </summary>
public IpV4Protocol? NextHeader { get; set; }
public byte HopLimit { get; set; }
/// <summary>
/// Address of the originator of the packet.
/// </summary>
public IpV6Address Source { get; set; }
/// <summary>
/// Address of the intended recipient of the packet (possibly not the ultimate recipient, if a Routing header is present).
/// </summary>
public IpV6Address CurrentDestination { get; set; }
public IpV6ExtensionHeaders ExtensionHeaders { get; set; }
/// <summary>
/// The Ethernet Type the Ethernet layer should write when this layer is the Ethernet payload.
/// </summary>
public EthernetType PreviousLayerEtherType
{
get { return EthernetType.IpV6; }
}
/// <summary>
/// The protocol that should be written in the previous (IPv4) layer (in this case: IP).
/// </summary>
public IpV4Protocol PreviousLayerProtocol
{
get { return IpV4Protocol.IpV6; }
}
/// <summary>
/// The default MAC Address value when this layer is the Ethernet payload.
/// null means there is no default value.
/// </summary>
public MacAddress? PreviousLayerDefaultDestination
{
get { return null; }
}
/// <summary>
/// The number of bytes this layer will take.
/// </summary>
public override int Length
{
get { return IpV6Datagram.HeaderLength + ExtensionHeaders.Sum(header => header.Length); }
}
/// <summary>
/// Writes the layer to the buffer.
/// </summary>
/// <param name="buffer">The buffer to write the layer to.</param>
/// <param name="offset">The offset in the buffer to start writing the layer at.</param>
/// <param name="payloadLength">The length of the layer's payload (the number of bytes after the layer in the packet).</param>
/// <param name="previousLayer">The layer that comes before this layer. null if this is the first layer.</param>
/// <param name="nextLayer">The layer that comes after this layer. null if this is the last layer.</param>
public override void Write(byte[] buffer, int offset, int payloadLength, ILayer previousLayer, ILayer nextLayer)
{
IpV4Protocol nextHeader;
if (NextHeader == null)
{
if (nextLayer == null)
throw new ArgumentException("Can't determine protocol automatically from next layer because there is no next layer");
IIpV4NextLayer ipV4NextLayer = nextLayer as IIpV4NextLayer;
if (ipV4NextLayer == null)
throw new ArgumentException("Can't determine protocol automatically from next layer (" + nextLayer.GetType() + ")");
nextHeader = ipV4NextLayer.PreviousLayerProtocol;
}
else
nextHeader = NextHeader.Value;
IpV6Datagram.WriteHeader(buffer, offset,
TrafficClass, FlowLabel, (ushort)payloadLength, nextHeader, HopLimit, Source, CurrentDestination, ExtensionHeaders);
}
/// <summary>
/// True iff the two IPv4 layers have the same TypeOfService, Identification, Fragmentation, Ttl, Protocol, HeaderChecksum, Source, Destination and Options.
/// </summary>
public bool Equals(IpV6Layer other)
{
return other != null &&
TrafficClass == other.TrafficClass && FlowLabel == other.FlowLabel &&
NextHeader == other.NextHeader && HopLimit == other.HopLimit &&
Source == other.Source && CurrentDestination == other.CurrentDestination &&
ExtensionHeaders.SequenceEqual(other.ExtensionHeaders);
}
/// <summary>
/// True iff the two IPv4 layers have the same TypeOfService, Identification, Fragmentation, Ttl, Protocol, HeaderChecksum, Source, Destination and Options.
/// </summary>
public override bool Equals(Layer other)
{
return Equals(other as IpV6Layer);
}
/// <summary>
/// Returns a hash code for the layer.
/// The hash code is a XOR of the TrafficClass and HopLimit combined and the hash codes of the FlowLabel, Source, CurrentDestination, NextHeader, HeaderChecksum, ExtensionHeaders.
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode() ^
Sequence.GetHashCode(BitSequence.Merge(TrafficClass, HopLimit),
FlowLabel, Source, CurrentDestination, NextHeader) ^ ExtensionHeaders.SequenceGetHashCode();
}
/// <summary>
/// Contains the Source, Destination and Protocol.
/// </summary>
public override string ToString()
{
return Source + " -> " + CurrentDestination + " (" + NextHeader + ")";
}
}
}
\ No newline at end of file
...@@ -30,7 +30,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -30,7 +30,7 @@ namespace PcapDotNet.Packets.IpV6
public class IpV6OptionSmfDpdIpV4 : IpV6OptionSmfDpdSequenceBased public class IpV6OptionSmfDpdIpV4 : IpV6OptionSmfDpdSequenceBased
{ {
public IpV6OptionSmfDpdIpV4(IpV4Address taggerId, DataSegment identifier) public IpV6OptionSmfDpdIpV4(IpV4Address taggerId, DataSegment identifier)
:base(identifier) : base(identifier)
{ {
TaggerId = taggerId; TaggerId = taggerId;
} }
......
...@@ -265,7 +265,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -265,7 +265,7 @@ namespace PcapDotNet.Packets.IpV6
/// RFC 5568. /// RFC 5568.
/// Mobility Header IPv6 Address/Prefix. /// Mobility Header IPv6 Address/Prefix.
/// </summary> /// </summary>
MobilityHeaderIpV6AddressPrefix = 0x22, IpV6AddressPrefix = 0x22,
/// <summary> /// <summary>
/// RFC 5648. /// RFC 5648.
......
...@@ -561,7 +561,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -561,7 +561,7 @@ namespace PcapDotNet.Packets.IpV6
} }
} }
public enum IpV6MobilityOptionLinkLayerAddressCode : byte public enum IpV6MobilityLinkLayerAddressCode : byte
{ {
/// <summary> /// <summary>
/// Wildcard requesting resolution for all nearby access points. /// Wildcard requesting resolution for all nearby access points.
...@@ -637,14 +637,14 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -637,14 +637,14 @@ namespace PcapDotNet.Packets.IpV6
public const int OptionDataMinimumLength = Offset.LinkLayerAddress; public const int OptionDataMinimumLength = Offset.LinkLayerAddress;
public IpV6MobilityOptionLinkLayerAddress(IpV6MobilityOptionLinkLayerAddressCode code, DataSegment linkLayerAddress) public IpV6MobilityOptionLinkLayerAddress(IpV6MobilityLinkLayerAddressCode code, DataSegment linkLayerAddress)
: base(IpV6MobilityOptionType.LinkLayerAddress) : base(IpV6MobilityOptionType.LinkLayerAddress)
{ {
Code = code; Code = code;
LinkLayerAddress = linkLayerAddress; LinkLayerAddress = linkLayerAddress;
} }
public IpV6MobilityOptionLinkLayerAddressCode Code { get; private set; } public IpV6MobilityLinkLayerAddressCode Code { get; private set; }
/// <summary> /// <summary>
/// Variable-length link-layer address. /// Variable-length link-layer address.
...@@ -656,7 +656,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -656,7 +656,7 @@ namespace PcapDotNet.Packets.IpV6
if (data.Length < OptionDataMinimumLength) if (data.Length < OptionDataMinimumLength)
return null; return null;
IpV6MobilityOptionLinkLayerAddressCode code = (IpV6MobilityOptionLinkLayerAddressCode)data[Offset.OptionCode]; IpV6MobilityLinkLayerAddressCode code = (IpV6MobilityLinkLayerAddressCode)data[Offset.OptionCode];
DataSegment linkLayerAddress = data.Subsegment(Offset.LinkLayerAddress, data.Length - Offset.LinkLayerAddress); DataSegment linkLayerAddress = data.Subsegment(Offset.LinkLayerAddress, data.Length - Offset.LinkLayerAddress);
return new IpV6MobilityOptionLinkLayerAddress(code, linkLayerAddress); return new IpV6MobilityOptionLinkLayerAddress(code, linkLayerAddress);
...@@ -2468,7 +2468,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2468,7 +2468,7 @@ namespace PcapDotNet.Packets.IpV6
/// <summary> /// <summary>
/// RFC 5845. /// RFC 5845.
/// </summary> /// </summary>
public enum IpV6MobilityHeaderIpV6AddressPrefixCode : byte public enum IpV6MobilityIpV6AddressPrefixCode : byte
{ {
/// <summary> /// <summary>
/// Old Care-of Address. /// Old Care-of Address.
...@@ -2514,8 +2514,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2514,8 +2514,8 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+-----------------------------+ /// +-----+-----------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.MobilityHeaderIpV6AddressPrefix)] [IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.IpV6AddressPrefix)]
public class IpV6MobilityOptionMobilityHeaderIpV6AddressPrefix : IpV6MobilityOptionComplex public class IpV6MobilityOptionIpV6AddressPrefix : IpV6MobilityOptionComplex
{ {
public const byte MaxPrefixLength = 128; public const byte MaxPrefixLength = 128;
...@@ -2528,8 +2528,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2528,8 +2528,8 @@ namespace PcapDotNet.Packets.IpV6
public const int OptionDataLength = Offset.AddressOrPrefix + IpV6Address.SizeOf; public const int OptionDataLength = Offset.AddressOrPrefix + IpV6Address.SizeOf;
public IpV6MobilityOptionMobilityHeaderIpV6AddressPrefix(IpV6MobilityHeaderIpV6AddressPrefixCode code, byte prefixLength, IpV6Address addressOrPrefix) public IpV6MobilityOptionIpV6AddressPrefix(IpV6MobilityIpV6AddressPrefixCode code, byte prefixLength, IpV6Address addressOrPrefix)
: base(IpV6MobilityOptionType.MobilityHeaderIpV6AddressPrefix) : base(IpV6MobilityOptionType.IpV6AddressPrefix)
{ {
if (prefixLength > MaxPrefixLength) if (prefixLength > MaxPrefixLength)
throw new ArgumentOutOfRangeException("prefixLength", prefixLength, string.Format("Max value is {0}", MaxPrefixLength)); throw new ArgumentOutOfRangeException("prefixLength", prefixLength, string.Format("Max value is {0}", MaxPrefixLength));
...@@ -2542,7 +2542,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2542,7 +2542,7 @@ namespace PcapDotNet.Packets.IpV6
/// <summary> /// <summary>
/// Describes the kind of the address or the prefix. /// Describes the kind of the address or the prefix.
/// </summary> /// </summary>
public IpV6MobilityHeaderIpV6AddressPrefixCode Code { get; private set; } public IpV6MobilityIpV6AddressPrefixCode Code { get; private set; }
/// <summary> /// <summary>
/// Indicates the length of the IPv6 Address Prefix. /// Indicates the length of the IPv6 Address Prefix.
...@@ -2560,10 +2560,10 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2560,10 +2560,10 @@ namespace PcapDotNet.Packets.IpV6
if (data.Length != OptionDataLength) if (data.Length != OptionDataLength)
return null; return null;
IpV6MobilityHeaderIpV6AddressPrefixCode code = (IpV6MobilityHeaderIpV6AddressPrefixCode)data[Offset.Code]; IpV6MobilityIpV6AddressPrefixCode code = (IpV6MobilityIpV6AddressPrefixCode)data[Offset.Code];
byte prefixLength = data[Offset.PrefixLength]; byte prefixLength = data[Offset.PrefixLength];
IpV6Address addressOrPrefix = data.ReadIpV6Address(Offset.AddressOrPrefix, Endianity.Big); IpV6Address addressOrPrefix = data.ReadIpV6Address(Offset.AddressOrPrefix, Endianity.Big);
return new IpV6MobilityOptionMobilityHeaderIpV6AddressPrefix(code, prefixLength, addressOrPrefix); return new IpV6MobilityOptionIpV6AddressPrefix(code, prefixLength, addressOrPrefix);
} }
internal override int DataLength internal override int DataLength
......
...@@ -9,6 +9,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -9,6 +9,12 @@ namespace PcapDotNet.Packets.IpV6
{ {
public class IpV6Options : Options<IpV6Option> public class IpV6Options : Options<IpV6Option>
{ {
public IpV6Options(IList<IpV6Option> options)
: base(options, true, null)
{
}
public IpV6Options(DataSegment data) : this(Read(data)) public IpV6Options(DataSegment data) : this(Read(data))
{ {
} }
......
...@@ -316,6 +316,7 @@ ...@@ -316,6 +316,7 @@
<Compile Include="Igmp\IgmpRecordType.cs" /> <Compile Include="Igmp\IgmpRecordType.cs" />
<Compile Include="Igmp\IgmpMessageType.cs" /> <Compile Include="Igmp\IgmpMessageType.cs" />
<Compile Include="Igmp\IIgmpLayerWithGroupAddress.cs" /> <Compile Include="Igmp\IIgmpLayerWithGroupAddress.cs" />
<Compile Include="IpV6\IpV6Layer.cs" />
<Compile Include="IpV6\Options\IpV6CalipsoDomainOfInterpretation.cs" /> <Compile Include="IpV6\Options\IpV6CalipsoDomainOfInterpretation.cs" />
<Compile Include="IpV6\IpV6ExtensionHeader.cs" /> <Compile Include="IpV6\IpV6ExtensionHeader.cs" />
<Compile Include="IpV6\IpV6ExtensionHeaderAuthentication.cs" /> <Compile Include="IpV6\IpV6ExtensionHeaderAuthentication.cs" />
......
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