Commit eeeea13e authored by Brickner_cp's avatar Brickner_cp

IPv6

parent 4d770fb0
...@@ -57,7 +57,7 @@ namespace PcapDotNet.Packets.Test ...@@ -57,7 +57,7 @@ namespace PcapDotNet.Packets.Test
Packet packet = PacketBuilder.Build(DateTime.Now, ethernetLayer, payloadLayer); Packet packet = PacketBuilder.Build(DateTime.Now, ethernetLayer, payloadLayer);
// Ethernet // Ethernet
Assert.IsTrue(new[] {EthernetType.IpV4, EthernetType.Arp, EthernetType.VLanTaggedFrame}.Contains(packet.Ethernet.EtherType) || Assert.IsTrue(new[] {EthernetType.IpV4, EthernetType.IpV6, EthernetType.Arp, EthernetType.VLanTaggedFrame}.Contains(packet.Ethernet.EtherType) ||
packet.IsValid, "IsValid - EtherType = " + packet.Ethernet.EtherType); packet.IsValid, "IsValid - EtherType = " + packet.Ethernet.EtherType);
Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLengthValue, packet.Ethernet.PayloadLength, "PayloadLength"); Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLengthValue, packet.Ethernet.PayloadLength, "PayloadLength");
Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer"); Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer");
......
...@@ -68,7 +68,7 @@ namespace PcapDotNet.Packets.Test ...@@ -68,7 +68,7 @@ namespace PcapDotNet.Packets.Test
Packet packet = packetBuilder.Build(DateTime.Now); Packet packet = packetBuilder.Build(DateTime.Now);
if (greLayer.Checksum == null && if (greLayer.Checksum == null &&
!new[] { EthernetType.IpV4, EthernetType.Arp, EthernetType.VLanTaggedFrame }.Contains(packet.Ethernet.IpV4.Gre.ProtocolType)) !new[] { EthernetType.IpV4, EthernetType.IpV6, EthernetType.Arp, EthernetType.VLanTaggedFrame }.Contains(packet.Ethernet.IpV4.Gre.ProtocolType))
{ {
Assert.IsTrue(packet.IsValid, "IsValid, ProtocolType=" + packet.Ethernet.IpV4.Gre.ProtocolType); Assert.IsTrue(packet.IsValid, "IsValid, ProtocolType=" + packet.Ethernet.IpV4.Gre.ProtocolType);
} }
...@@ -222,7 +222,7 @@ namespace PcapDotNet.Packets.Test ...@@ -222,7 +222,7 @@ namespace PcapDotNet.Packets.Test
PacketBuilder packetBuilder = new PacketBuilder(ethernetLayer, ipV4Layer, greLayer); PacketBuilder packetBuilder = new PacketBuilder(ethernetLayer, ipV4Layer, greLayer);
Packet packet = packetBuilder.Build(DateTime.Now); Packet packet = packetBuilder.Build(DateTime.Now);
Assert.IsTrue(packet.IsValid || Assert.IsTrue(packet.IsValid ||
new[] {EthernetType.IpV4, EthernetType.Arp, EthernetType.VLanTaggedFrame}.Contains(greLayer.ProtocolType), new[] { EthernetType.IpV4, EthernetType.IpV6, EthernetType.Arp, EthernetType.VLanTaggedFrame }.Contains(greLayer.ProtocolType),
"IsValid. ProtoclType=" + greLayer.ProtocolType); "IsValid. ProtoclType=" + greLayer.ProtocolType);
GreDatagram gre = packet.Ethernet.IpV4.Gre; GreDatagram gre = packet.Ethernet.IpV4.Gre;
......
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using PcapDotNet.Base; using PcapDotNet.Base;
...@@ -59,7 +60,7 @@ namespace PcapDotNet.Packets.Test ...@@ -59,7 +60,7 @@ namespace PcapDotNet.Packets.Test
EtherType = EthernetType EtherType = EthernetType
}; };
Random random = new Random(1); Random random = new Random();
for (int i = 0; i != 1000; ++i) for (int i = 0; i != 1000; ++i)
{ {
...@@ -67,7 +68,10 @@ namespace PcapDotNet.Packets.Test ...@@ -67,7 +68,10 @@ namespace PcapDotNet.Packets.Test
PayloadLayer payloadLayer = random.NextPayloadLayer(random.NextInt(0, 50 * 1024)); PayloadLayer payloadLayer = random.NextPayloadLayer(random.NextInt(0, 50 * 1024));
Packet packet = PacketBuilder.Build(DateTime.Now, ethernetLayer, ipV6Layer, payloadLayer); List<ILayer> layers = new List<ILayer> {ethernetLayer, ipV6Layer};
if (ipV6Layer.ExtensionHeaders.LastHeader != IpV4Protocol.EncapsulatingSecurityPayload)
layers.Add(payloadLayer);
Packet packet = PacketBuilder.Build(DateTime.Now, layers);
Assert.IsTrue(packet.IsValid, string.Format("IsValid ({0}...{1})", ipV6Layer.NextHeader, ipV6Layer.ExtensionHeaders.NextHeader)); Assert.IsTrue(packet.IsValid, string.Format("IsValid ({0}...{1})", ipV6Layer.NextHeader, ipV6Layer.ExtensionHeaders.NextHeader));
......
...@@ -16,11 +16,21 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -16,11 +16,21 @@ namespace PcapDotNet.Packets.TestUtils
return new IpV6Address(random.NextUInt128()); return new IpV6Address(random.NextUInt128());
} }
public static IpV6Address NextIpV6AddressWithLeadingZeroBytes(this Random random, int numLeadingZeros)
{
return new IpV6Address(random.NextUInt128() >> (8 * numLeadingZeros));
}
public static IpV6Address[] NextIpV6AddressArray(this Random random, int count) public static IpV6Address[] NextIpV6AddressArray(this Random random, int count)
{ {
return ((Func<IpV6Address>)(random.NextIpV6Address)).GenerateArray(count); return ((Func<IpV6Address>)(random.NextIpV6Address)).GenerateArray(count);
} }
public static IpV6Address[] NextIpV6AddressWithLeadingZeroBytesArray(this Random random, int numLeadingZeros, int count)
{
return ((Func<IpV6Address>)(() => random.NextIpV6AddressWithLeadingZeroBytes(numLeadingZeros))).GenerateArray(count);
}
public static IpV6Layer NextIpV6Layer(this Random random) public static IpV6Layer NextIpV6Layer(this Random random)
{ {
IpV6ExtensionHeaders extensionHeaders = random.NextIpV6ExtensionHeaders(random.NextInt(0, 10)); IpV6ExtensionHeaders extensionHeaders = random.NextIpV6ExtensionHeaders(random.NextInt(0, 10));
...@@ -73,10 +83,14 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -73,10 +83,14 @@ namespace PcapDotNet.Packets.TestUtils
return new IpV6ExtensionHeaderRoutingHomeAddress(nextHeader, random.NextByte(), random.NextIpV6Address()); return new IpV6ExtensionHeaderRoutingHomeAddress(nextHeader, random.NextByte(), random.NextIpV6Address());
case IpV6RoutingType.RplSourceRouteHeader: case IpV6RoutingType.RplSourceRouteHeader:
return new IpV6ExtensionHeaderRoutingRpl(nextHeader, random.NextByte(), byte commonPrefixLengthForNonLastAddresses = random.NextByte(IpV6ExtensionHeaderRoutingRpl.MaxCommonPrefixLength + 1);
random.NextByte(IpV6ExtensionHeaderRoutingRpl.MaxCommonPrefixLength + 1), byte commonPrefixLengthForLastAddress = random.NextByte(IpV6ExtensionHeaderRoutingRpl.MaxCommonPrefixLength + 1);
random.NextByte(IpV6ExtensionHeaderRoutingRpl.MaxCommonPrefixLength + 1), IpV6Address[] addresses = random.NextIpV6AddressWithLeadingZeroBytesArray(commonPrefixLengthForNonLastAddresses,
random.NextIpV6AddressArray(random.NextInt(0, 10))); random.NextInt(0, 10));
if (addresses.Any() || random.NextBool())
addresses = addresses.Concat(random.NextIpV6AddressWithLeadingZeroBytes(commonPrefixLengthForLastAddress)).ToArray();
return new IpV6ExtensionHeaderRoutingRpl(nextHeader, random.NextByte(), commonPrefixLengthForNonLastAddresses,
commonPrefixLengthForLastAddress, addresses);
default: default:
throw new InvalidOperationException(string.Format("Invalid routingType value {0}", routingType)); throw new InvalidOperationException(string.Format("Invalid routingType value {0}", routingType));
...@@ -155,7 +169,7 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -155,7 +169,7 @@ namespace PcapDotNet.Packets.TestUtils
return new IpV6ExtensionHeaderMobilityFastNeighborAdvertisement(nextHeader, checksum, random.NextIpV6MobilityOptions()); return new IpV6ExtensionHeaderMobilityFastNeighborAdvertisement(nextHeader, checksum, random.NextIpV6MobilityOptions());
case IpV6MobilityHeaderType.Experimental: // 11 case IpV6MobilityHeaderType.Experimental: // 11
return new IpV6ExtensionHeaderMobilityExperimental(nextHeader, checksum, random.NextDataSegment(random.Next(100))); return new IpV6ExtensionHeaderMobilityExperimental(nextHeader, checksum, random.NextDataSegment(2 + random.Next(10) * 8));
case IpV6MobilityHeaderType.HomeAgentSwitchMessage: // 12 case IpV6MobilityHeaderType.HomeAgentSwitchMessage: // 12
return new IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage(nextHeader, checksum, random.NextIpV6AddressArray(random.NextInt(0, 10)), return new IpV6ExtensionHeaderMobilityHomeAgentSwitchMessage(nextHeader, checksum, random.NextIpV6AddressArray(random.NextInt(0, 10)),
...@@ -260,7 +274,7 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -260,7 +274,7 @@ namespace PcapDotNet.Packets.TestUtils
return new IpV6OptionSmfDpdNull(identifier); return new IpV6OptionSmfDpdNull(identifier);
case IpV6TaggerIdType.Default: case IpV6TaggerIdType.Default:
return new IpV6OptionSmfDpdDefault(random.NextDataSegment(random.NextInt(0, 100)), identifier); return new IpV6OptionSmfDpdDefault(random.NextDataSegment(random.NextInt(1, 17)), identifier);
case IpV6TaggerIdType.IpV4: case IpV6TaggerIdType.IpV4:
return new IpV6OptionSmfDpdIpV4(random.NextIpV4Address(), identifier); return new IpV6OptionSmfDpdIpV4(random.NextIpV4Address(), identifier);
...@@ -447,7 +461,7 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -447,7 +461,7 @@ namespace PcapDotNet.Packets.TestUtils
return return
new IpV6MobilityOptionContextRequest( new IpV6MobilityOptionContextRequest(
((Func<IpV6MobilityOptionContextRequestEntry>)(() => new IpV6MobilityOptionContextRequestEntry( ((Func<IpV6MobilityOptionContextRequestEntry>)(() => new IpV6MobilityOptionContextRequestEntry(
random.NextByte(), random.NextDataSegment(random.NextInt(0, 100))))). random.NextByte(), random.NextDataSegment(random.NextInt(0, 25))))).
GenerateArray(random.NextInt(0, 10))); GenerateArray(random.NextInt(0, 10)));
case IpV6MobilityOptionType.LocalMobilityAnchorAddress: case IpV6MobilityOptionType.LocalMobilityAnchorAddress:
...@@ -516,7 +530,7 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -516,7 +530,7 @@ namespace PcapDotNet.Packets.TestUtils
return new IpV6FlowIdentificationSubOptionBindingReference(((Func<ushort>)(random.NextUShort)).GenerateArray(random.NextInt(0, 10))); return new IpV6FlowIdentificationSubOptionBindingReference(((Func<ushort>)(random.NextUShort)).GenerateArray(random.NextInt(0, 10)));
case IpV6FlowIdentificationSubOptionType.TrafficSelector: case IpV6FlowIdentificationSubOptionType.TrafficSelector:
return new IpV6FlowIdentificationSubOptionTrafficSelector(random.NextEnum<IpV6FlowIdentificationTrafficSelectorFormat>(), random.NextDataSegment(random.NextInt(0, 100))); return new IpV6FlowIdentificationSubOptionTrafficSelector(random.NextEnum<IpV6FlowIdentificationTrafficSelectorFormat>(), random.NextDataSegment(random.NextInt(0, 50)));
default: default:
throw new InvalidOperationException(string.Format("Invalid optionType value {0}", optionType)); throw new InvalidOperationException(string.Format("Invalid optionType value {0}", optionType));
...@@ -525,7 +539,18 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -525,7 +539,18 @@ namespace PcapDotNet.Packets.TestUtils
public static IpV6AccessNetworkIdentifierSubOptions NextIpV6AccessNetworkIdentifierSubOptions(this Random random) public static IpV6AccessNetworkIdentifierSubOptions NextIpV6AccessNetworkIdentifierSubOptions(this Random random)
{ {
return new IpV6AccessNetworkIdentifierSubOptions(((Func<IpV6AccessNetworkIdentifierSubOption>)(random.NextIpV6AccessNetworkIdentifierSubOption)).GenerateArray(random.NextInt(0, 10))); List<IpV6AccessNetworkIdentifierSubOption> subOptions = new List<IpV6AccessNetworkIdentifierSubOption>();
int numOptions = random.NextInt(0, 10);
int optionsBytesLength = 0;
for (int i = 0; i != numOptions; ++i)
{
IpV6AccessNetworkIdentifierSubOption subOption = random.NextIpV6AccessNetworkIdentifierSubOption();
if (optionsBytesLength + subOption.Length > byte.MaxValue - 2)
break;
subOptions.Add(subOption);
optionsBytesLength += subOption.Length;
}
return new IpV6AccessNetworkIdentifierSubOptions(subOptions);
} }
public static IpV6AccessNetworkIdentifierSubOption NextIpV6AccessNetworkIdentifierSubOption(this Random random) public static IpV6AccessNetworkIdentifierSubOption NextIpV6AccessNetworkIdentifierSubOption(this Random random)
......
...@@ -248,12 +248,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -248,12 +248,11 @@ namespace PcapDotNet.Packets.IpV6
protected override bool CalculateIsValid() protected override bool CalculateIsValid()
{ {
_isValid = true;
ParseExtensionHeaders(); ParseExtensionHeaders();
return _isValid; return _isValid;
} }
private IpV6ExtensionHeaders _extensionHeaders; private IpV6ExtensionHeaders _extensionHeaders;
private bool _isValid; private bool _isValid = true;
} }
} }
...@@ -244,6 +244,15 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -244,6 +244,15 @@ namespace PcapDotNet.Packets.IpV6
{ {
public IpV6ExtensionHeaders(ReadOnlyCollection<IpV6ExtensionHeader> extensionHeaders) public IpV6ExtensionHeaders(ReadOnlyCollection<IpV6ExtensionHeader> extensionHeaders)
{ {
for (int i = 0; i < extensionHeaders.Count; ++i)
{
if (extensionHeaders[i].Protocol == IpV4Protocol.EncapsulatingSecurityPayload && i != extensionHeaders.Count - 1)
{
throw new ArgumentException(
string.Format("EncapsulatingSecurityPayload can only be the last extension header. However it is the {0} out of {1}.", (i + 1),
extensionHeaders.Count), "extensionHeaders");
}
}
Headers = extensionHeaders; Headers = extensionHeaders;
IsValid = true; IsValid = true;
} }
...@@ -291,6 +300,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -291,6 +300,16 @@ namespace PcapDotNet.Packets.IpV6
} }
} }
public IpV4Protocol? LastHeader
{
get
{
if (!Headers.Any())
return null;
return Headers[Headers.Count - 1].Protocol;
}
}
public IpV4Protocol? NextHeader public IpV4Protocol? NextHeader
{ {
get get
......
...@@ -268,9 +268,6 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -268,9 +268,6 @@ namespace PcapDotNet.Packets.IpV6
} }
Checksum = checksum; Checksum = checksum;
MobilityOptions = mobilityOptions; MobilityOptions = mobilityOptions;
// TODO: Remove this.
if (Length % 8 != 0)
throw new InvalidOperationException("Must divide by 8");
} }
/// <summary> /// <summary>
...@@ -746,8 +743,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -746,8 +743,8 @@ namespace PcapDotNet.Packets.IpV6
return null; return null;
ushort homeNonceIndex = messageData.ReadUShort(MessageDataOffset.HomeNonceIndex, Endianity.Big); ushort homeNonceIndex = messageData.ReadUShort(MessageDataOffset.HomeNonceIndex, Endianity.Big);
ushort homeInitCookie = messageData.ReadUShort(MessageDataOffset.HomeInitCookie, Endianity.Big); ulong homeInitCookie = messageData.ReadULong(MessageDataOffset.HomeInitCookie, Endianity.Big);
ushort homeKeygenToken = messageData.ReadUShort(MessageDataOffset.HomeKeygenToken, Endianity.Big); ulong homeKeygenToken = messageData.ReadULong(MessageDataOffset.HomeKeygenToken, Endianity.Big);
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);
} }
...@@ -1892,7 +1889,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1892,7 +1889,7 @@ namespace PcapDotNet.Packets.IpV6
} }
/// <summary> /// <summary>
/// RFCs 5096. /// RFC 5096.
/// <pre> /// <pre>
/// +-----+-------------+-------------------------+ /// +-----+-------------+-------------------------+
/// | Bit | 0-7 | 8-15 | /// | Bit | 0-7 | 8-15 |
...@@ -1913,8 +1910,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -1913,8 +1910,8 @@ namespace PcapDotNet.Packets.IpV6
public IpV6ExtensionHeaderMobilityExperimental(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData) public IpV6ExtensionHeaderMobilityExperimental(IpV4Protocol nextHeader, ushort checksum, DataSegment messageData)
: base(nextHeader, checksum, IpV6MobilityOptions.None, null) : base(nextHeader, checksum, IpV6MobilityOptions.None, null)
{ {
if (messageData.Length % 8 != 4) if (messageData.Length % 8 != 2)
throw new ArgumentException("Message data size must be an integral product of 8 bytes plus 4 bytes", "messageData"); throw new ArgumentException("Message data size must be an integral product of 8 bytes plus 2 bytes", "messageData");
MessageData = messageData; MessageData = messageData;
} }
......
...@@ -80,14 +80,37 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -80,14 +80,37 @@ namespace PcapDotNet.Packets.IpV6
} }
CommonPrefixLengthForLastAddress = commonPrefixLengthForLastAddress; CommonPrefixLengthForLastAddress = commonPrefixLengthForLastAddress;
if (addresses.Any())
{
if (commonPrefixLengthForNonLastAddresses != 0)
{
for (int i = 0; i != addresses.Length - 1; ++i)
ValidateCommonPrefixForAddress(addresses, i, commonPrefixLengthForNonLastAddresses);
}
if (commonPrefixLengthForLastAddress != 0)
ValidateCommonPrefixForAddress(addresses, addresses.Length - 1, commonPrefixLengthForLastAddress);
}
Addresses = addresses.AsReadOnly(); Addresses = addresses.AsReadOnly();
PadSize = (byte)((8 - Length % 8) % 8); PadSize = (byte)((8 - Length % 8) % 8);
} }
private static void ValidateCommonPrefixForAddress(IpV6Address[] addresses, int addressIndex, byte commonPrefixLength)
{
IpV6Address address = addresses[addressIndex];
if (address.ToValue() >> (8 * (IpV6Address.SizeOf - commonPrefixLength)) != 0)
{
throw new ArgumentOutOfRangeException("addresses", address,
string.Format("When an address has {0} common bytes, it should start with {0} zero bytes.",
commonPrefixLength));
}
}
public override IpV6RoutingType RoutingType public override IpV6RoutingType RoutingType
{ {
get { return IpV6RoutingType.SourceRoute; } get { return IpV6RoutingType.RplSourceRouteHeader; }
} }
/// <summary> /// <summary>
...@@ -129,7 +152,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -129,7 +152,7 @@ namespace PcapDotNet.Packets.IpV6
byte commonPrefixLengthForNonLastAddresses = byte commonPrefixLengthForNonLastAddresses =
(byte)((routingData[RoutingDataOffset.CommonPrefixLengthForNonLastAddresses] & RoutingDataMask.CommonPrefixLengthForNonLastAddresses) >> (byte)((routingData[RoutingDataOffset.CommonPrefixLengthForNonLastAddresses] & RoutingDataMask.CommonPrefixLengthForNonLastAddresses) >>
RoutingDataShift.CommonPrefixLengthForNonLastAddresses); RoutingDataShift.CommonPrefixLengthForNonLastAddresses);
if (commonPrefixLengthForNonLastAddresses >= MaxCommonPrefixLength) if (commonPrefixLengthForNonLastAddresses > MaxCommonPrefixLength)
return null; return null;
byte commonPrefixLengthForLastAddress = byte commonPrefixLengthForLastAddress =
...@@ -141,8 +164,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -141,8 +164,11 @@ namespace PcapDotNet.Packets.IpV6
if (padSize > MaxPadSize) if (padSize > MaxPadSize)
return null; return null;
int numAddresses = (routingData.Length - RoutingDataOffset.Addresses - padSize - (IpV6Address.SizeOf - commonPrefixLengthForLastAddress)) / int addressesLength = routingData.Length - RoutingDataOffset.Addresses - padSize;
(IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses) + 1; int numAddresses = addressesLength == 0
? 0
: (addressesLength - (IpV6Address.SizeOf - commonPrefixLengthForLastAddress)) /
(IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses) + 1;
if (numAddresses < 0) if (numAddresses < 0)
return null; return null;
...@@ -154,16 +180,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -154,16 +180,16 @@ namespace PcapDotNet.Packets.IpV6
{ {
DataSegment addressSegment = DataSegment addressSegment =
routingData.Subsegment(RoutingDataOffset.Addresses + i * (IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses), routingData.Subsegment(RoutingDataOffset.Addresses + i * (IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses),
commonPrefixLengthForNonLastAddresses); IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses);
addressSegment.Write(addressBytes, 0); addressSegment.Write(addressBytes, commonPrefixLengthForNonLastAddresses);
addresses[i] = addressBytes.ReadIpV6Address(0, Endianity.Big); addresses[i] = addressBytes.ReadIpV6Address(0, Endianity.Big);
} }
addressBytes = new byte[IpV6Address.SizeOf]; addressBytes = new byte[IpV6Address.SizeOf];
DataSegment lastAddressSegment = DataSegment lastAddressSegment =
routingData.Subsegment(RoutingDataOffset.Addresses + (numAddresses - 1) * (IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses), routingData.Subsegment(RoutingDataOffset.Addresses + (numAddresses - 1) * (IpV6Address.SizeOf - commonPrefixLengthForNonLastAddresses),
commonPrefixLengthForLastAddress); IpV6Address.SizeOf - commonPrefixLengthForLastAddress);
lastAddressSegment.Write(addressBytes, 0); lastAddressSegment.Write(addressBytes, commonPrefixLengthForLastAddress);
addresses[numAddresses - 1] = addressBytes.ReadIpV6Address(0, Endianity.Big); addresses[numAddresses - 1] = addressBytes.ReadIpV6Address(0, Endianity.Big);
} }
return new IpV6ExtensionHeaderRoutingRpl(nextHeader, segmentsLeft, commonPrefixLengthForNonLastAddresses, commonPrefixLengthForLastAddress, return new IpV6ExtensionHeaderRoutingRpl(nextHeader, segmentsLeft, commonPrefixLengthForNonLastAddresses, commonPrefixLengthForLastAddress,
......
...@@ -105,6 +105,9 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -105,6 +105,9 @@ namespace PcapDotNet.Packets.IpV6
nextHeader = NextHeader.Value; nextHeader = NextHeader.Value;
} }
if (nextLayer != null && ExtensionHeaders.LastHeader == IpV4Protocol.EncapsulatingSecurityPayload)
throw new ArgumentException("Cannot have a layer after IpV6Layer with EncapsulatingSecurityPayload extension header.", "nextLayer");
IpV6Datagram.WriteHeader(buffer, offset, IpV6Datagram.WriteHeader(buffer, offset,
TrafficClass, FlowLabel, (ushort)(payloadLength + ExtensionHeaders.Sum(header => header.Length)), nextHeader, HopLimit, Source, CurrentDestination, ExtensionHeaders); TrafficClass, FlowLabel, (ushort)(payloadLength + ExtensionHeaders.Sum(header => header.Length)), nextHeader, HopLimit, Source, CurrentDestination, ExtensionHeaders);
} }
......
...@@ -67,15 +67,20 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -67,15 +67,20 @@ namespace PcapDotNet.Packets.IpV6
get { return base.Length + sizeof(byte) + DataLength; } get { return base.Length + sizeof(byte) + DataLength; }
} }
internal const int MaxDataLength = byte.MaxValue - sizeof(byte) - sizeof(byte);
internal abstract int DataLength { get; } internal abstract int DataLength { get; }
internal override sealed void Write(byte[] buffer, ref int offset) internal override sealed void Write(byte[] buffer, ref int offset)
{ {
base.Write(buffer, ref offset); base.Write(buffer, ref offset);
// TODO: Remove this check.
if (DataLength > byte.MaxValue)
throw new InvalidOperationException("DataLength is too big.");
buffer[offset++] = (byte)DataLength; buffer[offset++] = (byte)DataLength;
WriteData(buffer, ref offset); WriteData(buffer, ref offset);
} }
internal abstract void WriteData(byte[] buffer, ref int offset); internal abstract void WriteData(byte[] buffer, ref int offset);
} }
} }
\ No newline at end of file
using System;
namespace PcapDotNet.Packets.IpV6 namespace PcapDotNet.Packets.IpV6
{ {
/// <summary> /// <summary>
...@@ -28,6 +30,17 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -28,6 +30,17 @@ namespace PcapDotNet.Packets.IpV6
public IpV6OptionSmfDpdDefault(DataSegment taggerId, DataSegment identifier) public IpV6OptionSmfDpdDefault(DataSegment taggerId, DataSegment identifier)
: base(identifier) : base(identifier)
{ {
if (taggerId.Length > TaggerIdMaxLength)
{
throw new ArgumentOutOfRangeException("taggerId", taggerId,
string.Format("Length is {0} but it must not be longer than {1} bytes.", taggerId.Length,
TaggerIdMaxLength));
}
if (taggerId.Length == 0)
{
throw new ArgumentOutOfRangeException("taggerId", taggerId,
string.Format("Length is {0} but it must be longer than 0 bytes.", taggerId.Length));
}
TaggerId = taggerId; TaggerId = taggerId;
} }
......
...@@ -26,6 +26,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -26,6 +26,8 @@ namespace PcapDotNet.Packets.IpV6
/// </summary> /// </summary>
public abstract class IpV6OptionSmfDpdSequenceBased : IpV6OptionSmfDpd public abstract class IpV6OptionSmfDpdSequenceBased : IpV6OptionSmfDpd
{ {
internal const int TaggerIdMaxLength = 0xF + 1;
private static class Offset private static class Offset
{ {
public const int TaggerIdType = 0; public const int TaggerIdType = 0;
...@@ -138,7 +140,6 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -138,7 +140,6 @@ namespace PcapDotNet.Packets.IpV6
{ {
return other != null && return other != null &&
Identifier.Equals(other.Identifier) && TaggerIdType == other.TaggerIdType && EqualsTaggerId(other); Identifier.Equals(other.Identifier) && TaggerIdType == other.TaggerIdType && EqualsTaggerId(other);
} }
} }
} }
\ No newline at end of file
...@@ -158,7 +158,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -158,7 +158,7 @@ namespace PcapDotNet.Packets.IpV6
public IpV6MobilityOptionBindingRefreshAdvice(ushort refreshInterval) public IpV6MobilityOptionBindingRefreshAdvice(ushort refreshInterval)
: base(IpV6MobilityOptionType.BindingRefreshAdvice) : base(IpV6MobilityOptionType.BindingRefreshAdvice)
{ {
refreshInterval = refreshInterval; RefreshInterval = refreshInterval;
} }
/// <summary> /// <summary>
...@@ -2634,7 +2634,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -2634,7 +2634,7 @@ namespace PcapDotNet.Packets.IpV6
public const int RefreshTime = UdpEncapsulationRequired + sizeof(ushort); public const int RefreshTime = UdpEncapsulationRequired + sizeof(ushort);
} }
public const int OptionDataLength = Offset.RefreshTime + sizeof(ushort); public const int OptionDataLength = Offset.RefreshTime + sizeof(uint);
private static class Mask private static class Mask
{ {
...@@ -3602,7 +3602,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -3602,7 +3602,7 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+-----------------------+ /// +-----+-----------------------+
/// </pre> /// </pre>
/// </summary> /// </summary>
public class IpV6MobilityOptionContextRequestEntry public sealed class IpV6MobilityOptionContextRequestEntry : IEquatable<IpV6MobilityOptionContextRequestEntry>
{ {
public IpV6MobilityOptionContextRequestEntry(byte requestType, DataSegment option) public IpV6MobilityOptionContextRequestEntry(byte requestType, DataSegment option)
{ {
...@@ -3644,6 +3644,16 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -3644,6 +3644,16 @@ namespace PcapDotNet.Packets.IpV6
buffer.Write(ref offset, OptionLength); buffer.Write(ref offset, OptionLength);
Option.Write(buffer, ref offset); Option.Write(buffer, ref offset);
} }
public bool Equals(IpV6MobilityOptionContextRequestEntry other)
{
return (other != null && RequestType.Equals(other.RequestType) && Option.Equals(other.Option));
}
public override bool Equals(object obj)
{
return Equals(obj as IpV6MobilityOptionContextRequestEntry);
}
} }
/// <summary> /// <summary>
...@@ -3679,6 +3689,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -3679,6 +3689,8 @@ namespace PcapDotNet.Packets.IpV6
{ {
Requests = requests; Requests = requests;
_dataLength = Requests.Sum(request => request.Length); _dataLength = Requests.Sum(request => request.Length);
if (_dataLength > byte.MaxValue)
throw new ArgumentOutOfRangeException("requests", requests, string.Format("requests length is too large. Takes over {0}>{1} bytes.", _dataLength, byte.MaxValue));
} }
/// <summary> /// <summary>
...@@ -4782,6 +4794,12 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -4782,6 +4794,12 @@ namespace PcapDotNet.Packets.IpV6
IpV6FlowIdentificationSubOptions subOptions) IpV6FlowIdentificationSubOptions subOptions)
: base(IpV6MobilityOptionType.FlowIdentification) : base(IpV6MobilityOptionType.FlowIdentification)
{ {
if (Offset.SubOptions + subOptions.BytesLength > byte.MaxValue)
{
throw new ArgumentOutOfRangeException("subOptions", subOptions,
string.Format("Sub Options take {0} bytes, which is more than the maximum length of {1} bytes",
subOptions.BytesLength, (byte.MaxValue - Offset.SubOptions)));
}
FlowIdentifier = flowIdentifier; FlowIdentifier = flowIdentifier;
Priority = priority; Priority = priority;
Status = status; Status = status;
...@@ -5116,10 +5134,10 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -5116,10 +5134,10 @@ namespace PcapDotNet.Packets.IpV6
return null; return null;
ushort priority = data.ReadUShort(Offset.Priority, Endianity.Big); ushort priority = data.ReadUShort(Offset.Priority, Endianity.Big);
uint sessionsInUse = data.ReadUShort(Offset.SessionsInUse, Endianity.Big); uint sessionsInUse = data.ReadUInt(Offset.SessionsInUse, Endianity.Big);
uint maximumSessions = data.ReadUShort(Offset.MaximumSessions, Endianity.Big); uint maximumSessions = data.ReadUInt(Offset.MaximumSessions, Endianity.Big);
uint usedCapacity = data.ReadUShort(Offset.UsedCapacity, Endianity.Big); uint usedCapacity = data.ReadUInt(Offset.UsedCapacity, Endianity.Big);
uint maximumCapacity = data.ReadUShort(Offset.MaximumCapacity, Endianity.Big); uint maximumCapacity = data.ReadUInt(Offset.MaximumCapacity, Endianity.Big);
return new IpV6MobilityOptionLoadInformation(priority, sessionsInUse, maximumSessions, usedCapacity, maximumCapacity); return new IpV6MobilityOptionLoadInformation(priority, sessionsInUse, maximumSessions, usedCapacity, maximumCapacity);
} }
...@@ -5423,6 +5441,8 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -5423,6 +5441,8 @@ namespace PcapDotNet.Packets.IpV6
public IpV6MobilityOptionAccessNetworkIdentifier(IpV6AccessNetworkIdentifierSubOptions subOptions) public IpV6MobilityOptionAccessNetworkIdentifier(IpV6AccessNetworkIdentifierSubOptions subOptions)
: base(IpV6MobilityOptionType.AccessNetworkIdentifier) : base(IpV6MobilityOptionType.AccessNetworkIdentifier)
{ {
if (subOptions.BytesLength > MaxDataLength)
throw new ArgumentOutOfRangeException("subOptions", subOptions, string.Format("SubOptions take more than {0} bytes", MaxDataLength));
SubOptions = subOptions; SubOptions = subOptions;
} }
...@@ -5650,6 +5670,9 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -5650,6 +5670,9 @@ namespace PcapDotNet.Packets.IpV6
internal override void Write(byte[] buffer, ref int offset) internal override void Write(byte[] buffer, ref int offset)
{ {
buffer[offset++] = (byte)OptionType; buffer[offset++] = (byte)OptionType;
// TODO: Remove this check.
if (DataLength > byte.MaxValue)
throw new InvalidOperationException("Option length is too long.");
buffer[offset++] = (byte)DataLength; buffer[offset++] = (byte)DataLength;
WriteData(buffer, ref offset); WriteData(buffer, ref offset);
} }
...@@ -5701,6 +5724,11 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -5701,6 +5724,11 @@ namespace PcapDotNet.Packets.IpV6
public IpV6AccessNetworkIdentifierSubOptionNetworkIdentifier(bool isNetworkNameUtf8, DataSegment networkName, DataSegment accessPointName) public IpV6AccessNetworkIdentifierSubOptionNetworkIdentifier(bool isNetworkNameUtf8, DataSegment networkName, DataSegment accessPointName)
: base(IpV6AccessNetworkIdentifierSubOptionType.NetworkIdentifier) : base(IpV6AccessNetworkIdentifierSubOptionType.NetworkIdentifier)
{ {
if (networkName.Length > byte.MaxValue)
throw new ArgumentOutOfRangeException("networkName", networkName, string.Format("Network Name cannot be longer than {0} bytes.", byte.MaxValue));
if (accessPointName.Length > byte.MaxValue)
throw new ArgumentOutOfRangeException("accessPointName", accessPointName, string.Format("Access Point Name cannot be longer than {0} bytes.", byte.MaxValue));
IsNetworkNameUtf8 = isNetworkNameUtf8; IsNetworkNameUtf8 = isNetworkNameUtf8;
NetworkName = networkName; NetworkName = networkName;
AccessPointName = accessPointName; AccessPointName = accessPointName;
...@@ -5774,7 +5802,7 @@ namespace PcapDotNet.Packets.IpV6 ...@@ -5774,7 +5802,7 @@ namespace PcapDotNet.Packets.IpV6
if (IsNetworkNameUtf8) if (IsNetworkNameUtf8)
buffer.Write(offset + Offset.IsNetworkNameUtf8, Mask.IsNetworkNameUtf8); buffer.Write(offset + Offset.IsNetworkNameUtf8, Mask.IsNetworkNameUtf8);
buffer.Write(offset + Offset.NetworkNameLength, (byte)NetworkName.Length); buffer.Write(offset + Offset.NetworkNameLength, (byte)NetworkName.Length);
NetworkName.Write(buffer, offset + Offset.NetworkNameLength); NetworkName.Write(buffer, offset + Offset.NetworkName);
buffer.Write(offset + AccessPointNameLengthOffset, (byte)AccessPointName.Length); buffer.Write(offset + AccessPointNameLengthOffset, (byte)AccessPointName.Length);
AccessPointName.Write(buffer, offset + AccessPointNameOffset); AccessPointName.Write(buffer, offset + AccessPointNameOffset);
offset += DataLength; offset += DataLength;
......
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