2020-04-15 08:57:58 -04:00
|
|
|
using Microsoft.Win32.SafeHandles;
|
2020-04-11 18:17:06 -04:00
|
|
|
using NUnit.Framework;
|
|
|
|
using System;
|
|
|
|
using System.Linq;
|
2020-06-23 17:38:22 -04:00
|
|
|
using System.Net;
|
2020-04-11 18:17:06 -04:00
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
using System.Threading;
|
|
|
|
using Vanara.Extensions;
|
|
|
|
using Vanara.InteropServices;
|
|
|
|
using static Vanara.PInvoke.DnsApi;
|
|
|
|
|
|
|
|
namespace Vanara.PInvoke.Tests
|
|
|
|
{
|
|
|
|
public class DnsApiTests
|
|
|
|
{
|
|
|
|
private const string dnsSvr = "c1dns.cableone.net";
|
|
|
|
private const string dnsSvrIp = "24.116.0.53";
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsAcquireContextHandleTest()
|
|
|
|
{
|
|
|
|
Assert.That(DnsAcquireContextHandle(true, default, out var ctx), ResultIs.Successful);
|
|
|
|
Assert.That(ctx, ResultIs.ValidHandle);
|
|
|
|
Assert.That(() => ctx.Dispose(), Throws.Nothing);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsExtractRecordsFromMessageTest()
|
|
|
|
{
|
|
|
|
using var mem = new SafeHGlobalHandle(64);
|
|
|
|
Assert.That(DnsExtractRecordsFromMessage(mem, (ushort)(uint)mem.Size, out var results), ResultIs.Successful);
|
|
|
|
}
|
|
|
|
|
2020-05-11 12:24:10 -04:00
|
|
|
[Test]
|
|
|
|
public void DnsGetCacheDataTableTest()
|
|
|
|
{
|
|
|
|
Assert.That(DnsGetCacheDataTable(out var table), ResultIs.Successful);
|
|
|
|
foreach (var d in table)
|
|
|
|
TestContext.WriteLine($"{d.pszName} => {d.wType}");
|
|
|
|
Assert.That(() => table.Dispose(), Throws.Nothing);
|
|
|
|
}
|
|
|
|
|
2020-04-11 18:17:06 -04:00
|
|
|
[Test]
|
|
|
|
public void DnsGetProxyInformationTest()
|
|
|
|
{
|
|
|
|
var pi = new DNS_PROXY_INFORMATION { version = 1 };
|
|
|
|
var rpi = new DNS_PROXY_INFORMATION { version = 1 };
|
|
|
|
Assert.That(DnsGetProxyInformation(dnsSvr, ref pi, ref rpi), ResultIs.Successful);
|
|
|
|
if (pi.proxyName != default)
|
|
|
|
DnsFreeProxyName(pi.proxyName);
|
|
|
|
if (rpi.proxyName != default)
|
|
|
|
DnsFreeProxyName(rpi.proxyName);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsModifyRecordsInSetTest()
|
|
|
|
{
|
|
|
|
Assert.That(DnsQuery(dnsSvr, DNS_TYPE.DNS_TYPE_ALL, 0, default, out var results), ResultIs.Successful);
|
|
|
|
Assert.That(results, ResultIs.ValidHandle);
|
2020-04-15 08:57:58 -04:00
|
|
|
Assert.That(DnsModifyRecordsInSet(results, results, DNS_UPDATE.DNS_UPDATE_SECURITY_USE_DEFAULT), ResultIs.Value(Win32Error.ERROR_TIMEOUT));
|
2020-04-11 18:17:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsNameCompareTest()
|
|
|
|
{
|
|
|
|
Assert.That(DnsNameCompare(dnsSvr, dnsSvr), Is.True);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsQueryConfigTest([Values] DNS_CONFIG_TYPE ctype)
|
|
|
|
{
|
|
|
|
var type = CorrespondingTypeAttribute.GetCorrespondingTypes(ctype, CorrespondingAction.GetSet).FirstOrDefault();
|
|
|
|
if (type is null || type == typeof(StrPtrAnsi)) Assert.Pass($"{ctype} Ignored");
|
|
|
|
var sz = 1024U;
|
|
|
|
using var mem = new SafeCoTaskMemHandle(sz);
|
|
|
|
Assert.That(DnsQueryConfig(ctype, 0, null, default, mem, ref sz), ResultIs.Successful);
|
|
|
|
mem.DangerousGetHandle().Convert(sz, type, CharSet.Unicode).WriteValues();
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsQueryExTest()
|
|
|
|
{
|
2020-04-15 08:57:58 -04:00
|
|
|
using var evt = new System.Threading.AutoResetEvent(false);
|
2020-04-11 18:17:06 -04:00
|
|
|
var req = new DNS_QUERY_REQUEST
|
|
|
|
{
|
|
|
|
Version = DNS_QUERY_REQUEST_VERSION1,
|
|
|
|
QueryName = dnsSvr,
|
|
|
|
QueryOptions = DNS_QUERY_OPTIONS.DNS_QUERY_STANDARD,
|
|
|
|
QueryType = DNS_TYPE.DNS_TYPE_ALL,
|
|
|
|
pQueryCompletionCallback = Callback
|
|
|
|
};
|
|
|
|
var res = new DNS_QUERY_RESULT { Version = DNS_QUERY_REQUEST_VERSION1 };
|
2020-04-15 08:57:58 -04:00
|
|
|
Assert.That(DnsQueryEx(req, ref res, out var cancel), ResultIs.Value(Win32Error.DNS_REQUEST_PENDING));
|
|
|
|
if (!evt.WaitOne(20000))
|
|
|
|
{
|
2020-04-11 18:17:06 -04:00
|
|
|
Assert.That(DnsCancelQuery(cancel), ResultIs.Successful);
|
2020-04-15 08:57:58 -04:00
|
|
|
Assert.Fail("Completion callback not called.");
|
|
|
|
}
|
2020-04-11 18:17:06 -04:00
|
|
|
if (res.pQueryRecords != default)
|
|
|
|
DnsRecordListFree(res.pQueryRecords);
|
|
|
|
|
2020-04-15 08:57:58 -04:00
|
|
|
void Callback(IntPtr pQueryContext, ref DNS_QUERY_RESULT pQueryResults)
|
2020-04-11 18:17:06 -04:00
|
|
|
{
|
2020-04-15 08:57:58 -04:00
|
|
|
evt.Set();
|
2020-04-11 18:17:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-15 08:57:58 -04:00
|
|
|
[Test]
|
|
|
|
public void DnsQueryTest()
|
|
|
|
{
|
|
|
|
Assert.That(DnsQuery(dnsSvr, DNS_TYPE.DNS_TYPE_ALL, 0, default, out var results), ResultIs.Successful);
|
|
|
|
Assert.That(results, ResultIs.ValidHandle);
|
|
|
|
results.ToArray().WriteValues();
|
|
|
|
}
|
|
|
|
|
2020-04-11 18:17:06 -04:00
|
|
|
[Test]
|
|
|
|
public void DnsRecordCompareTest()
|
|
|
|
{
|
|
|
|
var r1 = new DNS_RECORD { pName = dnsSvr, wType = DNS_TYPE.DNS_TYPE_A, Data = new DNS_A_DATA { IpAddress = 0xFFFFFF0U } };
|
|
|
|
Assert.That(DnsRecordCompare(r1, r1), Is.True);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsRecordSetCompareTest()
|
|
|
|
{
|
|
|
|
Assert.That(DnsQuery(dnsSvr, DNS_TYPE.DNS_TYPE_ALL, 0, default, out var results), ResultIs.Successful);
|
|
|
|
Assert.That(DnsRecordSetCompare(results, results, out var p1, out var p2), ResultIs.Successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsServiceBrowseTest()
|
|
|
|
{
|
2020-04-15 08:57:58 -04:00
|
|
|
using var evt = Kernel32.CreateEvent(null, false, true);
|
|
|
|
|
2020-04-11 18:17:06 -04:00
|
|
|
var br = new DNS_SERVICE_BROWSE_REQUEST
|
|
|
|
{
|
|
|
|
Version = DNS_QUERY_REQUEST_VERSION1,
|
|
|
|
QueryName = "_windns-example._udp",
|
2020-04-15 08:57:58 -04:00
|
|
|
pQueryContext = (IntPtr)evt
|
2020-04-11 18:17:06 -04:00
|
|
|
};
|
|
|
|
br.Callback.pBrowseCallback = Callback;
|
2020-04-15 08:57:58 -04:00
|
|
|
Assert.That(DnsServiceBrowse(br, out var cancel), ResultIs.Value(Win32Error.DNS_REQUEST_PENDING));
|
|
|
|
if (Kernel32.WaitForSingleObject(evt, 20000) != Kernel32.WAIT_STATUS.WAIT_OBJECT_0)
|
|
|
|
{
|
|
|
|
Assert.That(DnsServiceBrowseCancel(cancel), ResultIs.Successful);
|
|
|
|
Assert.Fail("Browse callback not called.");
|
|
|
|
}
|
2020-04-11 18:17:06 -04:00
|
|
|
|
|
|
|
var queryRequest = new MDNS_QUERY_REQUEST
|
|
|
|
{
|
|
|
|
Version = DNS_QUERY_REQUEST_VERSION1,
|
|
|
|
Query = "_windns-example._udp.local",
|
|
|
|
QueryType = DNS_TYPE.DNS_TYPE_PTR,
|
|
|
|
QueryOptions = DNS_QUERY_OPTIONS.DNS_QUERY_STANDARD,
|
2020-04-15 08:57:58 -04:00
|
|
|
pQueryCallback = QueryCallback,
|
|
|
|
pQueryContext = (IntPtr)evt
|
2020-04-11 18:17:06 -04:00
|
|
|
};
|
|
|
|
Assert.That(DnsStartMulticastQuery(queryRequest, out var queryHandle), ResultIs.Successful);
|
2020-04-15 08:57:58 -04:00
|
|
|
if (Kernel32.WaitForSingleObject(evt, 20000) != Kernel32.WAIT_STATUS.WAIT_OBJECT_0)
|
|
|
|
{
|
|
|
|
Assert.That(DnsStopMulticastQuery(queryHandle), ResultIs.Successful);
|
|
|
|
Assert.Fail("Multicast callback not called.");
|
|
|
|
}
|
2020-04-11 18:17:06 -04:00
|
|
|
|
2020-04-15 08:57:58 -04:00
|
|
|
void Callback(uint Status, IntPtr pQueryContext, IntPtr pDnsRecord)
|
2020-04-11 18:17:06 -04:00
|
|
|
{
|
2020-04-15 08:57:58 -04:00
|
|
|
Kernel32.SetEvent(pQueryContext);
|
2020-04-11 18:17:06 -04:00
|
|
|
}
|
|
|
|
|
2020-04-15 08:57:58 -04:00
|
|
|
void QueryCallback(IntPtr pQueryContext, IntPtr pQueryHandle, IntPtr pQueryResults)
|
2020-04-11 18:17:06 -04:00
|
|
|
{
|
2020-04-15 08:57:58 -04:00
|
|
|
var pQueryRecs = IntPtr.Zero;
|
|
|
|
unsafe
|
|
|
|
{
|
|
|
|
var pQR = (DNS_QUERY_RESULT*)(void*)pQueryResults;
|
|
|
|
pQueryResults = pQR->pQueryRecords;
|
|
|
|
}
|
|
|
|
using var recs = new SafeDnsRecordList(pQueryRecs);
|
|
|
|
using var qevt = Kernel32.CreateEvent(null, false, true);
|
2020-04-11 18:17:06 -04:00
|
|
|
var rec = recs.FirstOrDefault();
|
|
|
|
if (rec.wDataLength == 0)
|
|
|
|
return;
|
|
|
|
var resolveRequest = new DNS_SERVICE_RESOLVE_REQUEST
|
|
|
|
{
|
|
|
|
Version = DNS_QUERY_REQUEST_VERSION1,
|
|
|
|
QueryName = rec.Data is DNS_PTR_DATA d ? d.pNameHost : null,
|
|
|
|
pResolveCompletionCallback = ResolveCallback,
|
2020-04-15 08:57:58 -04:00
|
|
|
pQueryContext = (IntPtr)qevt
|
2020-04-11 18:17:06 -04:00
|
|
|
};
|
2020-04-15 08:57:58 -04:00
|
|
|
Assert.That(DnsServiceResolve(resolveRequest, out var cancel), ResultIs.Value(Win32Error.DNS_REQUEST_PENDING));
|
|
|
|
if (Kernel32.WaitForSingleObject(qevt, 20000) != Kernel32.WAIT_STATUS.WAIT_OBJECT_0)
|
|
|
|
{
|
2020-04-11 18:17:06 -04:00
|
|
|
Assert.That(DnsServiceResolveCancel(cancel), ResultIs.Successful);
|
2020-04-15 08:57:58 -04:00
|
|
|
Assert.Fail("Resolve callback not called.");
|
|
|
|
}
|
|
|
|
Kernel32.SetEvent(pQueryContext);
|
2020-04-11 18:17:06 -04:00
|
|
|
}
|
|
|
|
|
2020-04-15 08:57:58 -04:00
|
|
|
void ResolveCallback(uint Status, IntPtr pQueryContext, IntPtr pInstance)
|
2020-04-11 18:17:06 -04:00
|
|
|
{
|
2020-04-15 08:57:58 -04:00
|
|
|
Kernel32.SetEvent(pQueryContext);
|
2020-04-11 18:17:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsServiceRegisterTest()
|
|
|
|
{
|
|
|
|
SafePDNS_SERVICE_INSTANCE si;
|
|
|
|
Assert.That(si = DnsServiceConstructInstance("initial._windns-example._udp.local", "example.com", IntPtr.Zero, IntPtr.Zero, 1, 0, 0, 0, null, null), ResultIs.ValidHandle);
|
2020-04-15 08:57:58 -04:00
|
|
|
|
2020-04-11 18:17:06 -04:00
|
|
|
var callbackCalled = false;
|
|
|
|
var sr = new DNS_SERVICE_REGISTER_REQUEST
|
|
|
|
{
|
|
|
|
Version = DNS_QUERY_REQUEST_VERSION1,
|
|
|
|
pRegisterCompletionCallback = Callback,
|
|
|
|
pServiceInstance = si,
|
|
|
|
};
|
2020-04-15 08:57:58 -04:00
|
|
|
Assert.That(DnsServiceRegister(sr, out var cancel), ResultIs.Value(Win32Error.DNS_REQUEST_PENDING));
|
2020-04-11 18:17:06 -04:00
|
|
|
Thread.Sleep(500);
|
|
|
|
if (!callbackCalled)
|
|
|
|
Assert.That(DnsServiceRegisterCancel(cancel), ResultIs.Successful);
|
2020-04-15 08:57:58 -04:00
|
|
|
Assert.That(DnsServiceDeRegister(sr, cancel), ResultIs.Value(Win32Error.DNS_REQUEST_PENDING));
|
2020-04-11 18:17:06 -04:00
|
|
|
|
2020-04-15 08:57:58 -04:00
|
|
|
void Callback(uint Status, IntPtr pQueryContext, IntPtr pInstance) => callbackCalled = true;
|
2020-04-11 18:17:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsValidateNameTest()
|
|
|
|
{
|
|
|
|
Assert.That(DnsValidateName(dnsSvr, DNS_NAME_FORMAT.DnsNameHostnameFull), ResultIs.Successful);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsValidateServerStatusTest()
|
|
|
|
{
|
|
|
|
Assert.That(DnsValidateServerStatus(new Ws2_32.SOCKADDR(System.Net.IPAddress.Parse(dnsSvrIp)), null, out var stat), ResultIs.Successful);
|
|
|
|
Assert.That(stat, Is.EqualTo(DnsServerStatus.ERROR_SUCCESS));
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsWriteQuestionToBufferTest()
|
|
|
|
{
|
|
|
|
var sz = 64U;
|
|
|
|
using var mem = new SafeHGlobalHandle(sz);
|
2020-04-15 08:57:58 -04:00
|
|
|
Assert.That(DnsWriteQuestionToBuffer(mem, ref sz, "microsoft", DNS_TYPE.DNS_TYPE_A, 1, true), ResultIs.Successful);
|
2020-04-11 18:17:06 -04:00
|
|
|
var buf = mem.ToStructure<DNS_MESSAGE_BUFFER>();
|
|
|
|
DNS_BYTE_FLIP_HEADER_COUNTS(ref buf);
|
|
|
|
buf.WriteValues();
|
2020-04-15 08:57:58 -04:00
|
|
|
if (sz <= mem.Size)
|
|
|
|
TestContext.Write(string.Join(":", mem.ToArray<byte>((int)sz - 12, 12)));
|
2020-04-11 18:17:06 -04:00
|
|
|
}
|
2020-06-23 17:38:22 -04:00
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void DnsCacheDataTable()
|
|
|
|
{
|
|
|
|
Assert.That(DnsGetCacheDataTable(out var dnsCacheDataTable), ResultIs.Successful);
|
|
|
|
foreach (var dnsCacheEntry in dnsCacheDataTable)
|
|
|
|
{
|
|
|
|
if (DnsQuery(dnsCacheEntry.pszName, dnsCacheEntry.wType, DNS_QUERY_OPTIONS.DNS_QUERY_NO_WIRE_QUERY | DNS_QUERY_OPTIONS.DNS_QUERY_LOCAL, default, out var dnsRecords).Failed)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
foreach (var dnsRecord in dnsRecords.GetRecordPointers().Select(p => p.ToStructure<DNS_RECORD>()))
|
|
|
|
{
|
|
|
|
switch (dnsRecord.wType)
|
|
|
|
{
|
|
|
|
case DNS_TYPE.DNS_TYPE_A:
|
|
|
|
var ipv4 = new IPAddress(((DNS_A_DATA)dnsRecord.Data).IpAddress.S_un_b);
|
|
|
|
Assert.That(ipv4.AddressFamily, Is.EqualTo(System.Net.Sockets.AddressFamily.InterNetwork));
|
|
|
|
Assert.That(ipv4.ToString(), Does.Not.EndWith("0.0"));
|
|
|
|
break;
|
|
|
|
case DNS_TYPE.DNS_TYPE_AAAA:
|
|
|
|
var ipv6 = new IPAddress(((DNS_AAAA_DATA)dnsRecord.Data).Ip6Address.bytes);
|
|
|
|
Assert.That(ipv6.AddressFamily, Is.EqualTo(System.Net.Sockets.AddressFamily.InterNetworkV6));
|
|
|
|
Assert.That(ipv6.ToString(), Does.Not.EndWith("0.0"));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-04-11 18:17:06 -04:00
|
|
|
}
|
|
|
|
}
|