private static void QueryCompletionRoutine(IntPtr queryContext, IntPtr queryResults) { QueryCompletionContext context = (QueryCompletionContext)Marshal.PtrToStructure(queryContext, typeof(QueryCompletionContext)); DNSQueryResult queryResult = (DNSQueryResult)Marshal.PtrToStructure(queryResults, typeof(DNSQueryResult)); Marshal.WriteInt32(context.resultCode, queryResult.QueryStatus); if (queryResult.QueryStatus != 0) { if (queryResult.QueryRecords != IntPtr.Zero) { DnsRecordListFree(queryResult.QueryRecords, DNS_FREE_TYPE.DnsFreeRecordList); } context.eventHandle.Set(); return; } List <IDictionary <string, object> > records = GCHandle.FromIntPtr(context.dnsRecords).Target as List <IDictionary <string, object> >; records.AddRange(ParseRecords(queryResult.QueryRecords, context.requestType)); if (queryResult.QueryRecords != IntPtr.Zero) { DnsRecordListFree(queryResult.QueryRecords, DNS_FREE_TYPE.DnsFreeRecordList); } context.eventHandle.Set(); }
public static IDictionary <string, object>[] QueryDNSForRecordTypeSpecificNameServers(string domainName, IPEndPoint[] dnsServers, DnsRecordTypes recordType) { if (dnsServers == null || dnsServers.Length == 0) { throw new Exception("At least one DNS Server must be provided to do the query"); } IntPtr dnsRequest, addrRequestBuffer, contextBuffer; QueryCompletionContext context = new QueryCompletionContext(); context.eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset); context.requestType = recordType; context.resultCode = Marshal.AllocHGlobal(Marshal.SizeOf <int>()); List <IDictionary <string, object> > dnsRecords = new List <IDictionary <string, object> >(); GCHandle handle = GCHandle.Alloc(dnsRecords, GCHandleType.Normal); context.dnsRecords = GCHandle.ToIntPtr(handle); MakeDnsRequest(domainName, dnsServers, context, out dnsRequest, out addrRequestBuffer, out contextBuffer); DNSQueryResult queryResult = new DNSQueryResult(); queryResult.Version = DnsQueryRequestVersion1; IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DNSQueryResult))); Marshal.StructureToPtr(queryResult, result, false); IntPtr cancelBuffer = Marshal.AllocHGlobal(DNSQueryCancelSize); int resCode = DnsQueryEx(dnsRequest, result, cancelBuffer); FreeDnsRequest(dnsRequest, addrRequestBuffer, contextBuffer); bool requestPending = false; switch (resCode) { case 0: { queryResult = (DNSQueryResult)Marshal.PtrToStructure(result, typeof(DNSQueryResult)); Marshal.FreeHGlobal(result); } break; case DnsRequestPending: { Marshal.FreeHGlobal(result); requestPending = true; } break; case DnsRecordsNoInfo: { Marshal.FreeHGlobal(result); Marshal.FreeHGlobal(cancelBuffer); handle.Free(); return(new Dictionary <string, object> [0]); } default: { Marshal.FreeHGlobal(result); Marshal.FreeHGlobal(cancelBuffer); handle.Free(); throw new Win32Exception(resCode); } } if (!requestPending) { Marshal.FreeHGlobal(cancelBuffer); handle.Free(); if (queryResult.QueryStatus != 0) { if (queryResult.QueryRecords != IntPtr.Zero) { DnsRecordListFree(queryResult.QueryRecords, DNS_FREE_TYPE.DnsFreeRecordList); } throw new Win32Exception(queryResult.QueryStatus); } dnsRecords.AddRange(ParseRecords(queryResult.QueryRecords, recordType)); if (queryResult.QueryRecords != IntPtr.Zero) { DnsRecordListFree(queryResult.QueryRecords, DNS_FREE_TYPE.DnsFreeRecordList); } return(dnsRecords.ToArray()); } if (!context.eventHandle.WaitOne(5000)) { resCode = DnsCancelQuery(cancelBuffer); context.eventHandle.WaitOne(); if (resCode != 0) { Marshal.FreeHGlobal(cancelBuffer); handle.Free(); throw new Win32Exception(resCode); } } Marshal.FreeHGlobal(cancelBuffer); handle.Free(); int retCode = Marshal.ReadInt32(context.resultCode); Marshal.FreeHGlobal(context.resultCode); if (retCode != 0) { throw new Win32Exception(retCode); } return(dnsRecords.ToArray()); }
private static void MakeDnsRequest(string domainName, IPEndPoint[] dnsServers, QueryCompletionContext context, out IntPtr requestBuffer, out IntPtr addrBuffer, out IntPtr contextBuffer) { requestBuffer = IntPtr.Zero; addrBuffer = IntPtr.Zero; contextBuffer = IntPtr.Zero; DNS_ADDR[] addrList = new DNS_ADDR[dnsServers.Length]; int curAddress = 0; foreach (var endpoint in dnsServers) { addrList[curAddress] = new DNS_ADDR(); if (endpoint.AddressFamily == AddressFamily.InterNetwork) { byte[] ipv4AddressBytes = endpoint.Address.GetAddressBytes(); SockAddrIn sockAddrIn = new SockAddrIn(); Buffer.BlockCopy(ipv4AddressBytes, 0, sockAddrIn.SinAddr, 0, IpAddressV4LengthBytes); sockAddrIn.SinFamily = AFInet; sockAddrIn.SinPort = (ushort)IPAddress.HostToNetworkOrder((short)endpoint.Port); IntPtr sockAddrInPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SockAddrIn))); Marshal.StructureToPtr(sockAddrIn, sockAddrInPtr, false); Marshal.Copy(sockAddrInPtr, addrList[curAddress].MaxSa, 0, Marshal.SizeOf(typeof(SockAddrIn))); Marshal.FreeHGlobal(sockAddrInPtr); } else if (endpoint.AddressFamily == AddressFamily.InterNetworkV6) { SockAddrIn6 sockAddrIn6 = new SockAddrIn6(); sockAddrIn6.Sin6Family = AFInet16; sockAddrIn6.Sin6Port = (ushort)IPAddress.HostToNetworkOrder((short)endpoint.Port); sockAddrIn6.Sin6FlowInfo = 0; byte[] ipv6AddressBytes = endpoint.Address.GetAddressBytes(); Buffer.BlockCopy(ipv6AddressBytes, 0, sockAddrIn6.Sin6Addr, 0, IpAddressV6LengthBytes); sockAddrIn6.Sin6ScopeId = 0; IntPtr sockAddrv6InPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SockAddrIn6))); Marshal.StructureToPtr(sockAddrIn6, sockAddrv6InPtr, false); Marshal.Copy(sockAddrv6InPtr, addrList[curAddress].MaxSa, 0, Marshal.SizeOf(typeof(SockAddrIn6))); Marshal.FreeHGlobal(sockAddrv6InPtr); } else { throw new Exception(string.Format("Address family {0} not supported", endpoint.AddressFamily.ToString())); } curAddress++; } int bufSize = Marshal.SizeOf(typeof(DNS_ADDR_ARRAY)) + (addrList.Length * Marshal.SizeOf(typeof(DNS_ADDR))); DNS_ADDR_ARRAY addrArray = new DNS_ADDR_ARRAY(); addrArray.MaxCount = (uint)dnsServers.Length; addrArray.AddrCount = (uint)dnsServers.Length; addrBuffer = Marshal.AllocHGlobal(bufSize); Marshal.StructureToPtr(addrArray, addrBuffer, false); IntPtr addrArrayPointer = new IntPtr(addrBuffer.ToInt64() + Marshal.SizeOf(typeof(DNS_ADDR_ARRAY))); for (int i = 0; i < addrList.Length; i++) { Marshal.StructureToPtr(addrList[i], addrArrayPointer, false); addrArrayPointer = new IntPtr(addrArrayPointer.ToInt64() + Marshal.SizeOf(typeof(DNS_ADDR))); } DNS_QUERY_REQUEST request = new DNS_QUERY_REQUEST(); request.Version = DnsQueryRequestVersion1; request.QueryName = domainName; request.QueryType = (ushort)context.requestType; request.QueryOptions = (ulong)(DnsQueryOptions.DNS_QUERY_STANDARD); request.DnsServerList = addrBuffer; request.InterfaceIndex = 0; // request.QueryCompletionCallback = Marshal.GetFunctionPointerForDelegate(new QueryCompletionRoutineFunctionPointer(QueryCompletionRoutine)); contextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(context)); Marshal.StructureToPtr(context, contextBuffer, false); request.QueryContext = contextBuffer; requestBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(request)); Marshal.StructureToPtr(request, requestBuffer, false); }