This is my first time using C #, so I am very strong from my element. But I believe that wonderful people here at Stack Overflow can help me! I came up with the following code (below) based on some other pieces of code that I found on the Internet. I am trying to find all the "text" DNS (TXT) records for this domain. I started simply with a console application in Visual C # 2008 Express, browsing through the entries for google.com. I will worry about setting up a domain based on command line options later; for now, I just want it to work. Any DNS lookup tools can tell you that google.com has this record of DNS records in its DNS:
v=spf1 include:_netblocks.google.com ip4:216.73.93.70/31 ip4:216.73.93.72/31 ~all
But, unfortunately, this is not what I get. Here is my code:
namespace DnsUtils { using System; using System.Collections; using System.ComponentModel; using System.Runtime.InteropServices; using System.Text; public class DnsTxt { [DllImport("dnsapi", EntryPoint = "DnsQuery_W", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] private static extern int DnsQuery([MarshalAs(UnmanagedType.VBByRefStr)]ref string pszName, QueryTypes wType, QueryOptions options, int aipServers, ref IntPtr ppQueryResults, int pReserved); [DllImport("dnsapi", CharSet = CharSet.Auto, SetLastError = true)] private static extern void DnsRecordListFree(IntPtr pRecordList, int FreeType); public static string[] GetTXTRecords(string domain) { IntPtr ptr1 = IntPtr.Zero; IntPtr ptr2 = IntPtr.Zero; TXTRecord recTxt; if (Environment.OSVersion.Platform != PlatformID.Win32NT) { throw new NotSupportedException(); } ArrayList list1 = new ArrayList(); UnicodeEncoding encoding = new UnicodeEncoding(); int num1 = DnsTxt.DnsQuery(ref domain, QueryTypes.DNS_TYPE_TEXT, QueryOptions.DNS_QUERY_BYPASS_CACHE, 0, ref ptr1, 0); if (num1 != 0) { throw new Win32Exception(num1); } for (ptr2 = ptr1; !ptr2.Equals(IntPtr.Zero); ptr2 = recTxt.pNext) { recTxt = (TXTRecord)Marshal.PtrToStructure(ptr2, typeof(TXTRecord)); if (recTxt.wType == 16) { IntPtr pointerToAddressStringArray = Marshal.AllocHGlobal(IntPtr.Size); IntPtr addressStringArray = Marshal.ReadIntPtr(pointerToAddressStringArray); for (int i = 0; i < recTxt.dwStringCount; i++) { IntPtr addressCharArray = Marshal.ReadIntPtr(recTxt.pStringArray, i * 4); int offset = 0; ArrayList bytesList = new ArrayList(); byte newByte = Marshal.ReadByte(addressCharArray, offset++); while (newByte != 0) { bytesList.Add(newByte); newByte = Marshal.ReadByte(addressCharArray, offset++); } byte[] bytesArray = new byte[offset]; bytesList.CopyTo(bytesArray); string textValue = encoding.GetString(bytesArray); list1.Add(textValue); } Marshal.FreeHGlobal(pointerToAddressStringArray); } } DnsTxt.DnsRecordListFree(ptr2, 0); return (string[])list1.ToArray(typeof(string)); } private enum QueryOptions { DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE = 1, DNS_QUERY_BYPASS_CACHE = 8, DNS_QUERY_DONT_RESET_TTL_VALUES = 0x100000, DNS_QUERY_NO_HOSTS_FILE = 0x40, DNS_QUERY_NO_LOCAL_NAME = 0x20, DNS_QUERY_NO_NETBT = 0x80, DNS_QUERY_NO_RECURSION = 4, DNS_QUERY_NO_WIRE_QUERY = 0x10, DNS_QUERY_RESERVED = -16777216, DNS_QUERY_RETURN_MESSAGE = 0x200, DNS_QUERY_STANDARD = 0, DNS_QUERY_TREAT_AS_FQDN = 0x1000, DNS_QUERY_USE_TCP_ONLY = 2, DNS_QUERY_WIRE_ONLY = 0x100 } private enum QueryTypes { DNS_TYPE_TEXT = 16 } [StructLayout(LayoutKind.Sequential)] private struct TXTRecord { public IntPtr pNext; public string pName; public short wType; public short wDataLength; public int flags; public int dwTtl; public int dwReserved; public int dwStringCount; public IntPtr pStringArray; } static void Main(string[] args) { try { string[] s = DnsUtils.DnsTxt.GetTXTRecords("google.com"); foreach (string st in s) { Console.WriteLine("Value: {0}", st); } } catch (Win32Exception e) { Console.WriteLine(e.Message); } Console.ReadLine(); } } }
When I run this code, it prints Value: ? . Now I hope this means that he actually executed the DNS query and got the results as expected, but I just screwed something into the part where he is trying to convert IntPtr to an array of strings (because I assume that it's harder to debug the first one). Anyway, are there any suggestions? Can anyone see where I made a mistake? Thanks in advance.