Skip to content

Commit

Permalink
* Added RFC 7828
Browse files Browse the repository at this point in the history
* Added RFC 7830
* Added RFC 7871
* Added RFC 7873
* Added RFC 8005
* Added RFC 8162
* Added RFC 8749
* Added RFC 8777
* Added RFC 9373
* Added draft-ietf-dnsop-svcb-https
* Fixed dynamic updates (#28)
* Optimized parsing of Zone masterfiles
* Updated BouncyCastle to latest version
  • Loading branch information
alexreinert committed May 19, 2023
1 parent 66001e9 commit 127b888
Show file tree
Hide file tree
Showing 66 changed files with 2,403 additions and 263 deletions.
19 changes: 16 additions & 3 deletions ARSoft.Tools.Net/ARSoft.Tools.Net.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
<BaseIntermediateOutputPath></BaseIntermediateOutputPath>
<DocumentationFile>..\bin\$(Configuration)\net6.0\ARSoft.Tools.Net.xml</DocumentationFile>
<Nullable>enable</Nullable>
<AssemblyOriginatorKeyFile>C:\Users\Alexander Reinert\source\repos\arsoft.pfx</AssemblyOriginatorKeyFile>
<Title>ARSoft.Tools.Net - C#/.Net DNS client/server, SPF and SenderID Library</Title>
<Authors>Alexander Reinert</Authors>
<Description>This project contains a complete managed .Net DNS and DNSSEC client, a DNS server and SPF and SenderID validation.</Description>
Expand All @@ -17,11 +16,11 @@
<PackageLicenseUrl>https://github.com/alexreinert/ARSoft.Tools.Net/blob/master/LICENSE</PackageLicenseUrl>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Copyright>Copyright 2010..2023 Alexander Reinert</Copyright>
<VersionPrefix>3.1.1</VersionPrefix>
<VersionPrefix>3.2.0</VersionPrefix>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BouncyCastle.Cryptography" Version="2.1.1" />
<PackageReference Include="BouncyCastle.Cryptography" Version="2.2.1" />
<PackageReference Include="System.Net.Sockets" Version="4.3.0" />
</ItemGroup>

Expand All @@ -30,12 +29,26 @@
<Content Include="..\NOTICE" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

<ItemGroup>
<None Include="..\README.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>ARSoft.Tools.Net.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001009B3C03B877D82BDB95D93615C1521BAE3C1D5E9AF140B9BE44BE07ADF2E2E303481FEF06BE780C26E9422384E9E5B0EFD7CF77B5F1F500BD79062D076F47F4F955BF3090AEEF3CE0D3FD2E9C27F496035D2055D40CFF7835CB4DC40A337C890BBE2973BDDDFEC2DE8EFB7B8B375BDBD96EE5B278D8A69866841BC5D06E817CB5</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

<PropertyGroup Condition="Exists('..\..\arsoft.pfx')">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\arsoft.pfx</AssemblyOriginatorKeyFile>
</PropertyGroup>

<PropertyGroup>
<NoWarn>1701;1702;1591</NoWarn>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
</Project>
2 changes: 1 addition & 1 deletion ARSoft.Tools.Net/Dns/Cache/DnsCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public override bool Equals(object? obj)

public override string ToString()
{
return _name + " " + _recordClass.ToShortString() + " " + _recordType.ToShortString();
return _name.ToString(true) + " " + _recordClass.ToShortString() + " " + _recordType.ToShortString();
}
}

Expand Down
6 changes: 3 additions & 3 deletions ARSoft.Tools.Net/Dns/DnsMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,15 +246,15 @@ protected internal override DnsMessageBase CreateFailureResponse()
return msg;
}

internal override bool IsReliableSendingRequested => (Questions.Count > 0) && ((Questions[0].RecordType == RecordType.Axfr) || (Questions[0].RecordType == RecordType.Ixfr) || (Questions[0].RecordType == RecordType.Any));
internal override bool IsReliableSendingRequested => (Questions.Count > 0) && Questions[0].RecordType is RecordType.Axfr or RecordType.Ixfr or RecordType.Any or RecordType.SMimeA;

internal override bool IsReliableResendingRequested => IsTruncated;

internal override bool IsNextMessageWaiting(bool isSubsequentResponseMessage)
{
if (isSubsequentResponseMessage)
{
return (AnswerRecords.Count > 0) && (AnswerRecords[AnswerRecords.Count - 1].RecordType != RecordType.Soa);
return (AnswerRecords.Count > 0) && (AnswerRecords[^1].RecordType != RecordType.Soa);
}

if (Questions.Count == 0)
Expand All @@ -265,7 +265,7 @@ internal override bool IsNextMessageWaiting(bool isSubsequentResponseMessage)

return (AnswerRecords.Count > 0)
&& (AnswerRecords[0].RecordType == RecordType.Soa)
&& ((AnswerRecords.Count == 1) || (AnswerRecords[AnswerRecords.Count - 1].RecordType != RecordType.Soa));
&& ((AnswerRecords.Count == 1) || (AnswerRecords[^1].RecordType != RecordType.Soa));
}
}
}
2 changes: 1 addition & 1 deletion ARSoft.Tools.Net/Dns/DnsMessageBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ internal static void EncodeDomainName(IList<byte> messageData, ref int currentPo
return;
}

var isCompressionAllowed = !useCanonical & (domainNames != null);
var isCompressionAllowed = !useCanonical && (domainNames != null);

if (isCompressionAllowed && domainNames!.TryGetValue(name, out var pointer))
{
Expand Down
2 changes: 1 addition & 1 deletion ARSoft.Tools.Net/Dns/DnsMessageEntryBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ protected DnsMessageEntryBase(DomainName name, RecordType recordType, RecordClas
/// <returns> Textual representation </returns>
public override string ToString()
{
return Name + " " + RecordType + " " + RecordClass;
return Name.ToString(true) + " " + RecordType + " " + RecordClass;
}

private int? _hashCode;
Expand Down
261 changes: 261 additions & 0 deletions ARSoft.Tools.Net/Dns/DnsRecord/AMTRelayRecord.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
#region Copyright and License
// Copyright 2010..2023 Alexander Reinert
//
// This file is part of the ARSoft.Tools.Net - C# DNS client/server and SPF Library (https://github.com/alexreinert/ARSoft.Tools.Net)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion

using System.Net;
using System.Net.Sockets;

namespace ARSoft.Tools.Net.Dns;

/// <summary>
/// <para>Automatic Multicast Tunneling Relay</para>
/// <para>
/// Defined in
/// <a href="https://www.rfc-editor.org/rfc/rfc8777.html">RFC 8777</a>.
/// </para>
/// </summary>
// ReSharper disable once InconsistentNaming
public class AMTRelayRecord : DnsRecordBase
{
public enum RelayFieldType : byte
{
/// <summary>
/// <para>The relay field is empty.</para>
/// <para>
/// Defined in
/// <a href="https://www.rfc-editor.org/rfc/rfc8777.html">RFC 8777</a>.
/// </para>
/// </summary>
None = 0,

/// <summary>
/// <para>The relay field contains an IPv4 address.</para>
/// <para>
/// Defined in
/// <a href="https://www.rfc-editor.org/rfc/rfc8777.html">RFC 8777</a>.
/// </para>
/// </summary>
// ReSharper disable once InconsistentNaming
IPv4 = 1,

/// <summary>
/// <para>The relay field contains an IPv6 address.</para>
/// <para>
/// Defined in
/// <a href="https://www.rfc-editor.org/rfc/rfc8777.html">RFC 8777</a>.
/// </para>
/// </summary>
// ReSharper disable once InconsistentNaming
IPv6 = 2,

/// <summary>
/// <para>The relay field contains a domain name.</para>
/// <para>
/// Defined in
/// <a href="https://www.rfc-editor.org/rfc/rfc8777.html">RFC 8777</a>.
/// </para>
/// </summary>
DomainName = 3,
}

/// <summary>
/// The precedence of the record
/// </summary>
public byte Precedence { get; }

/// <summary>
/// The Discovery Optional flag
/// </summary>
public bool IsDiscoveryOptional { get; }

/// <summary>
/// The type of the relay
/// </summary>
public RelayFieldType RelayType { get; }

/// <summary>
/// The relay
/// </summary>
public string Relay { get; }

internal AMTRelayRecord(DomainName name, RecordType recordType, RecordClass recordClass, int timeToLive, IList<byte> resultData, int currentPosition, int length)
: base(name, recordType, recordClass, timeToLive)
{
Precedence = resultData[currentPosition++];
var type = resultData[currentPosition++];
IsDiscoveryOptional = type > 127;
RelayType = (RelayFieldType) (type & 127);
switch (RelayType)
{
case RelayFieldType.IPv4:
Relay = new IPAddress(DnsMessageBase.ParseByteData(resultData, ref currentPosition, 4)).ToString();
break;
case RelayFieldType.IPv6:
Relay = new IPAddress(DnsMessageBase.ParseByteData(resultData, ref currentPosition, 16)).ToString();
break;
case RelayFieldType.DomainName:
Relay = DnsMessageBase.ParseDomainName(resultData, ref currentPosition).ToString(true);
break;
default:
Relay = DomainName.Root.ToString(true);
break;
}
}

internal AMTRelayRecord(DomainName name, RecordType recordType, RecordClass recordClass, int timeToLive, DomainName origin, string[] stringRepresentation)
: base(name, recordType, recordClass, timeToLive)
{
if (stringRepresentation.Length != 4)
throw new FormatException();

Precedence = Byte.Parse(stringRepresentation[0]);
switch (stringRepresentation[1])
{
case "0":
IsDiscoveryOptional = false;
break;
case "1":
IsDiscoveryOptional = true;
break;
default:
throw new FormatException();
}

RelayType = (RelayFieldType) Byte.Parse(stringRepresentation[2]);
switch (RelayType)
{
case RelayFieldType.IPv4:
{
if (IPAddress.TryParse(stringRepresentation[3], out var address) && address.AddressFamily == AddressFamily.InterNetwork)
{
Relay = address.ToString();
}
else
{
throw new FormatException();
}

break;
}
case RelayFieldType.IPv6:
{
if (IPAddress.TryParse(stringRepresentation[3], out var address) && address.AddressFamily == AddressFamily.InterNetworkV6)
{
Relay = address.ToString();
}
else
{
throw new FormatException();
}

break;
}
case RelayFieldType.DomainName:
Relay = ParseDomainName(origin, stringRepresentation[3]).ToString(true);
break;
default:
Relay = DomainName.Root.ToString(true);
break;
}
}

/// <summary>
/// Creates a new instance of the AMTRelayRecord class
/// </summary>
/// <param name="name"> Name of the zone </param>
/// <param name="timeToLive"> Seconds the record should be cached at most </param>
/// <param name="precedence">The precedence of the record</param>
public AMTRelayRecord(DomainName name, int timeToLive, byte precedence)
: base(name, RecordType.AMTRelay, RecordClass.INet, timeToLive)
{
Precedence = precedence;
IsDiscoveryOptional = false;
RelayType = RelayFieldType.None;
Relay = DomainName.Root.ToString(true);
}

/// <summary>
/// Creates a new instance of the AMTRelayRecord class
/// </summary>
/// <param name="name"> Name of the zone </param>
/// <param name="timeToLive"> Seconds the record should be cached at most </param>
/// <param name="precedence">The precedence of the record</param>
/// <param name="isDiscoveryOptional">The Discovery Optional flag</param>
/// <param name="relayAddress">The address of the relay</param>
public AMTRelayRecord(DomainName name, int timeToLive, byte precedence, bool isDiscoveryOptional, IPAddress relayAddress)
: base(name, RecordType.AMTRelay, RecordClass.INet, timeToLive)
{
Precedence = precedence;
IsDiscoveryOptional = isDiscoveryOptional;
RelayType = relayAddress.AddressFamily == AddressFamily.InterNetwork ? RelayFieldType.IPv4 : RelayFieldType.IPv6;
Relay = relayAddress.ToString();
}

/// <summary>
/// Creates a new instance of the AMTRelayRecord class
/// </summary>
/// <param name="name"> Name of the zone </param>
/// <param name="timeToLive"> Seconds the record should be cached at most </param>
/// <param name="precedence">The precedence of the record</param>
/// <param name="isDiscoveryOptional">The Discovery Optional flag</param>
/// <param name="relayName">The domain name of the relay</param>
public AMTRelayRecord(DomainName name, int timeToLive, byte precedence, bool isDiscoveryOptional, DomainName relayName)
: base(name, RecordType.AMTRelay, RecordClass.INet, timeToLive)
{
Precedence = precedence;
IsDiscoveryOptional = isDiscoveryOptional;
RelayType = RelayFieldType.DomainName;
Relay = relayName.ToString(true);
}

internal override string RecordDataToString()
{
return Precedence + " " + (IsDiscoveryOptional ? "1" : "0") + " " + (byte) RelayType + " " + Relay;
}

protected internal override int MaximumRecordDataLength
{
get
{
var res = 2;
return RelayType switch
{
RelayFieldType.IPv4 => res + 4,
RelayFieldType.IPv6 => res + 16,
RelayFieldType.DomainName => res + 2 + Relay.Length,
_ => res
};
}
}

protected internal override void EncodeRecordData(IList<byte> messageData, ref int currentPosition, Dictionary<DomainName, ushort>? domainNames, bool useCanonical)
{
messageData[currentPosition++] = Precedence;
messageData[currentPosition++] = (byte) ((byte) RelayType | (IsDiscoveryOptional ? 128 : 0));
switch (RelayType)
{
case RelayFieldType.IPv4:
case RelayFieldType.IPv6:
byte[] addressBuffer = IPAddress.Parse(Relay).GetAddressBytes();
DnsMessageBase.EncodeByteArray(messageData, ref currentPosition, addressBuffer);
break;
case RelayFieldType.DomainName:
DnsMessageBase.EncodeDomainName(messageData, ref currentPosition, ParseDomainName(DomainName.Root, Relay), null, false);
break;
}
}
}
2 changes: 1 addition & 1 deletion ARSoft.Tools.Net/Dns/DnsRecord/AfsdbRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public AfsdbRecord(DomainName name, int timeToLive, AfsSubType subType, DomainNa
internal override string RecordDataToString()
{
return (byte) SubType
+ " " + Hostname;
+ " " + Hostname.ToString(true);
}

protected internal override int MaximumRecordDataLength => Hostname.MaximumRecordDataLength + 4;
Expand Down
Loading

0 comments on commit 127b888

Please sign in to comment.