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
...@@ -36,7 +36,7 @@ namespace PcapDotNet.Packets.Dns ...@@ -36,7 +36,7 @@ namespace PcapDotNet.Packets.Dns
private const int MinimumLengthAfterDomainName = 4; private const int MinimumLengthAfterDomainName = 4;
public DnsResourceRecord(DnsDomainName domainName, DnsType type, DnsClass dnsClass) public DnsResourceRecord(DnsDomainName domainName, DnsType type, DnsClass dnsClass)
{ {
DomainName = domainName; DomainName = domainName;
Type = type; Type = type;
...@@ -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; }
...@@ -85,13 +85,12 @@ namespace PcapDotNet.Packets.Dns ...@@ -85,13 +85,12 @@ namespace PcapDotNet.Packets.Dns
DnsClass.Equals(other.DnsClass); DnsClass.Equals(other.DnsClass);
} }
internal static bool TryParseBase(DnsDatagram dns, int offsetInDns, internal static bool TryParseBase(DnsDatagram dns, int offsetInDns,
out DnsDomainName domainName, out DnsType type, out DnsClass dnsClass, out int numBytesRead) out DnsDomainName domainName, out DnsType type, out DnsClass dnsClass, out int numBytesRead)
{ {
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