Commit 5a676ce0 authored by Brickner_cp's avatar Brickner_cp

IPv6

parent 3cd99e60
...@@ -43,6 +43,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -43,6 +43,7 @@ namespace PcapDotNet.Packets.IpV6
case IpV4Protocol.IpV6Route: // 43 case IpV4Protocol.IpV6Route: // 43
case IpV4Protocol.FragmentHeaderForIpV6: // 44 case IpV4Protocol.FragmentHeaderForIpV6: // 44
case IpV4Protocol.IpV6Opts: // 60 case IpV4Protocol.IpV6Opts: // 60
case IpV4Protocol.MobilityHeader: // 135
return CreateStandardInstance(nextHeader, extensionHeaderData, out numBytesRead); return CreateStandardInstance(nextHeader, extensionHeaderData, out numBytesRead);
case IpV4Protocol.EncapsulatingSecurityPayload: // 50 case IpV4Protocol.EncapsulatingSecurityPayload: // 50
...@@ -50,13 +51,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -50,13 +51,7 @@ namespace PcapDotNet.Packets.IpV6
case IpV4Protocol.AuthenticationHeader: // 51 case IpV4Protocol.AuthenticationHeader: // 51
return IpV6ExtensionHeaderAuthentication.CreateInstance(extensionHeaderData, out numBytesRead); return IpV6ExtensionHeaderAuthentication.CreateInstance(extensionHeaderData, out numBytesRead);
/*
case IpV4Protocol.MobilityHeader: // 135
return IpV6MobilityExtensionHeader.Parse(data);
*/
default: default:
throw new InvalidOperationException("Invalid nextHeader value" + nextHeader); throw new InvalidOperationException("Invalid nextHeader value" + nextHeader);
} }
...@@ -90,6 +85,9 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -90,6 +85,9 @@ namespace PcapDotNet.Packets.IpV6
case IpV4Protocol.IpV6Opts: // 60 case IpV4Protocol.IpV6Opts: // 60
return IpV6ExtensionHeaderDestinationOptions.ParseData(nextNextHeader, data); return IpV6ExtensionHeaderDestinationOptions.ParseData(nextNextHeader, data);
case IpV4Protocol.MobilityHeader: // 135
return IpV6ExtensionHeaderMobility.ParseData(nextNextHeader, data);
default: default:
throw new InvalidOperationException("Invalid nextHeader value" + nextHeader); throw new InvalidOperationException("Invalid nextHeader value" + nextHeader);
} }
......
...@@ -79,4 +79,1201 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -79,4 +79,1201 @@ namespace PcapDotNet.Packets.IpV6
return new IpV6ExtensionHeaderFragmentData(nextHeader, fragmentOffset, moreFragments, identification); return new IpV6ExtensionHeaderFragmentData(nextHeader, fragmentOffset, moreFragments, identification);
} }
} }
public enum IpV6MobilityHeaderType : byte
{
/// <summary>
/// RFC 6275.
/// </summary>
BindingRefreshRequest = 0,
/// <summary>
/// RFC 6275.
/// </summary>
HomeTestInit = 1,
/// <summary>
/// RFC 6275.
/// </summary>
CareOfTestInit = 2,
/// <summary>
/// RFC 6275.
/// </summary>
HomeTest = 3,
/// <summary>
/// RFC6275
/// </summary>
CareOfTest = 4,
/// <summary>
/// RFC 6275.
/// </summary>
BindingUpdate = 5,
/// <summary>
/// RFC 6275.
/// </summary>
BindingAcknowledgement = 6,
/// <summary>
/// RFC 6275.
/// </summary>
BindingError = 7,
/// <summary>
/// RFC 5568.
/// </summary>
FastBindingUpdate = 8,
/// <summary>
/// RFC 5568.
/// </summary>
FastBindingAcknowledgment = 9,
/// <summary>
/// RFC 5568.
/// Deprecated.
/// </summary>
FastNeighborAdvertisement = 10,
/// <summary>
/// RFC 5096.
/// </summary>
ExperimentalMobilityHeader = 11,
/// <summary>
/// RFC 5142.
/// </summary>
HomeAgentSwitchMessage = 12,
/// <summary>
/// RFC 5847.
/// </summary>
HeartbeatMessage = 13,
/// <summary>
/// RFC 5568.
/// </summary>
HandoverInitiateMessage = 14,
/// <summary>
/// RFC 5568.
/// </summary>
HandoverAcknowledgeMessage = 15,
/// <summary>
/// RFC 5846.
/// </summary>
BindingRevocationMessage = 16,
/// <summary>
/// RFC-ietf-netext-pmip-lr-10.
/// </summary>
LocalizedRoutingInitiation = 17,
/// <summary>
/// RFC-ietf-netext-pmip-lr-10.
/// </summary>
LocalizedRoutingAcknowledgment = 18,
}
/// <summary>
/// RFC 3775, 6275.
/// <pre>
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | MH Type | Reserved |
/// +-----+-------------+-------------------------+
/// | 32 | Checksum |
/// +-----+---------------------------------------+
/// | 48 | Message Data |
/// | ... | ends with Mobility Options |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
public abstract class IpV6ExtensionHeaderMobility : IpV6ExtensionHeader
{
private static class DataOffset
{
public const int MobilityHeaderType = 0;
public const int Checksum = MobilityHeaderType + sizeof(byte) + sizeof(byte);
public const int MessageData = Checksum + sizeof(ushort);
}
public const int MinimumDataLength = DataOffset.MessageData;
public IpV6ExtensionHeaderMobility(IpV4Protocol nextHeader, ushort checksum, IpV6MobilityOptions mobilityOptions)
: base(nextHeader)
{
Checksum = checksum;
MobilityOptions = mobilityOptions;
}
/// <summary>
/// Identifies the particular mobility message in question.
/// An unrecognized MH Type field causes an error indication to be sent.
/// </summary>
public abstract IpV6MobilityHeaderType MobilityHeaderType { get; }
/// <summary>
/// <para>
/// Contains the checksum of the Mobility Header.
/// The checksum is calculated from the octet string consisting of a "pseudo-header"
/// followed by the entire Mobility Header starting with the Payload Proto field.
/// The checksum is the 16-bit one's complement of the one's complement sum of this string.
/// </para>
/// <para>
/// The pseudo-header contains IPv6 header fields.
/// The Next Header value used in the pseudo-header is 135.
/// The addresses used in the pseudo-header are the addresses that appear in the Source and Destination Address fields in the IPv6 packet
/// carrying the Mobility Header.
/// </para>
/// <para>
/// Note that the procedures of calculating upper-layer checksums while away from home apply even for the Mobility Header.
/// If a mobility message has a Home Address destination option, then the checksum calculation uses the home address in this option as the value of the IPv6 Source Address field.
/// </para>
/// <para>
/// The Mobility Header is considered as the upper-layer protocol for the purposes of calculating the pseudo-header.
/// The Upper-Layer Packet Length field in the pseudo-header MUST be set to the total length of the Mobility Header.
/// </para>
/// <para>
/// For computing the checksum, the checksum field is set to zero.
/// </para>
/// </summary>
public ushort Checksum { get; private set; }
/// <summary>
/// Zero or more TLV-encoded mobility options.
/// </summary>
public IpV6MobilityOptions MobilityOptions { get; private set; }
internal static IpV6ExtensionHeaderMobility ParseData(IpV4Protocol nextHeader, DataSegment data)
{
if (data.Length < MinimumDataLength)
return null;
IpV6MobilityHeaderType mobilityHeaderType = (IpV6MobilityHeaderType)data[DataOffset.MobilityHeaderType];
ushort checksum = data.ReadUShort(DataOffset.Checksum, Endianity.Big);
DataSegment messageData = data.Subsegment(DataOffset.MessageData, data.Length - DataOffset.MessageData);
switch (mobilityHeaderType)
{
case IpV6MobilityHeaderType.BindingRefreshRequest: // 0
return IpV6ExtensionHeaderMobilityBindingRefreshRequest.ParseMessageData(nextHeader, checksum, messageData);
case IpV6MobilityHeaderType.HomeTestInit: // 1
return IpV6ExtensionHeaderMobilityHomeTestInit.ParseMessageData(nextHeader, checksum, messageData);
case IpV6MobilityHeaderType.CareOfTestInit: // 2
return IpV6ExtensionHeaderMobilityCareOfTestInit.ParseMessageData(nextHeader, checksum, messageData);
case IpV6MobilityHeaderType.HomeTest: // 3
return IpV6ExtensionHeaderMobilityHomeTest.ParseMessageData(nextHeader, checksum, messageData);
case IpV6MobilityHeaderType.CareOfTest: // 4
return IpV6ExtensionHeaderMobilityCareOfTest.ParseMessageData(nextHeader, checksum, messageData);
case IpV6MobilityHeaderType.BindingUpdate: // 5
return IpV6ExtensionHeaderMobilityBindingUpdate.ParseMessageData(nextHeader, checksum, messageData);
case IpV6MobilityHeaderType.BindingAcknowledgement: // 6
return IpV6ExtensionHeaderMobilityBindingAcknowledgement.ParseMessageData(nextHeader, checksum, messageData);
case IpV6MobilityHeaderType.BindingError: // 7
case IpV6MobilityHeaderType.FastBindingUpdate: // 8
case IpV6MobilityHeaderType.FastBindingAcknowledgment: // 9
case IpV6MobilityHeaderType.FastNeighborAdvertisement: // 10
case IpV6MobilityHeaderType.ExperimentalMobilityHeader: // 11
case IpV6MobilityHeaderType.HomeAgentSwitchMessage: // 12
case IpV6MobilityHeaderType.HeartbeatMessage: // 13
case IpV6MobilityHeaderType.HandoverInitiateMessage: // 14
case IpV6MobilityHeaderType.HandoverAcknowledgeMessage: // 15
case IpV6MobilityHeaderType.BindingRevocationMessage: // 16
case IpV6MobilityHeaderType.LocalizedRoutingInitiation: // 17
case IpV6MobilityHeaderType.LocalizedRoutingAcknowledgment: // 18
default:
return null;
}
}
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | MH Type | Reserved |
/// +-----+-------------+-------------------------+
/// | 32 | Checksum |
/// +-----+---------------------------------------+
/// | 48 | Reserved |
/// +-----+---------------------------------------+
/// | 64 | Mobility Options |
/// | ... | |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderMobilityBindingRefreshRequest : IpV6ExtensionHeaderMobility
{
private static class MessageDataOffset
{
public const int Options = 2;
}
public const int MinimumMessageDataLength = MessageDataOffset.Options;
public IpV6ExtensionHeaderMobilityBindingRefreshRequest(IpV4Protocol nextHeader, ushort checksum, IpV6MobilityOptions options)
: base(nextHeader, checksum, options)
{
}
/// <summary>
/// Identifies the particular mobility message in question.
/// An unrecognized MH Type field causes an error indication to be sent.
/// </summary>
public override IpV6MobilityHeaderType MobilityHeaderType
{
get { return IpV6MobilityHeaderType.BindingRefreshRequest; }
}
internal static IpV6ExtensionHeaderMobilityBindingRefreshRequest ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{
if (messageData.Length < MinimumMessageDataLength)
return null;
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityBindingRefreshRequest(nextHeader, checksum, options);
}
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | MH Type | Reserved |
/// +-----+-------------+-------------------------+
/// | 32 | Checksum |
/// +-----+---------------------------------------+
/// | 48 | Reserved |
/// +-----+---------------------------------------+
/// | 64 | Home Init Cookie |
/// | | |
/// | | |
/// | | |
/// +-----+---------------------------------------+
/// | 128 | Mobility Options |
/// | ... | |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderMobilityHomeTestInit : IpV6ExtensionHeaderMobility
{
private static class MessageDataOffset
{
public const int HomeInitCookie = 2;
public const int Options = HomeInitCookie + sizeof(ulong);
}
public const int MinimumMessageDataLength = MessageDataOffset.Options;
public IpV6ExtensionHeaderMobilityHomeTestInit(IpV4Protocol nextHeader, ushort checksum, ulong homeInitCookie, IpV6MobilityOptions options)
: base(nextHeader, checksum, options)
{
HomeInitCookie = homeInitCookie;
}
/// <summary>
/// Identifies the particular mobility message in question.
/// An unrecognized MH Type field causes an error indication to be sent.
/// </summary>
public override IpV6MobilityHeaderType MobilityHeaderType
{
get { return IpV6MobilityHeaderType.HomeTestInit; }
}
/// <summary>
/// Contains a random value, the home init cookie.
/// </summary>
public ulong HomeInitCookie { get; private set; }
internal static IpV6ExtensionHeaderMobilityHomeTestInit ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{
if (messageData.Length < MinimumMessageDataLength)
return null;
ulong homeInitCookie = messageData.ReadULong(MessageDataOffset.HomeInitCookie, Endianity.Big);
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityHomeTestInit(nextHeader, checksum, homeInitCookie, options);
}
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | MH Type | Reserved |
/// +-----+-------------+-------------------------+
/// | 32 | Checksum |
/// +-----+---------------------------------------+
/// | 48 | Reserved |
/// +-----+---------------------------------------+
/// | 64 | Care-of Init Cookie |
/// | | |
/// | | |
/// | | |
/// +-----+---------------------------------------+
/// | 128 | Mobility Options |
/// | ... | |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderMobilityCareOfTestInit : IpV6ExtensionHeaderMobility
{
private static class MessageDataOffset
{
public const int CareOfInitCookie = 2;
public const int Options = CareOfInitCookie + sizeof(ulong);
}
public const int MinimumMessageDataLength = MessageDataOffset.Options;
public IpV6ExtensionHeaderMobilityCareOfTestInit(IpV4Protocol nextHeader, ushort checksum, ulong careOfInitCookie, IpV6MobilityOptions options)
: base(nextHeader, checksum, options)
{
CareOfInitCookie = careOfInitCookie;
}
/// <summary>
/// Identifies the particular mobility message in question.
/// An unrecognized MH Type field causes an error indication to be sent.
/// </summary>
public override IpV6MobilityHeaderType MobilityHeaderType
{
get { return IpV6MobilityHeaderType.CareOfTestInit; }
}
/// <summary>
/// Contains a random value, the care-of init cookie.
/// </summary>
public ulong CareOfInitCookie { get; private set; }
internal static IpV6ExtensionHeaderMobilityCareOfTestInit ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{
if (messageData.Length < MinimumMessageDataLength)
return null;
ulong careOfInitCookie = messageData.ReadULong(MessageDataOffset.CareOfInitCookie, Endianity.Big);
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityCareOfTestInit(nextHeader, checksum, careOfInitCookie, options);
}
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | MH Type | Reserved |
/// +-----+-------------+-------------------------+
/// | 32 | Checksum |
/// +-----+---------------------------------------+
/// | 48 | Home Nonce Index |
/// +-----+---------------------------------------+
/// | 64 | Home Init Cookie |
/// | | |
/// | | |
/// | | |
/// +-----+---------------------------------------+
/// | 128 | Home Keygen Token |
/// | | |
/// | | |
/// | | |
/// +-----+---------------------------------------+
/// | 192 | Mobility Options |
/// | ... | |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderMobilityHomeTest : IpV6ExtensionHeaderMobility
{
private static class MessageDataOffset
{
public const int HomeNonceIndex = 0;
public const int HomeInitCookie = HomeNonceIndex + sizeof(ushort);
public const int HomeKeygenToken = HomeInitCookie + sizeof(ulong);
public const int Options = HomeKeygenToken + sizeof(ulong);
}
public const int MinimumMessageDataLength = MessageDataOffset.Options;
public IpV6ExtensionHeaderMobilityHomeTest(IpV4Protocol nextHeader, ushort checksum, ushort homeNonceIndex, ulong homeInitCookie, ulong homeKeygenToken,
IpV6MobilityOptions options)
: base(nextHeader, checksum, options)
{
HomeNonceIndex = homeNonceIndex;
HomeInitCookie = homeInitCookie;
HomeKeygenToken = homeKeygenToken;
}
/// <summary>
/// Identifies the particular mobility message in question.
/// An unrecognized MH Type field causes an error indication to be sent.
/// </summary>
public override IpV6MobilityHeaderType MobilityHeaderType
{
get { return IpV6MobilityHeaderType.HomeTest; }
}
/// <summary>
/// Will be echoed back by the mobile node to the correspondent node in a subsequent Binding Update.
/// </summary>
public ushort HomeNonceIndex { get; private set; }
/// <summary>
/// Contains the home init cookie.
/// </summary>
public ulong HomeInitCookie { get; private set; }
/// <summary>
/// Contains the 64-bit home keygen token used in the return routability procedure.
/// </summary>
public ulong HomeKeygenToken { get; private set; }
internal static IpV6ExtensionHeaderMobilityHomeTest ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{
if (messageData.Length < MinimumMessageDataLength)
return null;
ushort homeNonceIndex = messageData.ReadUShort(MessageDataOffset.HomeNonceIndex, Endianity.Big);
ushort homeInitCookie = messageData.ReadUShort(MessageDataOffset.HomeInitCookie, Endianity.Big);
ushort homeKeygenToken = messageData.ReadUShort(MessageDataOffset.HomeKeygenToken, Endianity.Big);
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityHomeTest(nextHeader, checksum, homeNonceIndex, homeInitCookie, homeKeygenToken, options);
}
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | MH Type | Reserved |
/// +-----+-------------+-------------------------+
/// | 32 | Checksum |
/// +-----+---------------------------------------+
/// | 48 | Care-of Nonce Index |
/// +-----+---------------------------------------+
/// | 64 | Care-of Init Cookie |
/// | | |
/// | | |
/// | | |
/// +-----+---------------------------------------+
/// | 128 | Care-of Keygen Token |
/// | | |
/// | | |
/// | | |
/// +-----+---------------------------------------+
/// | 192 | Mobility Options |
/// | ... | |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderMobilityCareOfTest : IpV6ExtensionHeaderMobility
{
private static class MessageDataOffset
{
public const int CareOfNonceIndex = 0;
public const int CareOfInitCookie = CareOfNonceIndex + sizeof(ushort);
public const int CareOfKeygenToken = CareOfInitCookie + sizeof(ulong);
public const int Options = CareOfKeygenToken + sizeof(ulong);
}
public const int MinimumMessageDataLength = MessageDataOffset.Options;
public IpV6ExtensionHeaderMobilityCareOfTest(IpV4Protocol nextHeader, ushort checksum, ushort careOfNonceIndex, ulong careOfInitCookie,
ulong careOfKeygenToken, IpV6MobilityOptions options)
: base(nextHeader, checksum, options)
{
CareOfNonceIndex = careOfNonceIndex;
CareOfInitCookie = careOfInitCookie;
CareOfKeygenToken = careOfKeygenToken;
}
/// <summary>
/// Identifies the particular mobility message in question.
/// An unrecognized MH Type field causes an error indication to be sent.
/// </summary>
public override IpV6MobilityHeaderType MobilityHeaderType
{
get { return IpV6MobilityHeaderType.CareOfTest; }
}
/// <summary>
/// Will be echoed back by the mobile node to the correspondent node in a subsequent Binding Update.
/// </summary>
public ushort CareOfNonceIndex { get; private set; }
/// <summary>
/// Contains the care-of init cookie.
/// </summary>
public ulong CareOfInitCookie { get; private set; }
/// <summary>
/// Contains the 64-bit care-of keygen token used in the return routability procedure.
/// </summary>
public ulong CareOfKeygenToken { get; private set; }
internal static IpV6ExtensionHeaderMobilityCareOfTest ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{
if (messageData.Length < MinimumMessageDataLength)
return null;
ushort careOfNonceIndex = messageData.ReadUShort(MessageDataOffset.CareOfNonceIndex, Endianity.Big);
ushort careOfInitCookie = messageData.ReadUShort(MessageDataOffset.CareOfInitCookie, Endianity.Big);
ushort careOfKeygenToken = messageData.ReadUShort(MessageDataOffset.CareOfKeygenToken, Endianity.Big);
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityCareOfTest(nextHeader, checksum, careOfNonceIndex, careOfInitCookie, careOfKeygenToken, options);
}
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+---+---+---+---+-----+-------------------------+
/// | Bit | 0 | 1 | 2 | 3 | 4-7 | 8-15 |
/// +-----+---+---+---+---+-----+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+---------------------+-------------------------+
/// | 16 | MH Type | Reserved |
/// +-----+---------------------+-------------------------+
/// | 32 | Checksum |
/// +-----+-----------------------------------------------+
/// | 48 | Sequence # |
/// +-----+---+---+---+---+-------------------------------+
/// | 64 | A | H | L | K | Reserved |
/// +-----+---+---+---+---+-------------------------------+
/// | 80 | Lifetime |
/// +-----+-----------------------------------------------+
/// | 96 | Mobility Options |
/// | ... | |
/// +-----+-----------------------------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderMobilityBindingUpdate : IpV6ExtensionHeaderMobility
{
private static class MessageDataOffset
{
public const int SequenceNumber = 0;
public const int Acknowledge = SequenceNumber + sizeof(ushort);
public const int HomeRegistration = Acknowledge;
public const int LinkLocalAddressCompatibility = HomeRegistration;
public const int KeyManagementMobilityCapability = LinkLocalAddressCompatibility;
public const int Lifetime = KeyManagementMobilityCapability + sizeof(byte) + sizeof(byte);
public const int Options = Lifetime + sizeof(ushort);
}
private static class MessageDataMask
{
public const byte Acknowledge = 0x80;
public const byte HomeRegistration = 0x40;
public const byte LinkLocalAddressCompatibility = 0x20;
public const byte KeyManagementMobilityCapability = 0x10;
}
public const int MinimumMessageDataLength = MessageDataOffset.Options;
public IpV6ExtensionHeaderMobilityBindingUpdate(IpV4Protocol nextHeader, ushort checksum, ushort sequenceNumber, bool acknowledge, bool homeRegistration,
bool linkLocalAddressCompatibility, bool keyManagementMobilityCapability, ushort lifetime,
IpV6MobilityOptions options)
: base(nextHeader, checksum, options)
{
SequenceNumber = sequenceNumber;
Acknowledge = acknowledge;
HomeRegistration = homeRegistration;
LinkLocalAddressCompatibility = linkLocalAddressCompatibility;
KeyManagementMobilityCapability = keyManagementMobilityCapability;
Lifetime = lifetime;
}
/// <summary>
/// Identifies the particular mobility message in question.
/// An unrecognized MH Type field causes an error indication to be sent.
/// </summary>
public override IpV6MobilityHeaderType MobilityHeaderType
{
get { return IpV6MobilityHeaderType.BindingUpdate; }
}
/// <summary>
/// Used by the receiving node to sequence Binding Updates and by the sending node to match a returned Binding Acknowledgement with this Binding Update.
/// </summary>
public ushort SequenceNumber { get; private set; }
/// <summary>
/// Set by the sending mobile node to request a Binding Acknowledgement be returned upon receipt of the Binding Update.
/// </summary>
public bool Acknowledge { get; private set; }
/// <summary>
/// Set by the sending mobile node to request that the receiving node should act as this node's home agent.
/// The destination of the packet carrying this message must be that of a router sharing the same subnet prefix as the home address
/// of the mobile node in the binding.
/// </summary>
public bool HomeRegistration { get; private set; }
/// <summary>
/// Set when the home address reported by the mobile node has the same interface identifier as the mobile node's link-local address.
/// </summary>
public bool LinkLocalAddressCompatibility { get; private set; }
/// <summary>
/// <para>
/// If this is cleared, the protocol used for establishing the IPsec security associations between the mobile node and the home agent
/// does not survive movements.
/// It may then have to be rerun. (Note that the IPsec security associations themselves are expected to survive movements.)
/// If manual IPsec configuration is used, the bit must be cleared.
/// </para>
/// <para>
/// This bit is valid only in Binding Updates sent to the home agent, and mustbe cleared in other Binding Updates.
/// Correspondent nodes must ignore this bit.
/// </para>
/// </summary>
public bool KeyManagementMobilityCapability { get; private set; }
/// <summary>
/// The number of time units remaining before the binding must be considered expired.
/// A value of zero indicates that the Binding Cache entry for the mobile node must be deleted.
/// One time unit is 4 seconds.
/// </summary>
public ushort Lifetime { get; private set; }
internal static IpV6ExtensionHeaderMobilityBindingUpdate ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{
if (messageData.Length < MinimumMessageDataLength)
return null;
ushort sequenceNumber = messageData.ReadUShort(MessageDataOffset.SequenceNumber, Endianity.Big);
bool acknowledge = messageData.ReadBool(MessageDataOffset.Acknowledge, MessageDataMask.Acknowledge);
bool homeRegistration = messageData.ReadBool(MessageDataOffset.HomeRegistration, MessageDataMask.HomeRegistration);
bool linkLocalAddressCompatibility = messageData.ReadBool(MessageDataOffset.LinkLocalAddressCompatibility,
MessageDataMask.LinkLocalAddressCompatibility);
bool keyManagementMobilityCapability = messageData.ReadBool(MessageDataOffset.KeyManagementMobilityCapability,
MessageDataMask.KeyManagementMobilityCapability);
ushort lifetime = messageData.ReadUShort(MessageDataOffset.Lifetime, Endianity.Big);
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityBindingUpdate(nextHeader, checksum, sequenceNumber, acknowledge, homeRegistration,
linkLocalAddressCompatibility, keyManagementMobilityCapability, lifetime, options);
}
}
public enum IpV6BindingAcknowledgementStatus : byte
{
/// <summary>
/// RFCs 5213, 6275.
/// </summary>
BindingUpdateAcceptedProxyBindingUpdateAccepted = 0,
/// <summary>
/// RFC 6275.
/// </summary>
AcceptedButPrefixDiscoveryNecessary = 1,
/// <summary>
/// RFC 5845.
/// </summary>
GreKeyOptionNotRequired = 2,
/// <summary>
/// RFC 5845.
/// </summary>
GreTunnelingButTlvHeaderNotSupported = 3,
/// <summary>
/// RFC 5648.
/// </summary>
McoaNotComplete = 4,
/// <summary>
/// RFC 5648.
/// </summary>
McoaReturnHomeWoNdp = 5,
/// <summary>
/// RFC 6058.
/// </summary>
PbuAcceptedTbIgnoredSettingsMistmatch = 6,
/// <summary>
/// RFC 6275.
/// </summary>
ReasonUnspecified = 128,
/// <summary>
/// RFC 6275.
/// </summary>
AdministrativelyProhibited = 129,
/// <summary>
/// RFC 6275.
/// </summary>
InsufficientResources = 130,
/// <summary>
/// RFC 6275.
/// </summary>
HomeRegistrationNotSupported = 131,
/// <summary>
/// RFC 6275.
/// </summary>
NotHomeSubnet = 132,
/// <summary>
/// RFC 6275.
/// </summary>
NotHomeAgentForThisMobileNode = 133,
/// <summary>
/// RFC 6275.
/// </summary>
DuplicateAddressDetectionFailed = 134,
/// <summary>
/// RFC 6275.
/// </summary>
SequenceNumberOutOfWindow = 135,
/// <summary>
/// RFC 6275.
/// </summary>
ExpiredHomeNonceIndex = 136,
/// <summary>
/// RFC 6275.
/// </summary>
ExpiredCareOfNonceIndex = 137,
/// <summary>
/// RFC 6275.
/// </summary>
ExpiredNonces = 138,
/// <summary>
/// RFC 6275.
/// </summary>
RegistrationTypeChangeDisallowed = 139,
/// <summary>
/// RFC 3963.
/// </summary>
MobileRouterOperationNotPermitted = 140,
/// <summary>
/// RFC 3963.
/// </summary>
InvalidPrefix = 141,
/// <summary>
/// RFC 3963.
/// </summary>
NotAuthorizedForPrefix = 142,
/// <summary>
/// RFC 3963.
/// </summary>
ForwardingSetupFailed = 143,
/// <summary>
/// RFC 4285.
/// </summary>
MIpV6IdMismatch = 144,
/// <summary>
/// RFC 4285.
/// </summary>
MIpV6MesgIdReqd = 145,
/// <summary>
/// RFC 4285.
/// </summary>
MIpV6AuthFail = 146,
/// <summary>
/// RFC 4866.
/// </summary>
PermanentHomeKeygenTokenUnavailable = 147,
/// <summary>
/// RFC 4866.
/// </summary>
CgaAndSignatureVerificationFailed = 148,
/// <summary>
/// RFC 4866.
/// </summary>
PermanentHomeKeygenTokenExists = 149,
/// <summary>
/// RFC 4866.
/// </summary>
NonNullHomeNonceIndexExpected = 150,
/// <summary>
/// RFC 5149.
/// </summary>
ServiceAuthorizationFailed = 151,
/// <summary>
/// RFC 5213.
/// </summary>
ProxyRegNotEnabled = 152,
/// <summary>
/// RFC 5213.
/// </summary>
NotLmaForThisMobileNode = 153,
/// <summary>
/// RFC 5213.
/// </summary>
MagNotAuthorizedForProxyReg = 154,
/// <summary>
/// RFC 5213.
/// </summary>
NotAuthorizedForHomeNetworkPrefix = 155,
/// <summary>
/// RFC 5213.
/// </summary>
TimestampMismatch = 156,
/// <summary>
/// RFC 5213.
/// </summary>
TimestampLowerThanPrevAccepted = 157,
/// <summary>
/// RFC 5213.
/// </summary>
MissingHomeNetworkPrefixOption = 158,
/// <summary>
/// RFC 5213.
/// </summary>
BcePbuPrefixSetDoNotMatch = 159,
/// <summary>
/// RFC 5213.
/// </summary>
MissingMnIdentifierOption = 160,
/// <summary>
/// RFC 5213.
/// </summary>
MissingHandoffIndicatorOption = 161,
/// <summary>
/// RFC 5213.
/// </summary>
MissingAccessTechTypeOption = 162,
/// <summary>
/// RFC 5845.
/// </summary>
GreKeyOptionRequired = 163,
/// <summary>
/// RFC 5648.
/// </summary>
McoaMalformed = 164,
/// <summary>
/// RFC 5648.
/// </summary>
McoaNonMcoaBindingExists = 165,
/// <summary>
/// RFC 5648.
/// </summary>
McoaProhibited = 166,
/// <summary>
/// RFC 5648.
/// </summary>
McoaUnknownCoa = 167,
/// <summary>
/// RFC 5648.
/// </summary>
McoaBulkRegistarationProhiited = 168,
/// <summary>
/// RFC 5648.
/// </summary>
McoaSimultaneousHomeAndForeignProhibited = 169,
/// <summary>
/// RFC 5844.
/// </summary>
NotAuthorizedForIpV4MobilityService = 170,
/// <summary>
/// RFC 5844.
/// </summary>
NotAuthorizedForIpV4HomeAddress = 171,
/// <summary>
/// RFC 5844.
/// </summary>
NotAuthorizedForIpV6MobilityService = 172,
/// <summary>
/// RFC 5844.
/// </summary>
MultipleIpV4HomeAddressAssignmentNotSupported = 173,
/// <summary>
/// RFC 6275.
/// </summary>
InvalidCareOfAddress = 174,
/// <summary>
/// RFC 6602.
/// </summary>
InvalidMobileNodeGroupIdentifier = 175,
/// <summary>
/// RFC 6618.
/// </summary>
ReinitSaWithHac = 176,
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+-------------+---+---------------------+
/// | Bit | 0-7 | 8 | 9-15 |
/// +-----+-------------+---+---------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | MH Type | Reserved |
/// +-----+-------------+-------------------------+
/// | 32 | Checksum |
/// +-----+-------------+---+---------------------+
/// | 48 | Status | K | Reserved |
/// +-----+-------------+---+---------------------+
/// | 64 | Sequence # |
/// +-----+---------------------------------------+
/// | 80 | Lifetime |
/// +-----+---------------------------------------+
/// | 96 | Mobility Options |
/// | ... | |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderMobilityBindingAcknowledgement : IpV6ExtensionHeaderMobility
{
private static class MessageDataOffset
{
public const int Status = 0;
public const int KeyManagementMobilityCapability = Status + sizeof(byte);
public const int SequenceNumber = KeyManagementMobilityCapability + sizeof(byte);
public const int Lifetime = SequenceNumber + sizeof(ushort);
public const int Options = Lifetime + sizeof(ushort);
}
private static class MessageDataMask
{
public const byte KeyManagementMobilityCapability = 0x80;
}
public const int MinimumMessageDataLength = MessageDataOffset.Options;
public IpV6ExtensionHeaderMobilityBindingAcknowledgement(IpV4Protocol nextHeader, ushort checksum, IpV6BindingAcknowledgementStatus status,
bool keyManagementMobilityCapability, ushort sequenceNumber, ushort lifetime,
IpV6MobilityOptions options)
: base(nextHeader, checksum, options)
{
Status = status;
KeyManagementMobilityCapability = keyManagementMobilityCapability;
SequenceNumber = sequenceNumber;
Lifetime = lifetime;
}
/// <summary>
/// Identifies the particular mobility message in question.
/// An unrecognized MH Type field causes an error indication to be sent.
/// </summary>
public override IpV6MobilityHeaderType MobilityHeaderType
{
get { return IpV6MobilityHeaderType.BindingAcknowledgement; }
}
/// <summary>
/// Indicating the disposition of the Binding Update.
/// Values of the Status field less than 128 indicate that the Binding Update was accepted by the receiving node.
/// Values greater than or equal to 128 indicate that the Binding Update was rejected by the receiving node.
/// </summary>
public IpV6BindingAcknowledgementStatus Status { get; private set; }
/// <summary>
/// <para>
/// If this is cleared, the protocol used by the home agent for establishing the IPsec security associations between the mobile node and the home agent
/// does not survive movements.
/// It may then have to be rerun.
/// (Note that the IPsec security associations themselves are expected to survive movements.)
/// </para>
/// <para>
/// Correspondent nodes must set the K bit to 0.
/// </para>
/// </summary>
public bool KeyManagementMobilityCapability { get; private set; }
/// <summary>
/// Copied from the Sequence Number field in the Binding Update.
/// It is used by the mobile node in matching this Binding Acknowledgement with an outstanding Binding Update.
/// </summary>
public ushort SequenceNumber { get; private set; }
/// <summary>
/// <para>
/// The granted lifetime, in time units of 4 seconds, for which this node should retain the entry for this mobile node in its Binding Cache.
/// </para>
/// <para>
/// The value of this field is undefined if the Status field indicates that the Binding Update was rejected.
/// </para>
/// </summary>
public ushort Lifetime { get; private set; }
internal static IpV6ExtensionHeaderMobilityBindingAcknowledgement ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{
if (messageData.Length < MinimumMessageDataLength)
return null;
IpV6BindingAcknowledgementStatus status = (IpV6BindingAcknowledgementStatus)messageData[MessageDataOffset.Status];
bool keyManagementMobilityCapability = messageData.ReadBool(MessageDataOffset.KeyManagementMobilityCapability,
MessageDataMask.KeyManagementMobilityCapability);
ushort sequenceNumber = messageData.ReadUShort(MessageDataOffset.SequenceNumber, Endianity.Big);
ushort lifetime = messageData.ReadUShort(MessageDataOffset.Lifetime, Endianity.Big);
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityBindingAcknowledgement(nextHeader, checksum, status, keyManagementMobilityCapability, sequenceNumber, lifetime,
options);
}
}
public enum IpV6BindingErrorStatus : byte
{
/// <summary>
/// RFC 6275.
/// </summary>
UnknownBindingForHomeAddressDestinationOption = 1,
/// <summary>
/// RFC 6275.
/// </summary>
UnrecognizedMhTypeValue = 2,
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | MH Type | Reserved |
/// +-----+-------------+-------------------------+
/// | 32 | Checksum |
/// +-----+-------------+-------------------------+
/// | 48 | Status | Reserved |
/// +-----+-------------+-------------------------+
/// | 64 | Home Address |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// +-----+---------------------------------------+
/// | 192 | Mobility Options |
/// | ... | |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
public class IpV6ExtensionHeaderMobilityBindingError : IpV6ExtensionHeaderMobility
{
private static class MessageDataOffset
{
public const int Status = 0;
public const int HomeAddress = Status + sizeof(byte) + sizeof(byte);
public const int Options = HomeAddress + IpV6Address.SizeOf;
}
public const int MinimumMessageDataLength = MessageDataOffset.Options;
public IpV6ExtensionHeaderMobilityBindingError(IpV4Protocol nextHeader, ushort checksum, IpV6BindingErrorStatus status, IpV6Address homeAddress,
IpV6MobilityOptions options)
: base(nextHeader, checksum, options)
{
Status = status;
HomeAddress = homeAddress;
}
/// <summary>
/// Identifies the particular mobility message in question.
/// An unrecognized MH Type field causes an error indication to be sent.
/// </summary>
public override IpV6MobilityHeaderType MobilityHeaderType
{
get { return IpV6MobilityHeaderType.BindingError; }
}
/// <summary>
/// Indicating the reason for this message.
/// </summary>
public IpV6BindingErrorStatus Status { get; private set; }
/// <summary>
/// The home address that was contained in the Home Address destination option.
/// The mobile node uses this information to determine which binding does not exist, in cases where the mobile node has several home addresses.
/// </summary>
public IpV6Address HomeAddress { get; private set; }
internal static IpV6ExtensionHeaderMobilityBindingError ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{
if (messageData.Length < MinimumMessageDataLength)
return null;
IpV6BindingErrorStatus status = (IpV6BindingErrorStatus)messageData[MessageDataOffset.Status];
IpV6Address homeAddress = messageData.ReadIpV6Address(MessageDataOffset.HomeAddress, Endianity.Big);
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityBindingError(nextHeader, checksum, status, homeAddress, options);
}
}
} }
\ No newline at end of file
...@@ -39,4 +39,42 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -39,4 +39,42 @@ namespace PcapDotNet.Packets.IpV6
get { return sizeof(byte); } get { return sizeof(byte); }
} }
} }
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Option Type | Opt Data Len (optional) |
/// +-----+-------------+-------------------------+
/// | 16 | Option Data (optional) |
/// | ... | |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
public abstract class IpV6MobilityOption : Option
{
/// <summary>
/// The type of the IP option.
/// </summary>
public IpV6MobilityOptionType OptionType { get; private set; }
internal abstract IpV6MobilityOption CreateInstance(DataSegment data);
protected IpV6MobilityOption(IpV6MobilityOptionType type)
{
OptionType = type;
}
internal override void Write(byte[] buffer, ref int offset)
{
buffer[offset++] = (byte)OptionType;
}
public override int Length
{
get { return sizeof(byte); }
}
}
} }
\ No newline at end of file
...@@ -36,4 +36,41 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -36,4 +36,41 @@ namespace PcapDotNet.Packets.IpV6
internal abstract void WriteData(byte[] buffer, ref int offset); internal abstract void WriteData(byte[] buffer, ref int offset);
} }
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Option Data |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
public abstract class IpV6MobilityOptionComplex : IpV6MobilityOption
{
protected IpV6MobilityOptionComplex(IpV6MobilityOptionType type)
: base(type)
{
}
public override sealed int Length
{
get { return base.Length + sizeof(byte) + DataLength; }
}
internal abstract int DataLength { get; }
internal override sealed void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer[offset++] = (byte)DataLength;
WriteData(buffer, ref offset);
}
internal abstract void WriteData(byte[] buffer, ref int offset);
}
} }
\ No newline at end of file
...@@ -22,4 +22,28 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -22,4 +22,28 @@ namespace PcapDotNet.Packets.IpV6
return new IpV6OptionPad1(); return new IpV6OptionPad1();
} }
} }
/// <summary>
/// RFC 6275.
/// +-----+-----+
/// | Bit | 0-7 |
/// +-----+-----+
/// | 0 | 0 |
/// +-----+-----+
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.Pad1)]
public class IpV6MobilityOptionPad1 : IpV6MobilityOption
{
public const int OptionLength = sizeof(byte);
public IpV6MobilityOptionPad1()
: base(IpV6MobilityOptionType.Pad1)
{
}
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
return new IpV6MobilityOptionPad1();
}
}
} }
\ No newline at end of file
...@@ -67,4 +67,301 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -67,4 +67,301 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
LineIdentification = 0x8C, LineIdentification = 0x8C,
} }
}
\ No newline at end of file public enum IpV6MobilityOptionType : byte
{
/// <summary>
/// RFC 6275.
/// </summary>
Pad1 = 0x00,
/// <summary>
/// RFC 6275.
/// </summary>
PadN = 0x01,
/// <summary>
/// RFC 6275.
/// </summary>
BindingRefreshAdvice = 0x02,
/// <summary>
/// RFC 6275.
/// Alternate Care-of Address.
/// </summary>
AlternateCareOfAddress = 0x03,
/// <summary>
/// RFC 6275.
/// </summary>
NonceIndices = 0x04,
/// <summary>
/// RFC 6275.
/// </summary>
AuthorizationData = 0x05,
/// <summary>
/// RFC 3963.
/// Mobile Network Prefix Option.
/// </summary>
MobileNetworkPrefix = 0x06,
/// <summary>
/// RFC 5568.
/// Mobility Header Link-Layer Address option.
/// </summary>
MobilityHeaderLinkLayerAddress = 0x07,
/// <summary>
/// RFC 4283.
/// MN-ID-OPTION-TYPE.
/// </summary>
MnId = 0x08,
/// <summary>
/// RFC 4285.
/// AUTH-OPTION-TYPE.
/// </summary>
Auth = 0x09,
/// <summary>
/// RFC 4285.
/// MESG-ID-OPTION-TYPE
/// </summary>
MesgId = 0x0A,
/// <summary>
/// RFC 4866.
/// CGA Parameters Request.
/// </summary>
CgaParametersRequest = 0x0B,
/// <summary>
/// RFC 4866.
/// CGA Parameters.
/// </summary>
CgaParameters = 0x0C,
/// <summary>
/// RFC 4866.
/// </summary>
Signature = 0x0D,
/// <summary>
/// RFC 4866.
/// </summary>
PermanentHomeKeygenToken = 0x0E,
/// <summary>
/// RFC 4866.
/// Care-of Test Init
/// </summary>
CareOfTestInit = 0x0F,
/// <summary>
/// RFC 4866.
/// Care-of Test.
/// </summary>
CareOfTest = 0x10,
/// <summary>
/// RFC 5026.
/// DNS-UPDATE-TYPE.
/// </summary>
DnsUpdateType = 0x11,
/// <summary>
/// RFC 5096.
/// Experimental Mobility Option.
/// </summary>
ExperimentalMobilityOption = 0x12,
/// <summary>
/// RFC 5094.
/// </summary>
VendorSpecificMobilityOption = 0x13,
/// <summary>
/// RFC 5149.
/// </summary>
ServiceSelectionMobilityOption = 0x14,
/// <summary>
/// RFC 5568.
/// Binding Authorization Data for FMIPv6 (BADF).
/// </summary>
BindingAuthorizationDataForFmIpV6 = 0x15,
/// <summary>
/// RFC 5213.
/// </summary>
HomeNetworkPrefixOption = 0x16,
/// <summary>
/// RFC 5213.
/// </summary>
HandoffIndicatorOption = 0x17,
/// <summary>
/// RFC 5213.
/// </summary>
AccessTechnologyTypeOption = 0x18,
/// <summary>
/// RFC 5213.
/// Mobile Node Link-layer Identifier Option
/// </summary>
MobileNodeLinkLayerIdentifierOption = 0x19,
/// <summary>
/// RFC 5213.
/// Link-local Address Option.
/// </summary>
LinkLocalAddressOption = 0x1A,
/// <summary>
/// RFC 5213.
/// </summary>
TimestampOption = 0x1B,
/// <summary>
/// RFC 5847.
/// </summary>
RestartCounter = 0x1C,
/// <summary>
/// RFC 5555.
/// IPv4 Home Address.
/// </summary>
IpV4HomeAddress = 0x1D,
/// <summary>
/// RFC 5555.
/// IPv4 Address Acknowledgement.
/// </summary>
IpV4AddressAcknowledgement = 0x1E,
/// <summary>
/// RFC 5555.
/// NAT Detection.
/// </summary>
NatDetection = 0x1F,
/// <summary>
/// RFC 5555.
/// IPv4 Care-of Address.
/// </summary>
IpV4CareOfAddress = 0x20,
/// <summary>
/// RFC 5845.
/// GRE Key Option.
/// </summary>
GreKeyOption = 0x21,
/// <summary>
/// RFC 5568.
/// Mobility Header IPv6 Address/Prefix.
/// </summary>
MobilityHeaderIpV6AddressPrefix = 0x22,
/// <summary>
/// RFC 5648.
/// </summary>
BindingIdentifier = 0x23,
/// <summary>
/// RFC5844.
/// IPv4 Home Address Request.
/// </summary>
IpV4HomeAddressRequest = 0x24,
/// <summary>
/// RFC 5844.
/// IPv4 Home Address Reply.
/// </summary>
IpV4HomeAddressReply = 0x25,
/// <summary>
/// RFC 5844.
/// IPv4 Default-Router Address.
/// </summary>
IpV4DefaultRouterAddress = 0x26,
/// <summary>
/// RFC 5844.
/// IPv4 DHCP Support Mode.
/// </summary>
IpV4DHCPSupportMode = 0x27,
/// <summary>
/// RFC 5949.
/// </summary>
ContextRequestOption = 0x28,
/// <summary>
/// RFC 5949.
/// </summary>
LocalMobilityAnchorAddressOption = 0x29,
/// <summary>
/// RFC 5949.
/// Mobile Node Link-local Address Interface Identifier Option.
/// </summary>
MobileNodeLinkLocalAddressInterfaceIdentifierOption = 0x2A,
/// <summary>
/// RFC 6058.
/// </summary>
TransientBinding = 0x2B,
/// <summary>
/// RFC 6089
/// </summary>
FlowSummaryMobilityOption = 0x2C,
/// <summary>
/// RFC 6089.
/// </summary>
FlowIdentificationMobilityOption = 0x2D,
/// <summary>
/// RFC 6463.
/// Redirect-Capability Mobility Option.
/// </summary>
RedirectCapabilityMobilityOption = 0x2E,
/// <summary>
/// RFC 6463.
/// </summary>
RedirectMobilityOption = 0x2F,
/// <summary>
/// RFC 6463.
/// </summary>
LoadInformationMobilityOption = 0x30,
/// <summary>
/// RFC 6463.
/// Alternate IPv4 Care-of Address.
/// </summary>
AlternateIpV4CareOfAddress = 0x31,
/// <summary>
/// RFC 6602.
/// </summary>
MobileNodeGroupIdentifier = 0x32,
/// <summary>
/// RFC 6705.
/// MAG IPv6 Address.
/// </summary>
MagIpV6Address = 0x33,
/// <summary>
/// RFC 6757.
/// </summary>
AccessNetworkIdentifier = 0x34,
}
}
...@@ -11,4 +11,14 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -11,4 +11,14 @@ namespace PcapDotNet.Packets.IpV6
public IpV6OptionType OptionType { get; private set; } public IpV6OptionType OptionType { get; private set; }
} }
internal sealed class IpV6MobilityOptionTypeRegistrationAttribute : Attribute
{
public IpV6MobilityOptionTypeRegistrationAttribute(IpV6MobilityOptionType optionType)
{
OptionType = optionType;
}
public IpV6MobilityOptionType OptionType { get; private set; }
}
} }
\ No newline at end of file
...@@ -40,4 +40,43 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -40,4 +40,43 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(ref offset, Data); buffer.Write(ref offset, Data);
} }
} }
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Option Data |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
public class IpV6MobilityOptionUnknown : IpV6MobilityOptionComplex
{
public IpV6MobilityOptionUnknown(IpV6MobilityOptionType type, DataSegment data)
: base(type)
{
Data = data;
}
public DataSegment Data { get; private set; }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
throw new InvalidOperationException("IpV6MobilityOptionUnknown shouldn't be registered.");
}
internal override int DataLength
{
get { return Data.Length; }
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(ref offset, Data);
}
}
} }
\ No newline at end of file
...@@ -91,4 +91,91 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -91,4 +91,91 @@ namespace PcapDotNet.Packets.IpV6
return registraionAttributes.First(); return registraionAttributes.First();
} }
} }
public class IpV6MobilityOptions : Options<IpV6MobilityOption>
{
public IpV6MobilityOptions(DataSegment data)
: this(Read(data))
{
}
private IpV6MobilityOptions(Tuple<IList<IpV6MobilityOption>, bool> optionsAndIsValid)
: base(optionsAndIsValid.Item1, optionsAndIsValid.Item2, null)
{
}
public static Tuple<IList<IpV6MobilityOption>, bool> Read(DataSegment data)
{
int offset = 0;
List<IpV6MobilityOption> options = new List<IpV6MobilityOption>();
bool isValid = true;
while (offset < data.Length)
{
IpV6MobilityOptionType optionType = (IpV6MobilityOptionType)data[offset++];
if (optionType == IpV6MobilityOptionType.Pad1)
{
options.Add(new IpV6MobilityOptionPad1());
continue;
}
if (offset >= data.Length)
{
isValid = false;
break;
}
byte optionDataLength = data[offset++];
if (offset + optionDataLength > data.Length)
{
isValid = false;
break;
}
IpV6MobilityOption option = CreateOption(optionType, data.Subsegment(ref offset, optionDataLength));
if (option == null)
{
isValid = false;
break;
}
options.Add(option);
}
return new Tuple<IList<IpV6MobilityOption>, bool>(options, isValid);
}
private static IpV6MobilityOption CreateOption(IpV6MobilityOptionType optionType, DataSegment data)
{
IpV6MobilityOption prototype;
if (!_prototypes.TryGetValue(optionType, out prototype))
return new IpV6MobilityOptionUnknown(optionType, data);
return prototype.CreateInstance(data);
}
private static readonly Dictionary<IpV6MobilityOptionType, IpV6MobilityOption> _prototypes = InitializePrototypes();
private static Dictionary<IpV6MobilityOptionType, IpV6MobilityOption> InitializePrototypes()
{
var prototypes =
from type in Assembly.GetExecutingAssembly().GetTypes()
where typeof(IpV6MobilityOption).IsAssignableFrom(type) &&
GetRegistrationAttribute(type) != null
select new
{
GetRegistrationAttribute(type).OptionType,
Option = (IpV6MobilityOption)Activator.CreateInstance(type)
};
return prototypes.ToDictionary(option => option.OptionType, option => option.Option);
}
private static IpV6MobilityOptionTypeRegistrationAttribute GetRegistrationAttribute(Type type)
{
var registraionAttributes = type.GetCustomAttributes<IpV6MobilityOptionTypeRegistrationAttribute>(false);
if (!registraionAttributes.Any())
return null;
return registraionAttributes.First();
}
}
} }
\ No newline at end of file
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