Skip to content

Commit

Permalink
Improve domain name parsing and comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
jdomnitz committed Jul 18, 2024
1 parent e512e35 commit 7f1c237
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 12 deletions.
4 changes: 2 additions & 2 deletions TinyDNS/Cache/ResolverCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public void Store(IEnumerable<ResourceRecord> records)

public void Store(ResourceRecord record)
{
HashSet<ResourceRecord> recordSet = cache.GetOrAdd(record.Name, new HashSet<ResourceRecord>());
HashSet<ResourceRecord> recordSet = cache.GetOrAdd(record.Name.ToLowerInvariant(), new HashSet<ResourceRecord>());
lock (recordSet)
{
DateTime now = DateTime.Now;
Expand All @@ -26,7 +26,7 @@ public void Store(ResourceRecord record)

public ResourceRecord[]? Search(QuestionRecord question)
{
if (cache.TryGetValue(string.Join('.', question.Name), out HashSet<ResourceRecord>? recordSet))
if (cache.TryGetValue(string.Join('.', question.Name).ToLowerInvariant(), out HashSet<ResourceRecord>? recordSet))
{
lock (recordSet)
{
Expand Down
2 changes: 1 addition & 1 deletion TinyDNS/DNSResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ public async Task<List<IPAddress>> ResolveHostV6(string hostname)
}
foreach (ResourceRecord additional in response.Additionals)
{
if (question.Name.SequenceEqual(additional.Labels) && additional.Type == question.Type)
if (question.Name.SequenceEqual(additional.Labels, new DomainEqualityComparer()) && additional.Type == question.Type)
return response;
}

Expand Down
12 changes: 12 additions & 0 deletions TinyDNS/DomainEqualityComparer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace TinyDNS
{
public class DomainEqualityComparer : EqualityComparer<String>
{
public override bool Equals(string? d1, string? d2)
{
return string.Equals(d1, d2, StringComparison.OrdinalIgnoreCase);
}

public override int GetHashCode(string box) => box.GetHashCode();
}
}
28 changes: 25 additions & 3 deletions TinyDNS/DomainParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System.Globalization;
using System.Text;

namespace TinyDNS
Expand Down Expand Up @@ -80,10 +81,31 @@ public static void Write(List<string> labels, Span<byte> buffer, ref int pos)
buffer[pos++] = ROOT;
}

internal static List<string> Parse(string domain)
public static List<string> Parse(string domain)
{
//TODO - Handle escaped chars
return domain.Split('.', StringSplitOptions.TrimEntries).ToList();
List<string> labels = new List<string>();
StringBuilder label = new StringBuilder();
for (int i = 0; i < domain.Length; i++)
{
if (domain[i] == '\\')
{
//Escaped char follows
if (char.IsAsciiHexDigit(domain[++i]))
label.Append((char)int.Parse(domain.AsSpan().Slice(i++, 2), NumberStyles.HexNumber)); //2 digit char code
else
label.Append(domain[i]); //single character
}
else if (domain[i] == '.')
{
labels.Add(label.ToString());
label.Clear();
}
else
label.Append(domain[i]);
}
if (label.Length > 0)
labels.Add(label.ToString());
return labels;
}
}
}
2 changes: 1 addition & 1 deletion TinyDNS/Records/CNameRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal CNameRecord(ResourceRecordHeader header, Span<byte> buffer, ref int pos

public CNameRecord(string cname, List<string> labels, DNSClass @class, uint ttl) : base(labels, DNSRecordType.CNAME, @class, ttl)
{
CNameLabels = new List<string>(cname.Split('.'));
CNameLabels = DomainParser.Parse(cname);
}

public CNameRecord(ResourceRecordHeader header, string rdata) : base(header)
Expand Down
4 changes: 2 additions & 2 deletions TinyDNS/Records/NSRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ internal NSRecord(ResourceRecordHeader header, Span<byte> buffer, ref int pos) :
NSDomainLabels = DomainParser.Read(buffer, ref pos);
}

public NSRecord(string cname, List<string> labels, DNSClass @class, uint ttl) : base(labels, DNSRecordType.NS, @class, ttl)
public NSRecord(string ns, List<string> labels, DNSClass @class, uint ttl) : base(labels, DNSRecordType.NS, @class, ttl)
{
NSDomainLabels = new List<string>(cname.Split('.'));
NSDomainLabels = DomainParser.Parse(ns);
}

public NSRecord(ResourceRecordHeader header, string rdata) : base(header)
Expand Down
2 changes: 1 addition & 1 deletion TinyDNS/Records/PtrRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal PtrRecord(ResourceRecordHeader header, Span<byte> buffer, ref int pos)

public PtrRecord(string domain, List<string> labels, DNSClass @class, uint ttl) : base(labels, DNSRecordType.PTR, @class, ttl)
{
DomainLabels = new List<string>(domain.Split('.'));
DomainLabels = DomainParser.Parse(domain);
}

public PtrRecord(ResourceRecordHeader header, string rdata) : base(header)
Expand Down
2 changes: 1 addition & 1 deletion TinyDNS/Records/QuestionRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class QuestionRecord : IEquatable<QuestionRecord>
public DNSRecordType Type { get; set; }
public DNSClass Class { get; set; }
public bool UnicastResponse { get; set; }
public QuestionRecord(string domain, DNSRecordType recordType, bool unicastResponse) : this(new List<string>(domain.Split('.')), recordType, unicastResponse) { }
public QuestionRecord(string domain, DNSRecordType recordType, bool unicastResponse) : this(DomainParser.Parse(domain), recordType, unicastResponse) { }

public QuestionRecord(List<string> domain, DNSRecordType recordType, bool unicastResponse)
{
Expand Down
2 changes: 1 addition & 1 deletion TinyDNS/Records/SRVRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ internal SRVRecord(ResourceRecordHeader header, Span<byte> buffer, ref int pos)

public SRVRecord(string service, ushort priority, ushort port, ushort weight, List<string> labels, DNSClass @class, uint ttl) : base(labels, DNSRecordType.SRV, @class, ttl)
{
TargetLabels = new List<string>(service.Split('.'));
TargetLabels = DomainParser.Parse(service);
Priority = priority;
Port = port;
Weight = weight;
Expand Down

0 comments on commit 7f1c237

Please sign in to comment.