Commit c56980ec authored by Brickner_cp's avatar Brickner_cp

DNS

Remove PcapDotNet.Analysis dependency
parent 34309d46
......@@ -77,7 +77,7 @@
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>if not exist "$(SolutionDir)..\..\PcapDotNet\src\PcapDotNet.snk" ("%25PROGRAMFILES%25\Microsoft SDKs\Windows\v6.0A\bin\sn.exe" -k "$(SolutionDir)..\..\PcapDotNet\src\PcapDotNet.snk")</PreBuildEvent>
<PreBuildEvent>if not exist "$(SolutionDir)..\..\PcapDotNet\src\PcapDotNet.snk" ("%25PROGRAMFILES%25\Microsoft SDKs\Windows\v7.0A\bin\sn.exe" -k "$(SolutionDir)..\..\PcapDotNet\src\PcapDotNet.snk")</PreBuildEvent>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>if not exist "$(SolutionDir)..\..\PcapDotNet\3rdParty\PcapDotNet.Analysis\" (mkdir "$(SolutionDir)..\..\PcapDotNet\3rdParty\PcapDotNet.Analysis\")
......
......@@ -139,7 +139,7 @@
</Target>
-->
<PropertyGroup>
<PreBuildEvent>if not exist "$(SolutionDir)$(SolutionName).snk" ("%25PROGRAMFILES%25\Microsoft SDKs\Windows\v6.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</PreBuildEvent>
<PreBuildEvent>if not exist "$(SolutionDir)$(SolutionName).snk" ("%25PROGRAMFILES%25\Microsoft SDKs\Windows\v7.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
......
......@@ -130,7 +130,7 @@
</Target>
-->
<PropertyGroup>
<PreBuildEvent>if not exist "$(SolutionDir)$(SolutionName).snk" ("%25PROGRAMFILES%25\Microsoft SDKs\Windows\v6.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</PreBuildEvent>
<PreBuildEvent>if not exist "$(SolutionDir)$(SolutionName).snk" ("%25PROGRAMFILES%25\Microsoft SDKs\Windows\v7.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
......
......@@ -244,7 +244,6 @@ void PacketCommunicator::SendPacket(Packet^ packet)
pin_ptr<Byte> unamangedPacketBytes = &packet->Buffer[0];
if (pcap_sendpacket(_pcapDescriptor, unamangedPacketBytes, packet->Length) != 0)
throw BuildInvalidOperation("Failed writing to device");
PcapDotNet::Analysis::PcapDotNetAnalysis::PacketSent();
}
BerkeleyPacketFilter^ PacketCommunicator::CreateFilter(String^ filterValue)
......@@ -307,7 +306,6 @@ InvalidOperationException^ PacketCommunicator::BuildInvalidOperation(System::Str
// static
Packet^ PacketCommunicator::CreatePacket(const pcap_pkthdr& packetHeader, const unsigned char* packetData, IDataLink^ dataLink)
{
PcapDotNet::Analysis::PcapDotNetAnalysis::PacketReceived();
DateTime timestamp;
PacketTimestamp::PcapTimestampToDateTime(packetHeader.ts, timestamp);
......
......@@ -25,7 +25,6 @@ namespace PcapDotNet { namespace Core
private:
static PacketCommunicator()
{
PcapDotNet::Analysis::PcapDotNetAnalysis::Initialize();
}
public:
......
......@@ -41,6 +41,4 @@ void PacketSendBuffer::Transmit(pcap_t* pcapDescriptor, bool isSync)
unsigned int numBytesTransmitted = pcap_sendqueue_transmit(pcapDescriptor, _pcapSendQueue, isSync);
if (numBytesTransmitted < _pcapSendQueue->len)
throw PcapError::BuildInvalidOperation("Failed transmiting packets from queue", pcapDescriptor);
PcapDotNet::Analysis::PcapDotNetAnalysis::PacketSent(Length);
}
......@@ -22,9 +22,6 @@
<CodeAnalysisDictionary Include="..\PcapDotNet.CodeAnalysisDictionary.xml" />
</ItemGroup>
<ItemGroup>
<Reference Include="PcapDotNet.Analysis, Version=0.8.0.0, Culture=neutral, PublicKeyToken=4b6f3e583145a652">
<HintPath>..\..\3rdParty\PcapDotNet.Analysis\PcapDotNet.Analysis.dll</HintPath>
</Reference>
<Reference Include="System">
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
......@@ -206,11 +203,27 @@
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\PcapDotNet.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<PostBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</PostBuildEventUseInBuild>
<PostBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</PostBuildEventUseInBuild>
<PostBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</PostBuildEventUseInBuild>
<PostBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</PostBuildEventUseInBuild>
<LinkKeyFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\$(SolutionName).snk</LinkKeyFile>
<LinkKeyFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\$(SolutionName).snk</LinkKeyFile>
<LinkKeyFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\$(SolutionName).snk</LinkKeyFile>
<LinkKeyFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\$(SolutionName).snk</LinkKeyFile>
<LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</LinkDelaySign>
<LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</LinkDelaySign>
<LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</LinkDelaySign>
<LinkDelaySign Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</LinkDelaySign>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<PreBuildEvent>
<Message>Create Public/Private Key Pair</Message>
<Command>if not exist "$(SolutionDir)$(SolutionName).snk" ("%PROGRAMFILES%\Microsoft SDKs\Windows\v6.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</Command>
<Command>if not exist "$(SolutionDir)$(SolutionName).snk" ("%PROGRAMFILES%\Microsoft SDKs\Windows\v7.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</Command>
</PreBuildEvent>
<ClCompile>
<Optimization>Disabled</Optimization>
......@@ -240,13 +253,14 @@
<Command>sn -Ra "$(TargetPath)" "$(SolutionDir)$(SolutionName).snk"</Command>
</PostBuildEvent>
<PreLinkEvent>
<Command>sn -Ra "$(SolutionDir)\..\3rdParty\PcapDotNet.Analysis\PcapDotNet.Analysis.dll" "$(SolutionDir)$(SolutionName).snk"</Command>
<Command>
</Command>
</PreLinkEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PreBuildEvent>
<Message>Create Public/Private Key Pair</Message>
<Command>if not exist "$(SolutionDir)$(SolutionName).snk" ("%PROGRAMFILES%\Microsoft SDKs\Windows\v6.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</Command>
<Command>if not exist "$(SolutionDir)$(SolutionName).snk" ("%PROGRAMFILES%\Microsoft SDKs\Windows\v7.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</Command>
</PreBuildEvent>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
......@@ -279,13 +293,14 @@
<Command>sn -Ra "$(TargetPath)" "$(SolutionDir)$(SolutionName).snk"</Command>
</PostBuildEvent>
<PreLinkEvent>
<Command>sn -Ra "$(SolutionDir)\..\3rdParty\PcapDotNet.Analysis\PcapDotNet.Analysis.dll" "$(SolutionDir)$(SolutionName).snk"</Command>
<Command>
</Command>
</PreLinkEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<PreBuildEvent>
<Message>Create Public/Private Key Pair</Message>
<Command>if not exist "$(SolutionDir)$(SolutionName).snk" ("%PROGRAMFILES%\Microsoft SDKs\Windows\v6.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</Command>
<Command>if not exist "$(SolutionDir)$(SolutionName).snk" ("%PROGRAMFILES%\Microsoft SDKs\Windows\v7.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</Command>
</PreBuildEvent>
<ClCompile>
<AdditionalIncludeDirectories>..\..\3rdParty\WpdPack\Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
......@@ -313,13 +328,14 @@
<Command>sn -Ra "$(TargetPath)" "$(SolutionDir)$(SolutionName).snk"</Command>
</PostBuildEvent>
<PreLinkEvent>
<Command>sn -Ra "$(SolutionDir)\..\3rdParty\PcapDotNet.Analysis\PcapDotNet.Analysis.dll" "$(SolutionDir)$(SolutionName).snk"</Command>
<Command>
</Command>
</PreLinkEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<PreBuildEvent>
<Message>Create Public/Private Key Pair</Message>
<Command>if not exist "$(SolutionDir)$(SolutionName).snk" ("%PROGRAMFILES%\Microsoft SDKs\Windows\v6.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</Command>
<Command>if not exist "$(SolutionDir)$(SolutionName).snk" ("%PROGRAMFILES%\Microsoft SDKs\Windows\v7.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</Command>
</PreBuildEvent>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
......@@ -350,7 +366,8 @@
<Command>sn -Ra "$(TargetPath)" "$(SolutionDir)$(SolutionName).snk"</Command>
</PostBuildEvent>
<PreLinkEvent>
<Command>sn -Ra "$(SolutionDir)\..\3rdParty\PcapDotNet.Analysis\PcapDotNet.Analysis.dll" "$(SolutionDir)$(SolutionName).snk"</Command>
<Command>
</Command>
</PreLinkEvent>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
......
......@@ -158,5 +158,15 @@ namespace PcapDotNet.Packets.Test
Assert.AreEqual(expectedValue, actualValue);
}
}
[TestMethod]
public void ByteArrayULongTest()
{
ulong expectedValue = 10;
byte[] buffer = new byte[8];
buffer.Write(0, expectedValue, Endianity.Big);
ulong actualValue = buffer.ReadULong(0, Endianity.Big);
Assert.AreEqual(expectedValue, actualValue);
}
}
}
\ No newline at end of file
......@@ -10,6 +10,7 @@ using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.TestUtils;
using PcapDotNet.Packets.Transport;
using PcapDotNet.TestUtils;
namespace PcapDotNet.Packets.Test
{
......@@ -144,6 +145,30 @@ namespace PcapDotNet.Packets.Test
TestDomainNameCompression(6, dnsLayer);
}
[TestMethod]
public void DnsOptResourceRecordTest()
{
Random random = new Random();
for (int i = 0; i != 100; ++i)
{
DnsDomainName domainName = random.NextDnsDomainName();
ushort sendersUdpPayloadSize = random.NextUShort();
byte extendedRcode = random.NextByte();
DnsOptVersion version = (DnsOptVersion)random.NextByte();
DnsOptFlags flags = (DnsOptFlags)random.NextUShort();
DnsResourceDataOptions data = (DnsResourceDataOptions)random.NextDnsResourceData(DnsType.Opt);
DnsOptResourceRecord record = new DnsOptResourceRecord(domainName, sendersUdpPayloadSize, extendedRcode, version, flags, data);
Assert.AreEqual(domainName, record.DomainName);
Assert.AreEqual(sendersUdpPayloadSize, record.SendersUdpPayloadSize);
Assert.AreEqual(extendedRcode, record.ExtendedRcode);
Assert.AreEqual(version, record.Version);
Assert.AreEqual(flags, record.Flags);
Assert.AreEqual(data, record.Data);
}
}
[TestMethod]
public void SimpleDnsTest()
{
......
......@@ -96,7 +96,7 @@ namespace PcapDotNet.Packets.Test
IpV4Layer ipV4Layer = random.NextIpV4Layer();
ipV4Layer.HeaderChecksum = null;
PayloadLayer payloadLayer = random.NextPayloadLayer(random.Next(0, 50 * 1024));
PayloadLayer payloadLayer = random.NextPayloadLayer(random.NextInt(0, 50 * 1024));
Packet packet = PacketBuilder.Build(DateTime.Now, ethernetLayer, ipV4Layer, payloadLayer);
......
......@@ -57,8 +57,41 @@ namespace PcapDotNet.Packets.TestUtils
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;
if (type == DnsType.Opt)
{
return new DnsOptResourceRecord(random.NextDnsDomainName(), random.NextUShort(), random.NextByte(), (DnsOptVersion)random.NextByte(),
random.NextFlags<DnsOptFlags>(), (DnsResourceDataOptions)random.NextDnsResourceData(type));
}
return new DnsDataResourceRecord(random.NextDnsDomainName(), type, random.NextEnum<DnsClass>(), random.Next(), random.NextDnsResourceData(type));
}
public static DnsOptions NextDnsOptions(this Random random)
{
return new DnsOptions(((Func<DnsOption>)(() => random.NextDnsOption())).GenerateArray(random.Next(10)));
}
public static DnsOption NextDnsOption(this Random random)
{
if (random.NextBool())
{
return new DnsOptionAnything((DnsOptionCode)random.NextUShort(4, ushort.MaxValue + 1), random.NextDataSegment(random.Next(20)));
}
switch (random.NextEnum<DnsOptionCode>())
{
case DnsOptionCode.LongLivedQuery:
return new DnsOptionLongLivedQuery(random.NextUShort(), random.NextEnum<DnsLongLivedQueryOpcode>(),
random.NextEnum<DnsLongLivedQueryErrorCode>(), random.NextULong(), random.NextUInt());
case DnsOptionCode.UpdateLease:
return new DnsOptionUpdateLease(random.NextInt());
case DnsOptionCode.NameServerIdentifier:
return new DnsOptionAnything(DnsOptionCode.NameServerIdentifier, random.NextDataSegment(random.NextInt(0, 100)));
default:
throw new InvalidOperationException("Invalid value");
}
}
public static DnsDomainName NextDnsDomainName(this Random random)
......@@ -152,18 +185,18 @@ namespace PcapDotNet.Packets.TestUtils
return new DnsResourceDataX400Pointer(random.NextUShort(), random.NextDnsDomainName(), random.NextDnsDomainName());
case DnsType.GPos:
return new DnsResourceDataGeographicalPosition((random.Next(-90, 90) * random.NextDouble()).ToString("0.##########"),
(random.Next(-180, 180) * random.NextDouble()).ToString("0.##########"),
(random.Next(-500, 50000) * random.NextDouble()).ToString("0.##########"));
return new DnsResourceDataGeographicalPosition((random.NextInt(-90, 90) * random.NextDouble()).ToString("0.##########"),
(random.NextInt(-180, 180) * random.NextDouble()).ToString("0.##########"),
(random.NextInt(-500, 50000) * random.NextDouble()).ToString("0.##########"));
case DnsType.Aaaa:
return new DnsResourceDataIpV6(random.NextIpV6Address());
case DnsType.Loc:
return new DnsResourceDataLocationInformation(random.NextByte(),
(ulong)(random.Next(10) * Math.Pow(10, random.Next(10))),
(ulong)(random.Next(10) * Math.Pow(10, random.Next(10))),
(ulong)(random.Next(10) * Math.Pow(10, random.Next(10))),
(ulong)(random.NextInt(0, 10) * Math.Pow(10, random.NextInt(0, 10))),
(ulong)(random.NextInt(0, 10) * Math.Pow(10, random.NextInt(0, 10))),
(ulong)(random.NextInt(0, 10) * Math.Pow(10, random.NextInt(0, 10))),
random.NextUInt(), random.NextUInt(), random.NextUInt());
case DnsType.Nxt:
......@@ -210,6 +243,9 @@ namespace PcapDotNet.Packets.TestUtils
case DnsType.Sink:
return new DnsResourceDataSink(random.NextEnum<DnsSinkCoding>(), random.NextByte(), random.NextDataSegment(random.Next(100)));
case DnsType.Opt:
return new DnsResourceDataOptions(random.NextDnsOptions());
default:
return new DnsResourceDataAnything(random.NextDataSegment(random.Next(100)));
}
......
......@@ -39,25 +39,21 @@ namespace PcapDotNet.Packets.TestUtils
{
case GreSourceRouteEntryAddressFamily.AsSourceRoute:
{
ushort[] asNumbers = new ushort[random.Next(1, 5)];
for (int j = 0; j != asNumbers.Length; ++j)
asNumbers[j] = random.NextUShort();
ushort[] asNumbers = ((Func<ushort>)(() => random.NextUShort())).GenerateArray(random.NextInt(1, 5));
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();
IpV4Address[] ips = ((Func<IpV4Address>)(() => random.NextIpV4Address())).GenerateArray(random.NextInt(1, 5));
routing[i] = new GreSourceRouteEntryIp(ips.AsReadOnly(), random.Next(ips.Length + 1));
break;
}
default:
{
int dataLength = random.Next(1, 100);
int dataLength = random.NextInt(1, 100);
routing[i] = new GreSourceRouteEntryUnknown(family, random.NextDatagram(dataLength), random.Next(dataLength + 1));
break;
}
......
......@@ -65,11 +65,8 @@ namespace PcapDotNet.Packets.TestUtils
public static string NextHttpToken(this Random random)
{
int tokenLength = random.Next(1, 100);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i != tokenLength; ++i)
stringBuilder.Append(random.NextHttpTokenChar());
return stringBuilder.ToString();
char[] httpToken = ((Func<char>)(() => random.NextHttpTokenChar())).GenerateArray(random.NextInt(1, 100));
return new string(httpToken);
}
public static char NextHttpTokenChar(this Random random)
......@@ -85,7 +82,7 @@ namespace PcapDotNet.Packets.TestUtils
public static string NextHttpFieldValue(this Random random)
{
int valueLength = random.Next(1, 100);
int valueLength = random.NextInt(1, 100);
StringBuilder stringBuilder = new StringBuilder();
while (stringBuilder.Length < valueLength)
{
......@@ -178,10 +175,7 @@ namespace PcapDotNet.Packets.TestUtils
return HttpField.CreateField(fieldName, random.NextHttpFieldValue());
case HttpTransferEncodingField.FieldNameUpper:
int numTransferCodings = random.Next(1, 10);
List<string> transferCodings = new List<string>(numTransferCodings);
for (int i = 0; i != numTransferCodings; ++i)
transferCodings.Add(random.NextHttpTransferCoding());
string[] transferCodings = ((Func<string>)(() => random.NextHttpTransferCoding())).GenerateArray(random.NextInt(1, 10));
return new HttpTransferEncodingField(transferCodings);
case HttpContentLengthField.FieldNameUpper:
......@@ -267,7 +261,7 @@ namespace PcapDotNet.Packets.TestUtils
int numChunks = random.Next(10);
for (int i = 0; i != numChunks; ++i)
{
int chunkSize = random.Next(1, 1000);
int chunkSize = random.NextInt(1, 1000);
chunkedBody.AddRange(Encoding.ASCII.GetBytes(chunkSize.ToString("x")));
var chunkExtension = random.NextHttpFieldParameters();
foreach (var parameter in chunkExtension)
......@@ -281,7 +275,7 @@ namespace PcapDotNet.Packets.TestUtils
chunkedBody.AddRange(random.NextDatagram(chunkSize));
chunkedBody.AddRange(Encoding.ASCII.GetBytes("\r\n"));
}
int numZeros = random.Next(1, 10);
int numZeros = random.NextInt(1, 10);
for (int i = 0; i != numZeros; ++i)
chunkedBody.Add((byte)'0');
var lastChunkExtension = random.NextHttpFieldParameters();
......
......@@ -320,6 +320,19 @@ namespace PcapDotNet.Packets
return result;
}
public static long ReadLong(this byte[] buffer, int offset, Endianity endianity)
{
long value = ReadLong(buffer, offset);
if (IsWrongEndianity(endianity))
value = IPAddress.HostToNetworkOrder(value);
return value;
}
public static ulong ReadULong(this byte[] buffer, int offset, Endianity endianity)
{
return (ulong)buffer.ReadLong(offset, endianity);
}
/// <summary>
/// Reads 16 bytes from a specific offset as a UInt128 with a given endianity.
/// </summary>
......@@ -617,10 +630,22 @@ namespace PcapDotNet.Packets
/// <param name="endianity">The endianity to use when converting the value to bytes.</param>
public static void Write(this byte[] buffer, ref int offset, UInt48 value, Endianity endianity)
{
Write(buffer, offset, value, endianity);
buffer.Write(offset, value, endianity);
offset += UInt48.SizeOf;
}
public static void Write(this byte[] buffer, int offset, long value, Endianity endianity)
{
if (IsWrongEndianity(endianity))
value = IPAddress.HostToNetworkOrder(value);
Write(buffer, offset, value);
}
public static void Write(this byte[] buffer, int offset, ulong value, Endianity endianity)
{
buffer.Write(offset, (long)value, endianity);
}
/// <summary>
/// Writes the given value to the buffer using the given endianity.
/// </summary>
......@@ -919,6 +944,17 @@ namespace PcapDotNet.Packets
}
}
private static long ReadLong(byte[] buffer, int offset)
{
unsafe
{
fixed (byte* ptr = &buffer[offset])
{
return *((long*)ptr);
}
}
}
private static UInt128 ReadUInt128(byte[] buffer, int offset)
{
unsafe
......@@ -974,6 +1010,17 @@ namespace PcapDotNet.Packets
}
}
private static void Write(byte[] buffer, int offset, long value)
{
unsafe
{
fixed (byte* ptr = &buffer[offset])
{
*((long*)ptr) = value;
}
}
}
private static void Write(byte[] buffer, int offset, UInt128 value)
{
unsafe
......
......@@ -234,6 +234,11 @@ namespace PcapDotNet.Packets
return Buffer.ReadUInt48(StartOffset + offset, endianity);
}
internal ulong ReadULong(int offset, Endianity endianity)
{
return Buffer.ReadULong(StartOffset + offset, endianity);
}
internal BigInteger ReadUnsignedBigInteger(int offset, int length, Endianity endianity)
{
return Buffer.ReadUnsignedBigInteger(StartOffset + offset, length, endianity);
......
......@@ -2,7 +2,7 @@
namespace PcapDotNet.Packets.Dns
{
public sealed class DnsDataResourceRecord : DnsResourceRecord, IEquatable<DnsDataResourceRecord>
public class DnsDataResourceRecord : DnsResourceRecord, IEquatable<DnsDataResourceRecord>
{
private static class OffsetAfterBase
{
......@@ -73,6 +73,8 @@ namespace PcapDotNet.Packets.Dns
return null;
numBytesRead += dataLength;
if (type == DnsType.Opt)
return new DnsOptResourceRecord(domainName, dnsClass, ttl, data);
return new DnsDataResourceRecord(domainName, type, dnsClass, ttl, data);
}
......@@ -90,4 +92,75 @@ namespace PcapDotNet.Packets.Dns
return length;
}
}
public enum DnsOptVersion : byte
{
Version0 = 0,
}
[Flags]
public enum DnsOptFlags : ushort
{
DnsSecOk = 0x8000,
}
/// <summary>
/// RFC 2671.
/// <pre>
/// +------+----------------+----------+
/// | bit | 0-7 | 8-15 |
/// +------+----------------+----------+
/// | 0 | Name |
/// | ... | |
/// +------+---------------------------+
/// | | Type = OPT |
/// +------+---------------------------+
/// | | Sender's UDP payload size |
/// +------+----------------+----------+
/// | | EXTENDED-RCODE | VERSION |
/// +------+----------------+----------+
/// | | Flags |
/// +------+---------------------------+
/// | | Resource Data Length |
/// +------+---------------------------+
/// | | Resource Data |
/// | ... | |
/// +------+---------------------------+
/// </pre>
/// </summary>
public sealed class DnsOptResourceRecord : DnsDataResourceRecord
{
public DnsOptResourceRecord(DnsDomainName domainName, ushort sendersUdpPayloadSize, byte extendedRcode, DnsOptVersion version, DnsOptFlags flags, DnsResourceDataOptions data)
: this(domainName, (DnsClass)sendersUdpPayloadSize, (extendedRcode << 24) | ((byte)version << 16) | (ushort)flags, data)
{
}
/// <summary>
/// The number of octets of the largest UDP payload that can be reassembled and delivered in the sender's network stack.
/// Note that path MTU, with or without fragmentation, may be smaller than this.
/// </summary>
public ushort SendersUdpPayloadSize { get { return (ushort)DnsClass; } }
/// <summary>
/// Forms upper 8 bits of extended 12-bit RCODE.
/// Note that EXTENDED-RCODE value "0" indicates that an unextended RCODE is in use (values "0" through "15").
/// </summary>
public byte ExtendedRcode { get { return (byte)(Ttl >> 24); } }
/// <summary>
/// Indicates the implementation level of whoever sets it.
/// Full conformance with this specification is indicated by version "0".
/// Requestors are encouraged to set this to the lowest implemented level capable of expressing a transaction,
/// to minimize the responder and network load of discovering the greatest common implementation level between requestor and responder.
/// A requestor's version numbering strategy should ideally be a run time configuration option.
/// </summary>
public DnsOptVersion Version { get { return (DnsOptVersion)(Ttl >> 16); }}
public DnsOptFlags Flags { get { return (DnsOptFlags)Ttl; } }
internal DnsOptResourceRecord(DnsDomainName domainName, DnsClass dnsClass, int ttl, DnsResourceData data)
: base(domainName, DnsType.Opt, dnsClass, ttl, data)
{
}
}
}
\ No newline at end of file
......@@ -241,6 +241,15 @@ namespace PcapDotNet.Packets.Dns
}
}
public DnsOptResourceRecord OptionsRecord
{
get
{
ParseAdditionals();
return _options;
}
}
/// <summary>
/// Creates a Layer that represents the datagram to be used with PacketBuilder.
/// </summary>
......@@ -398,12 +407,16 @@ namespace PcapDotNet.Packets.Dns
private void ParseAdditionals()
{
int nextOffset = 0;
ParseRecords(AdditionalsOffset, () => AdditionalCount, DnsDataResourceRecord.Parse, ref _additionals, ref nextOffset);
if (ParseRecords(AdditionalsOffset, () => AdditionalCount, DnsDataResourceRecord.Parse, ref _additionals, ref nextOffset) &&
_additionals != null)
{
_options = (DnsOptResourceRecord)_additionals.FirstOrDefault(additional => additional.Type == DnsType.Opt);
}
}
private delegate TRecord ParseRecord<out TRecord>(DnsDatagram dns, int offset, out int numBytesRead);
private void ParseRecords<TRecord>(int offset, Func<ushort> countDelegate, ParseRecord<TRecord> parseRecord,
private bool ParseRecords<TRecord>(int offset, Func<ushort> countDelegate, ParseRecord<TRecord> parseRecord,
ref ReadOnlyCollection<TRecord> parsedRecords, ref int nextOffset) where TRecord : DnsResourceRecord
{
if (parsedRecords == null && Length >= offset)
......@@ -424,13 +437,17 @@ namespace PcapDotNet.Packets.Dns
}
parsedRecords = new ReadOnlyCollection<TRecord>(records.ToArray());
nextOffset = offset;
return true;
}
return false;
}
private ReadOnlyCollection<DnsQueryResourceRecord> _queries;
private ReadOnlyCollection<DnsDataResourceRecord> _answers;
private ReadOnlyCollection<DnsDataResourceRecord> _authorities;
private ReadOnlyCollection<DnsDataResourceRecord> _additionals;
private DnsOptResourceRecord _options;
private int _answersOffset;
private int _authoritiesOffset;
......
using System;
namespace PcapDotNet.Packets.Dns
{
public class DnsOptionAnything : DnsOption
{
public DnsOptionAnything(DnsOptionCode code, DataSegment data)
: base(code)
{
Data = data;
}
public DataSegment Data { get; private set; }
public override int DataLength
{
get { return Data.Length; }
}
internal override bool EqualsData(DnsOption other)
{
return Data.Equals(((DnsOptionAnything)other).Data);
}
internal override void WriteData(byte[] buffer, ref int offset)
{
Data.Write(buffer, ref offset);
}
}
}
\ No newline at end of file
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
......@@ -3675,4 +3676,410 @@ namespace PcapDotNet.Packets.Dns
return new DnsResourceDataSink(coding, subcoding, dataValue);
}
}
/// <summary>
/// http://files.dns-sd.org/draft-sekar-dns-llq.txt.
/// </summary>
public enum DnsLongLivedQueryOpcode : ushort
{
Setup = 1,
Refresh = 2,
Event = 3,
}
public enum DnsLongLivedQueryErrorCode : ushort
{
/// <summary>
/// The LLQ Setup Request was successful.
/// </summary>
NoError = 0,
/// <summary>
/// The server cannot grant the LLQ request because it is overloaded,
/// or the request exceeds the server's rate limit (see Section 8 "Security Considerations").
/// Upon returning this error, the server MUST include in the LEASE-LIFE field a time interval, in seconds,
/// after which the client may re-try the LLQ Setup.
/// </summary>
ServerFull = 1,
/// <summary>
/// The data for this name and type is not expected to change frequently, and the server therefore does not support the requested LLQ.
/// The client must not poll for this name and type, nor should it re-try the LLQ Setup, and should instead honor the normal resource record TTLs returned.
/// To reduce server load, an administrator MAY return this error for all records with types other than PTR and TXT as a matter of course.
/// </summary>
Static = 2,
/// <summary>
/// The LLQ was improperly formatted.
/// Note that if the rest of the DNS message is properly formatted, the DNS header error code must not include a format error code,
/// as this would cause confusion between a server that does not understand the LLQ format, and a client that sends malformed LLQs.
/// </summary>
FormatError = 3,
/// <summary>
/// The client attempts to refresh an expired or non-existent LLQ (as determined by the LLQ-ID in the request).
/// </summary>
NoSuchLlq = 4,
/// <summary>
/// The protocol version specified in the client's request is not supported by the server.
/// </summary>
BadVersion = 5,
/// <summary>
/// The LLQ was not granted for an unknown reason.
/// </summary>
UnknownError = 6,
}
public enum DnsOptionCode : ushort
{
/// <summary>
/// http://files.dns-sd.org/draft-sekar-dns-llq.txt.
/// LLQ.
/// </summary>
LongLivedQuery = 1,
/// <summary>
/// http://files.dns-sd.org/draft-sekar-dns-ul.txt.
/// UL.
/// </summary>
UpdateLease = 2,
/// <summary>
/// RFC 5001.
/// NSID.
/// </summary>
NameServerIdentifier = 3,
}
public abstract class DnsOption : IEquatable<DnsOption>
{
public const int MinimumLength = sizeof(ushort) + sizeof(ushort);
public DnsOptionCode Code { get; private set; }
public int Length { get { return MinimumLength + DataLength; } }
public abstract int DataLength { get; }
public bool Equals(DnsOption other)
{
return other != null &&
Code.Equals(other.Code) &&
GetType().Equals(other.GetType()) &&
EqualsData(other);
}
public override sealed bool Equals(object obj)
{
return Equals(obj as DnsOption);
}
internal DnsOption(DnsOptionCode code)
{
Code = code;
}
internal abstract bool EqualsData(DnsOption other);
internal void Write(byte[] buffer, ref int offset)
{
buffer.Write(ref offset, (ushort)Code, Endianity.Big);
buffer.Write(ref offset, (ushort)DataLength, Endianity.Big);
WriteData(buffer, ref offset);
}
internal abstract void WriteData(byte[] buffer, ref int offset);
internal static DnsOption CreateInstance(DnsOptionCode code, DataSegment data)
{
switch (code)
{
case DnsOptionCode.LongLivedQuery:
if (data.Length < DnsOptionLongLivedQuery.MinimumDataLength)
return null;
return DnsOptionLongLivedQuery.Read(data);
case DnsOptionCode.UpdateLease:
if (data.Length < DnsOptionUpdateLease.MinimumDataLength)
return null;
return DnsOptionUpdateLease.Read(data);
case DnsOptionCode.NameServerIdentifier:
default:
return new DnsOptionAnything(code, data);
}
}
}
/// <summary>
/// http://files.dns-sd.org/draft-sekar-dns-llq.txt.
/// <pre>
/// +-----+------------+
/// | bit | 0-15 |
/// +-----+------------+
/// | 0 | VERSION |
/// +-----+------------+
/// | 16 | LLQ-OPCODE |
/// +-----+------------+
/// | 32 | ERROR-CODE |
/// +-----+------------+
/// | 48 | LLQ-ID |
/// | | |
/// | | |
/// | | |
/// +-----+------------+
/// | 112 | LEASE-LIFE |
/// | | |
/// +-----+------------+
/// </pre>
/// </summary>
public class DnsOptionLongLivedQuery : DnsOption
{
private static class Offset
{
public const int Version = 0;
public const int Opcode = Version + sizeof(ushort);
public const int ErrorCode = Opcode + sizeof(ushort);
public const int Id = ErrorCode + sizeof(ushort);
public const int LeaseLife = Id + sizeof(ulong);
}
public const int MinimumDataLength = Offset.LeaseLife + sizeof(uint);
public DnsOptionLongLivedQuery(ushort version, DnsLongLivedQueryOpcode opcode, DnsLongLivedQueryErrorCode errorCode, ulong id, uint leaseLife)
: base(DnsOptionCode.LongLivedQuery)
{
Version = version;
Opcode = opcode;
ErrorCode = errorCode;
Id = id;
LeaseLife = leaseLife;
}
public ushort Version { get; private set; }
public DnsLongLivedQueryOpcode Opcode { get; private set; }
public DnsLongLivedQueryErrorCode ErrorCode { get; private set; }
public ulong Id { get; private set; }
public uint LeaseLife { get; private set; }
public override int DataLength
{
get { return MinimumDataLength; }
}
internal override bool EqualsData(DnsOption other)
{
DnsOptionLongLivedQuery castedOther = (DnsOptionLongLivedQuery)other;
return Version.Equals(castedOther.Version) &&
Opcode.Equals(castedOther.Opcode) &&
ErrorCode.Equals(castedOther.ErrorCode) &&
Id.Equals(castedOther.Id) &&
LeaseLife.Equals(castedOther.LeaseLife);
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(offset + Offset.Version, Version, Endianity.Big);
buffer.Write(offset + Offset.Opcode, (ushort)Opcode, Endianity.Big);
buffer.Write(offset + Offset.ErrorCode, (ushort)ErrorCode, Endianity.Big);
buffer.Write(offset + Offset.Id, Id, Endianity.Big);
buffer.Write(offset + Offset.LeaseLife, LeaseLife, Endianity.Big);
offset += DataLength;
}
internal static DnsOptionLongLivedQuery Read(DataSegment data)
{
if (data.Length < MinimumDataLength)
return null;
ushort version = data.ReadUShort(Offset.Version, Endianity.Big);
DnsLongLivedQueryOpcode opcode = (DnsLongLivedQueryOpcode)data.ReadUShort(Offset.Opcode, Endianity.Big);
DnsLongLivedQueryErrorCode errorCode = (DnsLongLivedQueryErrorCode)data.ReadUShort(Offset.ErrorCode, Endianity.Big);
ulong id = data.ReadULong(Offset.Id, Endianity.Big);
uint leaseLife = data.ReadUInt(Offset.LeaseLife, Endianity.Big);
return new DnsOptionLongLivedQuery(version, opcode, errorCode, id, leaseLife);
}
}
/// <summary>
/// http://files.dns-sd.org/draft-sekar-dns-ul.txt.
/// <pre>
/// +-----+-------+
/// | bit | 0-31 |
/// +-----+-------+
/// | 0 | LEASE |
/// +-----+-------+
/// </pre>
/// </summary>
public class DnsOptionUpdateLease : DnsOption
{
public const int MinimumDataLength = sizeof(int);
public DnsOptionUpdateLease(int lease)
: base(DnsOptionCode.UpdateLease)
{
Lease = lease;
}
/// <summary>
/// Indicating the lease life, in seconds, desired by the client.
/// In Update Responses, this field contains the actual lease granted by the server.
/// Note that the lease granted by the server may be less than, greater than, or equal to the value requested by the client.
/// To reduce network and server load, a minimum lease of 30 minutes (1800 seconds) is recommended.
/// Note that leases are expected to be sufficiently long as to make timer discrepancies (due to transmission latency, etc.)
/// between a client and server negligible.
/// Clients that expect the updated records to be relatively static may request appropriately longer leases.
/// Servers may grant relatively longer or shorter leases to reduce network traffic due to refreshes, or reduce stale data, respectively.
/// </summary>
public int Lease { get; private set; }
public override int DataLength
{
get { return MinimumDataLength; }
}
internal override bool EqualsData(DnsOption other)
{
return Lease.Equals(((DnsOptionUpdateLease)other).Lease);
}
internal override void WriteData(byte[] buffer, ref int offset)
{
buffer.Write(ref offset, Lease, Endianity.Big);
}
internal static DnsOptionUpdateLease Read(DataSegment data)
{
if (data.Length < MinimumDataLength)
return null;
int lease = data.ReadInt(0, Endianity.Big);
return new DnsOptionUpdateLease(lease);
}
}
public sealed class DnsOptions : IEquatable<DnsOptions>
{
public static DnsOptions None { get { return _none; } }
public DnsOptions(IList<DnsOption> options)
{
Options = options.AsReadOnly();
NumBytes = options.Sum(option => option.Length);
}
public DnsOptions(params DnsOption[] options)
: this((IList<DnsOption>)options)
{
}
public ReadOnlyCollection<DnsOption> Options { get; private set; }
public int NumBytes { get; private set; }
public bool Equals(DnsOptions other)
{
return other != null &&
Options.SequenceEqual(other.Options);
}
public override bool Equals(object obj)
{
return Equals(obj as DnsOptions);
}
private static readonly DnsOptions _none = new DnsOptions();
internal void Write(byte[] buffer, int offset)
{
foreach (DnsOption option in Options)
option.Write(buffer, ref offset);
}
public static DnsOptions Read(DataSegment data)
{
List<DnsOption> options = new List<DnsOption>();
while (data.Length != 0)
{
if (data.Length < DnsOption.MinimumLength)
return null;
DnsOptionCode code = (DnsOptionCode)data.ReadUShort(0, Endianity.Big);
ushort optionDataLength = data.ReadUShort(sizeof(ushort), Endianity.Big);
int optionLength = DnsOption.MinimumLength + optionDataLength;
if (data.Length < optionLength)
return null;
DnsOption option = DnsOption.CreateInstance(code, data.SubSegment(DnsOption.MinimumLength, optionDataLength));
if (option == null)
return null;
options.Add(option);
data = data.SubSegment(optionLength, data.Length - optionLength);
}
return new DnsOptions(options);
}
}
/// <summary>
/// RFC 2671.
/// <pre>
/// 0 Or more of:
/// +-----+---------------+
/// | bit | 0-15 |
/// +-----+---------------+
/// | 0 | OPTION-CODE |
/// +-----+---------------+
/// | 16 | OPTION-LENGTH |
/// +-----+---------------+
/// | 32 | OPTION-DATA |
/// | | |
/// +-----+---------------+
/// </pre>
/// </summary>
[DnsTypeRegistration(Type = DnsType.Opt)]
public sealed class DnsResourceDataOptions : DnsResourceDataSimple, IEquatable<DnsResourceDataOptions>
{
public DnsResourceDataOptions()
: this(DnsOptions.None)
{
}
public DnsResourceDataOptions(DnsOptions options)
{
Options = options;
}
public DnsOptions Options { get; private set; }
public bool Equals(DnsResourceDataOptions other)
{
return other != null &&
Options.Equals(other.Options);
}
public override bool Equals(DnsResourceData other)
{
return Equals(other as DnsResourceDataOptions);
}
internal override int GetLength()
{
return Options.NumBytes;
}
internal override void WriteDataSimple(byte[] buffer, int offset)
{
Options.Write(buffer, offset);
}
internal override DnsResourceData CreateInstance(DataSegment data)
{
DnsOptions options = DnsOptions.Read(data);
if (options == null)
return null;
return new DnsResourceDataOptions(options);
}
}
}
......@@ -26,6 +26,7 @@ namespace PcapDotNet.Packets.Dns
/// | ... | |
/// +------+-------------------------------------------------+
/// </pre>
/// </summary>
public abstract class DnsResourceRecord
{
private static class OffsetAfterDomainName
......
......@@ -114,7 +114,7 @@ namespace PcapDotNet.Packets
private Options(IList<T> options, bool isValid)
{
_options = new ReadOnlyCollection<T>(options);
_options = options.AsReadOnly();
IsValid = isValid;
......
......@@ -101,6 +101,7 @@
<Compile Include="Dns\DnsDomainNameCompressionMode.cs" />
<Compile Include="Dns\DnsLayer.cs" />
<Compile Include="Dns\DnsOpcode.cs" />
<Compile Include="Dns\DnsOptionAnything.cs" />
<Compile Include="Dns\DnsQueryResourceRecord.cs" />
<Compile Include="Dns\DnsResourceData.cs" />
<Compile Include="Dns\DnsResourceDataAnything.cs" />
......@@ -342,7 +343,7 @@
</Target>
-->
<PropertyGroup>
<PreBuildEvent>if not exist "$(SolutionDir)$(SolutionName).snk" ("%25PROGRAMFILES%25\Microsoft SDKs\Windows\v6.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</PreBuildEvent>
<PreBuildEvent>if not exist "$(SolutionDir)$(SolutionName).snk" ("%25PROGRAMFILES%25\Microsoft SDKs\Windows\v7.0A\bin\sn.exe" -k "$(SolutionDir)$(SolutionName).snk")</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
......
......@@ -16,12 +16,12 @@ namespace PcapDotNet.TestUtils
public static byte NextByte(this Random random, int minValue, int maxValue)
{
return (byte)random.Next(minValue, maxValue);
return (byte)random.NextInt(minValue, maxValue);
}
public static byte NextByte(this Random random, int maxValue)
{
return (byte)random.Next(maxValue);
return (byte)random.NextInt(0, maxValue);
}
public static byte NextByte(this Random random)
......@@ -38,12 +38,17 @@ namespace PcapDotNet.TestUtils
public static char NextChar(this Random random, char minValue, char maxValue)
{
return (char)random.Next(minValue, maxValue);
return (char)random.NextInt(minValue, maxValue);
}
public static ushort NextUShort(this Random random, int maxValue)
{
return (ushort)random.Next(maxValue);
return (ushort)random.NextInt(0, maxValue);
}
public static ushort NextUShort(this Random random, ushort minValue, int maxValue)
{
return (ushort)random.NextInt(minValue, maxValue);
}
public static ushort NextUShort(this Random random)
......@@ -53,12 +58,27 @@ namespace PcapDotNet.TestUtils
public static UInt24 NextUInt24(this Random random)
{
return (UInt24)random.Next(UInt24.MaxValue + 1);
return (UInt24)random.NextInt(0, UInt24.MaxValue + 1);
}
public static int NextInt(this Random random)
{
return random.Next(int.MinValue, int.MaxValue);
}
public static int NextInt(this Random random, int maxValue)
{
return random.Next(int.MinValue, maxValue);
}
public static int NextInt(this Random random, int minValue, int maxValue)
{
return random.Next(minValue, maxValue);
}
public static uint NextUInt(this Random random)
{
return (uint)random.Next(int.MinValue, int.MaxValue);
return (uint)random.NextInt();
}
public static uint NextUInt(this Random random, uint maxValue)
......
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