Commit ea4bf9ef authored by Brickner_cp's avatar Brickner_cp

IPv6

parent 12713caf
using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.IpV6;
using PcapDotNet.Packets.TestUtils;
using PcapDotNet.Packets.Transport;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.Test
{
/// <summary>
/// Summary description for IpV6Tests
/// </summary>
[TestClass]
public class IpV6Tests
{
/// <summary>
/// Gets or sets the test context which provides
/// information about and functionality for the current test run.
/// </summary>
public TestContext TestContext { get; set; }
#region Additional test attributes
//
// You can use the following additional attributes as you write your tests:
//
// Use ClassInitialize to run code before running the first test in the class
// [ClassInitialize()]
// public static void MyClassInitialize(TestContext testContext) { }
//
// Use ClassCleanup to run code after all tests in a class have run
// [ClassCleanup()]
// public static void MyClassCleanup() { }
//
// Use TestInitialize to run code before running each test
// [TestInitialize()]
// public void MyTestInitialize() { }
//
// Use TestCleanup to run code after each test has run
// [TestCleanup()]
// public void MyTestCleanup() { }
//
#endregion
[TestMethod]
public void RandomIpV6Test()
{
MacAddress ethernetSource = new MacAddress("00:01:02:03:04:05");
MacAddress ethernetDestination = new MacAddress("A0:A1:A2:A3:A4:A5");
const EthernetType EthernetType = EthernetType.IpV6;
EthernetLayer ethernetLayer = new EthernetLayer
{
Source = ethernetSource,
Destination = ethernetDestination,
EtherType = EthernetType
};
Random random = new Random();
for (int i = 0; i != 1000; ++i)
{
IpV6Layer ipV6Layer = random.NextIpV6Layer();
PayloadLayer payloadLayer = random.NextPayloadLayer(random.NextInt(0, 50 * 1024));
Packet packet = PacketBuilder.Build(DateTime.Now, ethernetLayer, ipV6Layer, payloadLayer);
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");
// IpV6
Assert.AreEqual(ipV6Layer, packet.Ethernet.IpV6.ExtractLayer(), "IP Layer");
/*
if (packet.Ethernet.IpV6.NextHeader == IpV4Protocol.Tcp)
Assert.IsInstanceOfType(packet.Ethernet.IpV6.Transport, typeof(TcpDatagram));
else if (packet.Ethernet.IpV6.NextHeader == IpV4Protocol.Udp)
Assert.IsInstanceOfType(packet.Ethernet.IpV6.Transport, typeof(UdpDatagram));
else
Assert.IsNull(packet.Ethernet.IpV6.Transport);
*/
// Assert.AreEqual(payloadLayer.Data, packet.Ethernet.IpV6.Payload, "IP Payload");
}
}
}
}
\ No newline at end of file
...@@ -81,6 +81,7 @@ ...@@ -81,6 +81,7 @@
<Compile Include="IgmpTests.cs" /> <Compile Include="IgmpTests.cs" />
<Compile Include="IpV4Tests.cs" /> <Compile Include="IpV4Tests.cs" />
<Compile Include="IpV6AddressTests.cs" /> <Compile Include="IpV6AddressTests.cs" />
<Compile Include="IpV6Tests.cs" />
<Compile Include="MacAddressTests.cs" /> <Compile Include="MacAddressTests.cs" />
<Compile Include="PacketBuilderTests.cs" /> <Compile Include="PacketBuilderTests.cs" />
<Compile Include="PacketTests.cs" /> <Compile Include="PacketTests.cs" />
......
using System; using System;
using System.Collections.Generic;
using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ip;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.IpV6; using PcapDotNet.Packets.IpV6;
using PcapDotNet.TestUtils; using PcapDotNet.TestUtils;
...@@ -10,5 +15,533 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -10,5 +15,533 @@ namespace PcapDotNet.Packets.TestUtils
{ {
return new IpV6Address(random.NextUInt128()); return new IpV6Address(random.NextUInt128());
} }
public static IpV6Address[] NextIpV6AddressArray(this Random random, int count)
{
return ((Func<IpV6Address>)(random.NextIpV6Address)).GenerateArray(count);
}
public static IpV6Layer NextIpV6Layer(this Random random)
{
IpV6ExtensionHeaders extensionHeaders = random.NextIpV6ExtensionHeaders(random.NextInt(0, 10));
IpV4Protocol nextHeader = extensionHeaders.FirstHeader ?? random.NextEnum<IpV4Protocol>(IpV6ExtensionHeader.ExtensionHeaders);
return new IpV6Layer
{
TrafficClass = random.NextByte(),
FlowLabel = random.NextInt(0, IpV6Datagram.MaxFlowLabel + 1),
NextHeader = nextHeader,
HopLimit = random.NextByte(),
Source = random.NextIpV6Address(),
CurrentDestination = random.NextIpV6Address(),
ExtensionHeaders = random.NextIpV6ExtensionHeaders(random.NextInt(0, 10)),
};
}
public static IpV6ExtensionHeaders NextIpV6ExtensionHeaders(this Random random, int count)
{
if (count == 0)
return IpV6ExtensionHeaders.Empty;
IpV4Protocol nextHeader = random.NextEnum<IpV4Protocol>(IpV6ExtensionHeader.ExtensionHeaders);
IpV6ExtensionHeader[] headers = new IpV6ExtensionHeader[count];
for (int i = headers.Length - 1; i >= 0; --i)
{
headers[i] = random.NextIpV6ExtensionHeader(nextHeader);
nextHeader = headers[i].Protocol;
}
return new IpV6ExtensionHeaders(headers);
}
public static IpV6ExtensionHeader NextIpV6ExtensionHeader(this Random random, IpV4Protocol nextHeader)
{
IpV4Protocol extensionHeaderType = random.NextValue(IpV6ExtensionHeader.ExtensionHeaders);
switch (extensionHeaderType)
{
case IpV4Protocol.IpV6HopByHopOption: // 0
return new IpV6ExtensionHeaderHopByHopOptions(nextHeader, random.NextIpV6Options());
case IpV4Protocol.IpV6Route: // 43
IpV6RoutingType routingType = random.NextEnum(IpV6RoutingType.Nimrod);
switch (routingType)
{
case IpV6RoutingType.SourceRoute:
return new IpV6ExtensionHeaderRoutingSourceRoute(nextHeader, random.NextByte(), random.NextIpV6AddressArray(random.NextInt(0, 10)));
case IpV6RoutingType.Type2RoutingHeader:
return new IpV6ExtensionHeaderRoutingHomeAddress(nextHeader, random.NextByte(), random.NextIpV6Address());
case IpV6RoutingType.RplSourceRouteHeader:
return new IpV6ExtensionHeaderRoutingRpl(nextHeader, random.NextByte(),
random.NextByte(IpV6ExtensionHeaderRoutingRpl.MaxCommonPrefixLength + 1),
random.NextByte(IpV6ExtensionHeaderRoutingRpl.MaxCommonPrefixLength + 1),
random.NextByte(IpV6ExtensionHeaderRoutingRpl.MaxPadSize + 1),
random.NextIpV6AddressArray(random.NextInt(0, 10)));
default:
throw new InvalidOperationException(string.Format("Invalid routingType value {0}", routingType));
}
case IpV4Protocol.FragmentHeaderForIpV6: // 44
return new IpV6ExtensionHeaderFragmentData(nextHeader, random.NextUShort(IpV6ExtensionHeaderFragmentData.MaxFragmentOffset + 1),
random.NextBool(), random.NextUInt());
case IpV4Protocol.IpV6Opts: // 60
return new IpV6ExtensionHeaderDestinationOptions(nextHeader, random.NextIpV6Options());
case IpV4Protocol.MobilityHeader: // 135
return random.NextIpV6ExtensionHeaderMobility(nextHeader);
case IpV4Protocol.EncapsulatingSecurityPayload: // 50
return new IpV6ExtensionHeaderEncapsulatingSecurityPayload(random.NextUInt(), random.NextUInt(), random.NextDataSegment(random.Next(100)));
case IpV4Protocol.AuthenticationHeader: // 51
return new IpV6ExtensionHeaderAuthentication(nextHeader, random.NextUInt(), random.NextUInt(), random.NextDataSegment(random.Next(100)));
default:
throw new InvalidOperationException(string.Format("Invalid extensionHeaderType value {0}", extensionHeaderType));
}
}
public static IpV6ExtensionHeaderMobility NextIpV6ExtensionHeaderMobility(this Random random, IpV4Protocol nextHeader)
{
IpV6MobilityHeaderType mobilityHeaderType = random.NextEnum<IpV6MobilityHeaderType>();
ushort checksum = random.NextUShort();
switch (mobilityHeaderType)
{
case IpV6MobilityHeaderType.BindingRefreshRequest: // 0
return new IpV6ExtensionHeaderMobilityBindingRefreshRequest(nextHeader, checksum, random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.HomeTestInit: // 1
return new IpV6ExtensionHeaderMobilityHomeTestInit(nextHeader, checksum, random.NextULong(), random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.CareOfTestInit: // 2
return new IpV6ExtensionHeaderMobilityCareOfTestInit(nextHeader, checksum, random.NextULong(), random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.HomeTest: // 3
return new IpV6ExtensionHeaderMobilityHomeTest(nextHeader, checksum, random.NextUShort(), random.NextULong(), random.NextULong(),
random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.CareOfTest: // 4
return new IpV6ExtensionHeaderMobilityCareOfTest(nextHeader, checksum, random.NextUShort(), random.NextULong(), random.NextULong(),
random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.BindingUpdate: // 5
return new IpV6ExtensionHeaderMobilityBindingUpdate(nextHeader, checksum, random.NextUShort(), random.NextBool(), random.NextBool(),
random.NextBool(), random.NextBool(), random.NextUShort(),
random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.BindingAcknowledgement: // 6
return new IpV6ExtensionHeaderMobilityBindingAcknowledgement(nextHeader, checksum, random.NextEnum<IpV6BindingAcknowledgementStatus>(),
random.NextBool(), random.NextUShort(), random.NextUShort(),
random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.BindingError: // 7
return new IpV6ExtensionHeaderMobilityBindingError(nextHeader, checksum, random.NextEnum<IpV6BindingErrorStatus>(), random.NextIpV6Address(),
random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.FastBindingUpdate: // 8
return new IpV6ExtensionHeaderMobilityFastBindingUpdate(nextHeader, checksum, random.NextUShort(), random.NextBool(), random.NextBool(),
random.NextBool(), random.NextBool(), random.NextUShort(),
random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.FastBindingAcknowledgement: // 9
return new IpV6ExtensionHeaderMobilityFastBindingAcknowledgement(nextHeader, checksum, random.NextEnum<IpV6BindingAcknowledgementStatus>(),
random.NextBool(), random.NextUShort(), random.NextUShort(),
random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.FastNeighborAdvertisement: // 10
return new IpV6ExtensionHeaderMobilityFastNeighborAdvertisement(nextHeader, checksum, random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.Experimental: // 11
return new IpV6ExtensionHeaderMobilityExperimental(nextHeader, checksum, random.NextDataSegment(random.Next(100)));
case IpV6MobilityHeaderType.HomeAgentSwitchMessage: // 12
return new IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage(nextHeader, checksum, random.NextIpV6AddressArray(random.NextInt(0, 10)),
random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.HeartbeatMessage: // 13
return new IpV6ExtensionHeaderMobilityHeartbeatMessage(nextHeader, checksum, random.NextBool(), random.NextBool(), random.NextUInt(),
random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.HandoverInitiateMessage: // 14
return new IpV6ExtensionHeaderMobilityHandoverInitiateMessage(nextHeader, checksum, random.NextUShort(), random.NextBool(),
random.NextBool(), random.NextEnum<IpV6HandoverInitiateMessageCode>(),
random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.HandoverAcknowledgeMessage: // 15
return new IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage(nextHeader, checksum, random.NextUShort(),
random.NextEnum<IpV6MobilityHandoverAcknowledgeCode>(),
random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.BindingRevocationMessage: // 16
IpV6MobilityBindingRevocationType bindingRevocationType = random.NextEnum<IpV6MobilityBindingRevocationType>();
byte revocationTriggerOrStatus = random.NextByte();
ushort sequenceNumber = random.NextUShort();
bool proxyBinding = random.NextBool();
bool ipV4HomeAddressBindingOnly = random.NextBool();
bool global = random.NextBool();
IpV6MobilityOptions options = random.NextIpV6MobilityOptions();
switch (bindingRevocationType)
{
case IpV6MobilityBindingRevocationType.BindingRevocationIndication:
return new IpV6ExtensionHeaderMobilityBindingRevocationIndicationMessage(
nextHeader, checksum, (Ipv6MobilityBindingRevocationTrigger)revocationTriggerOrStatus, sequenceNumber, proxyBinding,
ipV4HomeAddressBindingOnly, global, options);
case IpV6MobilityBindingRevocationType.BindingRevocationAcknowledgement:
return new IpV6ExtensionHeaderMobilityBindingRevocationAcknowledgementMessage(
nextHeader, checksum, (Ipv6MobilityBindingRevocationStatus)revocationTriggerOrStatus, sequenceNumber, proxyBinding,
ipV4HomeAddressBindingOnly, global, options);
default:
throw new InvalidOperationException(string.Format("Invalid bindingRevocationType value {0}", bindingRevocationType));
}
case IpV6MobilityHeaderType.LocalizedRoutingInitiation: // 17
return new IpV6ExtensionHeaderMobilityLocalizedRoutingInitiation(nextHeader, checksum, random.NextUShort(), random.NextUShort(),
random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.LocalizedRoutingAcknowledgement: // 18
return new IpV6ExtensionHeaderMobilityLocalizedRoutingAcknowledgement(nextHeader, checksum, random.NextUShort(), random.NextBool(),
random.NextUShort(), random.NextIpV6MobilityOptions());
default:
throw new InvalidOperationException(string.Format("Invalid mobilityHeaderType value {0}", mobilityHeaderType));
}
}
public static IpV6Options NextIpV6Options(this Random random)
{
return new IpV6Options(((Func<IpV6Option>)(random.NextIpV6Option)).GenerateArray(random.NextInt(0, 10)));
}
public static IpV6Option NextIpV6Option(this Random random)
{
IpV6OptionType optionType = random.NextEnum<IpV6OptionType>();
switch (optionType)
{
case IpV6OptionType.Pad1:
return new IpV6OptionPad1();
case IpV6OptionType.PadN:
return new IpV6OptionPadN(random.Next(10));
case IpV6OptionType.JumboPayload:
return new IpV6OptionJumboPayload(random.NextUInt());
case IpV6OptionType.TunnelEncapsulationLimit:
return new IpV6OptionTunnelEncapsulationLimit(random.NextByte());
case IpV6OptionType.RouterAlert:
return new IpV6OptionRouterAlert(random.NextEnum<IpV6RouterAlertType>());
case IpV6OptionType.QuickStart:
return new IpV6OptionQuickStart(random.NextEnum<IpV4OptionQuickStartFunction>(),
random.NextByte(IpOptionQuickStartCommon.RateMaximumValue + 1), random.NextByte(),
random.NextUInt() & 0xFFFFFFFC);
case IpV6OptionType.Calipso:
return new IpV6OptionCalipso(random.NextEnum<IpV6CalipsoDomainOfInterpretation>(), random.NextByte(), random.NextUShort(),
random.NextDataSegment(random.NextByte() * sizeof(int)));
case IpV6OptionType.SmfDpd:
if (random.NextBool())
return new IpV6OptionSmfDpdSequenceHashAssistValue(random.NextDataSegment(random.NextInt(0, 100)));
IpV6TaggerIdType taggerIdType = random.NextEnum<IpV6TaggerIdType>();
DataSegment identifier = random.NextDataSegment(random.NextInt(0, 100));
switch (taggerIdType)
{
case IpV6TaggerIdType.Null:
return new IpV6OptionSmfDpdNull(identifier);
case IpV6TaggerIdType.Default:
return new IpV6OptionSmfDpdDefault(random.NextDataSegment(random.NextInt(0, 100)), identifier);
case IpV6TaggerIdType.IpV4:
return new IpV6OptionSmfDpdIpV4(random.NextIpV4Address(), identifier);
case IpV6TaggerIdType.IpV6:
return new IpV6OptionSmfDpdIpV6(random.NextIpV6Address(), identifier);
default:
throw new InvalidOperationException(string.Format("Invalid taggerIdType value {0}", taggerIdType));
}
case IpV6OptionType.HomeAddress:
return new IpV6OptionHomeAddress(random.NextIpV6Address());
case IpV6OptionType.EndpointIdentification:
return new IpV6OptionEndpointIdentification(random.NextDataSegment(random.Next(10)), random.NextDataSegment(random.Next(10)));
case IpV6OptionType.RplOption:
return new IpV6OptionRoutingProtocolLowPowerAndLossyNetworks(random.NextBool(), random.NextBool(), random.NextBool(), random.NextByte(),
random.NextUShort(), random.NextDataSegment(random.Next(10)));
case IpV6OptionType.IlnpNonce:
return new IpV6OptionIlnpNonce(random.NextDataSegment(random.Next(10)));
case IpV6OptionType.LineIdentification:
return new IpV6OptionLineIdentificationDestination(random.NextDataSegment(random.Next(10)));
default:
throw new InvalidOperationException(string.Format("Invalid optionType value {0}", optionType));
}
}
public static IpV6MobilityOptions NextIpV6MobilityOptions(this Random random)
{
return new IpV6MobilityOptions(((Func<IpV6MobilityOption>)(random.NextIpV6MobilityOption)).GenerateArray(random.NextInt(0, 10)));
}
public static IpV6MobilityOption NextIpV6MobilityOption(this Random random)
{
IpV6MobilityOptionType optionType = random.NextEnum<IpV6MobilityOptionType>();
switch (optionType)
{
case IpV6MobilityOptionType.Pad1:
return new IpV6MobilityOptionPad1();
case IpV6MobilityOptionType.PadN:
return new IpV6MobilityOptionPadN(random.NextInt(0, 10));
case IpV6MobilityOptionType.BindingRefreshAdvice:
return new IpV6MobilityOptionBindingRefreshAdvice(random.NextUShort());
case IpV6MobilityOptionType.AlternateCareOfAddress:
return new IpV6MobilityOptionAlternateCareOfAddress(random.NextIpV6Address());
case IpV6MobilityOptionType.NonceIndices:
return new IpV6MobilityOptionNonceIndices(random.NextUShort(), random.NextUShort());
case IpV6MobilityOptionType.BindingAuthorizationData:
return new IpV6MobilityOptionBindingAuthorizationData(random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.MobileNetworkPrefix:
return new IpV6MobilityOptionMobileNetworkPrefix(random.NextByte(), random.NextIpV6Address());
case IpV6MobilityOptionType.LinkLayerAddress:
return new IpV6MobilityOptionLinkLayerAddress(random.NextEnum<IpV6MobilityLinkLayerAddressCode>(),
random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.MobileNodeIdentifier:
return new IpV6MobilityOptionMobileNodeIdentifier(random.NextEnum<IpV6MobileNodeIdentifierSubtype>(),
random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.Authentication:
return new IpV6MobilityOptionAuthentication(random.NextEnum<IpV6AuthenticationSubtype>(), random.NextUInt(),
random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.ReplayProtection:
return new IpV6MobilityOptionReplayProtection(random.NextULong());
case IpV6MobilityOptionType.CgaParametersRequest:
return new IpV6MobilityOptionCgaParametersRequest();
case IpV6MobilityOptionType.CgaParameters:
return new IpV6MobilityOptionCgaParameters(random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.Signature:
return new IpV6MobilityOptionSignature(random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.PermanentHomeKeygenToken:
return new IpV6MobilityOptionPermanentHomeKeygenToken(random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.CareOfTestInit:
return new IpV6MobilityOptionCareOfTest(random.NextULong());
case IpV6MobilityOptionType.CareOfTest:
return new IpV6MobilityOptionCareOfTest(random.NextULong());
case IpV6MobilityOptionType.DnsUpdate:
return new IpV6MobilityOptionDnsUpdate(random.NextEnum<IpV6DnsUpdateStatus>(), random.NextBool(),
random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.Experimental:
return new IpV6MobilityOptionExperimental(random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.VendorSpecific:
return new IpV6MobilityOptionVendorSpecific(random.NextUInt(), random.NextByte(), random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.ServiceSelection:
return new IpV6MobilityOptionServiceSelection(random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.BindingAuthorizationDataForFmIpV6:
return new IpV6MobilityOptionBindingAuthorizationDataForFmIpV6(random.NextUInt(), random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.HomeNetworkPrefix:
return new IpV6MobilityOptionHomeNetworkPrefix(random.NextByte(), random.NextIpV6Address());
case IpV6MobilityOptionType.HandoffIndicator:
return new IpV6MobilityOptionHandoffIndicator(random.NextEnum<IpV6HandoffIndicator>());
case IpV6MobilityOptionType.AccessTechnologyType:
return new IpV6MobilityOptionAccessTechnologyType(random.NextEnum<IpV6AccessTechnologyType>());
case IpV6MobilityOptionType.MobileNodeLinkLayerIdentifier:
return new IpV6MobilityOptionMobileNodeLinkLayerIdentifier(random.NextDataSegment(random.NextInt(0, 100)));
case IpV6MobilityOptionType.LinkLocalAddress:
return new IpV6MobilityOptionLinkLocalAddress(random.NextIpV6Address());
case IpV6MobilityOptionType.Timestamp:
return new IpV6MobilityOptionTimestamp(random.NextULong());
case IpV6MobilityOptionType.RestartCounter:
return new IpV6MobilityOptionRestartCounter(random.NextUInt());
case IpV6MobilityOptionType.IpV4HomeAddress:
return new IpV6MobilityOptionIpV4HomeAddress(random.NextByte(), random.NextBool(), random.NextIpV4Address());
case IpV6MobilityOptionType.IpV4AddressAcknowledgement:
return new IpV6MobilityOptionIpV4AddressAcknowledgement(random.NextEnum<IpV6AddressAcknowledgementStatus>(),
random.NextByte(IpV6MobilityOptionIpV4AddressAcknowledgement.MaxPrefixLength + 1),
random.NextIpV4Address());
case IpV6MobilityOptionType.NatDetection:
return new IpV6MobilityOptionNatDetection(random.NextBool(), random.NextUInt());
case IpV6MobilityOptionType.IpV4CareOfAddress:
return new IpV6MobilityOptionIpV4CareOfAddress(random.NextIpV4Address());
case IpV6MobilityOptionType.GreKey:
return new IpV6MobilityOptionGreKey(random.NextUInt());
case IpV6MobilityOptionType.IpV6AddressPrefix:
return new IpV6MobilityOptionIpV6AddressPrefix(random.NextEnum<IpV6MobilityIpV6AddressPrefixCode>(),
random.NextByte(IpV6MobilityOptionIpV6AddressPrefix.MaxPrefixLength + 1),
random.NextIpV6Address());
case IpV6MobilityOptionType.BindingIdentifier:
ushort bindingId = random.NextUShort();
IpV6BindingAcknowledgementStatus status = random.NextEnum<IpV6BindingAcknowledgementStatus>();
bool simultaneousHomeAndForeignBinding = random.NextBool();
byte priority = random.NextByte(IpV6MobilityOptionBindingIdentifier.MaxPriority + 1);
if (random.NextBool(3))
return new IpV6MobilityOptionBindingIdentifier(bindingId, status, simultaneousHomeAndForeignBinding, priority);
if (random.NextBool())
return new IpV6MobilityOptionBindingIdentifier(bindingId, status, simultaneousHomeAndForeignBinding, priority, random.NextIpV4Address());
return new IpV6MobilityOptionBindingIdentifier(bindingId, status, simultaneousHomeAndForeignBinding, priority, random.NextIpV6Address());
case IpV6MobilityOptionType.IpV4HomeAddressRequest:
return new IpV6MobilityOptionIpV4HomeAddressRequest(random.NextByte(IpV6MobilityOptionIpV4HomeAddressRequest.MaxPrefixLength + 1),
random.NextIpV4Address());
case IpV6MobilityOptionType.IpV4HomeAddressReply:
return new IpV6MobilityOptionIpV4HomeAddressReply(random.NextEnum<IpV6IpV4HomeAddressReplyStatus>(),
random.NextByte(IpV6MobilityOptionIpV4HomeAddressReply.MaxPrefixLength + 1),
random.NextIpV4Address());
case IpV6MobilityOptionType.IpV4DefaultRouterAddress:
return new IpV6MobilityOptionIpV4DefaultRouterAddress(random.NextIpV4Address());
case IpV6MobilityOptionType.IpV4DhcpSupportMode:
return new IpV6MobilityOptionIpV4DhcpSupportMode(random.NextBool());
case IpV6MobilityOptionType.ContextRequest:
return
new IpV6MobilityOptionContextRequest(
((Func<IpV6MobilityOptionContextRequestEntry>)(() => new IpV6MobilityOptionContextRequestEntry(
random.NextByte(), random.NextDataSegment(random.NextInt(0, 100))))).
GenerateArray(random.NextInt(0, 10)));
case IpV6MobilityOptionType.LocalMobilityAnchorAddress:
if (random.NextBool())
return new IpV6MobilityOptionLocalMobilityAnchorAddress(random.NextIpV4Address());
return new IpV6MobilityOptionLocalMobilityAnchorAddress(random.NextIpV6Address());
case IpV6MobilityOptionType.MobileNodeLinkLocalAddressInterfaceIdentifier:
return new IpV6MobilityOptionMobileNodeLinkLocalAddressInterfaceIdentifier(random.NextULong());
case IpV6MobilityOptionType.TransientBinding:
return new IpV6MobilityOptionTransientBinding(random.NextBool(), random.NextByte());
case IpV6MobilityOptionType.FlowSummary:
return new IpV6MobilityOptionFlowSummary(((Func<ushort>)(random.NextUShort)).GenerateArray(random.NextInt(1, 10)));
case IpV6MobilityOptionType.FlowIdentification:
return new IpV6MobilityOptionFlowIdentification(random.NextUShort(), random.NextUShort(), random.NextEnum<IpV6FlowIdentificationStatus>(),
random.NextIpV6FlowIdentificationSubOptions());
case IpV6MobilityOptionType.RedirectCapability:
return new IpV6MobilityOptionRedirectCapability();
case IpV6MobilityOptionType.Redirect:
if (random.NextBool())
return new IpV6MobilityOptionRedirect(random.NextIpV4Address());
return new IpV6MobilityOptionRedirect(random.NextIpV6Address());
case IpV6MobilityOptionType.LoadInformation:
return new IpV6MobilityOptionLoadInformation(random.NextUShort(), random.NextUInt(), random.NextUInt(), random.NextUInt(), random.NextUInt());
case IpV6MobilityOptionType.AlternateIpV4CareOfAddress:
return new IpV6MobilityOptionAlternateIpV4CareOfAddress(random.NextIpV4Address());
case IpV6MobilityOptionType.MobileNodeGroupIdentifier:
return new IpV6MobilityOptionMobileNodeGroupIdentifier(random.NextEnum<IpV6MobileNodeGroupIdentifierSubType>(), random.NextUInt());
case IpV6MobilityOptionType.MobileAccessGatewayIpV6Address:
return new IpV6MobilityOptionMobileAccessGatewayIpV6Address(random.NextIpV6Address());
case IpV6MobilityOptionType.AccessNetworkIdentifier:
return new IpV6MobilityOptionAccessNetworkIdentifier(random.NextIpV6AccessNetworkIdentifierSubOptions());
default:
throw new InvalidOperationException(string.Format("Invalid optionType value {0}", optionType));
}
}
public static IpV6FlowIdentificationSubOptions NextIpV6FlowIdentificationSubOptions(this Random random)
{
return new IpV6FlowIdentificationSubOptions(((Func<IpV6FlowIdentificationSubOption>)(random.NextIpV6FlowIdentificationSubOption)).GenerateArray(random.NextInt(0, 10)));
}
public static IpV6FlowIdentificationSubOption NextIpV6FlowIdentificationSubOption(this Random random)
{
IpV6FlowIdentificationSubOptionType optionType = random.NextEnum<IpV6FlowIdentificationSubOptionType>();
switch (optionType)
{
case IpV6FlowIdentificationSubOptionType.Pad1:
return new IpV6FlowIdentificationSubOptionPad1();
case IpV6FlowIdentificationSubOptionType.PadN:
return new IpV6FlowIdentificationSubOptionPadN(random.NextInt(0, 10));
case IpV6FlowIdentificationSubOptionType.BindingReference:
return new IpV6FlowIdentificationSubOptionBindingReference(((Func<ushort>)(random.NextUShort)).GenerateArray(random.NextInt(0, 10)));
case IpV6FlowIdentificationSubOptionType.TrafficSelector:
return new IpV6FlowIdentificationSubOptionTrafficSelector(random.NextEnum<IpV6FlowIdentificationTrafficSelectorFormat>(), random.NextDataSegment(random.NextInt(0, 100)));
default:
throw new InvalidOperationException(string.Format("Invalid optionType value {0}", optionType));
}
}
public static IpV6AccessNetworkIdentifierSubOptions NextIpV6AccessNetworkIdentifierSubOptions(this Random random)
{
return new IpV6AccessNetworkIdentifierSubOptions(((Func<IpV6AccessNetworkIdentifierSubOption>)(random.NextIpV6AccessNetworkIdentifierSubOption)).GenerateArray(random.NextInt(0, 10)));
}
public static IpV6AccessNetworkIdentifierSubOption NextIpV6AccessNetworkIdentifierSubOption(this Random random)
{
IpV6AccessNetworkIdentifierSubOptionType optionType = random.NextEnum<IpV6AccessNetworkIdentifierSubOptionType>();
switch (optionType)
{
case IpV6AccessNetworkIdentifierSubOptionType.NetworkIdentifier:
return new IpV6AccessNetworkIdentifierSubOptionNetworkIdentifier(random.NextBool(), random.NextDataSegment(random.NextInt(0, 100)),
random.NextDataSegment(random.NextInt(0, 100)));
case IpV6AccessNetworkIdentifierSubOptionType.GeoLocation:
return new IpV6AccessNetworkIdentifierSubOptionGeoLocation(random.NextUInt24(), random.NextUInt24());
case IpV6AccessNetworkIdentifierSubOptionType.OperatorIdentifier:
return new IpV6AccessNetworkIdentifierSubOptionOperatorIdentifier(random.NextEnum<IpV6AccessNetworkIdentifierOperatorIdentifierType>(),
random.NextDataSegment(random.NextInt(0, 100)));
default:
throw new InvalidOperationException(string.Format("Invalid optionType value {0}", optionType));
}
}
} }
} }
\ No newline at end of file
...@@ -62,6 +62,11 @@ namespace PcapDotNet.Packets ...@@ -62,6 +62,11 @@ namespace PcapDotNet.Packets
return array.Compare(offset, other, otherOffset, count) == 0; return array.Compare(offset, other, otherOffset, count) == 0;
} }
public static DataSegment SubSegment(this byte[] array, int offset, int length)
{
return new DataSegment(array, offset, length);
}
/// <summary> /// <summary>
/// Returns the first offset in the array where the other array's range sequence of bytes can be found or the length of the array if no match exists. /// Returns the first offset in the array where the other array's range sequence of bytes can be found or the length of the array if no match exists.
/// </summary> /// </summary>
......
using PcapDotNet.Packets.Arp; using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.IpV6;
namespace PcapDotNet.Packets.Ethernet namespace PcapDotNet.Packets.Ethernet
{ {
...@@ -83,6 +84,14 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -83,6 +84,14 @@ namespace PcapDotNet.Packets.Ethernet
get { return PayloadDatagrams.IpV4; } get { return PayloadDatagrams.IpV4; }
} }
/// <summary>
/// The Ethernet payload as an IPv6 datagram.
/// </summary>
public IpV6Datagram IpV6
{
get { return PayloadDatagrams.IpV6; }
}
/// <summary> /// <summary>
/// The Ethernet payload as an ARP datagram. /// The Ethernet payload as an ARP datagram.
/// </summary> /// </summary>
......
using PcapDotNet.Packets.Arp; using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.IpV6;
namespace PcapDotNet.Packets.Ethernet namespace PcapDotNet.Packets.Ethernet
{ {
...@@ -17,6 +18,9 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -17,6 +18,9 @@ namespace PcapDotNet.Packets.Ethernet
case EthernetType.IpV4: case EthernetType.IpV4:
return IpV4; return IpV4;
case EthernetType.IpV6:
return IpV6;
case EthernetType.Arp: case EthernetType.Arp:
return Arp; return Arp;
...@@ -41,6 +45,19 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -41,6 +45,19 @@ namespace PcapDotNet.Packets.Ethernet
} }
} }
/// <summary>
/// The Ethernet payload as an IPv6 datagram.
/// </summary>
public IpV6Datagram IpV6
{
get
{
if (_ipV6 == null && _payload != null)
_ipV6 = new IpV6Datagram(_payload.Buffer, _payload.StartOffset, IpV6Datagram.GetTotalLength(_payload));
return _ipV6;
}
}
/// <summary> /// <summary>
/// The Ethernet payload as an ARP datagram. /// The Ethernet payload as an ARP datagram.
/// </summary> /// </summary>
...@@ -74,6 +91,7 @@ namespace PcapDotNet.Packets.Ethernet ...@@ -74,6 +91,7 @@ namespace PcapDotNet.Packets.Ethernet
private readonly Datagram _payload; private readonly Datagram _payload;
private IpV4Datagram _ipV4; private IpV4Datagram _ipV4;
private IpV6Datagram _ipV6;
private ArpDatagram _arp; private ArpDatagram _arp;
private VLanTaggedFrameDatagram _vLanTaggedFrame; private VLanTaggedFrameDatagram _vLanTaggedFrame;
} }
......
...@@ -3,9 +3,9 @@ using PcapDotNet.Packets.IpV4; ...@@ -3,9 +3,9 @@ using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Ip namespace PcapDotNet.Packets.Ip
{ {
internal static class IpOptionQuickStartCommon public static class IpOptionQuickStartCommon
{ {
public const int DataLength = 6; internal const int DataLength = 6;
/// <summary> /// <summary>
/// The maximum value for the rate field. /// The maximum value for the rate field.
...@@ -26,7 +26,7 @@ namespace PcapDotNet.Packets.Ip ...@@ -26,7 +26,7 @@ namespace PcapDotNet.Packets.Ip
public const byte Rate = 0x0F; public const byte Rate = 0x0F;
} }
public static void AssertValidParameters(IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce) internal static void AssertValidParameters(IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce)
{ {
if (function != IpV4OptionQuickStartFunction.RateRequest && if (function != IpV4OptionQuickStartFunction.RateRequest &&
function != IpV4OptionQuickStartFunction.RateReport) function != IpV4OptionQuickStartFunction.RateReport)
...@@ -41,7 +41,7 @@ namespace PcapDotNet.Packets.Ip ...@@ -41,7 +41,7 @@ namespace PcapDotNet.Packets.Ip
throw new ArgumentException("nonce last two bits are reserved and must be zero", "nonce"); throw new ArgumentException("nonce last two bits are reserved and must be zero", "nonce");
} }
public static int CalcRateKbps(byte rate) internal static int CalcRateKbps(byte rate)
{ {
if (rate == 0) if (rate == 0)
return 0; return 0;
...@@ -49,7 +49,7 @@ namespace PcapDotNet.Packets.Ip ...@@ -49,7 +49,7 @@ namespace PcapDotNet.Packets.Ip
return 40*(1 << rate); return 40*(1 << rate);
} }
public static void ReadData(DataSegment data, out IpV4OptionQuickStartFunction function, out byte rate, out byte ttl, out uint nonce) internal static void ReadData(DataSegment data, out IpV4OptionQuickStartFunction function, out byte rate, out byte ttl, out uint nonce)
{ {
function = (IpV4OptionQuickStartFunction)(data[Offset.Function] & Mask.Function); function = (IpV4OptionQuickStartFunction)(data[Offset.Function] & Mask.Function);
rate = (byte)(data[Offset.Rate] & Mask.Rate); rate = (byte)(data[Offset.Rate] & Mask.Rate);
...@@ -57,7 +57,7 @@ namespace PcapDotNet.Packets.Ip ...@@ -57,7 +57,7 @@ namespace PcapDotNet.Packets.Ip
nonce = data.ReadUInt(Offset.Nonce, Endianity.Big); nonce = data.ReadUInt(Offset.Nonce, Endianity.Big);
} }
public static void WriteData(byte[] buffer, ref int offset, IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce) internal static void WriteData(byte[] buffer, ref int offset, IpV4OptionQuickStartFunction function, byte rate, byte ttl, uint nonce)
{ {
buffer[offset + Offset.Function] = (byte)(((byte)function & Mask.Function) | (rate & Mask.Rate)); buffer[offset + Offset.Function] = (byte)(((byte)function & Mask.Function) | (rate & Mask.Rate));
buffer[offset + Offset.Ttl] = ttl; buffer[offset + Offset.Ttl] = ttl;
......
...@@ -170,19 +170,22 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -170,19 +170,22 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
Il = 0x28, Il = 0x28,
/// <summary> /// <summary>
/// IPv6 RFC 2460 /// RFC 2460.
/// IPv6.
/// </summary> /// </summary>
IpV6 = 0x29, IpV6 = 0x29,
/// <summary> /// <summary>
/// Source Demand Routing Protocol /// Source Demand Routing Protocol.
/// </summary> /// </summary>
SourceDemandRoutingProtocol = 0x2A, SourceDemandRoutingProtocol = 0x2A,
/// <summary> /// <summary>
/// Routing Header for IPv6 RFC 2460 /// RFC 2460.
/// Routing Header for IPv6.
/// </summary> /// </summary>
IpV6Route = 0x2B, IpV6Route = 0x2B,
/// <summary> /// <summary>
/// Fragment Header for IPv6 RFC 2460 /// RFC 2460.
/// Fragment Header for IPv6.
/// </summary> /// </summary>
FragmentHeaderForIpV6 = 0x2C, FragmentHeaderForIpV6 = 0x2C,
/// <summary> /// <summary>
......
...@@ -39,6 +39,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -39,6 +39,8 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public const int HeaderLength = 40; public const int HeaderLength = 40;
public const int MaxFlowLabel = 0xFFFFF;
private static class Offset private static class Offset
{ {
public const int Version = 0; public const int Version = 0;
...@@ -107,7 +109,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -107,7 +109,12 @@ namespace PcapDotNet.Packets.IpV6
public ushort RealPayloadLength public ushort RealPayloadLength
{ {
get { return (ushort)Math.Min(PayloadLength, Length); } get
{
if (Length < HeaderLength)
return 0;
return (ushort)Math.Min(PayloadLength, Length - HeaderLength);
}
} }
/// <summary> /// <summary>
...@@ -144,7 +151,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -144,7 +151,7 @@ namespace PcapDotNet.Packets.IpV6
get { return ReadIpV6Address(Offset.DestinationAddress, Endianity.Big); } get { return ReadIpV6Address(Offset.DestinationAddress, Endianity.Big); }
} }
public ReadOnlyCollection<IpV6ExtensionHeader> ExtensionHeaders public IpV6ExtensionHeaders ExtensionHeaders
{ {
get get
{ {
...@@ -158,16 +165,17 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -158,16 +165,17 @@ namespace PcapDotNet.Packets.IpV6
if (_extensionHeaders != null) if (_extensionHeaders != null)
return; return;
List<IpV6ExtensionHeader> extensionHeaders = new List<IpV6ExtensionHeader>(); if (Length < HeaderLength)
if (HeaderLength > RealPayloadLength)
{ {
_isValid = false; _isValid = false;
_extensionHeaders = extensionHeaders.AsReadOnly(); _extensionHeaders = IpV6ExtensionHeaders.Empty;
return; return;
} }
_extensionHeaders = new IpV6ExtensionHeaders(Subsegment(HeaderLength, RealPayloadLength), NextHeader);
/*
int extendedHeaderLength = HeaderLength; int extendedHeaderLength = HeaderLength;
IpV4Protocol? nextHeader = NextHeader; IpV4Protocol? nextHeader = NextHeader;
while (extendedHeaderLength + 8 <= RealPayloadLength && nextHeader.HasValue && IsExtensionHeader(nextHeader.Value)) while (extendedHeaderLength + 8 <= RealPayloadLength && nextHeader.HasValue && IpV6ExtensionHeader.IsExtensionHeader(nextHeader.Value))
{ {
int numBytesRead; int numBytesRead;
IpV6ExtensionHeader extensionHeader = IpV6ExtensionHeader.CreateInstance(nextHeader.Value, IpV6ExtensionHeader extensionHeader = IpV6ExtensionHeader.CreateInstance(nextHeader.Value,
...@@ -178,27 +186,10 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -178,27 +186,10 @@ namespace PcapDotNet.Packets.IpV6
nextHeader = extensionHeader.NextHeader; nextHeader = extensionHeader.NextHeader;
extendedHeaderLength += numBytesRead; extendedHeaderLength += numBytesRead;
} }
_isValid = (!nextHeader.HasValue || !IsExtensionHeader(nextHeader.Value)) && (HeaderLength + _extensionHeadersLength == PayloadLength);
_extensionHeaders = extensionHeaders.AsReadOnly();
_extensionHeadersLength = extendedHeaderLength - HeaderLength; _extensionHeadersLength = extendedHeaderLength - HeaderLength;
} _extensionHeaders = extensionHeaders.AsReadOnly();
_isValid = (!nextHeader.HasValue || !IpV6ExtensionHeader.IsExtensionHeader(nextHeader.Value));
private static bool IsExtensionHeader(IpV4Protocol nextHeader) */
{
switch (nextHeader)
{
case IpV4Protocol.IpV6HopByHopOption: // 0
case IpV4Protocol.IpV6Route: // 43
case IpV4Protocol.FragmentHeaderForIpV6: // 44
case IpV4Protocol.EncapsulatingSecurityPayload: // 50
case IpV4Protocol.AuthenticationHeader: // 51
case IpV4Protocol.IpV6Opts: // 60
case IpV4Protocol.MobilityHeader: // 135
return true;
default:
return false;
}
} }
/// <summary> /// <summary>
...@@ -206,20 +197,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -206,20 +197,16 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public override ILayer ExtractLayer() public override ILayer ExtractLayer()
{ {
return null; return new IpV6Layer
// TODO: Implement. {
// return new IpV6Layer TrafficClass = TrafficClass,
// { FlowLabel = FlowLabel,
// Version = Version, NextHeader = NextHeader,
// TrafficClass = TrafficClass, HopLimit = HopLimit,
// FlowLabel = FlowLabel, Source = Source,
// PayloadLength = PayloadLength, CurrentDestination = CurrentDestination,
// NextHeader = NextHeader, ExtensionHeaders = ExtensionHeaders,
// HopLimit = HopLimit, };
// Source = Source,
// CurrentDestination = CurrentDestination,
// ExtensionHeaders = ExtensionHeaders,
// };
} }
...@@ -228,16 +215,34 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -228,16 +215,34 @@ namespace PcapDotNet.Packets.IpV6
{ {
} }
internal static int GetTotalLength(Datagram payload)
{
if (payload.Length <= HeaderLength)
return payload.Length;
int totalLength = HeaderLength;
IpV4Protocol? nextHeader = (IpV4Protocol)payload[Offset.NextHeader];
while (nextHeader.HasValue && IpV6ExtensionHeader.IsExtensionHeader(nextHeader.Value))
{
int extensionHeaderLength;
IpV6ExtensionHeader.GetNextNextHeaderAndLength(nextHeader.Value, payload.Subsegment(totalLength, payload.Length - totalLength), out nextHeader,
out extensionHeaderLength);
totalLength += extensionHeaderLength;
}
return totalLength;
}
internal static void WriteHeader(byte[] buffer, int offset, internal static void WriteHeader(byte[] buffer, int offset,
byte version, byte trafficClass, int flowLabel, ushort payloadLength, IpV4Protocol nextHeader, byte hopLimit, byte trafficClass, int flowLabel, ushort payloadLength, IpV4Protocol nextHeader, byte hopLimit,
IpV6Address source, IpV6Address currentDestination) IpV6Address source, IpV6Address currentDestination, IpV6ExtensionHeaders extensionHeaders)
{ {
buffer.Write(offset + Offset.Version, (uint)(((((version << Shift.Version) << 8) | trafficClass) << 16) | flowLabel), Endianity.Big); buffer.Write(offset + Offset.Version, (uint)(((((DefaultVersion << Shift.Version) << 8) | trafficClass) << 16) | flowLabel), Endianity.Big);
buffer.Write(offset + Offset.PayloadLength, payloadLength, Endianity.Big); buffer.Write(offset + Offset.PayloadLength, payloadLength, Endianity.Big);
buffer.Write(offset + Offset.NextHeader, (byte)nextHeader); buffer.Write(offset + Offset.NextHeader, (byte)nextHeader);
buffer.Write(offset + Offset.HopLimit, hopLimit); buffer.Write(offset + Offset.HopLimit, hopLimit);
buffer.Write(offset + Offset.SourceAddress, source, Endianity.Big); buffer.Write(offset + Offset.SourceAddress, source, Endianity.Big);
buffer.Write(offset + Offset.DestinationAddress, currentDestination, Endianity.Big); buffer.Write(offset + Offset.DestinationAddress, currentDestination, Endianity.Big);
extensionHeaders.Write(buffer, offset + HeaderLength);
} }
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
...@@ -246,68 +251,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -246,68 +251,8 @@ namespace PcapDotNet.Packets.IpV6
return _isValid; return _isValid;
} }
private ReadOnlyCollection<IpV6ExtensionHeader> _extensionHeaders; private IpV6ExtensionHeaders _extensionHeaders;
private int _extensionHeadersLength; private int _extensionHeadersLength;
private bool _isValid; private bool _isValid;
} }
/*
/// <summary>
/// RFC 2460.
/// +-----+-------------+-------------------------+--------------+---------------+
/// | Bit | 0-7 | 8-15 | 16-23 | 24-31 |
/// +-----+-------------+-------------------------+--------------+---------------+
/// | 0 | Next Header | Header Extension Length | Routing Type | Segments Left |
/// +-----+-------------+-------------------------+--------------+---------------+
/// | 32 | type-specific data |
/// | ... | |
/// +-----+----------------------------------------------------------------------+
/// </summary>
public class IpV6ExtensionHeaderRouting : IpV6ExtensionHeader
{
}
/// <summary>
/// RFC 2460.
/// +-----+-------------+----------+-----------------+----------+----+
/// | Bit | 0-7 | 8-15 | 16-28 | 29-30 | 31 |
/// +-----+-------------+----------+-----------------+----------+----+
/// | 0 | Next Header | Reserved | Fragment Offset | Reserved | M |
/// +-----+-------------+----------+-----------------+----------+----+
/// | 32 | Identification |
/// +-----+----------------------------------------------------------+
/// </summary>
public class IpV6ExtensionHeaderFragment : IpV6ExtensionHeader
{
}
/// <summary>
/// RFC 2460.
/// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+-------------------------+
/// | 0 | Next Header | Header Extension Length |
/// +-----+-------------+-------------------------+
/// | 16 | Options |
/// | ... | |
/// +-----+---------------------------------------+
/// </summary>
public class IpV6ExtensionHeaderDestinationOptions : IpV6ExtensionHeader
{
}
/// <summary>
/// RFC 2402.
/// </summary>
public class IpV6ExtensionHeaderAuthentication : IpV6ExtensionHeader
{
}
/// <summary>
/// RFC 2406.
/// </summary>
public class IpV6ExtensionHeaderEncapsulatingSecurityPayload : IpV6ExtensionHeader
{
}
*/
} }
using System; using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6 namespace PcapDotNet.Packets.IpV6
{ {
/// <summary> /// <summary>
/// RFC 2460. /// RFC 2460.
/// For IpV6HopByHopOption, IpV6Route and FragmentHeaderForIpV6 we use the following format:
/// <pre> /// <pre>
/// +-----+-------------+-------------------------+ /// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 | /// | Bit | 0-7 | 8-15 |
...@@ -17,48 +22,51 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -17,48 +22,51 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public abstract class IpV6ExtensionHeader public abstract class IpV6ExtensionHeaderStandard : IpV6ExtensionHeader
{ {
private static class Offset private static class Offset
{ {
public const int NextHeader = 0; public const int NextHeader = 0;
public const int HeaderExtensionLength = 1; public const int HeaderExtensionLength = NextHeader + sizeof(byte);
public const int Data = 2; public const int Data = HeaderExtensionLength + sizeof(byte);
} }
public const int MinimumLength = 8; public const int MinimumLength = 8;
public IpV4Protocol? NextHeader { get; private set; } internal IpV6ExtensionHeaderStandard(IpV4Protocol nextHeader)
: base(nextHeader)
{
}
protected IpV6ExtensionHeader(IpV4Protocol? nextHeader) internal override sealed void Write(byte[] buffer, ref int offset)
{ {
NextHeader = nextHeader; buffer.Write(offset + Offset.NextHeader, (byte)NextHeader);
int length = Length;
buffer.Write(offset + Offset.HeaderExtensionLength, (byte)((length / 8) - 1));
WriteData(buffer, offset + Offset.Data);
offset += length;
} }
internal static IpV6ExtensionHeader CreateInstance(IpV4Protocol nextHeader, DataSegment extensionHeaderData, out int numBytesRead) internal abstract void WriteData(byte[] buffer, int offset);
public override sealed int Length { get { return MinimumLength + DataLength; } }
internal abstract int DataLength { get; }
internal static bool IsStandard(IpV4Protocol nextHeader)
{ {
switch (nextHeader) switch (nextHeader)
{ {
case IpV4Protocol.IpV6HopByHopOption: // 0 case IpV4Protocol.IpV6HopByHopOption: // 0
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 case IpV4Protocol.MobilityHeader: // 135
return CreateStandardInstance(nextHeader, extensionHeaderData, out numBytesRead); return true;
case IpV4Protocol.EncapsulatingSecurityPayload: // 50
return IpV6ExtensionHeaderEncapsulatingSecurityPayload.CreateInstance(extensionHeaderData, out numBytesRead);
case IpV4Protocol.AuthenticationHeader: // 51
return IpV6ExtensionHeaderAuthentication.CreateInstance(extensionHeaderData, out numBytesRead);
default: default:
throw new InvalidOperationException("Invalid nextHeader value" + nextHeader); return false;
} }
} }
internal static IpV6ExtensionHeader CreateInstanceStandard(IpV4Protocol nextHeader, DataSegment extensionHeaderData, out int numBytesRead)
private static IpV6ExtensionHeader CreateStandardInstance(IpV4Protocol nextHeader, DataSegment extensionHeaderData, out int numBytesRead)
{ {
numBytesRead = 0; numBytesRead = 0;
if (extensionHeaderData.Length < MinimumLength) if (extensionHeaderData.Length < MinimumLength)
...@@ -81,7 +89,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -81,7 +89,7 @@ namespace PcapDotNet.Packets.IpV6
case IpV4Protocol.FragmentHeaderForIpV6: // 44 case IpV4Protocol.FragmentHeaderForIpV6: // 44
return IpV6ExtensionHeaderFragmentData.ParseData(nextNextHeader, data); return IpV6ExtensionHeaderFragmentData.ParseData(nextNextHeader, data);
case IpV4Protocol.IpV6Opts: // 60 case IpV4Protocol.IpV6Opts: // 60
return IpV6ExtensionHeaderDestinationOptions.ParseData(nextNextHeader, data); return IpV6ExtensionHeaderDestinationOptions.ParseData(nextNextHeader, data);
...@@ -92,5 +100,216 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -92,5 +100,216 @@ namespace PcapDotNet.Packets.IpV6
throw new InvalidOperationException("Invalid nextHeader value" + nextHeader); throw new InvalidOperationException("Invalid nextHeader value" + nextHeader);
} }
} }
internal static void GetNextNextHeaderAndLength(DataSegment extensionHeader, out IpV4Protocol? nextNextHeader, out int extensionHeaderLength)
{
if (extensionHeader.Length < MinimumLength)
{
nextNextHeader = null;
extensionHeaderLength = extensionHeader.Length;
return;
}
nextNextHeader = (IpV4Protocol)extensionHeader[Offset.NextHeader];
extensionHeaderLength = extensionHeader[Offset.HeaderExtensionLength] * 8;
}
internal static ReadOnlyCollection<IpV4Protocol> StandardExtensionHeaders
{
get { return _standardExtensionHeaders; }
}
private static readonly ReadOnlyCollection<IpV4Protocol> _standardExtensionHeaders =
new[]
{
IpV4Protocol.IpV6HopByHopOption,
IpV4Protocol.IpV6Route,
IpV4Protocol.FragmentHeaderForIpV6,
IpV4Protocol.IpV6Opts,
IpV4Protocol.MobilityHeader
}.AsReadOnly();
}
/// <summary>
/// RFC 2460.
/// </summary>
public abstract class IpV6ExtensionHeader
{
public abstract IpV4Protocol Protocol { get; }
public IpV4Protocol? NextHeader { get; private set; }
public abstract int Length { get; }
public static ReadOnlyCollection<IpV4Protocol> ExtensionHeaders
{
get { return _extensionHeaders; }
}
internal static bool IsExtensionHeader(IpV4Protocol nextHeader)
{
if (IpV6ExtensionHeaderStandard.IsStandard(nextHeader))
return true;
switch (nextHeader)
{
case IpV4Protocol.EncapsulatingSecurityPayload: // 50
case IpV4Protocol.AuthenticationHeader: // 51
return true;
default:
return false;
}
}
internal IpV6ExtensionHeader(IpV4Protocol? nextHeader)
{
NextHeader = nextHeader;
}
internal static IpV6ExtensionHeader CreateInstance(IpV4Protocol nextHeader, DataSegment extensionHeaderData, out int numBytesRead)
{
if (IpV6ExtensionHeaderStandard.IsStandard(nextHeader))
return IpV6ExtensionHeaderStandard.CreateInstanceStandard(nextHeader, extensionHeaderData, out numBytesRead);
switch (nextHeader)
{
case IpV4Protocol.EncapsulatingSecurityPayload: // 50
return IpV6ExtensionHeaderEncapsulatingSecurityPayload.CreateInstance(extensionHeaderData, out numBytesRead);
case IpV4Protocol.AuthenticationHeader: // 51
return IpV6ExtensionHeaderAuthentication.CreateInstance(extensionHeaderData, out numBytesRead);
default:
throw new InvalidOperationException("Invalid nextHeader value" + nextHeader);
}
}
internal static void GetNextNextHeaderAndLength(IpV4Protocol nextHeader, DataSegment data, out IpV4Protocol? nextNextHeader,
out int extensionHeaderLength)
{
if (IpV6ExtensionHeaderStandard.IsStandard(nextHeader))
{
IpV6ExtensionHeaderStandard.GetNextNextHeaderAndLength(data, out nextNextHeader, out extensionHeaderLength);
return;
}
switch (nextHeader)
{
case IpV4Protocol.EncapsulatingSecurityPayload: // 50
IpV6ExtensionHeaderEncapsulatingSecurityPayload.GetNextNextHeaderAndLength(data, out nextNextHeader, out extensionHeaderLength);
break;
case IpV4Protocol.AuthenticationHeader: // 51
IpV6ExtensionHeaderAuthentication.GetNextNextHeaderAndLength(data, out nextNextHeader, out extensionHeaderLength);
break;
default:
throw new InvalidOperationException(string.Format("Invalid nextHeader value {0}", nextHeader));
}
}
internal abstract void Write(byte[] buffer, ref int offset);
private static readonly ReadOnlyCollection<IpV4Protocol> _extensionHeaders =
IpV6ExtensionHeaderStandard.StandardExtensionHeaders.Concat(
new[]
{
IpV4Protocol.EncapsulatingSecurityPayload,
IpV4Protocol.AuthenticationHeader
}).
ToArray().AsReadOnly();
}
public class IpV6ExtensionHeaders : IEnumerable<IpV6ExtensionHeader>
{
public IpV6ExtensionHeaders(ReadOnlyCollection<IpV6ExtensionHeader> extensionHeaders)
{
Headers = extensionHeaders;
IsValid = true;
}
public IpV6ExtensionHeaders(params IpV6ExtensionHeader[] extensionHeaders)
: this(extensionHeaders.AsReadOnly())
{
}
public IpV6ExtensionHeaders(IList<IpV6ExtensionHeader> extensionHeaders)
: this(extensionHeaders.AsReadOnly())
{
}
public IpV6ExtensionHeaders(IEnumerable<IpV6ExtensionHeader> extensionHeaders)
: this(extensionHeaders.ToArray())
{
}
public IEnumerator<IpV6ExtensionHeader> GetEnumerator()
{
return Headers.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IpV6ExtensionHeader this[int index]
{
get { return Headers[index]; }
}
public ReadOnlyCollection<IpV6ExtensionHeader> Headers { get; private set; }
public bool IsValid { get; private set; }
public IpV4Protocol? FirstHeader
{
get
{
if (!Headers.Any())
return null;
return Headers[0].Protocol;
}
}
public IpV4Protocol? NextHeader
{
get
{
if (!Headers.Any())
return null;
return Headers[Headers.Count - 1].Protocol;
}
}
public static IpV6ExtensionHeaders Empty
{
get { return _empty; }
}
internal IpV6ExtensionHeaders(DataSegment data, IpV4Protocol firstHeader)
{
IpV4Protocol? nextHeader = firstHeader;
List<IpV6ExtensionHeader> headers = new List<IpV6ExtensionHeader>();
while (data.Length >= 8 && nextHeader.HasValue && IpV6ExtensionHeader.IsExtensionHeader(nextHeader.Value))
{
int numBytesRead;
IpV6ExtensionHeader extensionHeader = IpV6ExtensionHeader.CreateInstance(nextHeader.Value, data, out numBytesRead);
if (extensionHeader == null)
break;
headers.Add(extensionHeader);
nextHeader = extensionHeader.NextHeader;
data = data.Subsegment(numBytesRead, data.Length - numBytesRead);
}
Headers = headers.AsReadOnly();
IsValid = (!nextHeader.HasValue || !IpV6ExtensionHeader.IsExtensionHeader(nextHeader.Value));
}
private static readonly IpV6ExtensionHeaders _empty = new IpV6ExtensionHeaders();
public void Write(byte[] buffer, int offset)
{
foreach (IpV6ExtensionHeader extensionHeader in this)
extensionHeader.Write(buffer, ref offset);
}
} }
} }
...@@ -92,7 +92,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -92,7 +92,7 @@ namespace PcapDotNet.Packets.IpV6
return null; return null;
} }
IpV4Protocol nextHeader = (IpV4Protocol)extensionHeaderData[Offset.NextHeader]; IpV4Protocol nextHeader = (IpV4Protocol)extensionHeaderData[Offset.NextHeader];
byte payloadLength = extensionHeaderData[Offset.PayloadLength]; int payloadLength = (extensionHeaderData[Offset.PayloadLength] + 2) * 4;
if (extensionHeaderData.Length < Offset.AuthenticationData + payloadLength) if (extensionHeaderData.Length < Offset.AuthenticationData + payloadLength)
{ {
numBytesRead = 0; numBytesRead = 0;
...@@ -101,10 +101,44 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -101,10 +101,44 @@ namespace PcapDotNet.Packets.IpV6
uint securityParametersIndex = extensionHeaderData.ReadUInt(Offset.SecurityParametersIndex, Endianity.Big); uint securityParametersIndex = extensionHeaderData.ReadUInt(Offset.SecurityParametersIndex, Endianity.Big);
uint sequenceNumber = extensionHeaderData.ReadUInt(Offset.SequenceNumber, Endianity.Big); uint sequenceNumber = extensionHeaderData.ReadUInt(Offset.SequenceNumber, Endianity.Big);
DataSegment authenticationData = extensionHeaderData.Subsegment(Offset.AuthenticationData, payloadLength); DataSegment authenticationData = extensionHeaderData.Subsegment(Offset.AuthenticationData, payloadLength - Offset.AuthenticationData);
numBytesRead = Offset.AuthenticationData + payloadLength; numBytesRead = payloadLength;
return new IpV6ExtensionHeaderAuthentication(nextHeader, securityParametersIndex, sequenceNumber, authenticationData); return new IpV6ExtensionHeaderAuthentication(nextHeader, securityParametersIndex, sequenceNumber, authenticationData);
} }
public static void GetNextNextHeaderAndLength(DataSegment extensionHeader, out IpV4Protocol? nextNextHeader, out int extensionHeaderLength)
{
if (extensionHeader.Length < MinimumLength)
{
nextNextHeader = null;
extensionHeaderLength = extensionHeader.Length;
return;
}
nextNextHeader = (IpV4Protocol)extensionHeader[Offset.NextHeader];
extensionHeaderLength = extensionHeader[Offset.PayloadLength] * 4;
}
public override IpV4Protocol Protocol
{
get { return IpV4Protocol.AuthenticationHeader; }
}
public override int Length
{
get { return MinimumLength + AuthenticationData.Length; }
}
internal override void Write(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.NextHeader, (byte)NextHeader);
int length = Length;
buffer.Write(offset + Offset.PayloadLength, (byte)((length / 4) - 2));
buffer.Write(offset + Offset.SecurityParametersIndex, SecurityParametersIndex, Endianity.Big);
buffer.Write(offset + Offset.SequenceNumber, SequenceNumber, Endianity.Big);
AuthenticationData.Write(buffer, offset + Offset.AuthenticationData);
offset += length;
}
} }
} }
\ No newline at end of file
...@@ -22,6 +22,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -22,6 +22,11 @@ namespace PcapDotNet.Packets.IpV6
{ {
} }
public override IpV4Protocol Protocol
{
get { return IpV4Protocol.IpV6Opts; }
}
internal static IpV6ExtensionHeaderDestinationOptions ParseData(IpV4Protocol nextHeader, DataSegment data) internal static IpV6ExtensionHeaderDestinationOptions ParseData(IpV4Protocol nextHeader, DataSegment data)
{ {
IpV6Options options = new IpV6Options(data); IpV6Options options = new IpV6Options(data);
......
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6 namespace PcapDotNet.Packets.IpV6
{ {
/// <summary> /// <summary>
...@@ -62,6 +64,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -62,6 +64,16 @@ namespace PcapDotNet.Packets.IpV6
EncryptedDataAndAuthenticationData = encryptedDataAndAuthenticationData; EncryptedDataAndAuthenticationData = encryptedDataAndAuthenticationData;
} }
public override IpV4Protocol Protocol
{
get { return IpV4Protocol.EncapsulatingSecurityPayload; }
}
public override int Length
{
get { return MinimumLength + EncryptedDataAndAuthenticationData.Length; }
}
/// <summary> /// <summary>
/// <para> /// <para>
/// The SPI is an arbitrary 32-bit value that, in combination with the destination IP address and security protocol (ESP), /// The SPI is an arbitrary 32-bit value that, in combination with the destination IP address and security protocol (ESP),
...@@ -132,6 +144,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -132,6 +144,12 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public DataSegment EncryptedDataAndAuthenticationData { get; private set; } public DataSegment EncryptedDataAndAuthenticationData { get; private set; }
internal static void GetNextNextHeaderAndLength(DataSegment extensionHeader, out IpV4Protocol? nextNextHeader, out int extensionHeaderLength)
{
nextNextHeader = null;
extensionHeaderLength = extensionHeader.Length;
}
internal static IpV6ExtensionHeaderEncapsulatingSecurityPayload CreateInstance(DataSegment extensionHeaderData, out int numBytesRead) internal static IpV6ExtensionHeaderEncapsulatingSecurityPayload CreateInstance(DataSegment extensionHeaderData, out int numBytesRead)
{ {
if (extensionHeaderData.Length < MinimumLength) if (extensionHeaderData.Length < MinimumLength)
...@@ -146,5 +164,13 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -146,5 +164,13 @@ namespace PcapDotNet.Packets.IpV6
return new IpV6ExtensionHeaderEncapsulatingSecurityPayload(securityParametersIndex, sequenceNumber, encryptedDataAndAuthenticationData); return new IpV6ExtensionHeaderEncapsulatingSecurityPayload(securityParametersIndex, sequenceNumber, encryptedDataAndAuthenticationData);
} }
internal override void Write(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.SecurityParametersIndex, SecurityParametersIndex, Endianity.Big);
buffer.Write(offset + Offset.SequenceNumber, SequenceNumber, Endianity.Big);
EncryptedDataAndAuthenticationData.Write(buffer, offset + Offset.PayloadData);
offset += Length;
}
} }
} }
\ No newline at end of file
...@@ -18,7 +18,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -18,7 +18,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+----------------------------------------------------------------------+ /// +-----+----------------------------------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6ExtensionHeaderFragmentData : IpV6ExtensionHeader public class IpV6ExtensionHeaderFragmentData : IpV6ExtensionHeaderStandard
{ {
private static class DataOffset private static class DataOffset
{ {
...@@ -38,7 +38,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -38,7 +38,7 @@ namespace PcapDotNet.Packets.IpV6
public const int FragmentOffset = 3; public const int FragmentOffset = 3;
} }
public const int DataLength = DataOffset.Identification + sizeof(uint); public const int ExtensionHeaderDataLength = DataOffset.Identification + sizeof(uint);
public const ushort MaxFragmentOffset = 0x1FFF; public const ushort MaxFragmentOffset = 0x1FFF;
...@@ -70,9 +70,19 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -70,9 +70,19 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public uint Identification { get; private set; } public uint Identification { get; private set; }
public override IpV4Protocol Protocol
{
get { return IpV4Protocol.FragmentHeaderForIpV6; }
}
internal override int DataLength
{
get { return ExtensionHeaderDataLength; }
}
internal static IpV6ExtensionHeaderFragmentData ParseData(IpV4Protocol nextHeader, DataSegment data) internal static IpV6ExtensionHeaderFragmentData ParseData(IpV4Protocol nextHeader, DataSegment data)
{ {
if (data.Length != DataLength) if (data.Length != ExtensionHeaderDataLength)
return null; return null;
ushort fragmentOffset = (ushort)((data.ReadUShort(DataOffset.FragmentOffset, Endianity.Big) & DataMask.FragmentOffset) >> DataShift.FragmentOffset); ushort fragmentOffset = (ushort)((data.ReadUShort(DataOffset.FragmentOffset, Endianity.Big) & DataMask.FragmentOffset) >> DataShift.FragmentOffset);
...@@ -81,6 +91,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -81,6 +91,16 @@ namespace PcapDotNet.Packets.IpV6
return new IpV6ExtensionHeaderFragmentData(nextHeader, fragmentOffset, moreFragments, identification); return new IpV6ExtensionHeaderFragmentData(nextHeader, fragmentOffset, moreFragments, identification);
} }
internal override void WriteData(byte[] buffer, int offset)
{
ushort fragmentOffsetAndMoreFragments = (ushort)(FragmentOffset << DataShift.FragmentOffset);
if (MoreFragments)
fragmentOffsetAndMoreFragments |= DataMask.MoreFragments;
buffer.Write(offset + DataOffset.FragmentOffset, fragmentOffsetAndMoreFragments, Endianity.Big);
buffer.Write(offset + DataOffset.Identification, Identification, Endianity.Big);
}
} }
public enum IpV6MobilityHeaderType : byte public enum IpV6MobilityHeaderType : byte
...@@ -199,8 +219,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -199,8 +219,12 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public abstract class IpV6ExtensionHeaderMobility : IpV6ExtensionHeader public abstract class IpV6ExtensionHeaderMobility : IpV6ExtensionHeaderStandard
{ {
public override IpV4Protocol Protocol
{
get { return IpV4Protocol.MobilityHeader; }
}
private static class DataOffset private static class DataOffset
{ {
public const int MobilityHeaderType = 0; public const int MobilityHeaderType = 0;
...@@ -216,7 +240,14 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -216,7 +240,14 @@ namespace PcapDotNet.Packets.IpV6
Checksum = checksum; Checksum = checksum;
MobilityOptions = mobilityOptions; MobilityOptions = mobilityOptions;
} }
internal override sealed int DataLength
{
get { return MinimumDataLength + MessageDataLength; }
}
internal abstract int MessageDataLength { get; }
/// <summary> /// <summary>
/// Identifies the particular mobility message in question. /// Identifies the particular mobility message in question.
/// An unrecognized MH Type field causes an error indication to be sent. /// An unrecognized MH Type field causes an error indication to be sent.
...@@ -327,6 +358,15 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -327,6 +358,15 @@ namespace PcapDotNet.Packets.IpV6
return null; return null;
} }
} }
internal override sealed void WriteData(byte[] buffer, int offset)
{
buffer.Write(offset + DataOffset.MobilityHeaderType, (byte)MobilityHeaderType);
buffer.Write(offset + DataOffset.Checksum, Checksum, Endianity.Big);
WriteMessageData(buffer, offset + DataOffset.MessageData);
}
internal abstract void WriteMessageData(byte[] buffer, int offset);
} }
/// <summary> /// <summary>
...@@ -362,6 +402,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -362,6 +402,11 @@ namespace PcapDotNet.Packets.IpV6
{ {
} }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
/// <summary> /// <summary>
/// Identifies the particular mobility message in question. /// Identifies the particular mobility message in question.
/// An unrecognized MH Type field causes an error indication to be sent. /// An unrecognized MH Type field causes an error indication to be sent.
...@@ -379,6 +424,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -379,6 +424,11 @@ namespace PcapDotNet.Packets.IpV6
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options)); IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityBindingRefreshRequest(nextHeader, checksum, options); return new IpV6ExtensionHeaderMobilityBindingRefreshRequest(nextHeader, checksum, options);
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
/// <summary> /// <summary>
...@@ -435,6 +485,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -435,6 +485,11 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public ulong HomeInitCookie { get; private set; } public ulong HomeInitCookie { get; private set; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static IpV6ExtensionHeaderMobilityHomeTestInit ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityHomeTestInit ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -444,6 +499,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -444,6 +499,12 @@ namespace PcapDotNet.Packets.IpV6
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options)); IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityHomeTestInit(nextHeader, checksum, homeInitCookie, options); return new IpV6ExtensionHeaderMobilityHomeTestInit(nextHeader, checksum, homeInitCookie, options);
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
buffer.Write(offset + MessageDataOffset.HomeInitCookie, HomeInitCookie, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
/// <summary> /// <summary>
...@@ -500,6 +561,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -500,6 +561,11 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public ulong CareOfInitCookie { get; private set; } public ulong CareOfInitCookie { get; private set; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static IpV6ExtensionHeaderMobilityCareOfTestInit ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityCareOfTestInit ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -509,6 +575,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -509,6 +575,12 @@ namespace PcapDotNet.Packets.IpV6
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options)); IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityCareOfTestInit(nextHeader, checksum, careOfInitCookie, options); return new IpV6ExtensionHeaderMobilityCareOfTestInit(nextHeader, checksum, careOfInitCookie, options);
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
buffer.Write(offset + MessageDataOffset.CareOfInitCookie, CareOfInitCookie, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
/// <summary> /// <summary>
...@@ -585,6 +657,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -585,6 +657,11 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public ulong HomeKeygenToken { get; private set; } public ulong HomeKeygenToken { get; private set; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static IpV6ExtensionHeaderMobilityHomeTest ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityHomeTest ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -596,6 +673,14 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -596,6 +673,14 @@ namespace PcapDotNet.Packets.IpV6
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options)); IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityHomeTest(nextHeader, checksum, homeNonceIndex, homeInitCookie, homeKeygenToken, options); return new IpV6ExtensionHeaderMobilityHomeTest(nextHeader, checksum, homeNonceIndex, homeInitCookie, homeKeygenToken, options);
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
buffer.Write(offset + MessageDataOffset.HomeNonceIndex, HomeNonceIndex, Endianity.Big);
buffer.Write(offset + MessageDataOffset.HomeInitCookie, HomeInitCookie, Endianity.Big);
buffer.Write(offset + MessageDataOffset.HomeKeygenToken, HomeKeygenToken, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
/// <summary> /// <summary>
...@@ -672,6 +757,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -672,6 +757,11 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public ulong CareOfKeygenToken { get; private set; } public ulong CareOfKeygenToken { get; private set; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static IpV6ExtensionHeaderMobilityCareOfTest ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityCareOfTest ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -683,6 +773,14 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -683,6 +773,14 @@ namespace PcapDotNet.Packets.IpV6
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options)); IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityCareOfTest(nextHeader, checksum, careOfNonceIndex, careOfInitCookie, careOfKeygenToken, options); return new IpV6ExtensionHeaderMobilityCareOfTest(nextHeader, checksum, careOfNonceIndex, careOfInitCookie, careOfKeygenToken, options);
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
buffer.Write(offset + MessageDataOffset.CareOfNonceIndex, CareOfNonceIndex, Endianity.Big);
buffer.Write(offset + MessageDataOffset.CareOfInitCookie, CareOfInitCookie, Endianity.Big);
buffer.Write(offset + MessageDataOffset.CareOfKeygenToken, CareOfKeygenToken, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
/// <summary> /// <summary>
...@@ -789,6 +887,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -789,6 +887,11 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public ushort Lifetime { get; private set; } public ushort Lifetime { get; private set; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static bool ParseMessageDataToFields(DataSegment messageData, out ushort sequenceNumber, internal static bool ParseMessageDataToFields(DataSegment messageData, out ushort sequenceNumber,
out bool acknowledge, out bool homeRegistration, out bool linkLocalAddressCompatibility, out bool acknowledge, out bool homeRegistration, out bool linkLocalAddressCompatibility,
out bool keyManagementMobilityCapability, out ushort lifetime, out IpV6MobilityOptions options) out bool keyManagementMobilityCapability, out ushort lifetime, out IpV6MobilityOptions options)
...@@ -815,6 +918,25 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -815,6 +918,25 @@ namespace PcapDotNet.Packets.IpV6
options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options)); options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return true; return true;
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
buffer.Write(offset + MessageDataOffset.SequenceNumber, SequenceNumber, Endianity.Big);
byte flags = 0;
if (Acknowledge)
flags |= MessageDataMask.Acknowledge;
if (HomeRegistration)
flags |= MessageDataMask.HomeRegistration;
if (LinkLocalAddressCompatibility)
flags |= MessageDataMask.LinkLocalAddressCompatibility;
if (KeyManagementMobilityCapability)
flags |= MessageDataMask.KeyManagementMobilityCapability;
buffer.Write(offset + MessageDataOffset.Acknowledge, flags);
buffer.Write(offset + MessageDataOffset.Lifetime, Lifetime, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
/// <summary> /// <summary>
...@@ -1255,6 +1377,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1255,6 +1377,11 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public ushort Lifetime { get; private set; } public ushort Lifetime { get; private set; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static bool ParseMessageDataFields(DataSegment messageData, out IpV6BindingAcknowledgementStatus status, internal static bool ParseMessageDataFields(DataSegment messageData, out IpV6BindingAcknowledgementStatus status,
out bool keyManagementMobilityCapability, out ushort sequenceNumber, out ushort lifetime, out bool keyManagementMobilityCapability, out ushort sequenceNumber, out ushort lifetime,
out IpV6MobilityOptions options) out IpV6MobilityOptions options)
...@@ -1278,6 +1405,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1278,6 +1405,16 @@ namespace PcapDotNet.Packets.IpV6
options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options)); options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return true; return true;
} }
internal override sealed void WriteMessageData(byte[] buffer, int offset)
{
buffer.Write(offset + MessageDataOffset.Status, (byte)Status);
if (KeyManagementMobilityCapability)
buffer.Write(offset + MessageDataOffset.KeyManagementMobilityCapability, MessageDataMask.KeyManagementMobilityCapability);
buffer.Write(offset + MessageDataOffset.SequenceNumber, SequenceNumber, Endianity.Big);
buffer.Write(offset + MessageDataOffset.Lifetime, Lifetime, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
/// <summary> /// <summary>
...@@ -1416,6 +1553,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1416,6 +1553,11 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public IpV6Address HomeAddress { get; private set; } public IpV6Address HomeAddress { get; private set; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static IpV6ExtensionHeaderMobilityBindingError ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityBindingError ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -1426,6 +1568,13 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1426,6 +1568,13 @@ namespace PcapDotNet.Packets.IpV6
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options)); IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityBindingError(nextHeader, checksum, status, homeAddress, options); return new IpV6ExtensionHeaderMobilityBindingError(nextHeader, checksum, status, homeAddress, options);
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
buffer.Write(offset + MessageDataOffset.Status, (byte)Status);
buffer.Write(offset + MessageDataOffset.HomeAddress, HomeAddress, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
/// <summary> /// <summary>
...@@ -1586,6 +1735,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1586,6 +1735,11 @@ namespace PcapDotNet.Packets.IpV6
get { return IpV6MobilityHeaderType.FastNeighborAdvertisement; } get { return IpV6MobilityHeaderType.FastNeighborAdvertisement; }
} }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static IpV6ExtensionHeaderMobilityFastNeighborAdvertisement ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityFastNeighborAdvertisement ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -1594,6 +1748,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1594,6 +1748,11 @@ namespace PcapDotNet.Packets.IpV6
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options)); IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityFastNeighborAdvertisement(nextHeader, checksum, options); return new IpV6ExtensionHeaderMobilityFastNeighborAdvertisement(nextHeader, checksum, options);
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
/// <summary> /// <summary>
...@@ -1635,10 +1794,20 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1635,10 +1794,20 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public DataSegment MessageData { get; private set; } public DataSegment MessageData { get; private set; }
internal override int MessageDataLength
{
get { return MessageData.Length; }
}
internal static IpV6ExtensionHeaderMobilityExperimental ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityExperimental ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
return new IpV6ExtensionHeaderMobilityExperimental(nextHeader, checksum, messageData); return new IpV6ExtensionHeaderMobilityExperimental(nextHeader, checksum, messageData);
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
MessageData.Write(buffer, offset);
}
} }
/// <summary> /// <summary>
...@@ -1699,6 +1868,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1699,6 +1868,11 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public ReadOnlyCollection<IpV6Address> HomeAgentAddresses { get; private set; } public ReadOnlyCollection<IpV6Address> HomeAgentAddresses { get; private set; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + HomeAgentAddresses.Count * IpV6Address.SizeOf + MobilityOptions.BytesLength; }
}
internal static IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -1717,6 +1891,14 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1717,6 +1891,14 @@ namespace PcapDotNet.Packets.IpV6
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(optionsOffset, messageData.Length - optionsOffset)); IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(optionsOffset, messageData.Length - optionsOffset));
return new IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage(nextHeader, checksum, homeAgentAddresses, options); return new IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage(nextHeader, checksum, homeAgentAddresses, options);
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
buffer.Write(offset + MessageDataOffset.NumberOfAddresses, (byte)HomeAgentAddresses.Count);
for (int i = 0; i != HomeAgentAddresses.Count; ++i)
buffer.Write(offset + MessageDataOffset.HomeAgentAddresses + i * IpV6Address.SizeOf, HomeAgentAddresses[i], Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.HomeAgentAddresses + HomeAgentAddresses.Count * IpV6Address.SizeOf);
}
} }
/// <summary> /// <summary>
...@@ -1794,6 +1976,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1794,6 +1976,11 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public uint SequenceNumber { get; private set; } public uint SequenceNumber { get; private set; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static IpV6ExtensionHeaderMobilityHeartbeatMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityHeartbeatMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -1805,6 +1992,19 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1805,6 +1992,19 @@ namespace PcapDotNet.Packets.IpV6
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.MobilityOptions, messageData.Length - MessageDataOffset.MobilityOptions)); IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.MobilityOptions, messageData.Length - MessageDataOffset.MobilityOptions));
return new IpV6ExtensionHeaderMobilityHeartbeatMessage(nextHeader, checksum, isUnsolicitedHeartbeatResponse, isResponse, sequenceNumber, options); return new IpV6ExtensionHeaderMobilityHeartbeatMessage(nextHeader, checksum, isUnsolicitedHeartbeatResponse, isResponse, sequenceNumber, options);
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
byte isUnsolicitedHeartbeatResponseAndIsResponse = 0;
if (IsUnsolicitedHeartbeatResponse)
isUnsolicitedHeartbeatResponseAndIsResponse |= MessageDataMask.IsUnsolicitedHeartbeatResponse;
if (IsResponse)
isUnsolicitedHeartbeatResponseAndIsResponse |= MessageDataMask.IsResponse;
buffer.Write(MessageDataOffset.IsUnsolicitedHeartbeatResponse, isUnsolicitedHeartbeatResponseAndIsResponse);
buffer.Write(offset + MessageDataOffset.SequenceNumber, SequenceNumber, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.MobilityOptions);
}
} }
public enum IpV6HandoverInitiateMessageCode : byte public enum IpV6HandoverInitiateMessageCode : byte
...@@ -1842,7 +2042,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1842,7 +2042,7 @@ namespace PcapDotNet.Packets.IpV6
public const int AssignedAddressConfiguration = SequenceNumber + sizeof(ushort); public const int AssignedAddressConfiguration = SequenceNumber + sizeof(ushort);
public const int Buffer = AssignedAddressConfiguration; public const int Buffer = AssignedAddressConfiguration;
public const int Code = Buffer + sizeof(byte); public const int Code = Buffer + sizeof(byte);
public const int MobilityOptions = Code + sizeof(byte); public const int Options = Code + sizeof(byte);
} }
private static class MessageDataMask private static class MessageDataMask
...@@ -1851,7 +2051,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1851,7 +2051,7 @@ namespace PcapDotNet.Packets.IpV6
public const byte Buffer = 0x40; public const byte Buffer = 0x40;
} }
public const int MinimumMessageDataLength = MessageDataOffset.MobilityOptions; public const int MinimumMessageDataLength = MessageDataOffset.Options;
public IpV6ExtensionHeaderMobilityHandoverInitiateMessage(IpV4Protocol nextHeader, ushort checksum, ushort sequenceNumber, bool assignedAddressConfiguration, public IpV6ExtensionHeaderMobilityHandoverInitiateMessage(IpV4Protocol nextHeader, ushort checksum, ushort sequenceNumber, bool assignedAddressConfiguration,
bool buffer, IpV6HandoverInitiateMessageCode code, bool buffer, IpV6HandoverInitiateMessageCode code,
...@@ -1896,6 +2096,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1896,6 +2096,11 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public IpV6HandoverInitiateMessageCode Code { get; private set; } public IpV6HandoverInitiateMessageCode Code { get; private set; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static IpV6ExtensionHeaderMobilityHandoverInitiateMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityHandoverInitiateMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -1906,9 +2111,24 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1906,9 +2111,24 @@ namespace PcapDotNet.Packets.IpV6
MessageDataMask.AssignedAddressConfiguration); MessageDataMask.AssignedAddressConfiguration);
bool buffer = messageData.ReadBool(MessageDataOffset.Buffer, MessageDataMask.Buffer); bool buffer = messageData.ReadBool(MessageDataOffset.Buffer, MessageDataMask.Buffer);
IpV6HandoverInitiateMessageCode code = (IpV6HandoverInitiateMessageCode)messageData[MessageDataOffset.Code]; IpV6HandoverInitiateMessageCode code = (IpV6HandoverInitiateMessageCode)messageData[MessageDataOffset.Code];
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.MobilityOptions, messageData.Length - MessageDataOffset.MobilityOptions)); IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityHandoverInitiateMessage(nextHeader, checksum, sequenceNumber, assignedAddressConfiguration, buffer, code, options); return new IpV6ExtensionHeaderMobilityHandoverInitiateMessage(nextHeader, checksum, sequenceNumber, assignedAddressConfiguration, buffer, code, options);
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
buffer.Write(offset + MessageDataOffset.SequenceNumber, SequenceNumber, Endianity.Big);
byte assignedAddressConfigurationAndBuffer = 0;
if (AssignedAddressConfiguration)
assignedAddressConfigurationAndBuffer |= MessageDataMask.AssignedAddressConfiguration;
if (Buffer)
assignedAddressConfigurationAndBuffer |= MessageDataMask.Buffer;
buffer.Write(offset + MessageDataOffset.AssignedAddressConfiguration, assignedAddressConfigurationAndBuffer);
buffer.Write(offset + MessageDataOffset.Code, (byte)Code);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
public enum IpV6MobilityHandoverAcknowledgeCode : byte public enum IpV6MobilityHandoverAcknowledgeCode : byte
...@@ -1981,10 +2201,10 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1981,10 +2201,10 @@ namespace PcapDotNet.Packets.IpV6
{ {
public const int SequenceNumber = 0; public const int SequenceNumber = 0;
public const int Code = SequenceNumber + sizeof(ushort) + sizeof(byte); public const int Code = SequenceNumber + sizeof(ushort) + sizeof(byte);
public const int MobilityOptions = Code + sizeof(byte); public const int Options = Code + sizeof(byte);
} }
public const int MinimumMessageDataLength = MessageDataOffset.MobilityOptions; public const int MinimumMessageDataLength = MessageDataOffset.Options;
public IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage(IpV4Protocol nextHeader, ushort checksum, ushort sequenceNumber, public IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage(IpV4Protocol nextHeader, ushort checksum, ushort sequenceNumber,
IpV6MobilityHandoverAcknowledgeCode code, IpV6MobilityOptions options) IpV6MobilityHandoverAcknowledgeCode code, IpV6MobilityOptions options)
...@@ -2014,6 +2234,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2014,6 +2234,11 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public IpV6MobilityHandoverAcknowledgeCode Code { get; private set; } public IpV6MobilityHandoverAcknowledgeCode Code { get; private set; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -2021,9 +2246,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2021,9 +2246,16 @@ namespace PcapDotNet.Packets.IpV6
ushort sequenceNumber = messageData.ReadUShort(MessageDataOffset.SequenceNumber, Endianity.Big); ushort sequenceNumber = messageData.ReadUShort(MessageDataOffset.SequenceNumber, Endianity.Big);
IpV6MobilityHandoverAcknowledgeCode code = (IpV6MobilityHandoverAcknowledgeCode)messageData[MessageDataOffset.Code]; IpV6MobilityHandoverAcknowledgeCode code = (IpV6MobilityHandoverAcknowledgeCode)messageData[MessageDataOffset.Code];
IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.MobilityOptions, messageData.Length - MessageDataOffset.MobilityOptions)); IpV6MobilityOptions options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return new IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage(nextHeader, checksum, sequenceNumber, code, options); return new IpV6ExtensionHeaderMobilityHandoverAcknowledgeMessage(nextHeader, checksum, sequenceNumber, code, options);
} }
internal override void WriteMessageData(byte[] buffer, int offset)
{
buffer.Write(offset + MessageDataOffset.SequenceNumber, SequenceNumber, Endianity.Big);
buffer.Write(offset + MessageDataOffset.Code, (byte)Code);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
public enum IpV6MobilityBindingRevocationType : byte public enum IpV6MobilityBindingRevocationType : byte
...@@ -2072,10 +2304,10 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2072,10 +2304,10 @@ namespace PcapDotNet.Packets.IpV6
public const int ProxyBinding = SequenceNumber + sizeof(ushort); public const int ProxyBinding = SequenceNumber + sizeof(ushort);
public const int IpV4HomeAddressBindingOnly = ProxyBinding; public const int IpV4HomeAddressBindingOnly = ProxyBinding;
public const int Global = IpV4HomeAddressBindingOnly; public const int Global = IpV4HomeAddressBindingOnly;
public const int MobilityOptions = Global + sizeof(byte) + sizeof(byte); public const int Options = Global + sizeof(byte) + sizeof(byte);
} }
public const int MinimumMessageDataLength = MessageDataOffset.MobilityOptions; public const int MinimumMessageDataLength = MessageDataOffset.Options;
private static class MessageDataMask private static class MessageDataMask
{ {
...@@ -2139,6 +2371,13 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2139,6 +2371,13 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public bool Global { get; private set; } public bool Global { get; private set; }
internal abstract byte RevocationTriggerOrStatus { get; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static IpV6ExtensionHeaderMobilityBindingRevocationMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) internal static IpV6ExtensionHeaderMobilityBindingRevocationMessage ParseMessageData(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -2151,7 +2390,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2151,7 +2390,7 @@ namespace PcapDotNet.Packets.IpV6
bool ipV4HomeAddressBindingOnly = messageData.ReadBool(MessageDataOffset.IpV4HomeAddressBindingOnly, MessageDataMask.IpV4HomeAddressBindingOnly); bool ipV4HomeAddressBindingOnly = messageData.ReadBool(MessageDataOffset.IpV4HomeAddressBindingOnly, MessageDataMask.IpV4HomeAddressBindingOnly);
bool global = messageData.ReadBool(MessageDataOffset.Global, MessageDataMask.Global); bool global = messageData.ReadBool(MessageDataOffset.Global, MessageDataMask.Global);
IpV6MobilityOptions options = IpV6MobilityOptions options =
new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.MobilityOptions, messageData.Length - MessageDataOffset.MobilityOptions)); new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
switch (bindingRevocationType) switch (bindingRevocationType)
{ {
case IpV6MobilityBindingRevocationType.BindingRevocationIndication: case IpV6MobilityBindingRevocationType.BindingRevocationIndication:
...@@ -2168,6 +2407,24 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2168,6 +2407,24 @@ namespace PcapDotNet.Packets.IpV6
return null; return null;
} }
} }
internal override sealed void WriteMessageData(byte[] buffer, int offset)
{
buffer.Write(offset + MessageDataOffset.BindingRevocationType, (byte)BindingRevocationType);
buffer.Write(offset + MessageDataOffset.RevocationTriggerOrStatus, RevocationTriggerOrStatus);
buffer.Write(offset + MessageDataOffset.SequenceNumber, SequenceNumber, Endianity.Big);
byte flags = 0;
if (ProxyBinding)
flags |= MessageDataMask.ProxyBinding;
if (IpV4HomeAddressBindingOnly)
flags |= MessageDataMask.IpV4HomeAddressBindingOnly;
if (Global)
flags |= MessageDataMask.Global;
buffer.Write(offset + MessageDataOffset.ProxyBinding, flags);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
/// <summary> /// <summary>
...@@ -2278,6 +2535,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2278,6 +2535,11 @@ namespace PcapDotNet.Packets.IpV6
/// Indicating the event that triggered the initiator to send the BRI message. /// Indicating the event that triggered the initiator to send the BRI message.
/// </summary> /// </summary>
public Ipv6MobilityBindingRevocationTrigger RevocationTrigger { get; private set; } public Ipv6MobilityBindingRevocationTrigger RevocationTrigger { get; private set; }
internal override byte RevocationTriggerOrStatus
{
get { return (byte)RevocationTrigger; }
}
} }
/// <summary> /// <summary>
...@@ -2383,6 +2645,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2383,6 +2645,11 @@ namespace PcapDotNet.Packets.IpV6
/// Indicating the result of processing the Binding Revocation Indication message by the responder. /// Indicating the result of processing the Binding Revocation Indication message by the responder.
/// </summary> /// </summary>
public Ipv6MobilityBindingRevocationStatus Status { get; private set; } public Ipv6MobilityBindingRevocationStatus Status { get; private set; }
internal override byte RevocationTriggerOrStatus
{
get { return (byte)Status; }
}
} }
/// <summary> /// <summary>
...@@ -2399,7 +2666,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2399,7 +2666,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// | 48 | Sequence # | /// | 48 | Sequence # |
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// | 64 | | /// | 64 | Reserved |
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// | 80 | Lifetime | /// | 80 | Lifetime |
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
...@@ -2419,10 +2686,10 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2419,10 +2686,10 @@ namespace PcapDotNet.Packets.IpV6
{ {
public const int SequenceNumber = 0; public const int SequenceNumber = 0;
public const int Lifetime = SequenceNumber + sizeof(ushort) + sizeof(ushort); public const int Lifetime = SequenceNumber + sizeof(ushort) + sizeof(ushort);
public const int MobilityOptions = Lifetime + sizeof(ushort); public const int Options = Lifetime + sizeof(ushort);
} }
public const int MinimumMessageDataLength = MessageDataOffset.MobilityOptions; public const int MinimumMessageDataLength = MessageDataOffset.Options;
public IpV6ExtensionHeaderMobilityLocalizedRouting(IpV4Protocol nextHeader, ushort checksum, ushort sequenceNumber, ushort lifetime, public IpV6ExtensionHeaderMobilityLocalizedRouting(IpV4Protocol nextHeader, ushort checksum, ushort sequenceNumber, ushort lifetime,
IpV6MobilityOptions options) IpV6MobilityOptions options)
...@@ -2447,6 +2714,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2447,6 +2714,11 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public ushort Lifetime { get; private set; } public ushort Lifetime { get; private set; }
internal override int MessageDataLength
{
get { return MinimumMessageDataLength + MobilityOptions.BytesLength; }
}
internal static bool ParseMessageDataToFields(DataSegment messageData, out ushort sequenceNumber, out ushort lifetime, out IpV6MobilityOptions options) internal static bool ParseMessageDataToFields(DataSegment messageData, out ushort sequenceNumber, out ushort lifetime, out IpV6MobilityOptions options)
{ {
if (messageData.Length < MinimumMessageDataLength) if (messageData.Length < MinimumMessageDataLength)
...@@ -2459,9 +2731,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2459,9 +2731,16 @@ namespace PcapDotNet.Packets.IpV6
sequenceNumber = messageData.ReadUShort(MessageDataOffset.SequenceNumber, Endianity.Big); sequenceNumber = messageData.ReadUShort(MessageDataOffset.SequenceNumber, Endianity.Big);
lifetime = messageData.ReadUShort(MessageDataOffset.Lifetime, Endianity.Big); lifetime = messageData.ReadUShort(MessageDataOffset.Lifetime, Endianity.Big);
options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.MobilityOptions, messageData.Length - MessageDataOffset.MobilityOptions)); options = new IpV6MobilityOptions(messageData.Subsegment(MessageDataOffset.Options, messageData.Length - MessageDataOffset.Options));
return true; return true;
} }
internal override sealed void WriteMessageData(byte[] buffer, int offset)
{
buffer.Write(offset + MessageDataOffset.SequenceNumber, SequenceNumber, Endianity.Big);
buffer.Write(offset + MessageDataOffset.Lifetime, Lifetime, Endianity.Big);
MobilityOptions.Write(buffer, offset + MessageDataOffset.Options);
}
} }
/// <summary> /// <summary>
......
...@@ -17,11 +17,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -17,11 +17,16 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public class IpV6ExtensionHeaderHopByHopOptions : IpV6ExtensionHeaderOptions public class IpV6ExtensionHeaderHopByHopOptions : IpV6ExtensionHeaderOptions
{ {
private IpV6ExtensionHeaderHopByHopOptions(IpV4Protocol nextHeader, IpV6Options options) public IpV6ExtensionHeaderHopByHopOptions(IpV4Protocol nextHeader, IpV6Options options)
: base(nextHeader, options) : base(nextHeader, options)
{ {
} }
public override IpV4Protocol Protocol
{
get { return IpV4Protocol.IpV6HopByHopOption; }
}
internal static IpV6ExtensionHeaderHopByHopOptions ParseData(IpV4Protocol nextHeader, DataSegment data) internal static IpV6ExtensionHeaderHopByHopOptions ParseData(IpV4Protocol nextHeader, DataSegment data)
{ {
IpV6Options options = new IpV6Options(data); IpV6Options options = new IpV6Options(data);
......
...@@ -15,10 +15,20 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -15,10 +15,20 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+---------------------------------------+ /// +-----+---------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public abstract class IpV6ExtensionHeaderOptions : IpV6ExtensionHeader public abstract class IpV6ExtensionHeaderOptions : IpV6ExtensionHeaderStandard
{ {
public IpV6Options Options { get; private set; } public IpV6Options Options { get; private set; }
internal override sealed int DataLength
{
get { return Options.BytesLength; }
}
internal override void WriteData(byte[] buffer, int offset)
{
Options.Write(buffer, offset);
}
internal IpV6ExtensionHeaderOptions(IpV4Protocol nextHeader, IpV6Options options) internal IpV6ExtensionHeaderOptions(IpV4Protocol nextHeader, IpV6Options options)
: base(nextHeader) : base(nextHeader)
{ {
......
...@@ -15,7 +15,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -15,7 +15,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+----------------------------------------------------------------------+ /// +-----+----------------------------------------------------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public abstract class IpV6ExtensionHeaderRouting : IpV6ExtensionHeader public abstract class IpV6ExtensionHeaderRouting : IpV6ExtensionHeaderStandard
{ {
private static class DataOffset private static class DataOffset
{ {
...@@ -26,6 +26,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -26,6 +26,8 @@ namespace PcapDotNet.Packets.IpV6
public const int DataMinimumLength = DataOffset.TypeSpecificData; public const int DataMinimumLength = DataOffset.TypeSpecificData;
internal abstract int RoutingDataLength { get; }
/// <summary> /// <summary>
/// Identifier of a particular Routing header variant. /// Identifier of a particular Routing header variant.
/// </summary> /// </summary>
...@@ -36,6 +38,22 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -36,6 +38,22 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public byte SegmentsLeft { get; private set; } public byte SegmentsLeft { get; private set; }
public override IpV4Protocol Protocol
{
get { return IpV4Protocol.IpV6Route; }
}
internal IpV6ExtensionHeaderRouting(IpV4Protocol nextHeader, byte segmentsLeft)
: base(nextHeader)
{
SegmentsLeft = segmentsLeft;
}
internal override sealed int DataLength
{
get { return DataMinimumLength + RoutingDataLength; }
}
internal static IpV6ExtensionHeaderRouting ParseData(IpV4Protocol nextHeader, DataSegment data) internal static IpV6ExtensionHeaderRouting ParseData(IpV4Protocol nextHeader, DataSegment data)
{ {
if (data.Length < DataMinimumLength) if (data.Length < DataMinimumLength)
...@@ -63,10 +81,13 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -63,10 +81,13 @@ namespace PcapDotNet.Packets.IpV6
} }
} }
internal IpV6ExtensionHeaderRouting(IpV4Protocol nextHeader, byte segmentsLeft) internal override sealed void WriteData(byte[] buffer, int offset)
: base(nextHeader)
{ {
SegmentsLeft = segmentsLeft; buffer.Write(offset + DataOffset.RoutingType, (byte)RoutingType);
buffer.Write(offset + DataOffset.SegmentsLeft, SegmentsLeft);
WriteRoutingData(buffer, offset + DataOffset.TypeSpecificData);
} }
internal abstract void WriteRoutingData(byte[] buffer, int offset);
} }
} }
\ No newline at end of file
...@@ -23,11 +23,10 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -23,11 +23,10 @@ namespace PcapDotNet.Packets.IpV6
{ {
private static class RoutingDataOffset private static class RoutingDataOffset
{ {
public const int Reserved = 0; public const int HomeAddress = sizeof(uint);
public const int HomeAddress = Reserved + sizeof(uint);
} }
public const int RoutingDataLength = RoutingDataOffset.HomeAddress + IpV6Address.SizeOf; public const int ConstRoutingDataLength = RoutingDataOffset.HomeAddress + IpV6Address.SizeOf;
public IpV6ExtensionHeaderRoutingHomeAddress(IpV4Protocol nextHeader, byte segmentsLeft, IpV6Address homeAddress) public IpV6ExtensionHeaderRoutingHomeAddress(IpV4Protocol nextHeader, byte segmentsLeft, IpV6Address homeAddress)
: base(nextHeader, segmentsLeft) : base(nextHeader, segmentsLeft)
...@@ -45,13 +44,23 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -45,13 +44,23 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public IpV6Address HomeAddress { get; private set; } public IpV6Address HomeAddress { get; private set; }
internal override int RoutingDataLength
{
get { return ConstRoutingDataLength; }
}
internal static IpV6ExtensionHeaderRoutingHomeAddress ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData) internal static IpV6ExtensionHeaderRoutingHomeAddress ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
{ {
if (routingData.Length != RoutingDataLength) if (routingData.Length != ConstRoutingDataLength)
return null; return null;
IpV6Address homeAddress = routingData.ReadIpV6Address(RoutingDataOffset.HomeAddress, Endianity.Big); IpV6Address homeAddress = routingData.ReadIpV6Address(RoutingDataOffset.HomeAddress, Endianity.Big);
return new IpV6ExtensionHeaderRoutingHomeAddress(nextHeader, segmentsLeft, homeAddress); return new IpV6ExtensionHeaderRoutingHomeAddress(nextHeader, segmentsLeft, homeAddress);
} }
internal override void WriteRoutingData(byte[] buffer, int offset)
{
buffer.Write(offset + RoutingDataOffset.HomeAddress, HomeAddress, Endianity.Big);
}
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq;
using PcapDotNet.Base; using PcapDotNet.Base;
using PcapDotNet.Packets.IpV4; using PcapDotNet.Packets.IpV4;
...@@ -14,7 +15,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -14,7 +15,7 @@ namespace PcapDotNet.Packets.IpV6
/// | 0 | Next Header | Header Extension Length | Routing Type | Segments Left | /// | 0 | Next Header | Header Extension Length | Routing Type | Segments Left |
/// +-----+-------+-------+------+------------------+--------------+---------------+ /// +-----+-------+-------+------+------------------+--------------+---------------+
/// | 32 | CmprI | CmprE | Pad | Reserved | /// | 32 | CmprI | CmprE | Pad | Reserved |
/// +-----+-------+-------+------+------------------+--------------+---------------+ /// +-----+-------+-------+------+-------------------------------------------------+
/// | 64 | Address[1] | /// | 64 | Address[1] |
/// | ... | | /// | ... | |
/// +-----+------------------------------------------------------------------------+ /// +-----+------------------------------------------------------------------------+
...@@ -110,6 +111,18 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -110,6 +111,18 @@ namespace PcapDotNet.Packets.IpV6
public ReadOnlyCollection<IpV6Address> Addresses { get; private set; } public ReadOnlyCollection<IpV6Address> Addresses { get; private set; }
internal override int RoutingDataLength
{
get
{
return RoutingDataMinimumLength +
(Addresses.Any()
? Addresses.Count * IpV6Address.SizeOf -
(Addresses.Count - 1) * CommonPrefixLengthForNonLastAddresses - CommonPrefixLengthForLastAddress
: 0) + PadSize;
}
}
internal static IpV6ExtensionHeaderRoutingRpl ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData) internal static IpV6ExtensionHeaderRoutingRpl ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
{ {
if (routingData.Length < RoutingDataMinimumLength) if (routingData.Length < RoutingDataMinimumLength)
...@@ -158,5 +171,25 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -158,5 +171,25 @@ namespace PcapDotNet.Packets.IpV6
return new IpV6ExtensionHeaderRoutingRpl(nextHeader, segmentsLeft, commonPrefixLengthForNonLastAddresses, commonPrefixLengthForLastAddress, padSize, return new IpV6ExtensionHeaderRoutingRpl(nextHeader, segmentsLeft, commonPrefixLengthForNonLastAddresses, commonPrefixLengthForLastAddress, padSize,
addresses); addresses);
} }
internal override void WriteRoutingData(byte[] buffer, int offset)
{
buffer.Write(offset + RoutingDataOffset.CommonPrefixLengthForNonLastAddresses,
(byte)((CommonPrefixLengthForNonLastAddresses << RoutingDataShift.CommonPrefixLengthForNonLastAddresses) |
CommonPrefixLengthForLastAddress));
buffer.Write(offset + RoutingDataOffset.PadSize, (byte)(PadSize << RoutingDataShift.PadSize));
if (Addresses.Any())
{
int addressOffset = offset + RoutingDataOffset.Addresses;
byte[] addressBytes = new byte[IpV6Address.SizeOf];
for (int i = 0; i != Addresses.Count - 1; ++i)
{
addressBytes.Write(0, Addresses[i], Endianity.Big);
addressBytes.SubSegment(CommonPrefixLengthForNonLastAddresses, IpV6Address.SizeOf - CommonPrefixLengthForNonLastAddresses).Write(buffer, ref addressOffset);
}
addressBytes.Write(0, Addresses[Addresses.Count - 1], Endianity.Big);
addressBytes.SubSegment(CommonPrefixLengthForLastAddress, IpV6Address.SizeOf - CommonPrefixLengthForLastAddress).Write(buffer, ref addressOffset);
}
}
} }
} }
\ No newline at end of file
...@@ -58,6 +58,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -58,6 +58,11 @@ namespace PcapDotNet.Packets.IpV6
public ReadOnlyCollection<IpV6Address> Addresses { get; private set; } public ReadOnlyCollection<IpV6Address> Addresses { get; private set; }
internal override int RoutingDataLength
{
get { return RoutingDataMinimumLength + Addresses.Count * IpV6Address.SizeOf; }
}
internal static IpV6ExtensionHeaderRoutingSourceRoute ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData) internal static IpV6ExtensionHeaderRoutingSourceRoute ParseRoutingData(IpV4Protocol nextHeader, byte segmentsLeft, DataSegment routingData)
{ {
if (routingData.Length < RoutingDataMinimumLength) if (routingData.Length < RoutingDataMinimumLength)
...@@ -72,5 +77,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -72,5 +77,11 @@ namespace PcapDotNet.Packets.IpV6
addresses[i] = routingData.ReadIpV6Address(RoutingDataOffset.Addresses + i * IpV6Address.SizeOf, Endianity.Big); addresses[i] = routingData.ReadIpV6Address(RoutingDataOffset.Addresses + i * IpV6Address.SizeOf, Endianity.Big);
return new IpV6ExtensionHeaderRoutingSourceRoute(nextHeader, segmentsLeft, addresses); return new IpV6ExtensionHeaderRoutingSourceRoute(nextHeader, segmentsLeft, addresses);
} }
internal override void WriteRoutingData(byte[] buffer, int offset)
{
for (int i = 0; i != Addresses.Count; ++i)
buffer.Write(offset + RoutingDataOffset.Addresses + i * IpV6Address.SizeOf, Addresses[i], Endianity.Big);
}
} }
} }
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.IpV6
{
/// <summary>
/// Represents IPv6 layer.
/// <seealso cref="IpV6Datagram"/>
/// </summary>
public sealed class IpV6Layer : Layer, IEthernetNextLayer, IIpV4NextLayer
{
/// <summary>
/// Creates an IPv6 layer with all zero values.
/// </summary>
public IpV6Layer()
{
ExtensionHeaders = IpV6ExtensionHeaders.Empty;
}
public byte TrafficClass { get; set; }
public int FlowLabel { get; set; }
/// <summary>
/// Identifies the type of header immediately following the IPv6 header.
/// Uses the same values as the IPv4 Protocol field.
/// null means that this value should be calculated according to the next layer.
/// </summary>
public IpV4Protocol? NextHeader { get; set; }
public byte HopLimit { get; set; }
/// <summary>
/// Address of the originator of the packet.
/// </summary>
public IpV6Address Source { get; set; }
/// <summary>
/// Address of the intended recipient of the packet (possibly not the ultimate recipient, if a Routing header is present).
/// </summary>
public IpV6Address CurrentDestination { get; set; }
public IpV6ExtensionHeaders ExtensionHeaders { get; set; }
/// <summary>
/// The Ethernet Type the Ethernet layer should write when this layer is the Ethernet payload.
/// </summary>
public EthernetType PreviousLayerEtherType
{
get { return EthernetType.IpV6; }
}
/// <summary>
/// The protocol that should be written in the previous (IPv4) layer (in this case: IP).
/// </summary>
public IpV4Protocol PreviousLayerProtocol
{
get { return IpV4Protocol.IpV6; }
}
/// <summary>
/// The default MAC Address value when this layer is the Ethernet payload.
/// null means there is no default value.
/// </summary>
public MacAddress? PreviousLayerDefaultDestination
{
get { return null; }
}
/// <summary>
/// The number of bytes this layer will take.
/// </summary>
public override int Length
{
get { return IpV6Datagram.HeaderLength + ExtensionHeaders.Sum(header => header.Length); }
}
/// <summary>
/// Writes the layer to the buffer.
/// </summary>
/// <param name="buffer">The buffer to write the layer to.</param>
/// <param name="offset">The offset in the buffer to start writing the layer at.</param>
/// <param name="payloadLength">The length of the layer's payload (the number of bytes after the layer in the packet).</param>
/// <param name="previousLayer">The layer that comes before this layer. null if this is the first layer.</param>
/// <param name="nextLayer">The layer that comes after this layer. null if this is the last layer.</param>
public override void Write(byte[] buffer, int offset, int payloadLength, ILayer previousLayer, ILayer nextLayer)
{
IpV4Protocol nextHeader;
if (NextHeader == null)
{
if (nextLayer == null)
throw new ArgumentException("Can't determine protocol automatically from next layer because there is no next layer");
IIpV4NextLayer ipV4NextLayer = nextLayer as IIpV4NextLayer;
if (ipV4NextLayer == null)
throw new ArgumentException("Can't determine protocol automatically from next layer (" + nextLayer.GetType() + ")");
nextHeader = ipV4NextLayer.PreviousLayerProtocol;
}
else
nextHeader = NextHeader.Value;
IpV6Datagram.WriteHeader(buffer, offset,
TrafficClass, FlowLabel, (ushort)payloadLength, nextHeader, HopLimit, Source, CurrentDestination, ExtensionHeaders);
}
/// <summary>
/// True iff the two IPv4 layers have the same TypeOfService, Identification, Fragmentation, Ttl, Protocol, HeaderChecksum, Source, Destination and Options.
/// </summary>
public bool Equals(IpV6Layer other)
{
return other != null &&
TrafficClass == other.TrafficClass && FlowLabel == other.FlowLabel &&
NextHeader == other.NextHeader && HopLimit == other.HopLimit &&
Source == other.Source && CurrentDestination == other.CurrentDestination &&
ExtensionHeaders.SequenceEqual(other.ExtensionHeaders);
}
/// <summary>
/// True iff the two IPv4 layers have the same TypeOfService, Identification, Fragmentation, Ttl, Protocol, HeaderChecksum, Source, Destination and Options.
/// </summary>
public override bool Equals(Layer other)
{
return Equals(other as IpV6Layer);
}
/// <summary>
/// Returns a hash code for the layer.
/// The hash code is a XOR of the TrafficClass and HopLimit combined and the hash codes of the FlowLabel, Source, CurrentDestination, NextHeader, HeaderChecksum, ExtensionHeaders.
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode() ^
Sequence.GetHashCode(BitSequence.Merge(TrafficClass, HopLimit),
FlowLabel, Source, CurrentDestination, NextHeader) ^ ExtensionHeaders.SequenceGetHashCode();
}
/// <summary>
/// Contains the Source, Destination and Protocol.
/// </summary>
public override string ToString()
{
return Source + " -> " + CurrentDestination + " (" + NextHeader + ")";
}
}
}
\ No newline at end of file
...@@ -30,7 +30,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -30,7 +30,7 @@ namespace PcapDotNet.Packets.IpV6
public class IpV6OptionSmfDpdIpV4 : IpV6OptionSmfDpdSequenceBased public class IpV6OptionSmfDpdIpV4 : IpV6OptionSmfDpdSequenceBased
{ {
public IpV6OptionSmfDpdIpV4(IpV4Address taggerId, DataSegment identifier) public IpV6OptionSmfDpdIpV4(IpV4Address taggerId, DataSegment identifier)
:base(identifier) : base(identifier)
{ {
TaggerId = taggerId; TaggerId = taggerId;
} }
......
...@@ -265,7 +265,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -265,7 +265,7 @@ namespace PcapDotNet.Packets.IpV6
/// RFC 5568. /// RFC 5568.
/// Mobility Header IPv6 Address/Prefix. /// Mobility Header IPv6 Address/Prefix.
/// </summary> /// </summary>
MobilityHeaderIpV6AddressPrefix = 0x22, IpV6AddressPrefix = 0x22,
/// <summary> /// <summary>
/// RFC 5648. /// RFC 5648.
......
...@@ -561,7 +561,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -561,7 +561,7 @@ namespace PcapDotNet.Packets.IpV6
} }
} }
public enum IpV6MobilityOptionLinkLayerAddressCode : byte public enum IpV6MobilityLinkLayerAddressCode : byte
{ {
/// <summary> /// <summary>
/// Wildcard requesting resolution for all nearby access points. /// Wildcard requesting resolution for all nearby access points.
...@@ -637,14 +637,14 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -637,14 +637,14 @@ namespace PcapDotNet.Packets.IpV6
public const int OptionDataMinimumLength = Offset.LinkLayerAddress; public const int OptionDataMinimumLength = Offset.LinkLayerAddress;
public IpV6MobilityOptionLinkLayerAddress(IpV6MobilityOptionLinkLayerAddressCode code, DataSegment linkLayerAddress) public IpV6MobilityOptionLinkLayerAddress(IpV6MobilityLinkLayerAddressCode code, DataSegment linkLayerAddress)
: base(IpV6MobilityOptionType.LinkLayerAddress) : base(IpV6MobilityOptionType.LinkLayerAddress)
{ {
Code = code; Code = code;
LinkLayerAddress = linkLayerAddress; LinkLayerAddress = linkLayerAddress;
} }
public IpV6MobilityOptionLinkLayerAddressCode Code { get; private set; } public IpV6MobilityLinkLayerAddressCode Code { get; private set; }
/// <summary> /// <summary>
/// Variable-length link-layer address. /// Variable-length link-layer address.
...@@ -656,7 +656,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -656,7 +656,7 @@ namespace PcapDotNet.Packets.IpV6
if (data.Length < OptionDataMinimumLength) if (data.Length < OptionDataMinimumLength)
return null; return null;
IpV6MobilityOptionLinkLayerAddressCode code = (IpV6MobilityOptionLinkLayerAddressCode)data[Offset.OptionCode]; IpV6MobilityLinkLayerAddressCode code = (IpV6MobilityLinkLayerAddressCode)data[Offset.OptionCode];
DataSegment linkLayerAddress = data.Subsegment(Offset.LinkLayerAddress, data.Length - Offset.LinkLayerAddress); DataSegment linkLayerAddress = data.Subsegment(Offset.LinkLayerAddress, data.Length - Offset.LinkLayerAddress);
return new IpV6MobilityOptionLinkLayerAddress(code, linkLayerAddress); return new IpV6MobilityOptionLinkLayerAddress(code, linkLayerAddress);
...@@ -2468,7 +2468,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2468,7 +2468,7 @@ namespace PcapDotNet.Packets.IpV6
/// <summary> /// <summary>
/// RFC 5845. /// RFC 5845.
/// </summary> /// </summary>
public enum IpV6MobilityHeaderIpV6AddressPrefixCode : byte public enum IpV6MobilityIpV6AddressPrefixCode : byte
{ {
/// <summary> /// <summary>
/// Old Care-of Address. /// Old Care-of Address.
...@@ -2514,8 +2514,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2514,8 +2514,8 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+-----------------------------+ /// +-----+-----------------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
[IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.MobilityHeaderIpV6AddressPrefix)] [IpV6MobilityOptionTypeRegistration(IpV6MobilityOptionType.IpV6AddressPrefix)]
public class IpV6MobilityOptionMobilityHeaderIpV6AddressPrefix : IpV6MobilityOptionComplex public class IpV6MobilityOptionIpV6AddressPrefix : IpV6MobilityOptionComplex
{ {
public const byte MaxPrefixLength = 128; public const byte MaxPrefixLength = 128;
...@@ -2528,8 +2528,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2528,8 +2528,8 @@ namespace PcapDotNet.Packets.IpV6
public const int OptionDataLength = Offset.AddressOrPrefix + IpV6Address.SizeOf; public const int OptionDataLength = Offset.AddressOrPrefix + IpV6Address.SizeOf;
public IpV6MobilityOptionMobilityHeaderIpV6AddressPrefix(IpV6MobilityHeaderIpV6AddressPrefixCode code, byte prefixLength, IpV6Address addressOrPrefix) public IpV6MobilityOptionIpV6AddressPrefix(IpV6MobilityIpV6AddressPrefixCode code, byte prefixLength, IpV6Address addressOrPrefix)
: base(IpV6MobilityOptionType.MobilityHeaderIpV6AddressPrefix) : base(IpV6MobilityOptionType.IpV6AddressPrefix)
{ {
if (prefixLength > MaxPrefixLength) if (prefixLength > MaxPrefixLength)
throw new ArgumentOutOfRangeException("prefixLength", prefixLength, string.Format("Max value is {0}", MaxPrefixLength)); throw new ArgumentOutOfRangeException("prefixLength", prefixLength, string.Format("Max value is {0}", MaxPrefixLength));
...@@ -2542,7 +2542,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2542,7 +2542,7 @@ namespace PcapDotNet.Packets.IpV6
/// <summary> /// <summary>
/// Describes the kind of the address or the prefix. /// Describes the kind of the address or the prefix.
/// </summary> /// </summary>
public IpV6MobilityHeaderIpV6AddressPrefixCode Code { get; private set; } public IpV6MobilityIpV6AddressPrefixCode Code { get; private set; }
/// <summary> /// <summary>
/// Indicates the length of the IPv6 Address Prefix. /// Indicates the length of the IPv6 Address Prefix.
...@@ -2560,10 +2560,10 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2560,10 +2560,10 @@ namespace PcapDotNet.Packets.IpV6
if (data.Length != OptionDataLength) if (data.Length != OptionDataLength)
return null; return null;
IpV6MobilityHeaderIpV6AddressPrefixCode code = (IpV6MobilityHeaderIpV6AddressPrefixCode)data[Offset.Code]; IpV6MobilityIpV6AddressPrefixCode code = (IpV6MobilityIpV6AddressPrefixCode)data[Offset.Code];
byte prefixLength = data[Offset.PrefixLength]; byte prefixLength = data[Offset.PrefixLength];
IpV6Address addressOrPrefix = data.ReadIpV6Address(Offset.AddressOrPrefix, Endianity.Big); IpV6Address addressOrPrefix = data.ReadIpV6Address(Offset.AddressOrPrefix, Endianity.Big);
return new IpV6MobilityOptionMobilityHeaderIpV6AddressPrefix(code, prefixLength, addressOrPrefix); return new IpV6MobilityOptionIpV6AddressPrefix(code, prefixLength, addressOrPrefix);
} }
internal override int DataLength internal override int DataLength
......
...@@ -9,6 +9,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -9,6 +9,12 @@ namespace PcapDotNet.Packets.IpV6
{ {
public class IpV6Options : Options<IpV6Option> public class IpV6Options : Options<IpV6Option>
{ {
public IpV6Options(IList<IpV6Option> options)
: base(options, true, null)
{
}
public IpV6Options(DataSegment data) : this(Read(data)) public IpV6Options(DataSegment data) : this(Read(data))
{ {
} }
......
...@@ -316,6 +316,7 @@ ...@@ -316,6 +316,7 @@
<Compile Include="Igmp\IgmpRecordType.cs" /> <Compile Include="Igmp\IgmpRecordType.cs" />
<Compile Include="Igmp\IgmpMessageType.cs" /> <Compile Include="Igmp\IgmpMessageType.cs" />
<Compile Include="Igmp\IIgmpLayerWithGroupAddress.cs" /> <Compile Include="Igmp\IIgmpLayerWithGroupAddress.cs" />
<Compile Include="IpV6\IpV6Layer.cs" />
<Compile Include="IpV6\Options\IpV6CalipsoDomainOfInterpretation.cs" /> <Compile Include="IpV6\Options\IpV6CalipsoDomainOfInterpretation.cs" />
<Compile Include="IpV6\IpV6ExtensionHeader.cs" /> <Compile Include="IpV6\IpV6ExtensionHeader.cs" />
<Compile Include="IpV6\IpV6ExtensionHeaderAuthentication.cs" /> <Compile Include="IpV6\IpV6ExtensionHeaderAuthentication.cs" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment