10

I can't find any proper description in the documentation for what this actually does.

Does it check for the existence of A records or CNAME records or both?

My understanding is that in .NET 4, this throws a SocketException if the host does not exist, and this is confirmed by my testing.

Greg Tarr
  • 496
  • 3
  • 5
  • 19

3 Answers3

11

Dns.GetHostEntry is built on top of the Windows API and does not use the DNS protocol directly. If IPv6 is enabled it will call getaddrinfo. Otherwise it will call gethostbyaddr. These functions may use the local %SystemRoot%\System32\drivers\etc\hosts file, DNS or even NETBIOS to resolve a host name to an IP address. Resolving a host name to an IP address using DNS will use CNAME records to find the A record.

You can test this by resolving www.google.com that at least right now has a CNAME record that points to www.l.google.com. Using Dns.GetHostEntry will return the IP addresses from the A records for www.l.google.com.

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
  • Right, so you're saying it uses both CNAME and A records in that it follows the CNAME records to find the A records. And the failure to find any A records would throw the SocketException? – Greg Tarr Jun 06 '12 at 09:01
  • 1
    I'm not sure about the CNAME part. After all only subdomains use CNAMEs to map to fully qualified domains (ftp.domain.com CNAME domain.com). However domain.com itself must have an A record so how would that work with Dns.GetHostEntry("domain.com")? I just tested the GetHostEntry() with two of my subdomains, each has an A record pointing to a different server and GetHostEntry returned those Ip's and if I change those A records I am sure it will change the results of GetHostEntry(). Google.com is the busiest site in the world so I don't think that makes a good benchmark for consistencies sake. – Despertar Jun 06 '12 at 09:35
  • @GregT: Doing a small test is probably the best way to answer your question. I'm not sure how `getaddrinfo` behaves if there is a CNAME record that doesn't point to an A record. However, the source code for `Dns.GetHostEntry` is publicly available and as far I can see a socket error will be wrapped in a `SocketException`. – Martin Liversage Jun 06 '12 at 09:38
  • Thanks all, when you say "source code publicly available" you mean the gethostbyaddr source? Also anyone know which dns server GetHostEntry uses? – Greg Tarr Jun 06 '12 at 09:44
  • @GregT: It is the source code for `Dns.GetHostEntry` (the BCL source) that is publicly available. And this function calls the Windows API so the "dns server used" by `GetHostEntry` is defined by Windows. First it looks in the `hosts` file. Then it uses the DNS configured for the IP stack. It may then use NETBIOS name resolution. – Martin Liversage Jun 06 '12 at 09:51
  • I had also read it used the DNS from the IP stack. But I get two IP addresses as "DNS Servers" from ipconfig /all, and using these in DNSStuff with either google.com or microsoft.com times out, yet I get a reply from Dns.GetHostEntry. I can't explain this behaviour. – Greg Tarr Jun 06 '12 at 10:13
  • @GregT: You normally configure more than one DNS server to allow for uninterrupted service if one is down, but only one DNS server is queried. If you are in a Windows network you will use local DNS servers that interact with AD. These servers will be internal to your network and not visible on the internet or to services like DNSStuff but if you query these servers for domain names like www.google.com they will forward the query to the internet which explains your observations. It seems that your question is more about the DNS infrastructure than about `Dns.GetHostEntry`. – Martin Liversage Jun 06 '12 at 10:42
  • Thanks, think I understand now. The question was about Dns.GetHostEntry and whether it looks at A records or CNAME records, and I think we have established that it does. – Greg Tarr Jun 06 '12 at 10:51
10

This is the list of addresses returned by

var ips = System.Net.Dns.GetHostEntry("microsoft.com").AddressList;
foreach (var ip in ips)
    Console.WriteLine(ip);

// output
64.4.11.37
65.55.58.201

And these are the A records pulled from network-tools.com, DNS query.

Answer records
microsoft.com       A   64.4.11.37  
microsoft.com       A   65.55.58.201

So I'd say it does pull A records.

Despertar
  • 21,627
  • 11
  • 81
  • 79
  • Here is the open-source, C# library I use for DNS queries, http://www.codeproject.com/Articles/12072/C-NET-DNS-query-component which I found from this question, http://stackoverflow.com/questions/1061248/getting-ns-record-type-using-c-sharp-dns/1061268#comment12106649_1061268 – Despertar Jun 06 '12 at 08:49
3

To be explicitly clear here, Martin Liversage's answer is the most correct answer. The api will first attempt to locate CNAME records for the domain being resolved. If a CNAME record is found the api will then attempt to resolve the A records of the domain returned from the CNAME record. If there are no CNAME records for the domain being resolved then it will attempt to resolve A records for the domain itself.

To detect when a CNAME record exists the resolved hostname can be checked against the input hostname. Example:

IPHostEntry iphostEntry = Dns.GetHostEntry(inputHostname);
if (iphostEntry.Hostname != inputHostname) {
    Console.WriteLine("CNAME record exists pointing {0} to {1}", inputHostname, iphostEntry.Hostname);
    Console.WriteLine("iphostEntry.AddressList values are the A record values of {0}", iphostEntry.Hostname);
} else {
    Console.WriteLine("CNAME record does NOT exist for {0}", inputHostname);
    Console.WriteLine("iphostEntry.AddressList values are the A record values of {0}", inputHostname);
}
Stephen Eckels
  • 435
  • 6
  • 17