From 0d64bd32a6f808959de5a01e42eb02e9516cb69e Mon Sep 17 00:00:00 2001 From: GF-Huang Date: Sun, 19 Nov 2023 07:04:31 +0800 Subject: [PATCH 1/2] Fix `Domain.FromString` with empty string. --- DNS/Protocol/Domain.cs | 16 ++++++++++------ Tests/Protocol/ParseDomainTest.cs | 5 +++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/DNS/Protocol/Domain.cs b/DNS/Protocol/Domain.cs index 910015a..4211965 100644 --- a/DNS/Protocol/Domain.cs +++ b/DNS/Protocol/Domain.cs @@ -13,8 +13,12 @@ public class Domain : IComparable { private const byte ASCII_LOWERCASE_LAST = 122; private const byte ASCII_UPPERCASE_MASK = 223; + private static readonly char[] LabelSeparator = new[] { '.' }; + private byte[][] labels; + public static readonly Domain Empty = FromArray(new byte[] { 0 }, 0); + public static Domain FromString(string domain) { return new Domain(domain); } @@ -98,7 +102,7 @@ private static bool IsASCIIAlphabet(byte b) { } private static int CompareTo(byte a, byte b) { - if(IsASCIIAlphabet(a) && IsASCIIAlphabet(b)) { + if (IsASCIIAlphabet(a) && IsASCIIAlphabet(b)) { a &= ASCII_UPPERCASE_MASK; b &= ASCII_UPPERCASE_MASK; } @@ -111,7 +115,7 @@ private static int CompareTo(byte[] a, byte[] b) { for (int i = 0; i < length; i++) { int v = CompareTo(a[i], b[i]); - if(v != 0) return v; + if (v != 0) return v; } return a.Length - b.Length; @@ -125,9 +129,9 @@ public Domain(string[] labels, Encoding encoding) { this.labels = labels.Select(label => encoding.GetBytes(label)).ToArray(); } - public Domain(string domain) : this(domain.Split('.')) {} + public Domain(string domain) : this(domain.Split(LabelSeparator, StringSplitOptions.RemoveEmptyEntries)) { } - public Domain(string[] labels) : this(labels, Encoding.ASCII) {} + public Domain(string[] labels) : this(labels, Encoding.ASCII) { } public int Size { get { return labels.Sum(l => l.Length) + labels.Length + 1; } @@ -138,7 +142,7 @@ public byte[] ToArray() { int offset = 0; foreach (byte[] label in labels) { - result[offset++] = (byte) label.Length; + result[offset++] = (byte)label.Length; label.CopyTo(result, offset); offset += label.Length; } @@ -160,7 +164,7 @@ public int CompareTo(Domain other) { for (int i = 0; i < length; i++) { int v = CompareTo(this.labels[i], other.labels[i]); - if(v != 0) return v; + if (v != 0) return v; } return this.labels.Length - other.labels.Length; diff --git a/Tests/Protocol/ParseDomainTest.cs b/Tests/Protocol/ParseDomainTest.cs index d6486e7..4e7a009 100644 --- a/Tests/Protocol/ParseDomainTest.cs +++ b/Tests/Protocol/ParseDomainTest.cs @@ -14,6 +14,11 @@ public void EmptyDomain() { Assert.Equal("", domain.ToString()); Assert.Equal(1, domain.Size); Assert.Equal(1, endOffset); + + domain = Domain.Empty; + Assert.Equal("", domain.ToString()); + Assert.Equal(1, domain.Size); + Assert.Single(domain.ToArray()); } [Fact] From 2ea6a0923bad722027a0b59a96bdd6f87a6adaef Mon Sep 17 00:00:00 2001 From: GF-Huang Date: Sun, 19 Nov 2023 07:05:34 +0800 Subject: [PATCH 2/2] Add OptResourceRecord. --- DNS/DNS.csproj | 1 - .../ResourceRecords/OptResourceRecord.cs | 114 ++++++++++++++++++ .../ResourceRecords/ResourceRecordFactory.cs | 2 + .../ResourceRecord/edns-option-padding | Bin 0 -> 31 bytes .../ParseResourceRecordTest.cs | 23 ++++ .../SerializeResourceRecordTest.cs | 9 ++ 6 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 DNS/Protocol/ResourceRecords/OptResourceRecord.cs create mode 100644 Tests/Fixtures/ResourceRecord/edns-option-padding diff --git a/DNS/DNS.csproj b/DNS/DNS.csproj index 622cc01..c234195 100644 --- a/DNS/DNS.csproj +++ b/DNS/DNS.csproj @@ -16,7 +16,6 @@ - diff --git a/DNS/Protocol/ResourceRecords/OptResourceRecord.cs b/DNS/Protocol/ResourceRecords/OptResourceRecord.cs new file mode 100644 index 0000000..c76f151 --- /dev/null +++ b/DNS/Protocol/ResourceRecords/OptResourceRecord.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; +using System.IO; +using System.Net; +using System.Collections.ObjectModel; + +namespace DNS.Protocol.ResourceRecords { + public class OptResourceRecord : BaseResourceRecord { + public ushort UdpPayloadSize => (ushort)Class; + + public byte ExtendedResponseCode => (byte)((uint)TimeToLive.TotalSeconds >> 24); + + public byte Version => (byte)((uint)TimeToLive.TotalSeconds >> 16); + + public ushort Z => (ushort)((uint)TimeToLive.TotalSeconds & 0xffff); + + public IReadOnlyList