Commit ec3b6965 authored by Brickner_cp's avatar Brickner_cp

IPv6

parent ea4bf9ef
......@@ -19,6 +19,11 @@ namespace PcapDotNet.Base
/// </summary>
public static readonly UInt24 MaxValue = (UInt24)0x00FFFFFF;
public static implicit operator UInt24(ushort value)
{
return new UInt24(value);
}
/// <summary>
/// Converts a 32 bit signed integer to a 24 bit unsigned integer by taking the 24 least significant bits.
/// </summary>
......
......@@ -69,14 +69,14 @@ namespace PcapDotNet.Packets.Test
Packet packet = PacketBuilder.Build(DateTime.Now, ethernetLayer, ipV6Layer, payloadLayer);
Assert.IsTrue(packet.IsValid, string.Format("IsValid ({0})", ipV6Layer.NextHeader));
// Assert.IsTrue(packet.IsValid, string.Format("IsValid ({0})", ipV6Layer.NextHeader));
// Ethernet
Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLengthValue, packet.Ethernet.PayloadLength, "PayloadLength");
Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer");
// Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer");
// IpV6
Assert.AreEqual(ipV6Layer, packet.Ethernet.IpV6.ExtractLayer(), "IP Layer");
// Assert.AreEqual(ipV6Layer, packet.Ethernet.IpV6.ExtractLayer(), "IP Layer");
/*
if (packet.Ethernet.IpV6.NextHeader == IpV4Protocol.Tcp)
Assert.IsInstanceOfType(packet.Ethernet.IpV6.Transport, typeof(TcpDatagram));
......
......@@ -247,7 +247,7 @@ namespace PcapDotNet.Packets.TestUtils
case IpV6OptionType.SmfDpd:
if (random.NextBool())
return new IpV6OptionSmfDpdSequenceHashAssistValue(random.NextDataSegment(random.NextInt(0, 100)));
return new IpV6OptionSmfDpdSequenceHashAssistValue(random.NextDataSegment(random.NextInt(1, 100)));
IpV6TaggerIdType taggerIdType = random.NextEnum<IpV6TaggerIdType>();
DataSegment identifier = random.NextDataSegment(random.NextInt(0, 100));
switch (taggerIdType)
......@@ -391,7 +391,8 @@ namespace PcapDotNet.Packets.TestUtils
return new IpV6MobilityOptionRestartCounter(random.NextUInt());
case IpV6MobilityOptionType.IpV4HomeAddress:
return new IpV6MobilityOptionIpV4HomeAddress(random.NextByte(), random.NextBool(), random.NextIpV4Address());
return new IpV6MobilityOptionIpV4HomeAddress(random.NextByte(IpV6MobilityOptionIpV4HomeAddress.MaxPrefixLength + 1), random.NextBool(),
random.NextIpV4Address());
case IpV6MobilityOptionType.IpV4AddressAcknowledgement:
return new IpV6MobilityOptionIpV4AddressAcknowledgement(random.NextEnum<IpV6AddressAcknowledgementStatus>(),
......
......@@ -117,7 +117,7 @@ namespace PcapDotNet.Packets.IpV6
}
nextNextHeader = (IpV4Protocol)extensionHeader[Offset.NextHeader];
extensionHeaderLength = extensionHeader[Offset.PayloadLength] * 4;
extensionHeaderLength = (extensionHeader[Offset.PayloadLength] + 2) * 4;
}
public override IpV4Protocol Protocol
......
......@@ -22,8 +22,6 @@ namespace PcapDotNet.Packets.IpV6
/// </summary>
public IpV6OptionType OptionType { get; private set; }
internal abstract IpV6Option CreateInstance(DataSegment data);
protected IpV6Option(IpV6OptionType type)
{
OptionType = type;
......
......@@ -25,7 +25,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.Calipso)]
public class IpV6OptionCalipso : IpV6OptionComplex
public class IpV6OptionCalipso : IpV6OptionComplex, IIpV6OptionComplexFactory
{
private static class Offset
{
......@@ -138,7 +138,7 @@ namespace PcapDotNet.Packets.IpV6
get { return OptionDataMinimumLength + CompartmentLengthInBytes; }
}
internal override IpV6Option CreateInstance(DataSegment data)
public IpV6Option CreateInstance(DataSegment data)
{
if (data.Length < OptionDataMinimumLength)
return null;
......@@ -165,6 +165,11 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(ref offset, CompartmentBitmap);
}
private IpV6OptionCalipso()
: this(IpV6CalipsoDomainOfInterpretation.Null, 0, 0, DataSegment.Empty)
{
}
private bool? _isChecksumCorrect;
}
}
\ No newline at end of file
......@@ -21,7 +21,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.EndpointIdentification)]
public class IpV6OptionEndpointIdentification : IpV6OptionComplex
public class IpV6OptionEndpointIdentification : IpV6OptionComplex, IIpV6OptionComplexFactory
{
private static class Offset
{
......@@ -43,12 +43,7 @@ namespace PcapDotNet.Packets.IpV6
public DataSegment DestinationEndpointIdentifier { get; private set; }
internal IpV6OptionEndpointIdentification()
: this(DataSegment.Empty, DataSegment.Empty)
{
}
internal override IpV6Option CreateInstance(DataSegment data)
public IpV6Option CreateInstance(DataSegment data)
{
if (data.Length < OptionDataMinimumLength)
return null;
......@@ -76,5 +71,10 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(ref offset, SourceEndpointIdentifier);
buffer.Write(ref offset, DestinationEndpointIdentifier);
}
private IpV6OptionEndpointIdentification()
: this(DataSegment.Empty, DataSegment.Empty)
{
}
}
}
\ No newline at end of file
......@@ -21,7 +21,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.HomeAddress)]
public class IpV6OptionHomeAddress : IpV6OptionComplex
public class IpV6OptionHomeAddress : IpV6OptionComplex, IIpV6OptionComplexFactory
{
public const int OptionDataLength = IpV6Address.SizeOf;
......@@ -37,12 +37,7 @@ namespace PcapDotNet.Packets.IpV6
/// </summary>
public IpV6Address HomeAddress { get; private set; }
internal IpV6OptionHomeAddress()
: this(IpV6Address.Zero)
{
}
internal override IpV6Option CreateInstance(DataSegment data)
public IpV6Option CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
return null;
......@@ -60,5 +55,10 @@ namespace PcapDotNet.Packets.IpV6
{
buffer.Write(ref offset, HomeAddress, Endianity.Big);
}
private IpV6OptionHomeAddress()
: this(IpV6Address.Zero)
{
}
}
}
\ No newline at end of file
......@@ -16,7 +16,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.IlnpNonce)]
public class IpV6OptionIlnpNonce : IpV6OptionComplex
public class IpV6OptionIlnpNonce : IpV6OptionComplex, IIpV6OptionComplexFactory
{
public IpV6OptionIlnpNonce(DataSegment nonce)
: base(IpV6OptionType.IlnpNonce)
......@@ -29,12 +29,7 @@ namespace PcapDotNet.Packets.IpV6
/// </summary>
public DataSegment Nonce { get; private set; }
internal IpV6OptionIlnpNonce()
: this(DataSegment.Empty)
{
}
internal override IpV6Option CreateInstance(DataSegment data)
public IpV6Option CreateInstance(DataSegment data)
{
return new IpV6OptionIlnpNonce(data);
}
......@@ -48,5 +43,10 @@ namespace PcapDotNet.Packets.IpV6
{
buffer.Write(ref offset, Nonce);
}
private IpV6OptionIlnpNonce()
: this(DataSegment.Empty)
{
}
}
}
\ No newline at end of file
......@@ -14,7 +14,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.JumboPayload)]
public class IpV6OptionJumboPayload : IpV6OptionComplex
public class IpV6OptionJumboPayload : IpV6OptionComplex, IIpV6OptionComplexFactory
{
public const int OptionDataLength = sizeof(uint);
......@@ -29,7 +29,7 @@ namespace PcapDotNet.Packets.IpV6
/// </summary>
public uint JumboPayloadLength { get; private set; }
internal override IpV6Option CreateInstance(DataSegment data)
public IpV6Option CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
return null;
......@@ -46,5 +46,10 @@ namespace PcapDotNet.Packets.IpV6
{
buffer.Write(ref offset, JumboPayloadLength, Endianity.Big);
}
private IpV6OptionJumboPayload()
: this(0)
{
}
}
}
\ No newline at end of file
......@@ -22,7 +22,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.LineIdentification)]
public class IpV6OptionLineIdentificationDestination : IpV6OptionComplex
public class IpV6OptionLineIdentificationDestination : IpV6OptionComplex, IIpV6OptionComplexFactory
{
private static class Offset
{
......@@ -50,12 +50,7 @@ namespace PcapDotNet.Packets.IpV6
/// </summary>
public DataSegment LineIdentification { get; private set; }
internal IpV6OptionLineIdentificationDestination()
: this(DataSegment.Empty)
{
}
internal override IpV6Option CreateInstance(DataSegment data)
public IpV6Option CreateInstance(DataSegment data)
{
if (data.Length < OptionDataMinimumLength)
return null;
......@@ -78,5 +73,10 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(ref offset, (byte)LineIdentification.Length);
buffer.Write(ref offset, LineIdentification);
}
private IpV6OptionLineIdentificationDestination()
: this(DataSegment.Empty)
{
}
}
}
\ No newline at end of file
......@@ -16,7 +16,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.PadN)]
public class IpV6OptionPadN : IpV6OptionComplex
public class IpV6OptionPadN : IpV6OptionComplex, IIpV6OptionComplexFactory
{
public IpV6OptionPadN(int paddingDataLength) : base(IpV6OptionType.PadN)
{
......@@ -25,7 +25,7 @@ namespace PcapDotNet.Packets.IpV6
public int PaddingDataLength { get; private set; }
internal override IpV6Option CreateInstance(DataSegment data)
public IpV6Option CreateInstance(DataSegment data)
{
return new IpV6OptionPadN(data.Length);
}
......@@ -39,5 +39,10 @@ namespace PcapDotNet.Packets.IpV6
{
offset += PaddingDataLength;
}
private IpV6OptionPadN()
: this(0)
{
}
}
}
\ No newline at end of file
......@@ -16,7 +16,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.QuickStart)]
public class IpV6OptionQuickStart : IpV6OptionComplex, IIpOptionQuickStart
public class IpV6OptionQuickStart : IpV6OptionComplex, IIpOptionQuickStart, IIpV6OptionComplexFactory
{
public const int OptionDataLength = IpOptionQuickStartCommon.DataLength;
......@@ -47,7 +47,7 @@ namespace PcapDotNet.Packets.IpV6
get { return OptionDataLength; }
}
internal override IpV6Option CreateInstance(DataSegment data)
public IpV6Option CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
return null;
......@@ -65,5 +65,10 @@ namespace PcapDotNet.Packets.IpV6
{
IpOptionQuickStartCommon.WriteData(buffer, ref offset, Function, Rate, Ttl, Nonce);
}
private IpV6OptionQuickStart()
: this(IpV4OptionQuickStartFunction.RateRequest, 0, 0, 0)
{
}
}
}
\ No newline at end of file
......@@ -13,7 +13,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.RouterAlert)]
public class IpV6OptionRouterAlert : IpV6OptionComplex
public class IpV6OptionRouterAlert : IpV6OptionComplex, IIpV6OptionComplexFactory
{
public const int OptionDataLength = sizeof(ushort);
......@@ -28,7 +28,7 @@ namespace PcapDotNet.Packets.IpV6
/// </summary>
public IpV6RouterAlertType RouterAlertType { get; private set; }
internal override IpV6Option CreateInstance(DataSegment data)
public IpV6Option CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
return null;
......@@ -45,5 +45,10 @@ namespace PcapDotNet.Packets.IpV6
{
buffer.Write(ref offset, (ushort)RouterAlertType, Endianity.Big);
}
private IpV6OptionRouterAlert()
: this(IpV6RouterAlertType.MulticastListenerDiscovery)
{
}
}
}
\ No newline at end of file
......@@ -19,7 +19,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.RplOption)]
public class IpV6OptionRoutingProtocolLowPowerAndLossyNetworks : IpV6OptionComplex
public class IpV6OptionRoutingProtocolLowPowerAndLossyNetworks : IpV6OptionComplex, IIpV6OptionComplexFactory
{
private static class Offset
{
......@@ -89,12 +89,7 @@ namespace PcapDotNet.Packets.IpV6
/// </summary>
public DataSegment SubTlvs { get; private set; }
internal IpV6OptionRoutingProtocolLowPowerAndLossyNetworks()
: this(false, false, false, 0, 0, DataSegment.Empty)
{
}
internal override IpV6Option CreateInstance(DataSegment data)
public IpV6Option CreateInstance(DataSegment data)
{
if (data.Length < OptionDataMinimumLength)
return null;
......@@ -122,5 +117,10 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(ref offset, SenderRank, Endianity.Big);
buffer.Write(ref offset, SubTlvs);
}
private IpV6OptionRoutingProtocolLowPowerAndLossyNetworks()
: this(false, false, false, 0, 0, DataSegment.Empty)
{
}
}
}
\ No newline at end of file
......@@ -27,10 +27,5 @@ namespace PcapDotNet.Packets.IpV6
{
base.Write(buffer, ref offset);
}
internal override sealed IpV6Option CreateInstance(DataSegment data)
{
throw new InvalidOperationException("Simple options shouldn't be registered.");
}
}
}
......@@ -17,7 +17,6 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+----------------------+
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.SmfDpd)]
public abstract class IpV6OptionSmfDpd : IpV6OptionComplex
{
private static class Offset
......@@ -43,8 +42,7 @@ namespace PcapDotNet.Packets.IpV6
/// 1 == indicates a hash assist value (HAV) field follows to aid in avoiding hash-based DPD collisions.
/// </summary>
public abstract bool HashIndicator { get; }
internal override IpV6Option CreateInstance(DataSegment data)
internal static IpV6Option CreateInstance(DataSegment data)
{
if (data.Length < OptionDataMinimumLength)
return null;
......@@ -55,4 +53,13 @@ namespace PcapDotNet.Packets.IpV6
return IpV6OptionSmfDpdSequenceBased.CreateSpecificInstance(data);
}
}
[IpV6OptionTypeRegistration(IpV6OptionType.SmfDpd)]
internal class IpV6OptionSmfDpdFactory : IIpV6OptionComplexFactory
{
public IpV6Option CreateInstance(DataSegment data)
{
return IpV6OptionSmfDpd.CreateInstance(data);
}
}
}
\ No newline at end of file
......@@ -13,7 +13,7 @@ namespace PcapDotNet.Packets.IpV6
/// </pre>
/// </summary>
[IpV6OptionTypeRegistration(IpV6OptionType.TunnelEncapsulationLimit)]
public class IpV6OptionTunnelEncapsulationLimit : IpV6OptionComplex
public class IpV6OptionTunnelEncapsulationLimit : IpV6OptionComplex, IIpV6OptionComplexFactory
{
public const int OptionDataLength = sizeof(byte);
......@@ -28,7 +28,7 @@ namespace PcapDotNet.Packets.IpV6
/// </summary>
public byte TunnelEncapsulationLimit { get; private set; }
internal override IpV6Option CreateInstance(DataSegment data)
public IpV6Option CreateInstance(DataSegment data)
{
if (data.Length != OptionDataLength)
return null;
......@@ -45,5 +45,10 @@ namespace PcapDotNet.Packets.IpV6
{
buffer.Write(ref offset, TunnelEncapsulationLimit);
}
private IpV6OptionTunnelEncapsulationLimit()
: this(0)
{
}
}
}
\ No newline at end of file
......@@ -7,6 +7,11 @@ using PcapDotNet.Packets.Ip;
namespace PcapDotNet.Packets.IpV6
{
internal interface IIpV6OptionComplexFactory
{
IpV6Option CreateInstance(DataSegment data);
}
public class IpV6Options : Options<IpV6Option>
{
public IpV6Options(IList<IpV6Option> options)
......@@ -65,24 +70,23 @@ namespace PcapDotNet.Packets.IpV6
private static IpV6Option CreateOption(IpV6OptionType optionType, DataSegment data)
{
IpV6Option prototype;
if (!_prototypes.TryGetValue(optionType, out prototype))
IIpV6OptionComplexFactory factory;
if (!_factories.TryGetValue(optionType, out factory))
return new IpV6OptionUnknown(optionType, data);
return prototype.CreateInstance(data);
return factory.CreateInstance(data);
}
private static readonly Dictionary<IpV6OptionType, IpV6Option> _prototypes = InitializePrototypes();
private static readonly Dictionary<IpV6OptionType, IIpV6OptionComplexFactory> _factories = InitializeFactories();
private static Dictionary<IpV6OptionType, IpV6Option> InitializePrototypes()
private static Dictionary<IpV6OptionType, IIpV6OptionComplexFactory> InitializeFactories()
{
var prototypes =
from type in Assembly.GetExecutingAssembly().GetTypes()
where typeof(IpV6Option).IsAssignableFrom(type) &&
GetRegistrationAttribute(type) != null
where GetRegistrationAttribute(type) != null
select new
{
GetRegistrationAttribute(type).OptionType,
Option = (IpV6Option)Activator.CreateInstance(type)
Option = (IIpV6OptionComplexFactory)Activator.CreateInstance(type, true)
};
return prototypes.ToDictionary(option => option.OptionType, option => option.Option);
......@@ -195,7 +199,7 @@ namespace PcapDotNet.Packets.IpV6
select new
{
GetRegistrationAttribute(type).OptionType,
Option = (IpV6MobilityOption)Activator.CreateInstance(type)
Option = (IpV6MobilityOption)Activator.CreateInstance(type, true)
};
return prototypes.ToDictionary(option => option.OptionType, option => option.Option);
......
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