Commit 64ffbb1d authored by Brickner_cp's avatar Brickner_cp

DNS.

Separate RandomPacketExtension to different classes by protocol.
parent 066e0511
...@@ -66,14 +66,19 @@ namespace PcapDotNet.Packets.Test ...@@ -66,14 +66,19 @@ namespace PcapDotNet.Packets.Test
for (int i = 0; i != 1000; ++i) for (int i = 0; i != 1000; ++i)
{ {
DnsLayer dnsLayer = random.NextDnsLayer(); DnsLayer dnsLayer;
do
{
dnsLayer = random.NextDnsLayer();
} while (dnsLayer.Length > 65000);
Packet packet = PacketBuilder.Build(DateTime.Now, ethernetLayer, ipV4Layer, udpLayer, dnsLayer); Packet packet = PacketBuilder.Build(DateTime.Now, ethernetLayer, ipV4Layer, udpLayer, dnsLayer);
Assert.IsTrue(packet.IsValid, "IsValid"); Assert.IsTrue(packet.IsValid, "IsValid");
// DNS // DNS
Assert.AreEqual(dnsLayer, packet.Ethernet.IpV4.Udp.Dns.ExtractLayer(), "DNS Layer"); DnsLayer actualLayer = (DnsLayer)packet.Ethernet.IpV4.Udp.Dns.ExtractLayer();
Assert.AreEqual(dnsLayer, actualLayer, "DNS Layer");
} }
} }
...@@ -92,31 +97,53 @@ namespace PcapDotNet.Packets.Test ...@@ -92,31 +97,53 @@ namespace PcapDotNet.Packets.Test
dnsLayer.Queries.Add(new DnsQueryResourceRecord(new DnsDomainName(""), DnsType.All, DnsClass.In)); dnsLayer.Queries.Add(new DnsQueryResourceRecord(new DnsDomainName(""), DnsType.All, DnsClass.In));
TestDomainNameCompression(0, dnsLayer); TestDomainNameCompression(0, dnsLayer);
dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName(""), DnsType.All, DnsClass.In, 100, new DnsResourceDataUnknown(new DataSegment(new byte[0])))); dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName(""), DnsType.All, DnsClass.In, 100, new DnsResourceDataAnything(DataSegment.Empty)));
TestDomainNameCompression(0, dnsLayer); TestDomainNameCompression(0, dnsLayer);
dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName("abc"), DnsType.All, DnsClass.In, 100, new DnsResourceDataUnknown(new DataSegment(new byte[0])))); dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName("abc"), DnsType.All, DnsClass.In, 100, new DnsResourceDataAnything(DataSegment.Empty)));
TestDomainNameCompression(0, dnsLayer); TestDomainNameCompression(0, dnsLayer);
dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName("abc"), DnsType.All, DnsClass.In, 100, new DnsResourceDataUnknown(new DataSegment(new byte[0])))); dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName("abc"), DnsType.All, DnsClass.In, 100, new DnsResourceDataAnything(DataSegment.Empty)));
TestDomainNameCompression(3, dnsLayer); TestDomainNameCompression(3, dnsLayer);
dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName("def.abc"), DnsType.All, DnsClass.In, 100, new DnsResourceDataUnknown(new DataSegment(new byte[0])))); dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName("def.abc"), DnsType.All, DnsClass.In, 100, new DnsResourceDataAnything(DataSegment.Empty)));
TestDomainNameCompression(6, dnsLayer); TestDomainNameCompression(6, dnsLayer);
dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName("abc.def"), DnsType.All, DnsClass.In, 100, new DnsResourceDataUnknown(new DataSegment(new byte[0])))); dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName("abc.def"), DnsType.All, DnsClass.In, 100, new DnsResourceDataAnything(DataSegment.Empty)));
TestDomainNameCompression(6, dnsLayer); TestDomainNameCompression(6, dnsLayer);
dnsLayer.Authorities.Add(new DnsDataResourceRecord(new DnsDomainName("abc.def"), DnsType.All, DnsClass.In, 100, new DnsResourceDataUnknown(new DataSegment(new byte[0])))); dnsLayer.Authorities.Add(new DnsDataResourceRecord(new DnsDomainName("abc.def"), DnsType.All, DnsClass.In, 100, new DnsResourceDataAnything(DataSegment.Empty)));
TestDomainNameCompression(13, dnsLayer); TestDomainNameCompression(13, dnsLayer);
dnsLayer.Authorities.Add(new DnsDataResourceRecord(new DnsDomainName("abd.def"), DnsType.All, DnsClass.In, 100, new DnsResourceDataUnknown(new DataSegment(new byte[0])))); dnsLayer.Authorities.Add(new DnsDataResourceRecord(new DnsDomainName("abd.def"), DnsType.All, DnsClass.In, 100, new DnsResourceDataAnything(DataSegment.Empty)));
TestDomainNameCompression(16, dnsLayer); TestDomainNameCompression(16, dnsLayer);
dnsLayer.Additionals.Add(new DnsDataResourceRecord(new DnsDomainName("hello.abd.def"), DnsType.All, DnsClass.In, 100, new DnsResourceDataUnknown(new DataSegment(new byte[0])))); dnsLayer.Additionals.Add(new DnsDataResourceRecord(new DnsDomainName("hello.abd.def"), DnsType.All, DnsClass.In, 100, new DnsResourceDataAnything(DataSegment.Empty)));
TestDomainNameCompression(23, dnsLayer); TestDomainNameCompression(23, dnsLayer);
} }
[TestMethod]
public void DnsDomainNameCompressionTooLongTest()
{
DnsLayer dnsLayer = new DnsLayer();
TestDomainNameCompression(0, dnsLayer);
dnsLayer.Queries = new List<DnsQueryResourceRecord>();
dnsLayer.Answers = new List<DnsDataResourceRecord>();
dnsLayer.Authorities = new List<DnsDataResourceRecord>();
dnsLayer.Additionals = new List<DnsDataResourceRecord>();
TestDomainNameCompression(0, dnsLayer);
dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName("aaa"), DnsType.Null, DnsClass.In, 100, new DnsResourceDataAnything(new DataSegment(new byte[20000]))));
TestDomainNameCompression(0, dnsLayer);
dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName("bbb.aaa"), DnsType.Null, DnsClass.In, 100, new DnsResourceDataAnything(new DataSegment(new byte[1]))));
TestDomainNameCompression(3, dnsLayer);
dnsLayer.Answers.Add(new DnsDataResourceRecord(new DnsDomainName("bbb.aaa"), DnsType.Null, DnsClass.In, 100, new DnsResourceDataAnything(new DataSegment(new byte[1]))));
TestDomainNameCompression(6, dnsLayer);
}
[TestMethod] [TestMethod]
public void SimpleDnsTest() public void SimpleDnsTest()
{ {
......
...@@ -73,8 +73,19 @@ ...@@ -73,8 +73,19 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="HexEncoding.cs" /> <Compile Include="HexEncoding.cs" />
<Compile Include="RandomArpExtensions.cs" />
<Compile Include="RandomDnsExtensions.cs" />
<Compile Include="RandomEthernetExtensions.cs" />
<Compile Include="RandomGreExtensions.cs" />
<Compile Include="RandomHttpExtensions.cs" />
<Compile Include="RandomIcmpExtensions.cs" />
<Compile Include="RandomIgmpExtensions.cs" />
<Compile Include="RandomIpV4Extensions.cs" />
<Compile Include="RandomIpV6Extensions.cs" />
<Compile Include="RandomPacketsExtensions.cs" /> <Compile Include="RandomPacketsExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RandomTcpExtensions.cs" />
<Compile Include="RandomUdpExtensions.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\PcapDotNet.Base\PcapDotNet.Base.csproj"> <ProjectReference Include="..\PcapDotNet.Base\PcapDotNet.Base.csproj">
......
using System;
using PcapDotNet.Base;
using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.TestUtils
{
public static class RandomArpExtensions
{
public static ArpLayer NextArpLayer(this Random random)
{
byte hardwareAddressLength = random.NextByte();
byte protocolAddressLength = random.NextByte();
return new ArpLayer
{
SenderHardwareAddress = random.NextBytes(hardwareAddressLength).AsReadOnly(),
SenderProtocolAddress = random.NextBytes(protocolAddressLength).AsReadOnly(),
TargetHardwareAddress = random.NextBytes(hardwareAddressLength).AsReadOnly(),
TargetProtocolAddress = random.NextBytes(protocolAddressLength).AsReadOnly(),
ProtocolType = random.NextEnum<EthernetType>(),
Operation = random.NextEnum<ArpOperation>(),
};
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Text;
using PcapDotNet.Base;
using PcapDotNet.Packets.Dns;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.TestUtils
{
public static class RandomDnsExtensions
{
public static DnsLayer NextDnsLayer(this Random random)
{
DnsLayer dnsLayer = new DnsLayer();
dnsLayer.Id = random.NextUShort();
dnsLayer.IsQuery = random.NextBool();
dnsLayer.Opcode = random.NextEnum<DnsOpcode>();
dnsLayer.IsAuthoritiveAnswer = random.NextBool();
dnsLayer.IsTruncated = random.NextBool();
dnsLayer.IsRecusionDesired = random.NextBool();
dnsLayer.IsRecusionAvailable = random.NextBool();
dnsLayer.FutureUse = random.NextByte(DnsDatagram.MaxFutureUse + 1);
dnsLayer.ResponseCode = random.NextEnum<DnsResponseCode>();
dnsLayer.DomainNameCompressionMode = random.NextEnum<DnsDomainNameCompressionMode>();
int numQueries = random.Next(10);
List<DnsQueryResourceRecord> queries = new List<DnsQueryResourceRecord>();
for (int i = 0; i != numQueries; ++i)
queries.Add(random.NextDnsQueryResourceRecord());
dnsLayer.Queries = queries;
int numAnswers = random.Next(10);
List<DnsDataResourceRecord> answers = new List<DnsDataResourceRecord>();
for (int i = 0; i != numAnswers; ++i)
answers.Add(random.NextDnsDataResourceRecord());
dnsLayer.Answers = answers;
int numAuthorities = random.Next(10);
List<DnsDataResourceRecord> authorities = new List<DnsDataResourceRecord>();
for (int i = 0; i != numAuthorities; ++i)
authorities.Add(random.NextDnsDataResourceRecord());
dnsLayer.Authorities = authorities;
int numAdditionals = random.Next(10);
List<DnsDataResourceRecord> additionals = new List<DnsDataResourceRecord>();
for (int i = 0; i != numAdditionals; ++i)
additionals.Add(random.NextDnsDataResourceRecord());
dnsLayer.Additionals = additionals;
return dnsLayer;
}
public static DnsQueryResourceRecord NextDnsQueryResourceRecord(this Random random)
{
DnsQueryResourceRecord record = new DnsQueryResourceRecord(random.NextDnsDomainName(), random.NextEnum<DnsType>(), random.NextEnum<DnsClass>());
return record;
}
public static DnsDataResourceRecord NextDnsDataResourceRecord(this Random random)
{
DnsType type = random.NextEnum<DnsType>();
DnsDataResourceRecord record = new DnsDataResourceRecord(random.NextDnsDomainName(), type, random.NextEnum<DnsClass>(), random.Next(), random.NextDnsResourceData(type));
return record;
}
public static DnsDomainName NextDnsDomainName(this Random random)
{
List<string> labels = new List<string>();
int numLabels = random.Next(10);
for (int i = 0; i != numLabels; ++i)
{
int labelLength = random.Next(10);
StringBuilder label = new StringBuilder();
for (int j = 0; j != labelLength; ++j)
label.Append(random.NextChar('a', 'z'));
labels.Add(label.ToString());
}
return new DnsDomainName(string.Join(".", labels));
}
public static DnsResourceData NextDnsResourceData(this Random random, DnsType type)
{
switch (type)
{
case DnsType.A:
return new DnsResourceDataIpV4(random.NextIpV4Address());
case DnsType.Ns:
case DnsType.Md:
case DnsType.Mf:
case DnsType.CName:
case DnsType.Mb:
case DnsType.Mg:
case DnsType.Mr:
case DnsType.Ptr:
return new DnsResourceDataDomainName(random.NextDnsDomainName());
case DnsType.Soa:
return new DnsResourceDataStartOfAuthority(random.NextDnsDomainName(), random.NextDnsDomainName(),
random.NextUInt(), random.NextUInt(), random.NextUInt(), random.NextUInt(), random.NextUInt());
case DnsType.Null:
return new DnsResourceDataAnything(random.NextDataSegment(random.Next(65536)));
case DnsType.Wks:
return new DnsResourceDataWellKnownService(random.NextIpV4Address(), random.NextEnum<IpV4Protocol>(),
random.NextDataSegment(random.Next(10)));
case DnsType.HInfo:
return new DnsResourceDataHostInformation(random.NextDataSegment(random.Next(10)), random.NextDataSegment(random.Next(10)));
case DnsType.MInfo:
return new DnsResourceDataMailingListInfo(random.NextDnsDomainName(), random.NextDnsDomainName());
case DnsType.Mx:
return new DnsResourceDataMailExchange(random.NextUShort(), random.NextDnsDomainName());
case DnsType.Txt:
return new DnsResourceDataText(((Func<DataSegment>)(() => random.NextDataSegment(random.Next(10)))).GenerateArray(10).AsReadOnly());
case DnsType.Rp:
return new DnsResourceDataResponsiblePerson(random.NextDnsDomainName(), random.NextDnsDomainName());
case DnsType.AfsDb:
return new DnsResourceDataAfsDb(random.NextUShort(), random.NextDnsDomainName());
default:
return new DnsResourceDataAnything(random.NextDataSegment(random.Next(100)));
}
}
}
}
using System;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.TestUtils
{
public static class RandomEthernetExtensions
{
public static EthernetLayer NextEthernetLayer(this Random random, EthernetType etherType)
{
return new EthernetLayer
{
Source = random.NextMacAddress(),
Destination = random.NextMacAddress(),
EtherType = etherType
};
}
public static EthernetLayer NextEthernetLayer(this Random random)
{
return random.NextEthernetLayer(random.NextEnum(EthernetType.None));
}
public static MacAddress NextMacAddress(this Random random)
{
return new MacAddress(random.NextUInt48());
}
public static EthernetType NextEthernetType(this Random random)
{
return random.NextEnum(EthernetType.None);
}
public static Packet NextEthernetPacket(this Random random, int packetSize, DateTime timestamp, MacAddress ethernetSource, MacAddress ethernetDestination)
{
if (packetSize < EthernetDatagram.HeaderLength)
throw new ArgumentOutOfRangeException("packetSize", packetSize, "Must be at least the ethernet header length (" + EthernetDatagram.HeaderLength + ")");
return PacketBuilder.Build(timestamp,
new EthernetLayer
{
Source = ethernetSource,
Destination = ethernetDestination,
EtherType = random.NextEthernetType()
},
random.NextPayloadLayer(packetSize - EthernetDatagram.HeaderLength));
}
public static Packet NextEthernetPacket(this Random random, int packetSize, DateTime timestamp, string ethernetSource, string ethernetDestination)
{
return random.NextEthernetPacket(packetSize, timestamp, new MacAddress(ethernetSource), new MacAddress(ethernetDestination));
}
public static Packet NextEthernetPacket(this Random random, int packetSize, MacAddress ethernetSource, MacAddress ethernetDestination)
{
return random.NextEthernetPacket(packetSize, DateTime.Now, ethernetSource, ethernetDestination);
}
public static Packet NextEthernetPacket(this Random random, int packetSize, string ethernetSource, string ethernetDestination)
{
return random.NextEthernetPacket(packetSize, DateTime.Now, ethernetSource, ethernetDestination);
}
public static Packet NextEthernetPacket(this Random random, int packetSize)
{
return random.NextEthernetPacket(packetSize, DateTime.Now, random.NextMacAddress(), random.NextMacAddress());
}
}
}
\ No newline at end of file
using System;
using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.Gre;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.TestUtils
{
public static class RandomGreExtensions
{
public static GreLayer NextGreLayer(this Random random)
{
GreVersion version = random.NextEnum<GreVersion>();
bool isChecksum = random.NextBool();
GreSourceRouteEntry[] routing = null;
ushort? routingOffset = null;
bool strictSourceRoute = false;
EthernetType protocolType = random.NextEnum(EthernetType.None);
uint? key = random.NextBool() ? (uint?)random.NextUInt() : null;
if (version == GreVersion.Gre)
{
if (random.NextBool())
{
strictSourceRoute = random.NextBool();
routing = new GreSourceRouteEntry[random.Next(5)];
GreSourceRouteEntryAddressFamily family;
if (random.NextBool())
family = random.NextEnum(GreSourceRouteEntryAddressFamily.None);
else
family = (GreSourceRouteEntryAddressFamily)random.NextUShort();
for (int i = 0; i != routing.Length; ++i)
{
switch (family)
{
case GreSourceRouteEntryAddressFamily.AsSourceRoute:
{
ushort[] asNumbers = new ushort[random.Next(1, 5)];
for (int j = 0; j != asNumbers.Length; ++j)
asNumbers[j] = random.NextUShort();
routing[i] = new GreSourceRouteEntryAs(asNumbers.AsReadOnly(), random.Next(asNumbers.Length + 1));
break;
}
case GreSourceRouteEntryAddressFamily.IpSourceRoute:
{
IpV4Address[] ips = new IpV4Address[random.Next(1, 5)];
for (int j = 0; j != ips.Length; ++j)
ips[j] = random.NextIpV4Address();
routing[i] = new GreSourceRouteEntryIp(ips.AsReadOnly(), random.Next(ips.Length + 1));
break;
}
default:
{
int dataLength = random.Next(1, 100);
routing[i] = new GreSourceRouteEntryUnknown(family, random.NextDatagram(dataLength), random.Next(dataLength + 1));
break;
}
}
}
routingOffset = 0;
if (routing.Any())
{
int routingIndex = random.Next(routing.Length);
for (int i = 0; i != routingIndex; ++i)
routingOffset += (ushort)routing[i].Length;
}
}
}
else
{
protocolType = EthernetType.PointToPointProtocol;
isChecksum = false;
key = random.NextUInt();
}
return new GreLayer
{
Version = version,
ProtocolType = protocolType,
ChecksumPresent = isChecksum,
Checksum = isChecksum && random.NextBool() ? (ushort?)random.NextUShort() : null,
Key = key,
SequenceNumber = random.NextBool() ? (uint?)random.NextUInt() : null,
AcknowledgmentSequenceNumber = version == GreVersion.EnhancedGre && random.NextBool() ? (uint?)random.NextUInt() : null,
RecursionControl = random.NextByte(8),
// Flags = random.NextByte(32),
Routing = routing == null ? null : routing.AsReadOnly(),
RoutingOffset = routingOffset,
StrictSourceRoute = strictSourceRoute,
};
}
}
}
\ No newline at end of file
using System;
using System.Linq;
using PcapDotNet.Base;
using PcapDotNet.Packets.Igmp;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.TestUtils
{
public static class RandomIgmpExtensions
{
public static IgmpGroupRecord NextIgmpGroupRecord(this Random random)
{
IpV4Address[] sourceAddresses = random.NextIpV4Addresses(random.Next(10));
return new IgmpGroupRecord(random.NextEnum<IgmpRecordType>(), random.NextIpV4Address(), sourceAddresses, random.NextDatagram(random.Next(10) * 4));
}
public static IgmpGroupRecord[] NextIgmpGroupRecords(this Random random, int count)
{
return ((Func<IgmpGroupRecord>)random.NextIgmpGroupRecord).GenerateArray(count);
}
public static IgmpLayer NextIgmpLayer(this Random random)
{
IgmpMessageType igmpMessageType = random.NextEnum(IgmpMessageType.None, IgmpMessageType.CreateGroupRequestVersion0,
IgmpMessageType.CreateGroupReplyVersion0, IgmpMessageType.JoinGroupRequestVersion0,
IgmpMessageType.JoinGroupReplyVersion0, IgmpMessageType.LeaveGroupRequestVersion0,
IgmpMessageType.LeaveGroupReplyVersion0, IgmpMessageType.ConfirmGroupRequestVersion0,
IgmpMessageType.ConfirmGroupReplyVersion0,
IgmpMessageType.MulticastTraceRouteResponse); // todo support IGMP traceroute http://www.ietf.org/proceedings/48/I-D/idmr-traceroute-ipm-07.txt.
IgmpQueryVersion igmpQueryVersion = IgmpQueryVersion.None;
TimeSpan igmpMaxResponseTime = random.NextTimeSpan(TimeSpan.FromSeconds(0.1), TimeSpan.FromSeconds(256 * 0.1) - TimeSpan.FromTicks(1));
IpV4Address igmpGroupAddress = random.NextIpV4Address();
bool? igmpIsSuppressRouterSideProcessing;
byte? igmpQueryRobustnessVariable;
TimeSpan? igmpQueryInterval;
IpV4Address[] igmpSourceAddresses;
IgmpGroupRecord[] igmpGroupRecords;
switch (igmpMessageType)
{
case IgmpMessageType.MembershipQuery:
igmpQueryVersion = random.NextEnum(IgmpQueryVersion.None, IgmpQueryVersion.Unknown);
switch (igmpQueryVersion)
{
case IgmpQueryVersion.Version1:
return new IgmpQueryVersion1Layer
{
GroupAddress = igmpGroupAddress
};
case IgmpQueryVersion.Version2:
return new IgmpQueryVersion2Layer
{
MaxResponseTime = igmpMaxResponseTime,
GroupAddress = igmpGroupAddress
};
case IgmpQueryVersion.Version3:
igmpIsSuppressRouterSideProcessing = random.NextBool();
igmpQueryRobustnessVariable = random.NextByte(8);
igmpMaxResponseTime = random.NextTimeSpan(TimeSpan.FromSeconds(0.1),
IgmpDatagram.MaxVersion3MaxResponseTime - TimeSpan.FromTicks(1));
igmpQueryInterval = random.NextTimeSpan(TimeSpan.Zero, IgmpDatagram.MaxQueryInterval - TimeSpan.FromTicks(1));
igmpSourceAddresses = random.NextIpV4Addresses(random.Next(1000));
return new IgmpQueryVersion3Layer
{
SourceAddresses = igmpSourceAddresses.AsReadOnly(),
MaxResponseTime = igmpMaxResponseTime,
GroupAddress = igmpGroupAddress,
IsSuppressRouterSideProcessing = igmpIsSuppressRouterSideProcessing.Value,
QueryRobustnessVariable = igmpQueryRobustnessVariable.Value,
QueryInterval = igmpQueryInterval.Value,
};
default:
throw new InvalidOperationException("Invalid Query Version " + igmpQueryVersion);
}
case IgmpMessageType.MembershipReportVersion1:
return new IgmpReportVersion1Layer
{
GroupAddress = igmpGroupAddress
};
case IgmpMessageType.MembershipReportVersion2:
return new IgmpReportVersion2Layer
{
MaxResponseTime = igmpMaxResponseTime,
GroupAddress = igmpGroupAddress
};
case IgmpMessageType.LeaveGroupVersion2:
return new IgmpLeaveGroupVersion2Layer
{
MaxResponseTime = igmpMaxResponseTime,
GroupAddress = igmpGroupAddress
};
case IgmpMessageType.MembershipReportVersion3:
igmpGroupRecords = random.NextIgmpGroupRecords(random.Next(100));
if (igmpGroupRecords.Count() == 0 && random.NextBool())
return new IgmpReportVersion3Layer();
return new IgmpReportVersion3Layer
{
GroupRecords = igmpGroupRecords.AsReadOnly()
};
default:
throw new InvalidOperationException("Invalid message type " + igmpMessageType);
}
}
}
}
\ No newline at end of file
using System;
using PcapDotNet.Packets.IpV6;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.TestUtils
{
public static class RandomIpV6Extensions
{
public static IpV6Address NextIpV6Address(this Random random)
{
return new IpV6Address(random.NextUInt128());
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using PcapDotNet.Packets.Transport;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.TestUtils
{
public static class RandomTcpExtensions
{
public static TcpLayer NextTcpLayer(this Random random)
{
return new TcpLayer
{
SourcePort = random.NextUShort(),
DestinationPort = random.NextUShort(),
SequenceNumber = random.NextUInt(),
AcknowledgmentNumber = random.NextUInt(),
ControlBits = random.NextFlags<TcpControlBits>(),
Window = random.NextUShort(),
UrgentPointer = random.NextUShort(),
Options = random.NextTcpOptions(),
};
}
public static TcpOptions NextTcpOptions(this Random random)
{
int optionsLength = random.Next(TcpOptions.MaximumBytesLength) / 4 * 4;
List<TcpOption> options = new List<TcpOption>();
while (optionsLength > 0)
{
TcpOption option = random.NextTcpOption(optionsLength);
if (option.IsAppearsAtMostOnce &&
options.FindIndex(option.Equivalent) != -1)
{
continue;
}
options.Add(option);
optionsLength -= option.Length;
if (option.OptionType == TcpOptionType.EndOfOptionList)
break;
}
return new TcpOptions(options);
}
public static TcpOptionUnknown NextTcpOptionUnknown(this Random random, int maximumOptionLength)
{
TcpOptionType unknownOptionType;
byte unknownOptionTypeValue;
do
{
unknownOptionTypeValue = random.NextByte();
unknownOptionType = (TcpOptionType)unknownOptionTypeValue;
} while (unknownOptionType.ToString() != unknownOptionTypeValue.ToString());
byte[] unknownOptionData = random.NextBytes(maximumOptionLength - TcpOptionUnknown.OptionMinimumLength + 1);
return new TcpOptionUnknown(unknownOptionType, unknownOptionData);
}
public static TcpOption NextTcpOption(this Random random, int maximumOptionLength)
{
if (maximumOptionLength == 0)
throw new ArgumentOutOfRangeException("maximumOptionLength", maximumOptionLength, "option length must be positive");
if (maximumOptionLength >= TcpOptionUnknown.OptionMinimumLength && random.Next(100) > 90)
return random.NextTcpOptionUnknown(maximumOptionLength);
List<TcpOptionType> impossibleOptionTypes = new List<TcpOptionType>();
if (maximumOptionLength < TcpOptionMaximumSegmentSize.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.MaximumSegmentSize);
if (maximumOptionLength < TcpOptionWindowScale.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.WindowScale);
if (maximumOptionLength < TcpOptionSelectiveAcknowledgment.OptionMinimumLength)
impossibleOptionTypes.Add(TcpOptionType.SelectiveAcknowledgment);
if (maximumOptionLength < TcpOptionSelectiveAcknowledgmentPermitted.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.SelectiveAcknowledgmentPermitted);
if (maximumOptionLength < TcpOptionEcho.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.Echo);
if (maximumOptionLength < TcpOptionEchoReply.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.EchoReply);
if (maximumOptionLength < TcpOptionTimestamp.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.Timestamp);
if (maximumOptionLength < TcpOptionPartialOrderServiceProfile.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.PartialOrderServiceProfile);
if (maximumOptionLength < TcpOptionPartialOrderConnectionPermitted.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.PartialOrderConnectionPermitted);
if (maximumOptionLength < TcpOptionConnectionCountBase.OptionLength)
{
impossibleOptionTypes.Add(TcpOptionType.ConnectionCount);
impossibleOptionTypes.Add(TcpOptionType.ConnectionCountNew);
impossibleOptionTypes.Add(TcpOptionType.ConnectionCountEcho);
}
if (maximumOptionLength < TcpOptionAlternateChecksumRequest.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumRequest);
if (maximumOptionLength < TcpOptionAlternateChecksumData.OptionMinimumLength)
impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumData);
if (maximumOptionLength < TcpOptionMd5Signature.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.Md5Signature);
if (maximumOptionLength < TcpOptionMood.OptionMaximumLength)
impossibleOptionTypes.Add(TcpOptionType.Mood);
impossibleOptionTypes.Add(TcpOptionType.QuickStartResponse);
impossibleOptionTypes.Add(TcpOptionType.UserTimeout);
TcpOptionType optionType = random.NextEnum<TcpOptionType>(impossibleOptionTypes);
switch (optionType)
{
case TcpOptionType.EndOfOptionList:
return TcpOption.End;
case TcpOptionType.NoOperation:
return TcpOption.Nop;
case TcpOptionType.MaximumSegmentSize:
return new TcpOptionMaximumSegmentSize(random.NextUShort());
case TcpOptionType.WindowScale:
return new TcpOptionWindowScale(random.NextByte());
case TcpOptionType.SelectiveAcknowledgment:
int numBlocks = random.Next((maximumOptionLength - TcpOptionSelectiveAcknowledgment.OptionMinimumLength) / 8 + 1);
TcpOptionSelectiveAcknowledgmentBlock[] blocks = new TcpOptionSelectiveAcknowledgmentBlock[numBlocks];
for (int i = 0; i != numBlocks; ++i)
blocks[i] = new TcpOptionSelectiveAcknowledgmentBlock(random.NextUInt(), random.NextUInt());
return new TcpOptionSelectiveAcknowledgment(blocks);
case TcpOptionType.SelectiveAcknowledgmentPermitted:
return new TcpOptionSelectiveAcknowledgmentPermitted();
case TcpOptionType.Echo:
return new TcpOptionEcho(random.NextUInt());
case TcpOptionType.EchoReply:
return new TcpOptionEchoReply(random.NextUInt());
case TcpOptionType.Timestamp:
return new TcpOptionTimestamp(random.NextUInt(), random.NextUInt());
case TcpOptionType.PartialOrderServiceProfile:
return new TcpOptionPartialOrderServiceProfile(random.NextBool(), random.NextBool());
case TcpOptionType.PartialOrderConnectionPermitted:
return new TcpOptionPartialOrderConnectionPermitted();
case TcpOptionType.ConnectionCount:
return new TcpOptionConnectionCount(random.NextUInt());
case TcpOptionType.ConnectionCountEcho:
return new TcpOptionConnectionCountEcho(random.NextUInt());
case TcpOptionType.ConnectionCountNew:
return new TcpOptionConnectionCountNew(random.NextUInt());
case TcpOptionType.AlternateChecksumRequest:
return new TcpOptionAlternateChecksumRequest(random.NextEnum<TcpOptionAlternateChecksumType>());
case TcpOptionType.AlternateChecksumData:
return new TcpOptionAlternateChecksumData(random.NextBytes(random.Next(maximumOptionLength - TcpOptionAlternateChecksumData.OptionMinimumLength + 1)));
case TcpOptionType.Md5Signature:
return new TcpOptionMd5Signature(random.NextBytes(TcpOptionMd5Signature.OptionValueLength));
case TcpOptionType.Mood:
return new TcpOptionMood(random.NextEnum(TcpOptionMoodEmotion.None));
default:
throw new InvalidOperationException("optionType = " + optionType);
}
}
}
}
\ No newline at end of file
using System;
using PcapDotNet.Packets.Transport;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.TestUtils
{
public static class RandomUdpExtensions
{
public static UdpLayer NextUdpLayer(this Random random)
{
return new UdpLayer
{
Checksum = random.NextUShort(),
SourcePort = random.NextUShort(),
DestinationPort = random.NextUShort(),
CalculateChecksumValue = random.NextBool()
};
}
}
}
\ No newline at end of file
...@@ -130,9 +130,17 @@ namespace PcapDotNet.Packets ...@@ -130,9 +130,17 @@ namespace PcapDotNet.Packets
return encoding.GetString(Buffer, StartOffset, Length); return encoding.GetString(Buffer, StartOffset, Length);
} }
internal void Write(byte[] buffer, int offset) public static DataSegment Empty { get { return _empty; } }
internal void Write(byte[] buffer, ref int offset)
{ {
Buffer.BlockCopy(StartOffset, buffer, offset, Length); Buffer.BlockCopy(StartOffset, buffer, offset, Length);
offset += Length;
}
internal void Write(byte[] buffer, int offset)
{
Write(buffer, ref offset);
} }
/// <summary> /// <summary>
...@@ -157,9 +165,16 @@ namespace PcapDotNet.Packets ...@@ -157,9 +165,16 @@ namespace PcapDotNet.Packets
return Buffer.ReadBytes(StartOffset + offset, length); return Buffer.ReadBytes(StartOffset + offset, length);
} }
internal DataSegment SubSegment(ref int offset, int length)
{
DataSegment subSegemnt = new DataSegment(Buffer, StartOffset + offset, length);
offset += length;
return subSegemnt;
}
internal DataSegment SubSegment(int offset, int length) internal DataSegment SubSegment(int offset, int length)
{ {
return new DataSegment(Buffer, StartOffset + offset, length); return SubSegment(ref offset, length);
} }
internal bool ReadBool(int offset, byte mask) internal bool ReadBool(int offset, byte mask)
...@@ -198,7 +213,7 @@ namespace PcapDotNet.Packets ...@@ -198,7 +213,7 @@ namespace PcapDotNet.Packets
/// <param name="endianity">The endianity to use to translate the bytes to the value.</param> /// <param name="endianity">The endianity to use to translate the bytes to the value.</param>
/// <returns>The value converted from the read bytes according to the endianity.</returns> /// <returns>The value converted from the read bytes according to the endianity.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "uint")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "uint")]
protected uint ReadUInt(int offset, Endianity endianity) internal uint ReadUInt(int offset, Endianity endianity)
{ {
return Buffer.ReadUInt(StartOffset + offset, endianity); return Buffer.ReadUInt(StartOffset + offset, endianity);
} }
...@@ -278,5 +293,7 @@ namespace PcapDotNet.Packets ...@@ -278,5 +293,7 @@ namespace PcapDotNet.Packets
sum += (ushort)(buffer[offset] << 8); sum += (ushort)(buffer[offset] << 8);
return sum; return sum;
} }
private static readonly DataSegment _empty = new DataSegment(new byte[0]);
} }
} }
\ No newline at end of file
...@@ -68,7 +68,7 @@ namespace PcapDotNet.Packets.Dns ...@@ -68,7 +68,7 @@ namespace PcapDotNet.Packets.Dns
numBytesRead += MinimumLengthAfterBase; numBytesRead += MinimumLengthAfterBase;
if (offsetInDns + numBytesRead + dataLength > dns.Length) if (offsetInDns + numBytesRead + dataLength > dns.Length)
return null; return null;
DnsResourceData data = DnsResourceData.Read(type, dnsClass, dns.SubSegment(offsetInDns + numBytesRead, dataLength)); DnsResourceData data = DnsResourceData.Read(dns, type, dnsClass, offsetInDns + numBytesRead, dataLength);
if (data == null) if (data == null)
return null; return null;
numBytesRead += dataLength; numBytesRead += dataLength;
......
...@@ -13,7 +13,7 @@ namespace PcapDotNet.Packets.Dns ...@@ -13,7 +13,7 @@ namespace PcapDotNet.Packets.Dns
{ {
private const byte MaxLabelLength = 63; private const byte MaxLabelLength = 63;
private const ushort CompressionMarker = 0xC000; private const ushort CompressionMarker = 0xC000;
private const ushort OffsetMask = 0x3FFF; internal const ushort OffsetMask = 0x3FFF;
private static readonly char[] Colon = new[] {'.'}; private static readonly char[] Colon = new[] {'.'};
public DnsDomainName(string domainName) public DnsDomainName(string domainName)
...@@ -22,6 +22,8 @@ namespace PcapDotNet.Packets.Dns ...@@ -22,6 +22,8 @@ namespace PcapDotNet.Packets.Dns
_labels = labels.Select(label => new DataSegment(Encoding.UTF8.GetBytes(label))).ToList(); _labels = labels.Select(label => new DataSegment(Encoding.UTF8.GetBytes(label))).ToList();
} }
public static DnsDomainName Root { get { return _root; } }
public int NumLabels public int NumLabels
{ {
get get
...@@ -61,11 +63,16 @@ namespace PcapDotNet.Packets.Dns ...@@ -61,11 +63,16 @@ namespace PcapDotNet.Packets.Dns
return length + sizeof(byte); return length + sizeof(byte);
} }
internal static DnsDomainName Parse(DnsDatagram dns, int offsetInDns, out int numBytesRead) internal static bool TryParse(DnsDatagram dns, int offsetInDns, int maximumLength, out DnsDomainName domainName, out int numBytesRead)
{ {
List<DataSegment> labels = new List<DataSegment>(); List<DataSegment> labels = new List<DataSegment>();
ReadLabels(dns, offsetInDns, out numBytesRead, labels); if (!TryReadLabels(dns, offsetInDns, out numBytesRead, labels) || numBytesRead > maximumLength)
return new DnsDomainName(labels); {
domainName = null;
return false;
}
domainName = new DnsDomainName(labels);
return true;
} }
internal int Write(byte[] buffer, int dnsOffset, DnsDomainNameCompressionData compressionData, int offsetInDns) internal int Write(byte[] buffer, int dnsOffset, DnsDomainNameCompressionData compressionData, int offsetInDns)
...@@ -95,40 +102,45 @@ namespace PcapDotNet.Packets.Dns ...@@ -95,40 +102,45 @@ namespace PcapDotNet.Packets.Dns
_labels = labels; _labels = labels;
} }
private static void ReadLabels(DnsDatagram dns, int offsetInDns, out int numBytesRead, List<DataSegment> labels) private static bool TryReadLabels(DnsDatagram dns, int offsetInDns, out int numBytesRead, List<DataSegment> labels)
{ {
numBytesRead = 0; numBytesRead = 0;
byte labelLength; byte labelLength;
do do
{ {
if (offsetInDns >= dns.Length) if (offsetInDns >= dns.Length)
return; return false; // Can't read label's length.
labelLength = dns[offsetInDns]; labelLength = dns[offsetInDns];
++numBytesRead; ++numBytesRead;
if (labelLength > MaxLabelLength) if (labelLength > MaxLabelLength)
{ {
// Compression. // Compression.
if (offsetInDns + 1 >= dns.Length) if (offsetInDns + 1 >= dns.Length)
return; return false; // Can't read compression pointer.
offsetInDns = dns.ReadUShort(offsetInDns, Endianity.Big) & OffsetMask; int newOffsetInDns = dns.ReadUShort(offsetInDns, Endianity.Big) & OffsetMask;
if (newOffsetInDns >= offsetInDns)
return false; // Can't handle pointers that are not back pointers.
++numBytesRead; ++numBytesRead;
int internalBytesRead; int internalBytesRead;
ReadLabels(dns, offsetInDns, out internalBytesRead, labels); return TryReadLabels(dns, newOffsetInDns, out internalBytesRead, labels);
return;
} }
if (labelLength != 0) if (labelLength != 0)
{ {
++offsetInDns; ++offsetInDns;
if (offsetInDns + labelLength >= dns.Length) if (offsetInDns + labelLength >= dns.Length)
return; return false; // Can't read label.
labels.Add(dns.SubSegment(offsetInDns, labelLength)); labels.Add(dns.SubSegment(offsetInDns, labelLength));
numBytesRead += labelLength; numBytesRead += labelLength;
offsetInDns += labelLength; offsetInDns += labelLength;
} }
} while (labelLength != 0); } while (labelLength != 0);
return true;
} }
private static readonly DnsDomainName _root = new DnsDomainName("");
private readonly List<DataSegment> _labels; private readonly List<DataSegment> _labels;
private string _ascii; private string _ascii;
} }
......
...@@ -36,6 +36,9 @@ namespace PcapDotNet.Packets.Dns ...@@ -36,6 +36,9 @@ namespace PcapDotNet.Packets.Dns
public void AddCompressionData(ListSegment<DataSegment> labels, int dnsOffset) public void AddCompressionData(ListSegment<DataSegment> labels, int dnsOffset)
{ {
if (dnsOffset > DnsDomainName.OffsetMask)
return;
switch (DomainNameCompressionMode) switch (DomainNameCompressionMode)
{ {
case DnsDomainNameCompressionMode.All: case DnsDomainNameCompressionMode.All:
......
...@@ -2,23 +2,29 @@ ...@@ -2,23 +2,29 @@
namespace PcapDotNet.Packets.Dns namespace PcapDotNet.Packets.Dns
{ {
public sealed class DnsResourceDataUnknown : DnsResourceDataSimple, IEquatable<DnsResourceDataUnknown> [DnsTypeRegistration(Type = DnsType.Null)]
public sealed class DnsResourceDataAnything : DnsResourceDataSimple, IEquatable<DnsResourceDataAnything>
{ {
public DnsResourceDataUnknown(DataSegment data) public DnsResourceDataAnything()
{
Data = DataSegment.Empty;
}
public DnsResourceDataAnything(DataSegment data)
{ {
Data = data; Data = data;
} }
public DataSegment Data { get; private set; } public DataSegment Data { get; private set; }
public bool Equals(DnsResourceDataUnknown other) public bool Equals(DnsResourceDataAnything other)
{ {
return other != null && Data.Equals(other.Data); return other != null && Data.Equals(other.Data);
} }
public sealed override bool Equals(DnsResourceData other) public override bool Equals(DnsResourceData other)
{ {
return Equals(other as DnsResourceDataUnknown); return Equals(other as DnsResourceDataAnything);
} }
internal override int GetLength() internal override int GetLength()
...@@ -33,7 +39,7 @@ namespace PcapDotNet.Packets.Dns ...@@ -33,7 +39,7 @@ namespace PcapDotNet.Packets.Dns
internal override DnsResourceData CreateInstance(DataSegment data) internal override DnsResourceData CreateInstance(DataSegment data)
{ {
return new DnsResourceDataUnknown(data); return new DnsResourceDataAnything(data);
} }
} }
} }
\ No newline at end of file
...@@ -51,7 +51,7 @@ namespace PcapDotNet.Packets.Dns ...@@ -51,7 +51,7 @@ namespace PcapDotNet.Packets.Dns
/// <summary> /// <summary>
/// Two octets containing one of the RR TYPE codes. /// Two octets containing one of the RR TYPE codes.
/// </summary> /// </summary>
public DnsType Type { get; private set;} public DnsType Type { get; private set; }
public DnsClass DnsClass { get; private set; } public DnsClass DnsClass { get; private set; }
...@@ -90,8 +90,7 @@ namespace PcapDotNet.Packets.Dns ...@@ -90,8 +90,7 @@ namespace PcapDotNet.Packets.Dns
{ {
type = DnsType.All; type = DnsType.All;
dnsClass = DnsClass.Any; dnsClass = DnsClass.Any;
domainName = DnsDomainName.Parse(dns, offsetInDns, out numBytesRead); if (!DnsDomainName.TryParse(dns, offsetInDns, dns.Length - offsetInDns, out domainName, out numBytesRead))
if (domainName == null)
return false; return false;
if (offsetInDns + numBytesRead + MinimumLengthAfterDomainName > dns.Length) if (offsetInDns + numBytesRead + MinimumLengthAfterDomainName > dns.Length)
......
...@@ -103,7 +103,7 @@ ...@@ -103,7 +103,7 @@
<Compile Include="Dns\DnsOpcode.cs" /> <Compile Include="Dns\DnsOpcode.cs" />
<Compile Include="Dns\DnsQueryResourceRecord.cs" /> <Compile Include="Dns\DnsQueryResourceRecord.cs" />
<Compile Include="Dns\DnsResourceData.cs" /> <Compile Include="Dns\DnsResourceData.cs" />
<Compile Include="Dns\DnsResourceDataUnknown.cs" /> <Compile Include="Dns\DnsResourceDataAnything.cs" />
<Compile Include="Dns\DnsResourceRecord.cs" /> <Compile Include="Dns\DnsResourceRecord.cs" />
<Compile Include="Dns\DnsResponseCode.cs" /> <Compile Include="Dns\DnsResponseCode.cs" />
<Compile Include="Dns\DnsType.cs" /> <Compile Include="Dns\DnsType.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