diff --git a/DnsClientX.Benchmarks/DnsClientX.Benchmarks.csproj b/DnsClientX.Benchmarks/DnsClientX.Benchmarks.csproj
index db8ef31a..e7afe971 100644
--- a/DnsClientX.Benchmarks/DnsClientX.Benchmarks.csproj
+++ b/DnsClientX.Benchmarks/DnsClientX.Benchmarks.csproj
@@ -5,9 +5,9 @@
DnsClientX Benchmarks
DnsClientX Performance Benchmarks
Performance benchmarks for DnsClientX DNS library using BenchmarkDotNet.
- 1.0.6
- 1.0.6
- 1.0.6
+ 1.0.7
+ 1.0.7
+ 1.0.7
Evotec
Przemyslaw Klys
(c) 2011 - 2025 Przemyslaw Klys @ Evotec. All rights reserved.
diff --git a/DnsClientX.Cli/DnsClientX.Cli.csproj b/DnsClientX.Cli/DnsClientX.Cli.csproj
index 41e7aa12..247b05c6 100644
--- a/DnsClientX.Cli/DnsClientX.Cli.csproj
+++ b/DnsClientX.Cli/DnsClientX.Cli.csproj
@@ -5,9 +5,9 @@
DnsClientX CLI
DnsClientX Command Line Interface
Command-line interface for DnsClientX DNS library. Provides quick DNS queries and scripting capabilities.
- 1.0.6
- 1.0.6
- 1.0.6
+ 1.0.7
+ 1.0.7
+ 1.0.7
Evotec
Przemyslaw Klys
(c) 2011 - 2025 Przemyslaw Klys @ Evotec. All rights reserved.
diff --git a/DnsClientX.Examples/DnsClientX.Examples.csproj b/DnsClientX.Examples/DnsClientX.Examples.csproj
index 2a30c496..fc95c2f6 100644
--- a/DnsClientX.Examples/DnsClientX.Examples.csproj
+++ b/DnsClientX.Examples/DnsClientX.Examples.csproj
@@ -6,9 +6,9 @@
DnsClientX Examples
DnsClientX Examples
Example applications demonstrating DnsClientX library features and capabilities.
- 1.0.6
- 1.0.6
- 1.0.6
+ 1.0.7
+ 1.0.7
+ 1.0.7
Evotec
Przemyslaw Klys
(c) 2011 - 2025 Przemyslaw Klys @ Evotec. All rights reserved.
diff --git a/DnsClientX.PowerShell/DnsClientX.PowerShell.csproj b/DnsClientX.PowerShell/DnsClientX.PowerShell.csproj
index 8822b261..175e24fc 100644
--- a/DnsClientX.PowerShell/DnsClientX.PowerShell.csproj
+++ b/DnsClientX.PowerShell/DnsClientX.PowerShell.csproj
@@ -12,9 +12,9 @@
service discovery, zone transfers, and DNS updates.
DnsClientX.PowerShell
DnsClientX PowerShell Module
- 1.0.6
- 1.0.6
- 1.0.6
+ 1.0.7
+ 1.0.7
+ 1.0.7
False
Evotec
Przemyslaw Klys
@@ -55,4 +55,4 @@
-
\ No newline at end of file
+
diff --git a/DnsClientX.Tests/CdBitTests.cs b/DnsClientX.Tests/CdBitTests.cs
index 6dac8a62..fe824948 100644
--- a/DnsClientX.Tests/CdBitTests.cs
+++ b/DnsClientX.Tests/CdBitTests.cs
@@ -21,7 +21,7 @@ private static byte[] CreateDnsHeader() {
return bytes;
}
- private static int GetFreePort() {
+ private static int GetFreeTcpPort() {
TcpListener listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
int port = ((IPEndPoint)listener.LocalEndpoint).Port;
@@ -29,6 +29,12 @@ private static int GetFreePort() {
return port;
}
+ private static int GetFreeUdpPort() {
+ using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
+ return ((IPEndPoint)socket.LocalEndPoint!).Port;
+ }
+
private static async Task RunUdpServerAsync(int port, byte[] response, CancellationToken token) {
using var udp = new UdpClient(new IPEndPoint(IPAddress.Loopback, port));
UdpReceiveResult result = await udp.ReceiveAsync();
@@ -77,7 +83,7 @@ private static void AssertCdBit(byte[] query, string name, uint expectedTtl) {
///
[Fact]
public async Task UdpRequest_ShouldIncludeCdBit_WhenConfigured() {
- int port = GetFreePort();
+ int port = GetFreeUdpPort();
var response = CreateDnsHeader();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var udpTask = RunUdpServerAsync(port, response, cts.Token);
@@ -104,7 +110,7 @@ await DnsWireResolveUdp.ResolveWireFormatUdp(
///
[Fact]
public async Task TcpRequest_ShouldIncludeCdBit_WhenConfigured() {
- int port = GetFreePort();
+ int port = GetFreeTcpPort();
var response = CreateDnsHeader();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var tcpTask = RunTcpServerAsync(port, response, cts.Token);
@@ -130,7 +136,7 @@ await DnsWireResolveTcp.ResolveWireFormatTcp(
///
[Fact]
public async Task UdpRequest_ShouldIncludeCdBit_WhenValidateDnsSecTrue() {
- int port = GetFreePort();
+ int port = GetFreeUdpPort();
var response = CreateDnsHeader();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var udpTask = RunUdpServerAsync(port, response, cts.Token);
diff --git a/DnsClientX.Tests/CliDnssecFlagTests.cs b/DnsClientX.Tests/CliDnssecFlagTests.cs
index cbbbd5e2..28beaa23 100644
--- a/DnsClientX.Tests/CliDnssecFlagTests.cs
+++ b/DnsClientX.Tests/CliDnssecFlagTests.cs
@@ -53,7 +53,7 @@ private static void AssertDoCdBits(byte[] query, string name) {
///
[Fact]
public async Task Cli_ShouldSetDoAndCdBits_WhenDnssecValidationEnabled() {
- int port = TestUtilities.GetFreePort();
+ int port = TestUtilities.GetFreeUdpPort();
SystemInformation.SetDnsServerProvider(() => new List { "127.0.0.1" });
diff --git a/DnsClientX.Tests/DnsClientX.Tests.csproj b/DnsClientX.Tests/DnsClientX.Tests.csproj
index 8c8ad5bb..c0c6e351 100644
--- a/DnsClientX.Tests/DnsClientX.Tests.csproj
+++ b/DnsClientX.Tests/DnsClientX.Tests.csproj
@@ -4,9 +4,9 @@
DnsClientX Tests
DnsClientX Unit Tests
Unit tests for DnsClientX DNS library.
- 1.0.6
- 1.0.6
- 1.0.6
+ 1.0.7
+ 1.0.7
+ 1.0.7
Evotec
Przemyslaw Klys
(c) 2011 - 2025 Przemyslaw Klys @ Evotec. All rights reserved.
diff --git a/DnsClientX.Tests/EdnsDoBitTests.cs b/DnsClientX.Tests/EdnsDoBitTests.cs
index 3c46a92b..1dfeca93 100644
--- a/DnsClientX.Tests/EdnsDoBitTests.cs
+++ b/DnsClientX.Tests/EdnsDoBitTests.cs
@@ -21,7 +21,7 @@ private static byte[] CreateDnsHeader() {
return bytes;
}
- private static int GetFreePort() {
+ private static int GetFreeTcpPort() {
TcpListener listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
int port = ((IPEndPoint)listener.LocalEndpoint).Port;
@@ -29,6 +29,12 @@ private static int GetFreePort() {
return port;
}
+ private static int GetFreeUdpPort() {
+ using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
+ return ((IPEndPoint)socket.LocalEndPoint!).Port;
+ }
+
private static async Task RunUdpServerAsync(int port, byte[] response, CancellationToken token) {
using var udp = new UdpClient(new IPEndPoint(IPAddress.Loopback, port));
UdpReceiveResult result = await udp.ReceiveAsync();
@@ -117,7 +123,7 @@ private static void AssertBufferSize(byte[] query, string name, ushort size) {
///
[Fact]
public async Task UdpRequest_ShouldIncludeDoBit_WhenRequested() {
- int port = GetFreePort();
+ int port = GetFreeUdpPort();
var response = CreateDnsHeader();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var udpTask = RunUdpServerAsync(port, response, cts.Token);
@@ -144,7 +150,7 @@ await DnsWireResolveUdp.ResolveWireFormatUdp(
///
[Fact]
public async Task TcpRequest_ShouldIncludeDoBit_WhenRequested() {
- int port = GetFreePort();
+ int port = GetFreeTcpPort();
var response = CreateDnsHeader();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var tcpTask = RunTcpServerAsync(port, response, cts.Token);
@@ -170,7 +176,7 @@ await DnsWireResolveTcp.ResolveWireFormatTcp(
///
[Fact]
public async Task UdpRequest_ShouldUseCustomBufferSize() {
- int port = GetFreePort();
+ int port = GetFreeUdpPort();
var response = CreateDnsHeader();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var udpTask = RunUdpServerAsync(port, response, cts.Token);
@@ -197,7 +203,7 @@ await DnsWireResolveUdp.ResolveWireFormatUdp(
///
[Fact]
public async Task UdpRequest_ShouldUseBufferSize_FromEdnsOptions() {
- int port = GetFreePort();
+ int port = GetFreeUdpPort();
var response = CreateDnsHeader();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var udpTask = RunUdpServerAsync(port, response, cts.Token);
@@ -227,7 +233,7 @@ await DnsWireResolveUdp.ResolveWireFormatUdp(
///
[Fact]
public async Task UdpRequest_ShouldNotSetDoBit_WhenDnssecNotRequested() {
- int port = GetFreePort();
+ int port = GetFreeUdpPort();
var response = CreateDnsHeader();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var udpTask = RunUdpServerAsync(port, response, cts.Token);
diff --git a/DnsClientX.Tests/EdnsOptionsTests.cs b/DnsClientX.Tests/EdnsOptionsTests.cs
index 42c3e874..e61a7ade 100644
--- a/DnsClientX.Tests/EdnsOptionsTests.cs
+++ b/DnsClientX.Tests/EdnsOptionsTests.cs
@@ -22,11 +22,9 @@ private static byte[] CreateDnsHeader() {
}
private static int GetFreePort() {
- TcpListener listener = new TcpListener(IPAddress.Loopback, 0);
- listener.Start();
- int port = ((IPEndPoint)listener.LocalEndpoint).Port;
- listener.Stop();
- return port;
+ using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
+ return ((IPEndPoint)socket.LocalEndPoint!).Port;
}
private static async Task RunUdpServerAsync(int port, byte[] response, CancellationToken token) {
diff --git a/DnsClientX.Tests/ResolveFirst.cs b/DnsClientX.Tests/ResolveFirst.cs
index 9e3c8d6f..146cfa9a 100644
--- a/DnsClientX.Tests/ResolveFirst.cs
+++ b/DnsClientX.Tests/ResolveFirst.cs
@@ -58,8 +58,9 @@ public async Task ShouldWorkForA(DnsEndpoint endpoint) {
using var Client = new ClientX(endpoint);
var answer = await Client.ResolveFirst("evotec.pl", DnsRecordType.A, cancellationToken: CancellationToken.None);
Assert.True(answer != null);
- Assert.True(answer.Value.Name == "evotec.pl");
Assert.True(answer.Value.Type == DnsRecordType.A);
+ Assert.True(!string.IsNullOrWhiteSpace(answer.Value.Name), "Expected answer name to not be empty");
+ Assert.True(System.Net.IPAddress.TryParse(answer.Value.Data, out var ipAddress) && ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork, $"Expected A record data to be an IPv4 address but got '{answer.Value.Data}' (name '{answer.Value.Name}', original '{answer.Value.OriginalName}')");
}
///
@@ -111,8 +112,9 @@ public void ShouldWorkForA_Sync(DnsEndpoint endpoint) {
using var Client = new ClientX(endpoint);
var answer = Client.ResolveFirstSync("evotec.pl", DnsRecordType.A, cancellationToken: CancellationToken.None);
Assert.True(answer != null);
- Assert.True(answer.Value.Name == "evotec.pl");
Assert.True(answer.Value.Type == DnsRecordType.A);
+ Assert.True(!string.IsNullOrWhiteSpace(answer.Value.Name), "Expected answer name to not be empty");
+ Assert.True(System.Net.IPAddress.TryParse(answer.Value.Data, out var ipAddress) && ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork, $"Expected A record data to be an IPv4 address but got '{answer.Value.Data}' (name '{answer.Value.Name}', original '{answer.Value.OriginalName}')");
}
}
}
diff --git a/DnsClientX.Tests/ResolveSync.cs b/DnsClientX.Tests/ResolveSync.cs
index b8a3b137..52b1a9d7 100644
--- a/DnsClientX.Tests/ResolveSync.cs
+++ b/DnsClientX.Tests/ResolveSync.cs
@@ -298,10 +298,11 @@ public void ShouldWorkForFirstSyncA(DnsEndpoint endpoint) {
if (ShouldSkipEndpoint(endpoint)) return;
using var client = new ClientX(endpoint);
var answer = client.ResolveFirstSync("evotec.pl", DnsRecordType.A, cancellationToken: CancellationToken.None);
- Assert.True(answer != null);
- Assert.True(answer.Value.Name == "evotec.pl");
- Assert.True(answer.Value.Type == DnsRecordType.A);
- Assert.True(answer.Value.Data.Length > 0);
+ Assert.True(answer != null, "Expected a non-null answer");
+ Assert.True(answer.Value.Type == DnsRecordType.A, $"Expected A record but got {answer.Value.Type}");
+ Assert.True(!string.IsNullOrWhiteSpace(answer.Value.Name), "Expected answer name to not be empty");
+ Assert.True(!string.IsNullOrWhiteSpace(answer.Value.Data), "Expected answer data to not be empty");
+ Assert.True(System.Net.IPAddress.TryParse(answer.Value.Data, out var ipAddress) && ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork, $"Expected A record data to be an IPv4 address but got '{answer.Value.Data}' (name '{answer.Value.Name}', original '{answer.Value.OriginalName}')");
}
///
diff --git a/DnsClientX.Tests/TestSkipHelpers.cs b/DnsClientX.Tests/TestSkipHelpers.cs
index 38e114cc..d013c7c3 100644
--- a/DnsClientX.Tests/TestSkipHelpers.cs
+++ b/DnsClientX.Tests/TestSkipHelpers.cs
@@ -8,7 +8,40 @@ internal static class TestSkipHelpers
{
internal static bool ShouldSkipEndpoint(DnsEndpoint endpoint, ITestOutputHelper? output = null)
{
- return ShouldSkipSystemTcp(endpoint, output) || ShouldSkipOdoh(endpoint, output);
+ return ShouldSkipSystemUdp(endpoint, output) || ShouldSkipSystemTcp(endpoint, output) || ShouldSkipOdoh(endpoint, output);
+ }
+
+ private static bool ShouldSkipSystemUdp(DnsEndpoint endpoint, ITestOutputHelper? output)
+ {
+ if (endpoint != DnsEndpoint.System)
+ {
+ return false;
+ }
+
+ var servers = SystemInformation.GetDnsFromActiveNetworkCard();
+ if (servers == null || servers.Count == 0)
+ {
+ output?.WriteLine("[Diagnostic] System UDP DNS skipped: no active DNS servers detected.");
+ return true;
+ }
+
+ var allLoopback = true;
+ foreach (var server in servers)
+ {
+ if (IPAddress.TryParse(server, out var ip) && !IPAddress.IsLoopback(ip))
+ {
+ allLoopback = false;
+ break;
+ }
+ }
+
+ if (allLoopback)
+ {
+ output?.WriteLine("[Diagnostic] System UDP DNS skipped: only loopback resolvers detected.");
+ return true;
+ }
+
+ return false;
}
private static bool ShouldSkipSystemTcp(DnsEndpoint endpoint, ITestOutputHelper? output)
diff --git a/DnsClientX.Tests/TestUtilities.cs b/DnsClientX.Tests/TestUtilities.cs
index 140cb5a9..73eb59da 100644
--- a/DnsClientX.Tests/TestUtilities.cs
+++ b/DnsClientX.Tests/TestUtilities.cs
@@ -4,11 +4,21 @@
namespace DnsClientX.Tests {
internal static class TestUtilities {
public static int GetFreePort() {
+ return GetFreeTcpPort();
+ }
+
+ public static int GetFreeTcpPort() {
TcpListener listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
int port = ((IPEndPoint)listener.LocalEndpoint).Port;
listener.Stop();
return port;
}
+
+ public static int GetFreeUdpPort() {
+ using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
+ return ((IPEndPoint)socket.LocalEndPoint!).Port;
+ }
}
}
diff --git a/DnsClientX.Tests/UdpClientDisposeTests.cs b/DnsClientX.Tests/UdpClientDisposeTests.cs
index f2cb4194..eb4d0abf 100644
--- a/DnsClientX.Tests/UdpClientDisposeTests.cs
+++ b/DnsClientX.Tests/UdpClientDisposeTests.cs
@@ -22,11 +22,9 @@ private static byte[] CreateDnsHeader() {
}
private static int GetFreePort() {
- TcpListener listener = new TcpListener(IPAddress.Loopback, 0);
- listener.Start();
- int port = ((IPEndPoint)listener.LocalEndpoint).Port;
- listener.Stop();
- return port;
+ using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
+ return ((IPEndPoint)socket.LocalEndPoint!).Port;
}
private static async Task RunUdpServerCapturePortAsync(int port, byte[] response, CancellationToken token) {
diff --git a/DnsClientX/DnsClientX.ResolveFirst.cs b/DnsClientX/DnsClientX.ResolveFirst.cs
index f5839e9e..49e4f6c5 100644
--- a/DnsClientX/DnsClientX.ResolveFirst.cs
+++ b/DnsClientX/DnsClientX.ResolveFirst.cs
@@ -43,7 +43,17 @@ public partial class ClientX {
retryDelayMs: retryDelayMs,
cancellationToken: cancellationToken).ConfigureAwait(false);
- return res.Answers?.FirstOrDefault(x => x.Type == type);
+ if (res.Answers == null || res.Answers.Length == 0) {
+ return null;
+ }
+
+ foreach (DnsAnswer answer in res.Answers) {
+ if (answer.Type == type) {
+ return answer;
+ }
+ }
+
+ return null;
}
///
diff --git a/DnsClientX/DnsClientX.csproj b/DnsClientX/DnsClientX.csproj
index c99452a8..612b78fe 100644
--- a/DnsClientX/DnsClientX.csproj
+++ b/DnsClientX/DnsClientX.csproj
@@ -10,9 +10,9 @@
DnsClientX
DnsClientX
- 1.0.6
- 1.0.6
- 1.0.6
+ 1.0.7
+ 1.0.7
+ 1.0.7
netstandard2.0;net472;net8.0;net9.0
@@ -80,4 +80,4 @@
\
-
\ No newline at end of file
+
diff --git a/Module/Build/Build-Module.ps1 b/Module/Build/Build-Module.ps1
index d12e39a9..052613f6 100644
--- a/Module/Build/Build-Module.ps1
+++ b/Module/Build/Build-Module.ps1
@@ -3,7 +3,7 @@
Build-Module -ModuleName 'DnsClientX' {
# Usual defaults as per standard module
$Manifest = [ordered] @{
- ModuleVersion = '1.0.6'
+ ModuleVersion = '1.0.7'
CompatiblePSEditions = @('Desktop', 'Core')
GUID = '77fa806c-70b7-48d9-8b88-942ed73f24ed'
Author = 'Przemyslaw Klys'
diff --git a/Module/DnsClientX.psd1 b/Module/DnsClientX.psd1
index 60b788e5..5788b2d1 100644
--- a/Module/DnsClientX.psd1
+++ b/Module/DnsClientX.psd1
@@ -9,7 +9,7 @@
FunctionsToExport = @()
GUID = '77fa806c-70b7-48d9-8b88-942ed73f24ed'
HelpInfoURI = 'https://github.com/EvotecIT/DnsClientX/blob/master/README.md'
- ModuleVersion = '1.0.6'
+ ModuleVersion = '1.0.7'
PowerShellVersion = '5.1'
PrivateData = @{
PSData = @{
@@ -19,4 +19,4 @@
}
}
RootModule = 'DnsClientX.psm1'
-}
\ No newline at end of file
+}