Commit 65a24f13 authored by Brickner_cp's avatar Brickner_cp

DNS

parent 64ffbb1d
...@@ -117,6 +117,20 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -117,6 +117,20 @@ namespace PcapDotNet.Packets.TestUtils
case DnsType.AfsDb: case DnsType.AfsDb:
return new DnsResourceDataAfsDb(random.NextUShort(), random.NextDnsDomainName()); return new DnsResourceDataAfsDb(random.NextUShort(), random.NextDnsDomainName());
case DnsType.X25:
return new DnsResourceDataString(random.NextDataSegment(random.Next(10)));
case DnsType.Isdn:
return random.NextBool()
? new DnsResourceDataIsdn(random.NextDataSegment(random.Next(10)))
: new DnsResourceDataIsdn(random.NextDataSegment(random.Next(10)), random.NextDataSegment(random.Next(10)));
case DnsType.Rt:
return new DnsResourceDataRouteThrough(random.NextUShort(), random.NextDnsDomainName());
case DnsType.Nsap:
return new DnsResourceDataNetworkServiceAccessPoint(random.NextDataSegment(1 + random.Next(10)), random.NextUInt48(), random.NextByte());
default: default:
return new DnsResourceDataAnything(random.NextDataSegment(random.Next(100))); return new DnsResourceDataAnything(random.NextDataSegment(random.Next(100)));
} }
......
...@@ -218,6 +218,17 @@ namespace PcapDotNet.Packets ...@@ -218,6 +218,17 @@ namespace PcapDotNet.Packets
return Buffer.ReadUInt(StartOffset + offset, endianity); return Buffer.ReadUInt(StartOffset + offset, endianity);
} }
/// <summary>
/// Reads 6 bytes from a specific offset in the segment as a UInt48 with a given endianity.
/// </summary>
/// <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>
internal UInt48 ReadUInt48(int offset, Endianity endianity)
{
return Buffer.ReadUInt48(StartOffset + offset, endianity);
}
/// <summary> /// <summary>
/// Reads 6 bytes from a specific offset in the segment as a MacAddress with a given endianity. /// Reads 6 bytes from a specific offset in the segment as a MacAddress with a given endianity.
/// </summary> /// </summary>
......
...@@ -45,6 +45,29 @@ namespace PcapDotNet.Packets.Dns ...@@ -45,6 +45,29 @@ namespace PcapDotNet.Packets.Dns
internal abstract DnsResourceData CreateInstance(DnsDatagram dns, int offsetInDns, int length); internal abstract DnsResourceData CreateInstance(DnsDatagram dns, int offsetInDns, int length);
internal static int GetStringLength(DataSegment str)
{
return sizeof(byte) + str.Length;
}
internal static DataSegment ReadString(DataSegment data, ref int offset)
{
if (data.Length <= offset)
return null;
int stringLength = data[offset++];
if (data.Length < offset + stringLength)
return null;
DataSegment str = data.SubSegment(ref offset, stringLength);
return str;
}
internal static void WriteString(byte[] buffer, ref int offset, DataSegment str)
{
buffer.Write(ref offset, (byte)str.Length);
str.Write(buffer, ref offset);
}
private static DnsResourceData TryGetPrototype(DnsType type, DnsClass dnsClass) private static DnsResourceData TryGetPrototype(DnsType type, DnsClass dnsClass)
{ {
DnsResourceData prototype; DnsResourceData prototype;
...@@ -490,16 +513,62 @@ namespace PcapDotNet.Packets.Dns ...@@ -490,16 +513,62 @@ namespace PcapDotNet.Packets.Dns
int offset = 0; int offset = 0;
while (offset != data.Length) while (offset != data.Length)
{ {
int stringLength = data[offset++]; DataSegment str = ReadString(data, ref offset);
if (data.Length < offset + stringLength) if (str == null)
return null; return null;
strings.Add(data.SubSegment(ref offset, stringLength)); strings.Add(str);
} }
return strings; return strings;
} }
} }
[DnsTypeRegistration(Type = DnsType.X25)]
public sealed class DnsResourceDataString : DnsResourceDataSimple, IEquatable<DnsResourceDataString>
{
public DnsResourceDataString()
: this(DataSegment.Empty)
{
}
public DnsResourceDataString(DataSegment str)
{
String = str;
}
public DataSegment String { get; private set; }
public bool Equals(DnsResourceDataString other)
{
return other != null &&
String.Equals(other.String);
}
public override bool Equals(DnsResourceData other)
{
return Equals(other as DnsResourceDataString);
}
internal override int GetLength()
{
return GetStringLength(String);
}
internal override void WriteDataSimple(byte[] buffer, int offset)
{
WriteString(buffer, ref offset, String);
}
internal override DnsResourceData CreateInstance(DataSegment data)
{
int offset = 0;
DataSegment str = ReadString(data, ref offset);
if (str == null)
return null;
return new DnsResourceDataString(str);
}
}
/// <summary> /// <summary>
/// +-----+ /// +-----+
/// | CPU | /// | CPU |
...@@ -902,4 +971,216 @@ namespace PcapDotNet.Packets.Dns ...@@ -902,4 +971,216 @@ namespace PcapDotNet.Packets.Dns
return new DnsResourceDataAfsDb(subType, hostName); return new DnsResourceDataAfsDb(subType, hostName);
} }
} }
/// <summary>
/// +---------------+
/// | ISDN-address |
/// +---------------+
/// | sa (optional) |
/// +---------------+
/// </summary>
[DnsTypeRegistration(Type = DnsType.Isdn)]
public sealed class DnsResourceDataIsdn : DnsResourceDataStrings
{
private const int MinNumStrings = 1;
private const int MaxNumStrings = 2;
public DnsResourceDataIsdn()
: this(DataSegment.Empty)
{
}
public DnsResourceDataIsdn(DataSegment isdnAddress)
: base(isdnAddress)
{
}
public DnsResourceDataIsdn(DataSegment isdnAddress, DataSegment subAddress)
: base(isdnAddress, subAddress)
{
}
/// <summary>
/// Identifies the ISDN number of the owner and DDI (Direct Dial In) if any, as defined by E.164 and E.163,
/// the ISDN and PSTN (Public Switched Telephone Network) numbering plan.
/// E.163 defines the country codes, and E.164 the form of the addresses.
/// </summary>
public DataSegment IsdnAddress { get { return Strings[0]; } }
/// <summary>
/// Specifies the subaddress (SA).
/// </summary>
public DataSegment SubAddress { get { return Strings.Count == MaxNumStrings ? Strings[1] : null; } }
internal override DnsResourceData CreateInstance(DataSegment data)
{
List<DataSegment> strings = ReadStrings(data, MaxNumStrings);
if (strings == null)
return null;
if (strings.Count == MinNumStrings)
return new DnsResourceDataIsdn(strings[0]);
if (strings.Count == MaxNumStrings)
return new DnsResourceDataIsdn(strings[0], strings[1]);
return null;
}
}
/// <summary>
/// +-----+-------------------+
/// | bit | 0-15 |
/// +-----+-------------------+
/// | 0 | preference |
/// +-----+-------------------+
/// | 16 | intermediate-host |
/// +-----+-------------------+
/// </summary>
[DnsTypeRegistration(Type = DnsType.Rt)]
public sealed class DnsResourceDataRouteThrough : DnsResourceDataUShortDomainName
{
public DnsResourceDataRouteThrough()
: this(0, DnsDomainName.Root)
{
}
public DnsResourceDataRouteThrough(ushort preference, DnsDomainName intermediateHost)
: base(preference, intermediateHost)
{
}
/// <summary>
/// Representing the preference of the route.
/// Smaller numbers indicate more preferred routes.
/// </summary>
public ushort Preference { get { return Value; } }
/// <summary>
/// The domain name of a host which will serve as an intermediate in reaching the host specified by the owner.
/// The DNS RRs associated with IntermediateHost are expected to include at least one A, X25, or ISDN record.
/// </summary>
public DnsDomainName IntermediateHost { get { return DomainName; } }
internal override DnsResourceData CreateInstance(DnsDatagram dns, int offsetInDns, int length)
{
ushort preference;
DnsDomainName intermediateHost;
if (!TryRead(out preference, out intermediateHost, dns, offsetInDns, length))
return null;
return new DnsResourceDataRouteThrough(preference, intermediateHost);
}
}
/// <summary>
/// +-----+-----+----------------------+----------+-----------+
/// | bit | 0-7 | 8-7+X | 8+X-55+X | 56+X-63+X |
/// +-----+-----+----------------------+----------+-----------+
/// | 0 | AFI | Domain Specific Area | ID | Sel |
/// +-----+-----+-----+----------------+----------+-----------+
/// | 0 | AFI | IDI | HO-DSP | ID | Sel |
/// +-----+-----+-----+----------------+----------+-----------+
/// | 0 | Area Address | ID | Sel |
/// +-----+-----------+----------------+----------+-----------+
/// | 0 | IDP | DSP |
/// +-----+-----------+---------------------------------------+
/// IDP is Initial Domain Part.
/// DSP is Domain Specific Part.
/// HO-DSP may use any format as defined by the authority identified by IDP.
/// </summary>
[DnsTypeRegistration(Type = DnsType.Nsap)]
public sealed class DnsResourceDataNetworkServiceAccessPoint : DnsResourceDataSimple, IEquatable<DnsResourceDataNetworkServiceAccessPoint>
{
private static class Offset
{
public const int AreaAddress = 0;
}
private static class OffsetAfterArea
{
public const int SystemIdentifier = 0;
public const int Selector = SystemIdentifier + UInt48.SizeOf;
}
private const int MinAreaAddressLength = sizeof(byte);
private const int ConstantPartLength = MinAreaAddressLength + OffsetAfterArea.Selector + sizeof(byte);
public DnsResourceDataNetworkServiceAccessPoint()
: this(new DataSegment(new byte[MinAreaAddressLength]), 0, 0)
{
}
public DnsResourceDataNetworkServiceAccessPoint(DataSegment areaAddress, UInt48 systemIdentifier, byte selector)
{
if (areaAddress.Length < MinAreaAddressLength)
throw new ArgumentOutOfRangeException("areaAddress", areaAddress.Length,
string.Format("Area Address length must be at least {0}.", MinAreaAddressLength));
AreaAddress = areaAddress;
SystemIdentifier = systemIdentifier;
Selector = selector;
}
/// <summary>
/// Authority and Format Identifier.
/// </summary>
public byte AuthorityAndFormatIdentifier { get { return AreaAddress[0]; } }
/// <summary>
/// The combination of [IDP, HO-DSP] identify both the routing domain and the area within the routing domain.
/// Hence the combination [IDP, HO-DSP] is called the "Area Address".
/// All nodes within the area must have same Area address.
/// </summary>
public DataSegment AreaAddress { get; private set; }
/// <summary>
/// System Identifier.
/// </summary>
public UInt48 SystemIdentifier { get; private set; }
/// <summary>
/// NSAP Selector
/// </summary>
public byte Selector { get; private set; }
public bool Equals(DnsResourceDataNetworkServiceAccessPoint other)
{
return other != null &&
AreaAddress.Equals(other.AreaAddress) &&
SystemIdentifier.Equals(other.SystemIdentifier) &&
Selector.Equals(other.Selector);
}
public override bool Equals(DnsResourceData other)
{
return Equals(other as DnsResourceDataNetworkServiceAccessPoint);
}
internal override int GetLength()
{
return ConstantPartLength + AreaAddress.Length - MinAreaAddressLength;
}
internal override void WriteDataSimple(byte[] buffer, int offset)
{
AreaAddress.Write(buffer, offset + Offset.AreaAddress);
int afterAreaOffset = offset + AreaAddress.Length;
buffer.Write(afterAreaOffset + OffsetAfterArea.SystemIdentifier, SystemIdentifier, Endianity.Big);
buffer.Write(afterAreaOffset + OffsetAfterArea.Selector, Selector);
}
internal override DnsResourceData CreateInstance(DataSegment data)
{
if (data.Length < ConstantPartLength)
return null;
DataSegment areaAddress = data.SubSegment(Offset.AreaAddress, MinAreaAddressLength + data.Length - ConstantPartLength);
int afterAreaOffset = areaAddress.Length;
UInt48 systemIdentifier = data.ReadUInt48(afterAreaOffset + OffsetAfterArea.SystemIdentifier, Endianity.Big);
byte selector = data[afterAreaOffset + OffsetAfterArea.Selector];
return new DnsResourceDataNetworkServiceAccessPoint(areaAddress, systemIdentifier, selector);
}
}
} }
...@@ -136,6 +136,7 @@ ...@@ -136,6 +136,7 @@
/// <summary> /// <summary>
/// RFC 1706. /// RFC 1706.
/// Network Service Access Point.
/// For NSAP address, NSAP style A record. /// For NSAP address, NSAP style A record.
/// </summary> /// </summary>
Nsap = 22, Nsap = 22,
......
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