Commit de0ecfbc authored by Brickner_cp's avatar Brickner_cp

IPv6

parent 3e290c34
......@@ -166,11 +166,11 @@ namespace PcapDotNet.Packets.IpV6
return;
}
int extendedHeaderLength = HeaderLength;
IpV4Protocol nextHeader = NextHeader;
while (extendedHeaderLength + 8 <= RealPayloadLength && IsExtensionHeader(nextHeader))
IpV4Protocol? nextHeader = NextHeader;
while (extendedHeaderLength + 8 <= RealPayloadLength && nextHeader.HasValue && IsExtensionHeader(nextHeader.Value))
{
int numBytesRead;
IpV6ExtensionHeader extensionHeader = IpV6ExtensionHeader.CreateInstance(nextHeader,
IpV6ExtensionHeader extensionHeader = IpV6ExtensionHeader.CreateInstance(nextHeader.Value,
Subsegment(extendedHeaderLength, Length - extendedHeaderLength),
out numBytesRead);
if (extensionHeader == null)
......@@ -178,7 +178,7 @@ namespace PcapDotNet.Packets.IpV6
nextHeader = extensionHeader.NextHeader;
extendedHeaderLength += numBytesRead;
}
_isValid = !IsExtensionHeader(nextHeader) && (HeaderLength + _extensionHeadersLength == PayloadLength);
_isValid = (!nextHeader.HasValue || !IsExtensionHeader(nextHeader.Value)) && (HeaderLength + _extensionHeadersLength == PayloadLength);
_extensionHeaders = extensionHeaders.AsReadOnly();
_extensionHeadersLength = extendedHeaderLength - HeaderLength;
}
......
using System;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6
{
/// <summary>
/// RFC 2460.
/// For IpV6HopByHopOption, IpV6Route and FragmentHeaderForIpV6 we use the following format:
/// <pre>
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
......@@ -12,6 +15,7 @@ namespace PcapDotNet.Packets.IpV6
/// | 16 | Data |
/// | ... | |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
public abstract class IpV6ExtensionHeader
{
......@@ -24,26 +28,54 @@ namespace PcapDotNet.Packets.IpV6
public const int MinimumLength = 8;
public IpV4Protocol NextHeader { get; private set; }
public IpV4Protocol? NextHeader { get; private set; }
protected IpV6ExtensionHeader(IpV4Protocol nextHeader)
protected IpV6ExtensionHeader(IpV4Protocol? nextHeader)
{
NextHeader = nextHeader;
}
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;
switch (nextHeader)
{
case IpV4Protocol.IpV6HopByHopOption: // 0
case IpV4Protocol.IpV6Route: // 43
case IpV4Protocol.FragmentHeaderForIpV6: // 44
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;
return CreateStandardInstance(nextHeader, nextNextHeader, data);
case IpV4Protocol.EncapsulatingSecurityPayload: // 50
return IpV6ExtensionHeaderEncapsulatingSecurityPayload.CreateInstance(extensionHeaderData, out numBytesRead);
/*
case IpV4Protocol.AuthenticationHeader: // 51
return IpV6ExtensionHeaderAuthentication.Parse(data);
DataSegment data = extensionHeaderData.Subsegment(Offset.Data, length - Offset.Data);
numBytesRead = data.Length;
case IpV4Protocol.IpV6Opts: // 60
return IpV6ExtensionHeaderDestinationOptions.Parse(data);
case IpV4Protocol.MobilityHeader: // 135
return IpV6MobilityExtensionHeader.Parse(data);
*/
default:
throw new InvalidOperationException("Invalid nextHeader value" + nextHeader);
}
}
private static IpV6ExtensionHeader CreateStandardInstance(IpV4Protocol nextHeader, IpV4Protocol nextNextHeader, DataSegment data)
{
switch (nextHeader)
{
case IpV4Protocol.IpV6HopByHopOption: // 0
......@@ -54,23 +86,10 @@ namespace PcapDotNet.Packets.IpV6
case IpV4Protocol.FragmentHeaderForIpV6: // 44
return IpV6ExtensionHeaderFragmentData.ParseData(nextNextHeader, 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;
throw new InvalidOperationException("Invalid nextHeader value" + nextHeader);
}
}
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.IpV6
{
/// <summary>
/// RFC 2406.
/// <pre>
/// +-----+------------+-------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+------------+-------------+
/// | 0 | Security Parameters |
/// | | Index (SPI) |
/// +-----+--------------------------+
/// | 32 | Sequence Number |
/// | | |
/// +-----+--------------------------+
/// | 64 | Payload Data |
/// | ... | |
/// +-----+--------------------------+
/// | | Padding |
/// | ... | |
/// +-----+------------+-------------+
/// | | Pad Length | Next Header |
/// +-----+------------+-------------+
/// | | Authentication Data |
/// | ... | |
/// +-----+--------------------------+
/// </pre>
///
/// <pre>
/// +-----+------------+-------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+------------+-------------+
/// | 0 | Security Parameters |
/// | | Index (SPI) |
/// +-----+--------------------------+
/// | 32 | Sequence Number |
/// | | |
/// +-----+--------------------------+
/// | 64 | Encrypted Data |
/// | ... | |
/// +-----+--------------------------+
/// | | Authentication Data |
/// | ... | |
/// +-----+--------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderEncapsulatingSecurityPayload : IpV6ExtensionHeader
{
private static class Offset
{
public const int SecurityParametersIndex = 0;
public const int SequenceNumber = SecurityParametersIndex + sizeof(uint);
public const int PayloadData = SequenceNumber + sizeof(uint);
}
public const int MinimumLength = Offset.PayloadData;
public IpV6ExtensionHeaderEncapsulatingSecurityPayload(uint securityParametersIndex, uint sequenceNumber, DataSegment encryptedDataAndAuthenticationData)
: base(null)
{
SecurityParametersIndex = securityParametersIndex;
SequenceNumber = sequenceNumber;
EncryptedDataAndAuthenticationData = encryptedDataAndAuthenticationData;
}
/// <summary>
/// <para>
/// The SPI is an arbitrary 32-bit value that, in combination with the destination IP address and security protocol (ESP),
/// uniquely identifies the Security Association for this datagram.
/// The set of SPI values in the range 1 through 255 are reserved by the Internet Assigned Numbers Authority (IANA) for future use;
/// a reserved SPI value will not normally be assigned by IANA unless the use of the assigned SPI value is specified in an RFC.
/// It is ordinarily selected by the destination system upon establishment of an SA (see the Security Architecture document for more details).
/// The SPI field is mandatory.
/// </para>
/// <para>
/// The SPI value of zero (0) is reserved for local, implementation-specific use and must not be sent on the wire.
/// For example, a key management implementation MAY use the zero SPI value to mean "No Security Association Exists"
/// during the period when the IPsec implementation has requested that its key management entity establish a new SA,
/// but the SA has not yet been established.
/// </para>
/// </summary>
public uint SecurityParametersIndex { get; private set; }
/// <summary>
/// <para>
/// Contains a monotonically increasing counter value (sequence number).
/// It is mandatory and is always present even if the receiver does not elect to enable the anti-replay service for a specific SA.
/// Processing of the Sequence Number field is at the discretion of the receiver, i.e., the sender must always transmit this field,
/// but the receiver need not act upon it.
/// </para>
/// <para>
/// The sender's counter and the receiver's counter are initialized to 0 when an SA is established.
/// (The first packet sent using a given SA will have a Sequence Number of 1.)
/// If anti-replay is enabled (the default), the transmitted Sequence Number must never be allowed to cycle.
/// Thus, the sender's counter and the receiver's counter must be reset (by establishing a new SA and thus a new key)
/// prior to the transmission of the 2^32nd packet on an SA.
/// </para>
/// </summary>
public uint SequenceNumber { get; private set; }
/// <summary>
/// Contains the encrupted Payload Data, Padding, Pad Length and Next Header and the Authentication Data.
/// <para>
/// Payload Data is a variable-length field containing data described by the Next Header field.
/// The Payload Data field is mandatory and is an integral number of bytes in length.
/// If the algorithm used to encrypt the payload requires cryptographic synchronization data, e.g., an Initialization Vector (IV),
/// then this data may be carried explicitly in the Payload field.
/// Any encryption algorithm that requires such explicit, per-packet synchronization data must indicate the length, any structure for such data,
/// and the location of this data as part of an RFC specifying how the algorithm is used with ESP.
/// If such synchronization data is implicit, the algorithm for deriving the data must be part of the RFC.
/// </para>
/// <para>
/// The sender may add 0-255 bytes of padding.
/// Inclusion of the Padding field in an ESP packet is optional, but all implementations must support generation and consumption of padding.
/// </para>
/// <para>
/// The Pad Length field indicates the number of pad bytes immediately preceding it.
/// The range of valid values is 0-255, where a value of zero indicates that no Padding bytes are present.
/// The Pad Length field is mandatory.
/// </para>
/// <para>
/// The Next Header is an 8-bit field that identifies the type of data contained in the Payload Data field,
/// e.g., an extension header in IPv6 or an upper layer protocol identifier.
/// The Next Header field is mandatory.
/// </para>
/// <para>
/// The Authentication Data is a variable-length field containing an Integrity Check Value (ICV)
/// computed over the ESP packet minus the Authentication Data.
/// The length of the field is specified by the authentication function selected.
/// The Authentication Data field is optional, and is included only if the authentication service has been selected for the SA in question.
/// The authentication algorithm specification must specify the length of the ICV and the comparison rules and processing steps for validation.
/// </para>
/// </summary>
public DataSegment EncryptedDataAndAuthenticationData { get; private set; }
internal static IpV6ExtensionHeaderEncapsulatingSecurityPayload CreateInstance(DataSegment extensionHeaderData, out int numBytesRead)
{
if (extensionHeaderData.Length < MinimumLength)
{
numBytesRead = 0;
return null;
}
uint securityParametersIndex = extensionHeaderData.ReadUInt(Offset.SecurityParametersIndex, Endianity.Big);
uint sequenceNumber = extensionHeaderData.ReadUInt(Offset.SequenceNumber, Endianity.Big);
DataSegment encryptedDataAndAuthenticationData = extensionHeaderData.Subsegment(Offset.PayloadData, extensionHeaderData.Length - Offset.PayloadData);
numBytesRead = extensionHeaderData.Length;
return new IpV6ExtensionHeaderEncapsulatingSecurityPayload(securityParametersIndex, sequenceNumber, encryptedDataAndAuthenticationData);
}
}
}
\ No newline at end of file
......@@ -318,6 +318,7 @@
<Compile Include="Igmp\IIgmpLayerWithGroupAddress.cs" />
<Compile Include="IpV6\IpV6CalipsoDomainOfInterpretation.cs" />
<Compile Include="IpV6\IpV6ExtensionHeader.cs" />
<Compile Include="IpV6\IpV6ExtensionHeaderEncapsulatingSecurityPayload.cs" />
<Compile Include="IpV6\IpV6ExtensionHeaderFragmentData.cs" />
<Compile Include="IpV6\IpV6ExtensionHeaderHopByHopOptions.cs" />
<Compile Include="IpV6\IpV6ExtensionHeaderRouting.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