Commit d1cd96f5 authored by Brickner_cp's avatar Brickner_cp

DNS

parent eff86bb1
......@@ -130,7 +130,7 @@ namespace PcapDotNet.Packets.Test
// new DnsResourceDataUnknown(new DataSegment(Encoding.ASCII.GetBytes("abcd")))),
// new DnsDataResourceRecord(new DnsDomainName("abc.def."), DnsType.A, DnsClass.In, 100,
// new DnsResourceDataUnknown(new DataSegment(Encoding.ASCII.GetBytes("abce")))),
new DnsDataResourceRecord(new DnsDomainName(""), DnsType.A, DnsClass.Any, 1, new DnsResourceDataUnknown(new DataSegment(new byte[0])))
new DnsDataResourceRecord(new DnsDomainName(""), DnsType.A, DnsClass.Any, 1, new DnsResourceDataIpV4(new IpV4Address("1.2.3.4")))
}.ToList(),
// Authorities =
// new[]
......
......@@ -1002,7 +1002,8 @@ namespace PcapDotNet.Packets.TestUtils
public static DnsDataResourceRecord NextDnsDataResourceRecord(this Random random)
{
DnsDataResourceRecord record = new DnsDataResourceRecord(random.NextDnsDomainName(), random.NextEnum<DnsType>(), random.NextEnum<DnsClass>(), random.Next(), random.NextDnsResourceData());
DnsType type = random.NextEnum<DnsType>();
DnsDataResourceRecord record = new DnsDataResourceRecord(random.NextDnsDomainName(), type, random.NextEnum<DnsClass>(), random.Next(), random.NextDnsResourceData(type));
return record;
}
......@@ -1021,10 +1022,15 @@ namespace PcapDotNet.Packets.TestUtils
return new DnsDomainName(string.Join(".", labels));
}
public static DnsResourceData NextDnsResourceData(this Random random)
public static DnsResourceData NextDnsResourceData(this Random random, DnsType type)
{
DnsResourceData resourceData = new DnsResourceDataUnknown(new DataSegment(random.NextBytes(random.Next(100))));
return resourceData;
switch (type)
{
case DnsType.A:
return new DnsResourceDataIpV4(random.NextIpV4Address());
default:
return new DnsResourceDataUnknown(new DataSegment(random.NextBytes(random.Next(100))));
}
}
// HTTP
......
......@@ -220,7 +220,7 @@ namespace PcapDotNet.Packets
/// <param name="offset">The offset in the segment to start reading.</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>
protected IpV4Address ReadIpV4Address(int offset, Endianity endianity)
internal IpV4Address ReadIpV4Address(int offset, Endianity endianity)
{
return Buffer.ReadIpV4Address(StartOffset + offset, endianity);
}
......
......@@ -68,7 +68,7 @@ namespace PcapDotNet.Packets.Dns
numBytesRead += MinimumLengthAfterBase;
if (offsetInDns + numBytesRead + dataLength > dns.Length)
return null;
DnsResourceData data = DnsResourceData.Read(dns, offsetInDns + numBytesRead, dataLength);
DnsResourceData data = DnsResourceData.Read(type, dnsClass, dns.SubSegment(offsetInDns + numBytesRead, dataLength));
if (data == null)
return null;
numBytesRead += dataLength;
......
namespace PcapDotNet.Packets.Dns
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using PcapDotNet.Base;
using PcapDotNet.Packets.IpV4;
namespace PcapDotNet.Packets.Dns
{
public abstract class DnsResourceData
internal class DnsTypeRegistrationAttribute : Attribute
{
public DnsType Type { get; set; }
}
public abstract class DnsResourceData : IEquatable<DnsResourceData>
{
internal static DnsResourceData Read(DnsDatagram dns, int offsetInDns, int dataLength)
public abstract bool Equals(DnsResourceData other);
public sealed override bool Equals(object obj)
{
return new DnsResourceDataUnknown(dns.SubSegment(offsetInDns, dataLength));
return Equals(obj as DnsResourceData);
}
internal abstract int GetLength(DnsDomainNameCompressionData compressionData, int offsetInDns);
......@@ -18,5 +33,109 @@
}
internal abstract int WriteData(byte[] buffer, int dnsOffset, int offsetInDns, DnsDomainNameCompressionData compressionData);
internal static DnsResourceData Read(DnsType type, DnsClass dnsClass, DataSegment data)
{
DnsResourceData prototype = TryGetPrototype(type, dnsClass);
if (prototype != null)
return prototype.CreateInstance(data);
return new DnsResourceDataUnknown(data);
}
internal abstract DnsResourceData CreateInstance(DataSegment data);
private static DnsResourceData TryGetPrototype(DnsType type, DnsClass dnsClass)
{
DnsResourceData prototype;
if (!_prototypes.TryGetValue(type, out prototype))
return null;
return prototype;
}
private static Dictionary<DnsType, DnsResourceData> InitializePrototypes()
{
var prototypes =
from type in Assembly.GetExecutingAssembly().GetTypes()
where typeof(DnsResourceData).IsAssignableFrom(type) &&
type.GetCustomAttributes<DnsTypeRegistrationAttribute>(false).Any()
select new
{
type.GetCustomAttributes<DnsTypeRegistrationAttribute>(false).First().Type,
Prototype = (DnsResourceData)Activator.CreateInstance(type),
};
return prototypes.ToDictionary(prototype => prototype.Type, prototype => prototype.Prototype);
}
private static readonly Dictionary<DnsType, DnsResourceData> _prototypes = InitializePrototypes();
}
public abstract class DnsResourceDataNoCompression : DnsResourceData
{
internal sealed override int GetLength(DnsDomainNameCompressionData compressionData, int offsetInDns)
{
return GetLength();
}
internal sealed override int WriteData(byte[] buffer, int dnsOffset, int offsetInDns, DnsDomainNameCompressionData compressionData)
{
return WriteData(buffer, dnsOffset + offsetInDns);
}
internal abstract int GetLength();
internal abstract int WriteData(byte[] buffer, int offset);
}
public abstract class DnsResourceDataSimple : DnsResourceDataNoCompression
{
internal sealed override int WriteData(byte[] buffer, int offset)
{
WriteDataSimple(buffer, offset);
return GetLength();
}
internal abstract void WriteDataSimple(byte[] buffer, int offset);
}
[DnsTypeRegistration(Type = DnsType.A)]
public class DnsResourceDataIpV4 : DnsResourceDataSimple, IEquatable<DnsResourceDataIpV4>
{
public DnsResourceDataIpV4()
{
}
public DnsResourceDataIpV4(IpV4Address data)
{
Data = data;
}
public IpV4Address Data { get; private set; }
public bool Equals(DnsResourceDataIpV4 other)
{
return other != null && Data.Equals(other.Data);
}
public sealed override bool Equals(DnsResourceData other)
{
return Equals(other as DnsResourceDataIpV4);
}
internal sealed override int GetLength()
{
return IpV4Address.SizeOf;
}
internal sealed override void WriteDataSimple(byte[] buffer, int offset)
{
buffer.Write(offset, Data, Endianity.Big);
}
internal sealed override DnsResourceData CreateInstance(DataSegment data)
{
return new DnsResourceDataIpV4(data.ReadIpV4Address(0, Endianity.Big));
}
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
namespace PcapDotNet.Packets.Dns
{
public class DnsResourceDataUnknown : DnsResourceData, IEquatable<DnsResourceDataUnknown>
public class DnsResourceDataUnknown : DnsResourceDataSimple, IEquatable<DnsResourceDataUnknown>
{
public DnsResourceDataUnknown(DataSegment data)
{
......@@ -16,20 +16,24 @@ namespace PcapDotNet.Packets.Dns
return other != null && Data.Equals(other.Data);
}
public override bool Equals(object obj)
public sealed override bool Equals(DnsResourceData other)
{
return Equals(obj as DnsResourceDataUnknown);
return Equals(other as DnsResourceDataUnknown);
}
internal override int GetLength(DnsDomainNameCompressionData compressionData, int offsetInDns)
internal override int GetLength()
{
return Data.Length;
}
internal override int WriteData(byte[] buffer, int dnsOffset, int offsetInDns, DnsDomainNameCompressionData compressionData)
internal override void WriteDataSimple(byte[] buffer, int offset)
{
Data.Write(buffer, dnsOffset + offsetInDns);
return Data.Length;
Data.Write(buffer, offset);
}
internal override DnsResourceData CreateInstance(DataSegment data)
{
return new DnsResourceDataUnknown(data);
}
}
}
\ No newline at end of file
......@@ -6,7 +6,7 @@ using PcapDotNet.Base;
namespace PcapDotNet.Packets
{
internal static class OptionComplexFactory<TOptionType>// : OptionComplexFactoryBase
internal static class OptionComplexFactory<TOptionType>
{
/// <summary>
/// The header length in bytes for the option (type and size).
......
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