Commit f019b9d7 authored by Brickner_cp's avatar Brickner_cp

IPv6

parent 136b512d
......@@ -169,23 +169,24 @@ namespace PcapDotNet.Packets.IpV6
/// RFC 5026.
/// DNS-UPDATE-TYPE.
/// </summary>
DnsUpdateType = 0x11,
DnsUpdate = 0x11,
/// <summary>
/// RFC 5096.
/// Experimental Mobility Option.
/// </summary>
ExperimentalMobilityOption = 0x12,
Experimental = 0x12,
/// <summary>
/// RFC 5094.
/// Vendor Specific Mobility Option.
/// </summary>
VendorSpecificMobilityOption = 0x13,
VendorSpecific = 0x13,
/// <summary>
/// RFC 5149.
/// </summary>
ServiceSelectionMobilityOption = 0x14,
ServiceSelection = 0x14,
/// <summary>
/// RFC 5568.
......@@ -196,34 +197,34 @@ namespace PcapDotNet.Packets.IpV6
/// <summary>
/// RFC 5213.
/// </summary>
HomeNetworkPrefixOption = 0x16,
HomeNetworkPrefix = 0x16,
/// <summary>
/// RFC 5213.
/// </summary>
HandoffIndicatorOption = 0x17,
HandoffIndicator = 0x17,
/// <summary>
/// RFC 5213.
/// </summary>
AccessTechnologyTypeOption = 0x18,
AccessTechnologyType = 0x18,
/// <summary>
/// RFC 5213.
/// Mobile Node Link-layer Identifier Option
/// </summary>
MobileNodeLinkLayerIdentifierOption = 0x19,
MobileNodeLinkLayerIdentifier = 0x19,
/// <summary>
/// RFC 5213.
/// Link-local Address Option.
/// </summary>
LinkLocalAddressOption = 0x1A,
LinkLocalAddress = 0x1A,
/// <summary>
/// RFC 5213.
/// </summary>
TimestampOption = 0x1B,
Timestamp = 0x1B,
/// <summary>
/// RFC 5847.
......
using System;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6
{
......@@ -15,7 +16,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+----------------------------+
/// </pre>
/// </summary>
public class IpV6OptionUnknown : IpV6OptionComplex
public sealed class IpV6OptionUnknown : IpV6OptionComplex
{
public IpV6OptionUnknown(IpV6OptionType type, DataSegment data)
: base(type)
......@@ -54,7 +55,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+----------------------------+
/// </pre>
/// </summary>
public class IpV6MobilityOptionUnknown : IpV6MobilityOptionSingleDataSegmentField
public sealed class IpV6MobilityOptionUnknown : IpV6MobilityOptionSingleDataSegmentField
{
public IpV6MobilityOptionUnknown(IpV6MobilityOptionType type, DataSegment data)
: base(type, data)
......@@ -88,7 +89,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.PadN)]
public class IpV6MobilityOptionPadN : IpV6MobilityOptionComplex
public sealed class IpV6MobilityOptionPadN : IpV6MobilityOptionComplex
{
public IpV6MobilityOptionPadN(int paddingDataLength)
: base(IpV6MobilityOptionType.PadN)
......@@ -128,7 +129,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.BindingRefreshAdvice)]
public class IpV6MobilityOptionBindingRefreshAdvice : IpV6MobilityOptionComplex
public sealed class IpV6MobilityOptionBindingRefreshAdvice : IpV6MobilityOptionComplex
{
public const int OptionDataLength = sizeof(ushort);
......@@ -164,14 +165,13 @@ namespace PcapDotNet.Packets.IpV6
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+--------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+--------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+--------------+--------------+
/// | 16 | Alternate Care-of Address |
/// | 16 | Address |
/// | | |
/// | | |
/// | | |
......@@ -182,38 +182,80 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+-----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.AlternateCareOfAddress)]
public class IpV6MobilityOptionAlternateCareOfAddress : IpV6MobilityOptionComplex
public abstract class IpV6MobilityOptionIpV6Address : IpV6MobilityOptionComplex
{
public const int OptionDataLength = IpV6Address.SizeOf;
public IpV6MobilityOptionAlternateCareOfAddress(IpV6Address alternateCareOfAddress)
: base(IpV6MobilityOptionType.AlternateCareOfAddress)
public IpV6MobilityOptionIpV6Address(IpV6MobilityOptionType type, IpV6Address address)
: base(type)
{
AlternateCareOfAddress = alternateCareOfAddress;
Address = address;
}
/// <summary>
/// Contains an address to use as the care-of address for the binding, rather than using the Source Address of the packet as the care-of address.
/// </summary>
public IpV6Address AlternateCareOfAddress { get; private set; }
internal IpV6Address Address { get; private set; }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
internal static bool Read(DataSegment data, out IpV6Address address)
{
if (data.Length != OptionDataLength)
return null;
{
address = IpV6Address.Zero;
return false;
}
return new IpV6MobilityOptionAlternateCareOfAddress(data.ReadIpV6Address(0, Endianity.Big));
address = data.ReadIpV6Address(0, Endianity.Big);
return true;
}
internal override int DataLength
internal override sealed int DataLength
{
get { return OptionDataLength; }
}
internal override void WriteData(byte[] buffer, ref int offset)
internal override sealed void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(ref offset, Address, Endianity.Big);
}
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+--------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+--------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+--------------+--------------+
/// | 16 | Alternate Care-of Address |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// +-----+-----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.AlternateCareOfAddress)]
public sealed class IpV6MobilityOptionAlternateCareOfAddress : IpV6MobilityOptionIpV6Address
{
public IpV6MobilityOptionAlternateCareOfAddress(IpV6Address alternateCareOfAddress)
: base(IpV6MobilityOptionType.AlternateCareOfAddress, alternateCareOfAddress)
{
}
/// <summary>
/// Contains an address to use as the care-of address for the binding, rather than using the Source Address of the packet as the care-of address.
/// </summary>
public IpV6Address AlternateCareOfAddress { get { return Address; } }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
buffer.Write(ref offset, AlternateCareOfAddress, Endianity.Big);
IpV6Address alternateCareOfAddress;
if (!Read(data, out alternateCareOfAddress))
return null;
return new IpV6MobilityOptionAlternateCareOfAddress(alternateCareOfAddress);
}
}
......@@ -232,7 +274,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.NonceIndices)]
public class IpV6MobilityOptionNonceIndices : IpV6MobilityOptionComplex
public sealed class IpV6MobilityOptionNonceIndices : IpV6MobilityOptionComplex
{
private static class Offset
{
......@@ -297,7 +339,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.BindingAuthorizationData)]
public class IpV6MobilityOptionBindingAuthorizationData : IpV6MobilityOptionSingleDataSegmentField
public sealed class IpV6MobilityOptionBindingAuthorizationData : IpV6MobilityOptionSingleDataSegmentField
{
public IpV6MobilityOptionBindingAuthorizationData(DataSegment authenticator)
: base(IpV6MobilityOptionType.BindingAuthorizationData, authenticator)
......@@ -355,7 +397,7 @@ namespace PcapDotNet.Packets.IpV6
}
/// <summary>
/// RFC 3963.
/// RFC 3963, 5213.
/// <pre>
/// +-----+--------------+---------------+
/// | Bit | 0-7 | 8-15 |
......@@ -364,7 +406,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+--------------+---------------+
/// | 16 | Reserved | Prefix Length |
/// +-----+--------------+---------------+
/// | 32 | Mobile Network Prefix |
/// | 32 | Network Prefix |
/// | | |
/// | | |
/// | | |
......@@ -375,22 +417,21 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+------------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.MobileNetworkPrefix)]
public class IpV6MobilityOptionMobileNetworkPrefix : IpV6MobilityOptionComplex
public abstract class IpV6MobilityOptionNetworkPrefix : IpV6MobilityOptionComplex
{
private static class Offset
{
public const int PrefixLength = sizeof(ushort);
public const int MobileNetworkPrefix = PrefixLength + sizeof(ushort);
public const int NetworkPrefix = PrefixLength + sizeof(ushort);
}
public const int OptionDataLength = Offset.MobileNetworkPrefix + IpV6Address.SizeOf;
public const int OptionDataLength = Offset.NetworkPrefix + IpV6Address.SizeOf;
public IpV6MobilityOptionMobileNetworkPrefix(byte prefixLength, IpV6Address mobileNetworkPrefix)
: base(IpV6MobilityOptionType.MobileNetworkPrefix)
public IpV6MobilityOptionNetworkPrefix(IpV6MobilityOptionType type, byte prefixLength, IpV6Address networkPrefix)
: base(type)
{
PrefixLength = prefixLength;
MobileNetworkPrefix = mobileNetworkPrefix;
NetworkPrefix = networkPrefix;
}
/// <summary>
......@@ -399,31 +440,115 @@ namespace PcapDotNet.Packets.IpV6
public byte PrefixLength { get; private set; }
/// <summary>
/// Contains the Mobile Network Prefix.
/// Contains the Network Prefix.
/// </summary>
public IpV6Address MobileNetworkPrefix { get; private set; }
public IpV6Address NetworkPrefix { get; private set; }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
internal override sealed int DataLength
{
get { return OptionDataLength; }
}
internal override sealed void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.PrefixLength, PrefixLength);
buffer.Write(offset + Offset.NetworkPrefix, NetworkPrefix, Endianity.Big);
offset += OptionDataLength;
}
internal static bool Read(DataSegment data, out byte prefixLength, out IpV6Address networkPrefix)
{
if (data.Length != OptionDataLength)
return null;
{
prefixLength = 0;
networkPrefix = IpV6Address.Zero;
return false;
}
prefixLength = data[Offset.PrefixLength];
networkPrefix = data.ReadIpV6Address(Offset.NetworkPrefix, Endianity.Big);
return true;
}
}
/// <summary>
/// RFC 3963.
/// <pre>
/// +-----+--------------+---------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+--------------+---------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+--------------+---------------+
/// | 16 | Reserved | Prefix Length |
/// +-----+--------------+---------------+
/// | 32 | Mobile Network Prefix |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// +-----+------------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.MobileNetworkPrefix)]
public sealed class IpV6MobilityOptionMobileNetworkPrefix : IpV6MobilityOptionNetworkPrefix
{
public IpV6MobilityOptionMobileNetworkPrefix(byte prefixLength, IpV6Address mobileNetworkPrefix)
: base(IpV6MobilityOptionType.MobileNetworkPrefix, prefixLength, mobileNetworkPrefix)
{
}
byte prefixLength = data[Offset.PrefixLength];
IpV6Address mobileNetworkPrefix = data.ReadIpV6Address(Offset.MobileNetworkPrefix, Endianity.Big);
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
byte prefixLength;
IpV6Address mobileNetworkPrefix;
if (!Read(data, out prefixLength, out mobileNetworkPrefix))
return null;
return new IpV6MobilityOptionMobileNetworkPrefix(prefixLength, mobileNetworkPrefix);
}
}
internal override int DataLength
/// <summary>
/// RFC 5213.
/// <pre>
/// +-----+--------------+---------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+--------------+---------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+--------------+---------------+
/// | 16 | Reserved | Prefix Length |
/// +-----+--------------+---------------+
/// | 32 | Mobile Network Prefix |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// +-----+------------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.HomeNetworkPrefix)]
public sealed class IpV6MobilityOptionHomeNetworkPrefix : IpV6MobilityOptionNetworkPrefix
{
public IpV6MobilityOptionHomeNetworkPrefix(byte prefixLength, IpV6Address homeNetworkPrefix)
: base(IpV6MobilityOptionType.HomeNetworkPrefix, prefixLength, homeNetworkPrefix)
{
get { return OptionDataLength; }
}
internal override void WriteData(byte[] buffer, ref int offset)
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
buffer.Write(offset + Offset.PrefixLength, PrefixLength);
buffer.Write(offset + Offset.MobileNetworkPrefix, MobileNetworkPrefix, Endianity.Big);
offset += OptionDataLength;
byte prefixLength;
IpV6Address mobileNetworkPrefix;
if (!Read(data, out prefixLength, out mobileNetworkPrefix))
return null;
return new IpV6MobilityOptionHomeNetworkPrefix(prefixLength, mobileNetworkPrefix);
}
}
......@@ -493,7 +618,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.LinkLayerAddress)]
public class IpV6MobilityOptionLinkLayerAddress : IpV6MobilityOptionComplex
public sealed class IpV6MobilityOptionLinkLayerAddress : IpV6MobilityOptionComplex
{
private static class Offset
{
......@@ -501,7 +626,7 @@ namespace PcapDotNet.Packets.IpV6
public const int LinkLayerAddress = OptionCode + sizeof(byte);
}
public const int OptionDataMiniumLength = Offset.LinkLayerAddress;
public const int OptionDataMinimumLength = Offset.LinkLayerAddress;
public IpV6MobilityOptionLinkLayerAddress(IpV6MobilityOptionLinkLayerAddressCode code, DataSegment linkLayerAddress)
: base(IpV6MobilityOptionType.LinkLayerAddress)
......@@ -519,7 +644,7 @@ namespace PcapDotNet.Packets.IpV6
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
if (data.Length < OptionDataMiniumLength)
if (data.Length < OptionDataMinimumLength)
return null;
IpV6MobilityOptionLinkLayerAddressCode code = (IpV6MobilityOptionLinkLayerAddressCode)data[Offset.OptionCode];
......@@ -530,7 +655,7 @@ namespace PcapDotNet.Packets.IpV6
internal override int DataLength
{
get { return OptionDataMiniumLength + LinkLayerAddress.Length; }
get { return OptionDataMinimumLength + LinkLayerAddress.Length; }
}
internal override void WriteData(byte[] buffer, ref int offset)
......@@ -571,7 +696,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.MobileNodeIdentifier)]
public class IpV6MobilityOptionMobileNodeIdentifier : IpV6MobilityOptionComplex
public sealed class IpV6MobilityOptionMobileNodeIdentifier : IpV6MobilityOptionComplex
{
private static class Offset
{
......@@ -579,7 +704,7 @@ namespace PcapDotNet.Packets.IpV6
public const int Identifier = Subtype + sizeof(byte);
}
public const int OptionDataMiniumLength = Offset.Identifier;
public const int OptionDataMinimumLength = Offset.Identifier;
public IpV6MobilityOptionMobileNodeIdentifier(IpV6MobileNodeIdentifierSubtype subtype, DataSegment identifier)
: base(IpV6MobilityOptionType.MobileNodeIdentifier)
......@@ -600,7 +725,7 @@ namespace PcapDotNet.Packets.IpV6
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
if (data.Length < OptionDataMiniumLength)
if (data.Length < OptionDataMinimumLength)
return null;
IpV6MobileNodeIdentifierSubtype subtype = (IpV6MobileNodeIdentifierSubtype)data[Offset.Subtype];
......@@ -611,7 +736,7 @@ namespace PcapDotNet.Packets.IpV6
internal override int DataLength
{
get { return OptionDataMiniumLength + Identifier.Length; }
get { return OptionDataMinimumLength + Identifier.Length; }
}
internal override void WriteData(byte[] buffer, ref int offset)
......@@ -697,7 +822,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.Authentication)]
public class IpV6MobilityOptionAuthentication : IpV6MobilityOptionComplex
public sealed class IpV6MobilityOptionAuthentication : IpV6MobilityOptionComplex
{
private static class Offset
{
......@@ -706,7 +831,7 @@ namespace PcapDotNet.Packets.IpV6
public const int AuthenticationData = MobilitySecurityParameterIndex + sizeof(uint);
}
public const int OptionDataMiniumLength = Offset.AuthenticationData;
public const int OptionDataMinimumLength = Offset.AuthenticationData;
public IpV6MobilityOptionAuthentication(IpV6AuthenticationSubtype subtype, uint mobilitySecurityParameterIndex, DataSegment authenticationData)
: base(IpV6MobilityOptionType.Authentication)
......@@ -734,7 +859,7 @@ namespace PcapDotNet.Packets.IpV6
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
if (data.Length < OptionDataMiniumLength)
if (data.Length < OptionDataMinimumLength)
return null;
IpV6AuthenticationSubtype subtype = (IpV6AuthenticationSubtype)data[Offset.Subtype];
......@@ -746,7 +871,7 @@ namespace PcapDotNet.Packets.IpV6
internal override int DataLength
{
get { return OptionDataMiniumLength + AuthenticationData.Length; }
get { return OptionDataMinimumLength + AuthenticationData.Length; }
}
internal override void WriteData(byte[] buffer, ref int offset)
......@@ -759,54 +884,89 @@ namespace PcapDotNet.Packets.IpV6
}
/// <summary>
/// RFC 4285.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Timestamp |
/// | 16 | Value |
/// | | |
/// | | |
/// | | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.ReplayProtection)]
public class IpV6MobilityOptionReplayProtection : IpV6MobilityOptionComplex
public abstract class IpV6MobilityOptionULong : IpV6MobilityOptionComplex
{
public const int OptionDataLength = sizeof(ulong);
public IpV6MobilityOptionReplayProtection(ulong timestamp)
: base(IpV6MobilityOptionType.ReplayProtection)
public IpV6MobilityOptionULong(IpV6MobilityOptionType type, ulong value)
: base(type)
{
Timestamp = timestamp;
Value = value;
}
/// <summary>
/// 64 bit timestamp.
/// </summary>
public ulong Timestamp { get; private set; }
internal ulong Value { get; private set; }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
internal static bool Read(DataSegment data, out ulong value)
{
if (data.Length != OptionDataLength)
return null;
ulong timestamp = data.ReadULong(0, Endianity.Big);
{
value = 0;
return false;
}
return new IpV6MobilityOptionReplayProtection(timestamp);
value = data.ReadULong(0, Endianity.Big);
return true;
}
internal override int DataLength
internal override sealed int DataLength
{
get { return OptionDataLength; }
}
internal override void WriteData(byte[] buffer, ref int offset)
internal override sealed void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(ref offset, Value, Endianity.Big);
}
}
/// <summary>
/// RFC 4285.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Timestamp |
/// | | |
/// | | |
/// | | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.ReplayProtection)]
public sealed class IpV6MobilityOptionReplayProtection : IpV6MobilityOptionULong
{
public IpV6MobilityOptionReplayProtection(ulong timestamp)
: base(IpV6MobilityOptionType.ReplayProtection, timestamp)
{
}
/// <summary>
/// 64 bit timestamp.
/// </summary>
public ulong Timestamp { get { return Value; } }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
buffer.Write(ref offset, Timestamp, Endianity.Big);
ulong timestamp;
if (!Read(data, out timestamp))
return null;
return new IpV6MobilityOptionReplayProtection(timestamp);
}
}
......@@ -840,7 +1000,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.CgaParametersRequest)]
public class IpV6MobilityOptionCgaParametersRequest : IpV6MobilityOptionEmpty
public sealed class IpV6MobilityOptionCgaParametersRequest : IpV6MobilityOptionEmpty
{
public IpV6MobilityOptionCgaParametersRequest()
: base(IpV6MobilityOptionType.CgaParametersRequest)
......@@ -856,6 +1016,18 @@ namespace PcapDotNet.Packets.IpV6
}
}
/// <summary>
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Value |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
public abstract class IpV6MobilityOptionSingleDataSegmentField : IpV6MobilityOptionComplex
{
public IpV6MobilityOptionSingleDataSegmentField(IpV6MobilityOptionType type, DataSegment value)
......@@ -892,7 +1064,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.CgaParameters)]
public class IpV6MobilityOptionCgaParameters : IpV6MobilityOptionSingleDataSegmentField
public sealed class IpV6MobilityOptionCgaParameters : IpV6MobilityOptionSingleDataSegmentField
{
public const int OptionDataMaxLength = 255;
......@@ -938,7 +1110,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.Signature)]
public class IpV6MobilityOptionSignature : IpV6MobilityOptionSingleDataSegmentField
public sealed class IpV6MobilityOptionSignature : IpV6MobilityOptionSingleDataSegmentField
{
public IpV6MobilityOptionSignature(DataSegment signature)
: base(IpV6MobilityOptionType.Signature, signature)
......@@ -973,7 +1145,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.PermanentHomeKeygenToken)]
public class IpV6MobilityOptionPermanentHomeKeygenToken : IpV6MobilityOptionSingleDataSegmentField
public sealed class IpV6MobilityOptionPermanentHomeKeygenToken : IpV6MobilityOptionSingleDataSegmentField
{
public IpV6MobilityOptionPermanentHomeKeygenToken(DataSegment permanentHomeKeygenToken)
: base(IpV6MobilityOptionType.PermanentHomeKeygenToken, permanentHomeKeygenToken)
......@@ -1008,7 +1180,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.CareOfTestInit)]
public class IpV6MobilityOptionCareOfTestInit : IpV6MobilityOptionEmpty
public sealed class IpV6MobilityOptionCareOfTestInit : IpV6MobilityOptionEmpty
{
public IpV6MobilityOptionCareOfTestInit()
: base(IpV6MobilityOptionType.CareOfTestInit)
......@@ -1040,39 +1212,1029 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.CareOfTest)]
public class IpV6MobilityOptionCareOfTest : IpV6MobilityOptionComplex
public sealed class IpV6MobilityOptionCareOfTest : IpV6MobilityOptionULong
{
public const int OptionDataLength = sizeof(ulong);
public IpV6MobilityOptionCareOfTest(ulong careOfKeygenToken)
: base(IpV6MobilityOptionType.CareOfTest)
: base(IpV6MobilityOptionType.CareOfTest, careOfKeygenToken)
{
}
/// <summary>
/// Contains the care-of keygen token generated by the correspondent node.
/// </summary>
public ulong CareOfKeygenToken { get; private set; }
public ulong CareOfKeygenToken { get { return Value; } }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
ulong careOfKeygenToken;
if (!Read(data, out careOfKeygenToken))
return null;
ulong careOfKeygenToken = data.ReadULong(0, Endianity.Big);
return new IpV6MobilityOptionCareOfTest(careOfKeygenToken);
}
}
/// <summary>
/// RFC 5026.
/// </summary>
public enum IpV6DnsUpdateStatus : byte
{
/// <summary>
/// DNS update performed.
/// </summary>
DnsUpdatePerformed = 0,
/// <summary>
/// Reason unspecified.
/// </summary>
ReasonUnspecified = 128,
/// <summary>
/// Administratively prohibited.
/// </summary>
AdministrativelyProhibited = 129,
/// <summary>
/// DNS update failed.
/// </summary>
DnsUpdateFailed = 130,
}
/// <summary>
/// RFC 5026.
/// <pre>
/// +-----+-------------+---+----------+
/// | Bit | 0-7 | 8 | 9-15 |
/// +-----+-------------+---+----------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+---+----------+
/// | 16 | Status | R | Reserved |
/// +-----+-------------+---+----------+
/// | 32 | MN identity (FQDN) |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.DnsUpdate)]
public sealed class IpV6MobilityOptionDnsUpdate : IpV6MobilityOptionComplex
{
private static class Offset
{
public const int Status = 0;
public const int Remove = Status + sizeof(byte);
public const int MobileNodeIdentity = Remove + sizeof(byte);
}
private static class Mask
{
public const byte Remove = 0x80;
}
public const int OptionDataMinimumLength = Offset.MobileNodeIdentity;
public IpV6MobilityOptionDnsUpdate(IpV6DnsUpdateStatus status, bool remove, DataSegment mobileNodeIdentity)
: base(IpV6MobilityOptionType.DnsUpdate)
{
Status = status;
Remove = remove;
MobileNodeIdentity = mobileNodeIdentity;
}
/// <summary>
/// Indicating the result of the dynamic DNS update procedure.
/// This field must be set to 0 and ignored by the receiver when the DNS Update mobility option is included in a Binding Update message.
/// When the DNS Update mobility option is included in the Binding Acknowledgement message,
/// values of the Status field less than 128 indicate that the dynamic DNS update was performed successfully by the Home Agent.
/// Values greater than or equal to 128 indicate that the dynamic DNS update was not completed by the HA.
/// </summary>
public IpV6DnsUpdateStatus Status { get; private set; }
/// <summary>
/// Whether the Mobile Node is requesting the HA to remove the DNS entry identified by the FQDN specified in this option and the HoA of the Mobile Node.
/// If false, the Mobile Node is requesting the HA to create or update a DNS entry with its HoA and the FQDN specified in the option.
/// </summary>
public bool Remove { get; private set; }
/// <summary>
/// The identity of the Mobile Node in FQDN format to be used by the Home Agent to send a Dynamic DNS update.
/// </summary>
public DataSegment MobileNodeIdentity { get; private set; }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
if (data.Length < OptionDataMinimumLength)
return null;
IpV6DnsUpdateStatus status = (IpV6DnsUpdateStatus)data[Offset.Status];
bool remove = data.ReadBool(Offset.Remove, Mask.Remove);
DataSegment mobileNodeIdentity = data.Subsegment(Offset.MobileNodeIdentity, data.Length - Offset.MobileNodeIdentity);
return new IpV6MobilityOptionDnsUpdate(status, remove, mobileNodeIdentity);
}
internal override int DataLength
{
get { return OptionDataLength; }
get { return OptionDataMinimumLength + MobileNodeIdentity.Length; }
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(ref offset, CareOfKeygenToken, Endianity.Big);
buffer.Write(offset + Offset.Status, (byte)Status);
byte flags = 0;
if (Remove)
flags |= Mask.Remove;
buffer.Write(offset + Offset.Remove, flags);
buffer.Write(offset + Offset.MobileNodeIdentity, MobileNodeIdentity);
offset += DataLength;
}
}
/// <summary>
/// RFC 5096.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Data |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.Experimental)]
public sealed class IpV6MobilityOptionExperimental : IpV6MobilityOptionSingleDataSegmentField
{
public IpV6MobilityOptionExperimental(DataSegment data)
: base(IpV6MobilityOptionType.Experimental, data)
{
}
/// <summary>
/// Data related to the experimental protocol extension.
/// </summary>
public DataSegment Data
{
get { return Value; }
}
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
return new IpV6MobilityOptionExperimental(data);
}
}
/// <summary>
/// RFC 5094.
/// <pre>
/// +-----+--------------+
/// | Bit | 0-7 |
/// +-----+--------------+
/// | 0 | Option Type |
/// +-----+--------------+
/// | 8 | Opt Data Len |
/// +-----+--------------+
/// | 16 | Vendor ID |
/// | | |
/// | | |
/// | | |
/// +-----+--------------+
/// | 48 | Sub-Type |
/// +-----+--------------+
/// | 56 | Data |
/// | ... | |
/// +-----+--------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.VendorSpecific)]
public sealed class IpV6MobilityOptionVendorSpecific : IpV6MobilityOptionComplex
{
private static class Offset
{
public const int VendorId = 0;
public const int SubType = VendorId + sizeof(uint);
public const int Data = SubType + sizeof(byte);
}
public const int OptionDataMinimumLength = Offset.Data;
public IpV6MobilityOptionVendorSpecific(uint vendorId, byte subType, DataSegment data)
: base(IpV6MobilityOptionType.VendorSpecific)
{
VendorId = vendorId;
SubType = subType;
Data = data;
}
/// <summary>
/// The SMI Network Management Private Enterprise Code of the IANA- maintained Private Enterprise Numbers registry.
/// See http://www.iana.org/assignments/enterprise-numbers/enterprise-numbers
/// </summary>
public uint VendorId { get; private set; }
/// <summary>
/// Indicating the type of vendor-specific information carried in the option.
/// The administration of the Sub-type is done by the Vendor.
/// </summary>
public byte SubType { get; private set; }
/// <summary>
/// Vendor-specific data that is carried in this message.
/// </summary>
public DataSegment Data { get; private set; }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
if (data.Length < OptionDataMinimumLength)
return null;
uint vendorId = data.ReadUInt(Offset.VendorId, Endianity.Big);
byte subType = data[Offset.SubType];
DataSegment vendorSpecificData = data.Subsegment(Offset.Data, data.Length - Offset.Data);
return new IpV6MobilityOptionVendorSpecific(vendorId, subType, vendorSpecificData);
}
internal override int DataLength
{
get { return OptionDataMinimumLength + Data.Length; }
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.VendorId, VendorId, Endianity.Big);
buffer.Write(offset + Offset.SubType, SubType);
buffer.Write(offset + Offset.Data, Data);
offset += DataLength;
}
}
/// <summary>
/// RFC 5149.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Identifier |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.ServiceSelection)]
public sealed class IpV6MobilityOptionServiceSelection : IpV6MobilityOptionSingleDataSegmentField
{
public IpV6MobilityOptionServiceSelection(DataSegment data)
: base(IpV6MobilityOptionType.Experimental, data)
{
}
/// <summary>
/// Encoded service identifier string used to identify the requested service.
/// The identifier string length is between 1 and 255 octets.
/// This specification allows international identifier strings that are based on the use of Unicode characters, encoded as UTF-8,
/// and formatted using Normalization Form KC (NFKC).
///
/// 'ims', 'voip', and 'voip.companyxyz.example.com' are valid examples of Service Selection option Identifiers.
/// At minimum, the Identifier must be unique among the home agents to which the mobile node is authorized to register.
/// </summary>
public DataSegment Identifier
{
get { return Value; }
}
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
return new IpV6MobilityOptionServiceSelection(data);
}
}
/// <summary>
/// RFC 5568.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | SPI |
/// | | |
/// +-----+----------------------------+
/// | 48 | Authenticator |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.BindingAuthorizationDataForFmIpV6)]
public sealed class IpV6MobilityOptionBindingAuthorizationDataForFmIpV6 : IpV6MobilityOptionComplex
{
private static class Offset
{
public const int SecurityParameterIndex = 0;
public const int Authenticator = SecurityParameterIndex + sizeof(uint);
}
public const int OptionDataMinimumLength = Offset.Authenticator;
public IpV6MobilityOptionBindingAuthorizationDataForFmIpV6(uint securityParameterIndex, DataSegment authenticator)
: base(IpV6MobilityOptionType.BindingAuthorizationDataForFmIpV6)
{
SecurityParameterIndex = securityParameterIndex;
Authenticator = authenticator;
}
/// <summary>
/// SPI = 0 is reserved for the Authenticator computed using SEND-based handover keys.
/// </summary>
public uint SecurityParameterIndex { get; private set; }
/// <summary>
/// <para>
/// Contains a cryptographic value that can be used to determine that the message in question comes from the right authority.
/// Rules for calculating this value depends on the used authorization procedure.
/// </para>
/// <para>
/// For the return routability procedure, this option can appear in the Binding Update and Binding Acknowledgements.
/// Rules for calculating the Authenticator value are the following:
/// </para>
/// <para>
/// Mobility Data = care-of address | correspondent | MH Data
/// Authenticator = First (96, HMAC_SHA1 (Kbm, Mobility Data))
/// </para>
/// <para>
/// Where | denotes concatenation.
/// "Care-of address" is the care-of address that will be registered for the mobile node if the Binding Update succeeds,
/// or the home address of the mobile node if this option is used in de-registration.
/// Note also that this address might be different from the source address of the Binding Update message,
/// if the Alternative Care-of Address mobility option is used, or when the lifetime of the binding is set to zero.
/// </para>
/// <para>
/// The "correspondent" is the IPv6 address of the Previous Access Router (PAR).
/// Note that, if the message is sent to a destination that is itself mobile, the "correspondent" address may not be the address found in the
/// Destination Address field of the IPv6 header; instead, the home address from the type 2 Routing header should be used.
/// </para>
/// <para>
/// "MH Data" is the content of the Mobility Header, excluding the Authenticator field itself.
/// The Authenticator value is calculated as if the Checksum field in the Mobility Header was zero.
/// The Checksum in the transmitted packet is still calculated in the usual manner,
/// with the calculated Authenticator being a part of the packet protected by the Checksum.
/// Kbm is a shared key between the MN and the PAR.
/// Note that while the contents of a potential Home Address destination option are not covered in this formula,
/// the rules for the calculation of the Kbm do take the home address in account.
/// This ensures that the MAC will be different for different home addresses.
/// </para>
/// <para>
/// The first 96 bits from the MAC result are used as the Authenticator field.
/// </para>
/// </summary>
public DataSegment Authenticator { get; private set; }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
if (data.Length < OptionDataMinimumLength)
return null;
uint securityParameterIndex = data.ReadUInt(Offset.SecurityParameterIndex, Endianity.Big);
DataSegment authenticator = data.Subsegment(Offset.Authenticator, data.Length - Offset.Authenticator);
return new IpV6MobilityOptionBindingAuthorizationDataForFmIpV6(securityParameterIndex, authenticator);
}
internal override int DataLength
{
get { return OptionDataMinimumLength + Authenticator.Length; }
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.SecurityParameterIndex, SecurityParameterIndex, Endianity.Big);
buffer.Write(offset + Offset.Authenticator, Authenticator);
offset += DataLength;
}
}
/// <summary>
/// RFC 5213.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Reserved | Value |
/// +-----+----------------------------+
/// </pre>
/// </summary>
public abstract class IpV6MobilityOptionReservedByteValueByte : IpV6MobilityOptionComplex
{
private static class Offset
{
public const int Value = sizeof(byte);
}
public const int OptionDataLength = Offset.Value + sizeof(byte);
public IpV6MobilityOptionReservedByteValueByte(IpV6MobilityOptionType type, byte value)
: base(type)
{
Value = value;
}
internal byte Value { get; private set; }
internal static bool Read(DataSegment data, out byte value)
{
if (data.Length != OptionDataLength)
{
value = 0;
return false;
}
value = data[Offset.Value];
return true;
}
internal override sealed int DataLength
{
get { return OptionDataLength; }
}
internal override sealed void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.Value, Value);
offset += DataLength;
}
}
/// <summary>
/// RFC 5213.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Reserved | HI |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.HandoffIndicator)]
public sealed class IpV6MobilityOptionHandoffIndicator : IpV6MobilityOptionReservedByteValueByte
{
public IpV6MobilityOptionHandoffIndicator(IpV6HandoffIndicator handoffIndicator)
: base(IpV6MobilityOptionType.HandoffIndicator, (byte)handoffIndicator)
{
}
/// <summary>
/// Specifies the type of handoff.
/// </summary>
public IpV6HandoffIndicator HandoffIndicator { get { return (IpV6HandoffIndicator)Value; } }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
byte value;
if (!Read(data, out value))
return null;
return new IpV6MobilityOptionHandoffIndicator((IpV6HandoffIndicator)value);
}
}
/// <summary>
/// RFC 5213.
/// </summary>
public enum IpV6HandoffIndicator : byte
{
/// <summary>
/// Attachment over a new interface.
/// </summary>
AttachmentOverNewInterface = 1,
/// <summary>
/// Handoff between two different interfaces of the mobile node.
/// </summary>
HandoffBetweenTwoDifferentInterfacesOfTheMobileNode = 2,
/// <summary>
/// Handoff between mobile access gateways for the same interface.
/// </summary>
HandoffBetweenMobileAccessGatewaysForTheSameInterface = 3,
/// <summary>
/// Handoff state unknown.
/// </summary>
HandoffStateUnknown = 4,
/// <summary>
/// Handoff state not changed (Re-registration).
/// </summary>
HandoffStateNotChanged = 5,
}
/// <summary>
/// RFC 5213.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Reserved | ATT |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.AccessTechnologyType)]
public sealed class IpV6MobilityOptionAccessTechnologyType : IpV6MobilityOptionReservedByteValueByte
{
public IpV6MobilityOptionAccessTechnologyType(IpV6AccessTechnologyType accessTechnologyType)
: base(IpV6MobilityOptionType.AccessTechnologyType, (byte)accessTechnologyType)
{
}
/// <summary>
/// Specifies the access technology through which the mobile node is connected to the access link on the mobile access gateway.
/// </summary>
public IpV6AccessTechnologyType AccessTechnologyType { get { return (IpV6AccessTechnologyType)Value; } }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
byte value;
if (!Read(data, out value))
return null;
return new IpV6MobilityOptionAccessTechnologyType((IpV6AccessTechnologyType)value);
}
}
/// <summary>
/// RFC 5213.
/// </summary>
public enum IpV6AccessTechnologyType : byte
{
/// <summary>
/// Reserved.
/// </summary>
Reserved = 0,
/// <summary>
/// Virtual.
/// Logical Network Interface.
/// </summary>
LogicalNetworkInterface = 1,
/// <summary>
/// Point-to-Point Protocol.
/// </summary>
PointToPointProtocol = 2,
/// <summary>
/// IEEE 802.3.
/// Ethernet.
/// </summary>
Ethernet = 3,
/// <summary>
/// IEEE 802.11a/b/g.
/// Wireless LAN.
/// </summary>
WirelessLan = 4,
/// <summary>
/// IEEE 802.16e.
/// WIMAX.
/// </summary>
WiMax = 5,
}
/// <summary>
/// RFC 5213.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Reserved |
/// +-----+----------------------------+
/// | 32 | Link-layer Identifier |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.MobileNodeLinkLayerIdentifier)]
public class IpV6MobilityOptionMobileNodeLinkLayerIdentifier : IpV6MobilityOptionComplex
{
private static class Offset
{
public const int LinkLayerIdentifier = sizeof(ushort);
}
public const int OptionDataMinimumLength = Offset.LinkLayerIdentifier;
public IpV6MobilityOptionMobileNodeLinkLayerIdentifier(DataSegment linkLayerIdentifier)
: base(IpV6MobilityOptionType.MobileNodeLinkLayerIdentifier)
{
LinkLayerIdentifier = linkLayerIdentifier;
}
/// <summary>
/// Contains the mobile node's link-layer identifier.
/// </summary>
public DataSegment LinkLayerIdentifier { get; private set; }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
if (data.Length < OptionDataMinimumLength)
return null;
DataSegment linkLayerIdentifier = data.Subsegment(Offset.LinkLayerIdentifier, data.Length - Offset.LinkLayerIdentifier);
return new IpV6MobilityOptionMobileNodeLinkLayerIdentifier(linkLayerIdentifier);
}
internal override int DataLength
{
get { return OptionDataMinimumLength + LinkLayerIdentifier.Length; }
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.LinkLayerIdentifier, LinkLayerIdentifier);
offset += DataLength;
}
}
/// <summary>
/// RFC 5213.
/// <pre>
/// +-----+--------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+--------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+--------------+--------------+
/// | 16 | Link-local Address |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// +-----+-----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.LinkLocalAddress)]
public sealed class IpV6MobilityOptionLinkLocalAddress : IpV6MobilityOptionIpV6Address
{
public IpV6MobilityOptionLinkLocalAddress(IpV6Address linkLocalAddress)
: base(IpV6MobilityOptionType.LinkLocalAddress, linkLocalAddress)
{
}
/// <summary>
/// Contains the link-local address.
/// </summary>
public IpV6Address LinkLocalAddress { get { return Address; } }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
IpV6Address linkLocalAddress;
if (!Read(data, out linkLocalAddress))
return null;
return new IpV6MobilityOptionLinkLocalAddress(linkLocalAddress);
}
}
/// <summary>
/// RFC 5213.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Timestamp |
/// | | |
/// | | |
/// | | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.Timestamp)]
public sealed class IpV6MobilityOptionTimestamp : IpV6MobilityOptionULong
{
public IpV6MobilityOptionTimestamp(ulong timestamp)
: base(IpV6MobilityOptionType.Timestamp, timestamp)
{
}
/// <summary>
/// Timestamp.
/// The value indicates the number of seconds since January 1, 1970, 00:00 UTC, by using a fixed point format.
/// In this format, the integer number of seconds is contained in the first 48 bits of the field, and the remaining 16 bits indicate the number of 1/65536 fractions of a second.
/// </summary>
public ulong Timestamp { get { return Value; } }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
ulong timestamp;
if (!Read(data, out timestamp))
return null;
return new IpV6MobilityOptionTimestamp(timestamp);
}
}
/// <summary>
/// RFC 5847.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Restart Counter |
/// | | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.RestartCounter)]
public class IpV6MobilityOptionRestartCounter : IpV6MobilityOptionComplex
{
public const int OptionDataLength = sizeof(uint);
public IpV6MobilityOptionRestartCounter(uint restartCounter)
: base(IpV6MobilityOptionType.RestartCounter)
{
RestartCounter = restartCounter;
}
/// <summary>
/// Indicates the current Restart Counter value.
/// </summary>
public uint RestartCounter { get; private set; }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
return null;
uint restartCounter = data.ReadUInt(0, Endianity.Big);
return new IpV6MobilityOptionRestartCounter(restartCounter);
}
internal override int DataLength
{
get { return OptionDataLength; }
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(ref offset, RestartCounter, Endianity.Big);
}
}
/// <summary>
/// RFC 5555.
/// <pre>
/// +-----+-------------+--------------+----------+
/// | Bit | 0-7 | 8-13 | 14-15 |
/// +-----+-------------+--------------+----------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+----------+
/// | 16 | Status | Prefix-len | Reserved |
/// +-----+-------------+--------------+----------+
/// | 32 | IPv4 home address |
/// | | |
/// +-----+---------------------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.IpV4AddressAcknowledgement)]
public class IpV6MobilityOptionIpV4AddressAcknowledgement : IpV6MobilityOptionComplex
{
public const byte MaxPrefixLength = 0x3F;
private static class Offset
{
public const int Status = 0;
public const int PrefixLength = Status + sizeof(byte);
public const int HomeAddress = PrefixLength + sizeof(byte);
}
private static class Mask
{
public const byte PrefixLength = 0xFC;
}
private static class Shift
{
public const int PrefixLength = 2;
}
public const int OptionDataLength = Offset.HomeAddress + IpV4Address.SizeOf;
public IpV6MobilityOptionIpV4AddressAcknowledgement(IpV6AddressAcknowledgementStatus status, byte prefixLength, IpV4Address homeAddress)
: base(IpV6MobilityOptionType.IpV4AddressAcknowledgement)
{
if (prefixLength > MaxPrefixLength)
throw new ArgumentOutOfRangeException("prefixLength", prefixLength, string.Format("Exceeded maximum value {0}", MaxPrefixLength));
Status = status;
PrefixLength = prefixLength;
HomeAddress = homeAddress;
}
/// <summary>
/// Indicates success or failure for the IPv4 home address binding.
/// Values from 0 to 127 indicate success.
/// Higher values indicate failure.
/// </summary>
public IpV6AddressAcknowledgementStatus Status { get; private set; }
/// <summary>
/// The prefix length of the address allocated.
/// This field is only valid in case of success and must be set to zero and ignored in case of failure.
/// This field overrides what the mobile node requested (if not equal to the requested length).
/// </summary>
public byte PrefixLength { get; private set; }
/// <summary>
/// The IPv4 home address that the home agent will use in the binding cache entry.
/// This could be a public or private address.
/// This field must contain the mobile node's IPv4 home address.
/// If the address were dynamically allocated, the home agent will add the address to inform the mobile node.
/// Otherwise, if the address is statically allocated to the mobile node, the home agent will copy it from the binding update message.
/// </summary>
public IpV4Address HomeAddress { get; private set; }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
return null;
IpV6AddressAcknowledgementStatus status = (IpV6AddressAcknowledgementStatus)data[Offset.Status];
byte prefixLength = (byte)((data[Offset.PrefixLength] & Mask.PrefixLength) >> Shift.PrefixLength);
IpV4Address homeAddress = data.ReadIpV4Address(Offset.HomeAddress, Endianity.Big);
return new IpV6MobilityOptionIpV4AddressAcknowledgement(status, prefixLength, homeAddress);
}
internal override int DataLength
{
get { return OptionDataLength; }
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.Status, (byte)Status);
buffer.Write(offset + Offset.PrefixLength, (byte)(PrefixLength << Shift.PrefixLength));
buffer.Write(offset + Offset.HomeAddress, HomeAddress, Endianity.Big);
offset += OptionDataLength;
}
}
/// <summary>
/// RFC 5555.
/// </summary>
public enum IpV6AddressAcknowledgementStatus : byte
{
/// <summary>
/// Success.
/// </summary>
Success = 0,
/// <summary>
/// Failure, reason unspecified.
/// </summary>
FailureReasonUnspecified = 128,
/// <summary>
/// Administratively prohibited.
/// </summary>
AdministrativelyProhibited = 129,
/// <summary>
/// Incorrect IPv4 home address.
/// </summary>
IncorrectIpV4HomeAddress = 130,
/// <summary>
/// Invalid IPv4 address.
/// </summary>
InvalidIpV4Address = 131,
/// <summary>
/// Dynamic IPv4 home address assignment not available.
/// </summary>
DynamicIpV4HomeAddressAssignmentNotAvailable = 132,
/// <summary>
/// Prefix allocation unauthorized.
/// </summary>
PrefixAllocationUnauthorized = 133,
}
/// <summary>
/// RFC 5555.
/// <pre>
/// +-----+------------+---+---+--------------+
/// | Bit | 0-5 | 6 | 7 | 8-15 |
/// +-----+------------+---+---+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+------------+---+---+--------------+
/// | 16 | Prefix-len | P | Reserved |
/// +-----+------------+---+------------------+
/// | 32 | IPv4 home address |
/// | | |
/// +-----+-----------------------------------+
/// </pre>
/// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.IpV4HomeAddress)]
public class IpV6MobilityOptionIpV4HomeAddress : IpV6MobilityOptionComplex
{
public const byte MaxPrefixLength = 0x3F;
private static class Offset
{
public const int PrefixLength = 0;
public const int RequestPrefix = PrefixLength;
public const int HomeAddress = RequestPrefix + sizeof(byte) + sizeof(byte);
}
private static class Mask
{
public const byte PrefixLength = 0xFC;
public const byte RequestPrefix = 0x02;
}
private static class Shift
{
public const int PrefixLength = 2;
}
public const int OptionDataLength = Offset.HomeAddress + IpV4Address.SizeOf;
public IpV6MobilityOptionIpV4HomeAddress(byte prefixLength, bool requestPrefix, IpV4Address homeAddress)
: base(IpV6MobilityOptionType.IpV4HomeAddress)
{
if (prefixLength > MaxPrefixLength)
throw new ArgumentOutOfRangeException("prefixLength", prefixLength, string.Format("Exceeded maximum value {0}", MaxPrefixLength));
PrefixLength = prefixLength;
RequestPrefix = requestPrefix;
HomeAddress = homeAddress;
}
/// <summary>
/// The length of the prefix allocated to the mobile node.
/// If only a single address is allocated, this field must be set to 32.
/// In the first binding update requesting a prefix, the field contains the prefix length requested.
/// However, in the following binding updates, this field must contain the length of the prefix allocated.
/// A value of zero is invalid and must be considered an error.
/// </summary>
public byte PrefixLength { get; private set; }
/// <summary>
/// When true, indicates that the mobile node requests a mobile network prefix.
/// This flag is only relevant for new requests, and must be ignored for binding refreshes.
/// </summary>
public bool RequestPrefix { get; private set; }
/// <summary>
/// The mobile node's IPv4 home address that should be defended by the home agent.
/// This field could contain any unicast IPv4 address (public or private) that was assigned to the mobile node.
/// The value 0.0.0.0 is used to request an IPv4 home address from the home agent.
/// A mobile node may choose to use this option to request a prefix by setting the address to All Zeroes and setting the RequestPrefix flag.
/// The mobile node could then form an IPv4 home address based on the allocated prefix.
/// Alternatively, the mobile node may use two different options, one for requesting an address (static or dynamic) and another for requesting a
/// prefix.
/// </summary>
public IpV4Address HomeAddress { get; private set; }
internal override IpV6MobilityOption CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
return null;
byte prefixLength = (byte)((data[Offset.PrefixLength] & Mask.PrefixLength) >> Shift.PrefixLength);
bool requestPrefix = data.ReadBool(Offset.RequestPrefix, Mask.RequestPrefix);
IpV4Address homeAddress = data.ReadIpV4Address(Offset.HomeAddress, Endianity.Big);
return new IpV6MobilityOptionIpV4HomeAddress(prefixLength, requestPrefix, homeAddress);
}
internal override int DataLength
{
get { return OptionDataLength; }
}
internal override void WriteData(byte[] buffer, ref int offset)
{
byte prefixLengthAndRequestPrefix = (byte)(PrefixLength << Shift.PrefixLength);
if (RequestPrefix)
prefixLengthAndRequestPrefix |= Mask.RequestPrefix;
buffer.Write(offset + Offset.PrefixLength, prefixLengthAndRequestPrefix);
buffer.Write(offset + Offset.HomeAddress, HomeAddress, Endianity.Big);
offset += OptionDataLength;
}
}
}
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