Commit b5779710 authored by Brickner_cp's avatar Brickner_cp

IPv6

parent ea5c39de
......@@ -170,7 +170,9 @@ namespace PcapDotNet.Packets.IpV6
while (extendedHeaderLength + 8 <= RealPayloadLength && IsExtensionHeader(nextHeader))
{
int numBytesRead;
IpV6ExtensionHeader extensionHeader = CreateExtensionHeader(nextHeader, Subsegment(extendedHeaderLength, Length - extendedHeaderLength), out numBytesRead);
IpV6ExtensionHeader extensionHeader = IpV6ExtensionHeader.CreateInstance(nextHeader,
Subsegment(extendedHeaderLength, Length - extendedHeaderLength),
out numBytesRead);
if (extensionHeader == null)
break;
nextHeader = extensionHeader.NextHeader;
......@@ -181,36 +183,6 @@ namespace PcapDotNet.Packets.IpV6
_extensionHeadersLength = extendedHeaderLength - HeaderLength;
}
private IpV6ExtensionHeader CreateExtensionHeader(IpV4Protocol nextHeader, DataSegment data, out int numBytesRead)
{
switch (nextHeader)
{
case IpV4Protocol.IpV6HopByHopOption: // 0
return IpV6ExtensionHeaderHopByHopOptions.Parse(data, out numBytesRead);
/*
case IpV4Protocol.IpV6Route: // 43
return IpV6ExtensionHeaderRouting.Parse(data);
case IpV4Protocol.FragmentHeaderForIpV6: // 44
return IpV6ExtensionHeaderFragment.Parse(data);
case IpV4Protocol.EncapsulatingSecurityPayload: // 50
return IpV6ExtensionHeaderEncapsulatingSecurityPayload.Parse(data);
case IpV4Protocol.AuthenticationHeader: // 51
return IpV6ExtensionHeaderAuthentication.Parse(data);
case IpV4Protocol.IpV6Opts: // 60
return IpV6ExtensionHeaderDestinationOptions.Parse(data);
case IpV4Protocol.MobilityHeader: // 135
return IpV6MobilityExtensionHeader.Parse(data);
*/
default:
throw new InvalidOperationException(string.Format("Invalid next header value {0}", nextHeader));
}
}
private static bool IsExtensionHeader(IpV4Protocol nextHeader)
{
switch (nextHeader)
......
......@@ -4,14 +4,73 @@ namespace PcapDotNet.Packets.IpV6
{
/// <summary>
/// RFC 2460.
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | Data |
/// | ... | |
/// +-----+---------------------------------------+
/// </summary>
public abstract class IpV6ExtensionHeader
{
private static class Offset
{
public const int NextHeader = 0;
public const int HeaderExtensionLength = 1;
public const int Data = 2;
}
public const int MinimumLength = 8;
public IpV4Protocol NextHeader { get; private set; }
protected IpV6ExtensionHeader(IpV4Protocol nextHeader)
{
NextHeader = nextHeader;
}
public IpV4Protocol NextHeader { get; private set; }
internal static IpV6ExtensionHeader CreateInstance(IpV4Protocol nextHeader, DataSegment extensionHeaderData, out int numBytesRead)
{
numBytesRead = 0;
if (extensionHeaderData.Length < MinimumLength)
return null;
IpV4Protocol nextNextHeader = (IpV4Protocol)extensionHeaderData[Offset.NextHeader];
int length = (extensionHeaderData[Offset.HeaderExtensionLength] + 1) * 8;
if (extensionHeaderData.Length < length)
return null;
DataSegment data = extensionHeaderData.Subsegment(Offset.Data, length - Offset.Data);
numBytesRead = data.Length;
switch (nextHeader)
{
case IpV4Protocol.IpV6HopByHopOption: // 0
return IpV6ExtensionHeaderHopByHopOptions.ParseData(nextNextHeader, data);
case IpV4Protocol.IpV6Route: // 43
return IpV6ExtensionHeaderRouting.ParseData(nextNextHeader, data);
/*
case IpV4Protocol.FragmentHeaderForIpV6: // 44
return IpV6ExtensionHeaderFragment.Parse(data);
case IpV4Protocol.EncapsulatingSecurityPayload: // 50
return IpV6ExtensionHeaderEncapsulatingSecurityPayload.Parse(data);
case IpV4Protocol.AuthenticationHeader: // 51
return IpV6ExtensionHeaderAuthentication.Parse(data);
case IpV4Protocol.IpV6Opts: // 60
return IpV6ExtensionHeaderDestinationOptions.Parse(data);
case IpV4Protocol.MobilityHeader: // 135
return IpV6MobilityExtensionHeader.Parse(data);
*/
default:
return null;
}
}
}
}
\ No newline at end of file
......@@ -4,6 +4,7 @@ namespace PcapDotNet.Packets.IpV6
{
/// <summary>
/// RFC 2460.
/// <pre>
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
......@@ -12,18 +13,10 @@ namespace PcapDotNet.Packets.IpV6
/// | 16 | Options |
/// | ... | |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderHopByHopOptions : IpV6ExtensionHeader
{
private static class Offset
{
public const int NextHeader = 0;
public const int HeaderExtensionLength = 1;
public const int Options = 2;
}
public const int MinimumLength = 8;
private IpV6ExtensionHeaderHopByHopOptions(IpV4Protocol nextHeader, IpV6Options options)
: base(nextHeader)
{
......@@ -32,18 +25,9 @@ namespace PcapDotNet.Packets.IpV6
public IpV6Options Options { get; private set; }
internal static IpV6ExtensionHeaderHopByHopOptions Parse(DataSegment data, out int numBytesRead)
internal static IpV6ExtensionHeaderHopByHopOptions ParseData(IpV4Protocol nextHeader, DataSegment data)
{
numBytesRead = 0;
if (data.Length < MinimumLength)
return null;
IpV4Protocol nextHeader = (IpV4Protocol)data[Offset.NextHeader];
int length = (data[Offset.HeaderExtensionLength] + 1) * 8;
if (data.Length < length)
return null;
IpV6Options options = new IpV6Options(data.Subsegment(Offset.Options, length - Offset.Options));
numBytesRead = length;
IpV6Options options = new IpV6Options(data);
return new IpV6ExtensionHeaderHopByHopOptions(nextHeader, options);
}
}
......
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6
{
/// <summary>
/// RFC 2460.
/// <pre>
/// +-----+-------------+-------------------------+--------------+---------------+
/// | Bit | 0-7 | 8-15 | 16-23 | 24-31 |
/// +-----+-------------+-------------------------+--------------+---------------+
/// | 0 | Next Header | Header Extension Length | Routing Type | Segments Left |
/// +-----+-------------+-------------------------+--------------+---------------+
/// | 32 | Routing Data - type-specific data |
/// | ... | |
/// +-----+----------------------------------------------------------------------+
/// </pre>
/// </summary>
public abstract class IpV6ExtensionHeaderRouting : IpV6ExtensionHeader
{
private static class DataOffset
{
public const int RoutingType = 0;
public const int SegmentsLeft = RoutingType + sizeof(byte);
public const int TypeSpecificData = SegmentsLeft + sizeof(byte);
}
public const int DataMinimumLength = DataOffset.TypeSpecificData;
/// <summary>
/// Identifier of a particular Routing header variant.
/// </summary>
public abstract IpV6RoutingType RoutingType { get; }
/// <summary>
/// Number of route segments remaining, i.e., number of explicitly listed intermediate nodes still to be visited before reaching the final destination.
/// </summary>
public byte SegmentsLeft { get; private set; }
internal static IpV6ExtensionHeaderRouting ParseData(IpV4Protocol nextHeader, DataSegment data)
{
if (data.Length < DataMinimumLength)
return null;
IpV6RoutingType routingType = (IpV6RoutingType)data[DataOffset.RoutingType];
byte segmentsLeft = data[DataOffset.SegmentsLeft];
DataSegment routingData = data.Subsegment(DataOffset.TypeSpecificData, data.Length - DataOffset.TypeSpecificData);
switch (routingType)
{
case IpV6RoutingType.SourceRoute:
return IpV6ExtensionHeaderRoutingSourceRoute.ParseRoutingData(nextHeader, segmentsLeft, routingData);
case IpV6RoutingType.Nimrod:
// Unused.
return null;
case IpV6RoutingType.Type2RoutingHeader:
return IpV6ExtensionHeaderRoutingHomeAddress.ParseRoutingData(nextHeader, segmentsLeft, routingData);
case IpV6RoutingType.RplSourceRouteHeader:
return IpV6ExtensionHeaderRoutingRpl.ParseRoutingData(nextHeader, segmentsLeft, routingData);
default:
return null;
}
}
internal IpV6ExtensionHeaderRouting(IpV4Protocol nextHeader, byte segmentsLeft)
: base(nextHeader)
{
SegmentsLeft = segmentsLeft;
}
}
}
\ No newline at end of file
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6
{
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+-------------+-------------------------+--------------+---------------+
/// | Bit | 0-7 | 8-15 | 16-23 | 24-31 |
/// +-----+-------------+-------------------------+--------------+---------------+
/// | 0 | Next Header | Header Extension Length | Routing Type | Segments Left |
/// +-----+-------------+-------------------------+--------------+---------------+
/// | 32 | Reserved |
/// +-----+----------------------------------------------------------------------+
/// | 64 | Home Address |
/// | | |
/// | | |
/// | | |
/// +-----+----------------------------------------------------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderRoutingHomeAddress : IpV6ExtensionHeaderRouting
{
private static class RoutingDataOffset
{
public const int Reserved = 0;
public const int HomeAddress = Reserved + sizeof(uint);
}
public const int RoutingDataLength = RoutingDataOffset.HomeAddress + IpV6Address.SizeOf;
public IpV6ExtensionHeaderRoutingHomeAddress(IpV4Protocol nextHeader, byte segmentsLeft, IpV6Address homeAddress)
: base(nextHeader, segmentsLeft)
{
HomeAddress = homeAddress;
}
public override IpV6RoutingType RoutingType
{
get { return IpV6RoutingType.Type2RoutingHeader; }
}
/// <summary>
/// The home address of the destination mobile node.
/// </summary>
public IpV6Address HomeAddress { get; private set; }
internal static IpV6ExtensionHeaderRoutingHomeAddress ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
{
if (routingData.Length != RoutingDataLength)
return null;
IpV6Address homeAddress = routingData.ReadIpV6Address(RoutingDataOffset.HomeAddress, Endianity.Big);
return new IpV6ExtensionHeaderRoutingHomeAddress(nextHeader, segmentsLeft, homeAddress);
}
}
}
\ No newline at end of file
using System;
using System.Collections.ObjectModel;
using PcapDotNet.Base;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6
{
/// <summary>
/// RFC 6554.
/// <pre>
/// +-----+-------+-------+------+------------------+--------------+---------------+
/// | Bit | 0-3 | 4-7 | 8-11 | 12-15 | 16-23 | 24-31 |
/// +-----+-------+-------+------+------------------+--------------+---------------+
/// | 0 | Next Header | Header Extension Length | Routing Type | Segments Left |
/// +-----+-------+-------+------+------------------+--------------+---------------+
/// | 32 | CmprI | CmprE | Pad | Reserved |
/// +-----+-------+-------+------+------------------+--------------+---------------+
/// | 64 | Address[1] |
/// | ... | |
/// +-----+------------------------------------------------------------------------+
/// | | Address[2] |
/// | ... | |
/// +-----+------------------------------------------------------------------------+
/// | . | . |
/// | . | . |
/// | . | . |
/// +-----+------------------------------------------------------------------------+
/// | | Address[n] |
/// | ... | |
/// +-----+------------------------------------------------------------------------+
/// | | Padding |
/// | ... | |
/// +-----+------------------------------------------------------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderRoutingRpl : IpV6ExtensionHeaderRouting
{
private static class RoutingDataOffset
{
public const int CommonPrefixLengthForNonLastAddresses = 0;
public const int CommonPrefixLengthForLastAddress = CommonPrefixLengthForNonLastAddresses;
public const int PadSize = CommonPrefixLengthForLastAddress + sizeof(byte);
public const int Reserved = PadSize;
public const int Addresses = Reserved + UInt24.SizeOf;
}
private static class RoutingDataMask
{
public const byte CommonPrefixLengthForNonLastAddresses = 0xF0;
public const byte CommonPrefixLengthForLastAddress = 0x0F;
public const byte PadSize = 0xF0;
}
private static class RoutingDataShift
{
public const int CommonPrefixLengthForNonLastAddresses = 4;
public const int PadSize = 4;
}
public const int RoutingDataMinimumLength = RoutingDataOffset.Addresses;
public const byte MaxCommonPrefixLength = IpV6Address.SizeOf - 1;
public const byte MaxPadSize = IpV6Address.SizeOf - 1;
public IpV6ExtensionHeaderRoutingRpl(IpV4Protocol nextHeader, byte segmentsLeft, byte commonPrefixLengthForNonLastAddresses,
byte commonPrefixLengthForLastAddress, byte padSize, params IpV6Address[] addresses)
: base(nextHeader, segmentsLeft)
{
if (commonPrefixLengthForNonLastAddresses > MaxCommonPrefixLength)
{
throw new ArgumentOutOfRangeException("commonPrefixLengthForNonLastAddresses", commonPrefixLengthForNonLastAddresses,
string.Format("Maximum value is {0}", MaxCommonPrefixLength));
}
CommonPrefixLengthForNonLastAddresses = commonPrefixLengthForNonLastAddresses;
if (commonPrefixLengthForLastAddress > MaxCommonPrefixLength)
{
throw new ArgumentOutOfRangeException("commonPrefixLengthForLastAddress", commonPrefixLengthForLastAddress,
string.Format("Maximum value is {0}", MaxCommonPrefixLength));
}
CommonPrefixLengthForLastAddress = commonPrefixLengthForLastAddress;
if (padSize > MaxPadSize)
throw new ArgumentOutOfRangeException("padSize", padSize, string.Format("Maximum value is {0}", MaxPadSize));
PadSize = padSize;
Addresses = addresses.AsReadOnly();
}
public override IpV6RoutingType RoutingType
{
get { return IpV6RoutingType.SourceRoute; }
}
/// <summary>
/// Number of prefix octets from each segment, except than the last segment, (i.e., segments 1 through n-1) that are elided.
/// For example, a header carrying full IPv6 addresses in Addresses[1..n-1] sets this to 0.
/// </summary>
public byte CommonPrefixLengthForNonLastAddresses { get; private set; }
/// <summary>
/// Number of prefix octets from the last segment (i.e., segment n) that are elided.
/// For example, a header carrying a full IPv6 address in Addresses[n] sets this to 0.
/// </summary>
public byte CommonPrefixLengthForLastAddress { get; private set; }
/// <summary>
/// Number of octets that are used for padding after Address[n] at the end of the header.
/// </summary>
public byte PadSize { get; private set; }
public ReadOnlyCollection<IpV6Address> Addresses { get; private set; }
internal static IpV6ExtensionHeaderRoutingRpl ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
{
if (routingData.Length < RoutingDataMinimumLength)
return null;
byte commonPrefixLengthForNonLastAddresses =
(byte)((routingData[RoutingDataOffset.CommonPrefixLengthForNonLastAddresses] & RoutingDataMask.CommonPrefixLengthForNonLastAddresses) >>
RoutingDataShift.CommonPrefixLengthForNonLastAddresses);
if (commonPrefixLengthForNonLastAddresses >= MaxCommonPrefixLength)
return null;
byte commonPrefixLengthForLastAddress =
(byte)(routingData[RoutingDataOffset.CommonPrefixLengthForLastAddress] & RoutingDataMask.CommonPrefixLengthForLastAddress);
if (commonPrefixLengthForLastAddress > MaxCommonPrefixLength)
return null;
byte padSize = (byte)((routingData[RoutingDataOffset.PadSize] & RoutingDataMask.PadSize) >> RoutingDataShift.PadSize);
if (padSize > MaxPadSize)
return null;
int numAddresses = (routingData.Length - RoutingDataOffset.Addresses - padSize - (IpV6Address.SizeOf - commonPrefixLengthForLastAddress)) /
(IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses) + 1;
if (numAddresses < 0)
return null;
IpV6Address[] addresses = new IpV6Address[numAddresses];
if (numAddresses > 0)
{
byte[] addressBytes = new byte[IpV6Address.SizeOf];
for (int i = 0; i < numAddresses - 1; ++i)
{
DataSegment addressSegment =
routingData.Subsegment(RoutingDataOffset.Addresses + i * (IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses),
commonPrefixLengthForNonLastAddresses);
addressSegment.Write(addressBytes, 0);
addresses[i] = addressBytes.ReadIpV6Address(0, Endianity.Big);
}
addressBytes = new byte[IpV6Address.SizeOf];
DataSegment lastAddressSegment =
routingData.Subsegment(RoutingDataOffset.Addresses + (numAddresses - 1) * (IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses),
commonPrefixLengthForLastAddress);
lastAddressSegment.Write(addressBytes, 0);
addresses[numAddresses - 1] = addressBytes.ReadIpV6Address(0, Endianity.Big);
}
return new IpV6ExtensionHeaderRoutingRpl(nextHeader, segmentsLeft, commonPrefixLengthForNonLastAddresses, commonPrefixLengthForLastAddress, padSize,
addresses);
}
}
}
\ No newline at end of file
using System.Collections.ObjectModel;
using PcapDotNet.Base;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6
{
/// <summary>
/// RFC 2460.
/// <pre>
/// +-----+-------------+-------------------------+--------------+---------------+
/// | Bit | 0-7 | 8-15 | 16-23 | 24-31 |
/// +-----+-------------+-------------------------+--------------+---------------+
/// | 0 | Next Header | Header Extension Length | Routing Type | Segments Left |
/// +-----+-------------+-------------------------+--------------+---------------+
/// | 32 | Reserved |
/// +-----+----------------------------------------------------------------------+
/// | 64 | Address[1] |
/// | | |
/// | | |
/// | | |
/// +-----+----------------------------------------------------------------------+
/// | 192 | Address[2] |
/// | | |
/// | | |
/// | | |
/// +-----+----------------------------------------------------------------------+
/// | . | . |
/// | . | . |
/// | . | . |
/// +-----+----------------------------------------------------------------------+
/// | | Address[n] |
/// | | |
/// | | |
/// | | |
/// +-----+----------------------------------------------------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderRoutingSourceRoute : IpV6ExtensionHeaderRouting
{
private static class RoutingDataOffset
{
public const int Reserved = 0;
public const int Addresses = Reserved + sizeof(uint);
}
public const int RoutingDataMinimumLength = RoutingDataOffset.Addresses;
public IpV6ExtensionHeaderRoutingSourceRoute(IpV4Protocol nextHeader, byte segmentsLeft, params IpV6Address[] addresses)
: base(nextHeader, segmentsLeft)
{
Addresses = addresses.AsReadOnly();
}
public override IpV6RoutingType RoutingType
{
get { return IpV6RoutingType.SourceRoute; }
}
public ReadOnlyCollection<IpV6Address> Addresses { get; private set; }
internal static IpV6ExtensionHeaderRoutingSourceRoute ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
{
if (routingData.Length < RoutingDataMinimumLength)
return null;
if ((routingData.Length - RoutingDataMinimumLength) % IpV6Address.SizeOf != 0)
return null;
int numAddresses = (routingData.Length - RoutingDataMinimumLength) / 8;
IpV6Address[] addresses = new IpV6Address[numAddresses];
for (int i = 0; i != numAddresses; ++i)
addresses[i] = routingData.ReadIpV6Address(RoutingDataOffset.Addresses + i * IpV6Address.SizeOf, Endianity.Big);
return new IpV6ExtensionHeaderRoutingSourceRoute(nextHeader, segmentsLeft, addresses);
}
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.IpV6
{
public enum IpV6RoutingType : byte
{
/// <summary>
/// RFCs 2460, 5095.
/// Deprecated.
/// </summary>
SourceRoute = 0,
/// <summary>
/// Deprecated 06-May-2009.
/// </summary>
Nimrod = 1,
/// <summary>
/// RFC 6275.
/// </summary>
Type2RoutingHeader = 2,
/// <summary>
/// RFC 6554.
/// </summary>
RplSourceRouteHeader = 3,
}
}
\ No newline at end of file
......@@ -319,6 +319,10 @@
<Compile Include="IpV6\IpV6CalipsoDomainOfInterpretation.cs" />
<Compile Include="IpV6\IpV6ExtensionHeader.cs" />
<Compile Include="IpV6\IpV6ExtensionHeaderHopByHopOptions.cs" />
<Compile Include="IpV6\IpV6ExtensionHeaderRouting.cs" />
<Compile Include="IpV6\IpV6ExtensionHeaderRoutingHomeAddress.cs" />
<Compile Include="IpV6\IpV6ExtensionHeaderRoutingRpl.cs" />
<Compile Include="IpV6\IpV6ExtensionHeaderRoutingSourceRoute.cs" />
<Compile Include="IpV6\IpV6Option.cs" />
<Compile Include="IpV6\IpV6OptionCalipso.cs" />
<Compile Include="IpV6\IpV6OptionComplex.cs" />
......@@ -346,6 +350,7 @@
<Compile Include="IpV6\IpV6OptionTypeRegistrationAttribute.cs" />
<Compile Include="IpV6\IpV6OptionUnknown.cs" />
<Compile Include="IpV6\IpV6RouterAlertType.cs" />
<Compile Include="IpV6\IpV6RoutingType.cs" />
<Compile Include="IpV6\IpV6TaggerIdType.cs" />
<Compile Include="IpV6\PppFrameCheckSequenceCalculator.cs" />
<Compile Include="Ip\V4Option.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