Beispiel #1
0
            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();
            }
Beispiel #2
0
            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());
            }
Beispiel #3
0
            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);
            }