12

While working on a program I recently found that hostnames in .net (or at least in the ping class) are not supposed to have more than 126 characters. The ping class throws an exception if a hostname is longer.

However Wikipedia states that up to 255 characters are allowed. And it looks that indeed there are machines with a hostname longer than 126 chars out there, so the question is: can this limit be changed, who is right and how to resolve names if it cannot?

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
FinalNotriX
  • 385
  • 2
  • 13
  • 12
    Gotta love "specs". From [RFC 1123](http://www.ietf.org/rfc/rfc1123.txt), "Host software MUST handle host names of up to 63 characters and SHOULD handle host names of up to 255 characters." – Joel Spolsky Oct 30 '11 at 22:03
  • 4
    Wikpedia is not the definitive repository of specifications. – John Saunders Oct 30 '11 at 22:05
  • @John True. However there are machines that use it (my example is from google) and it works in the command line and also in my 3 installed browsers. So it should also work in .net – FinalNotriX Oct 30 '11 at 22:07
  • I have no idea what you mean. There are machines that use what? Wikipedia? – John Saunders Oct 30 '11 at 22:10
  • @FinalNotriX it would be *nice* if it did, I agree - but it does at least meet the formal spec demands – Marc Gravell Oct 30 '11 at 22:11
  • @John Hostnames longer than 126 chars. – FinalNotriX Oct 30 '11 at 22:13
  • Thanks for clarifying - I'll do the same. Don't ever again use Wikipedia as the source of truth about formal specifications. In every case, a formal specification will be published _formally_, and that will be the _only_ definition of the specification. Note how Wikipedia was telling you the truth, and yet gave you the wrong answer. – John Saunders Oct 30 '11 at 22:16
  • @MarcGravell: In this case I believe the "MUST" sets the minimum value for resource-constrained microcontrollers. .NET Framework isn't resource-constrained, and has no excuse for not meeting the "SHOULD" specification. – Ben Voigt Oct 30 '11 at 23:15
  • 1
    Note that while this still occurs on .NET2 with the current SP, it does not repro on the current v4 .NET Framework. Look at the InternalGetHostByName method to see their fix. – EricLaw May 08 '13 at 22:02

4 Answers4

9

The .NET Dns class has a hard upper limit of 126 characters for hostnames (checked for .NET4).

However, you can use the lower-level Win32 DnsQuery method using P/Invoke to translate host names into IP addresses and then use those raw addresses with the .NET networking classes.

Here is a sample DnsAddr class using this approach:

public static class DnsAddr
{
    [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 IEnumerable<IPAddress> GetAddress(string domain)
    {
        IntPtr ptr1 = IntPtr.Zero;
        IntPtr ptr2 = IntPtr.Zero;
        List<IPAddress> list = new List<IPAddress>();
        DnsRecord record = new DnsRecord();
        int num1 = DnsAddr.DnsQuery(ref domain, QueryTypes.DNS_TYPE_A, QueryOptions.DNS_QUERY_NONE, 0, ref ptr1, 0);
        if (num1 != 0)
            throw new Win32Exception(num1);
        for (ptr2 = ptr1; !ptr2.Equals(IntPtr.Zero); ptr2 = record.pNext)
        {
            record = (DnsRecord)Marshal.PtrToStructure(ptr2, typeof(DnsRecord));
            list.Add(new IPAddress(record.ipAddress));
        }
        DnsAddr.DnsRecordListFree(ptr1, 0);
        return list;
    }

    private enum QueryOptions
    {     
        DNS_QUERY_NONE = 0,
    }

    private enum QueryTypes
    {
        DNS_TYPE_A = 1,
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct DnsRecord
    {
        public IntPtr pNext;
        public string pName;
        public short wType;
        public short wDataLength;
        public int flags;
        public int dwTtl;
        public int dwReserved;
        public uint ipAddress;
    }
}

Here is a sample test program:

class Program
{
    static void Main(string[] args)
    {
        var addresses = DnsAddr.GetAddress("google.com");
        foreach (var address in addresses)
            Console.WriteLine(address.ToString());
    }
}

which on my machine produces this output:

173.194.33.51
173.194.33.50
173.194.33.49
173.194.33.52
173.194.33.48
Rick Sladkey
  • 33,988
  • 6
  • 71
  • 95
  • Great answer, thanks for sharing. Note that this example only looks for DNS_TYPE_A records and not DNS_TYPE_AAAA (0x1c), so it will return only IPv4 addresses and no IPv6 addresses. – EricLaw May 08 '13 at 16:21
2

Call gethostbyname, then pass an IP address (which is never more than a couple dozen characters, even for IPv6) to the ping class.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
1

Both informations are right.

The 255 character limit refers to the entire hostname (e.g. some.thing.example.com).

In turn, each label (e.g. example or com) is limited to 63 characters. So top-level domains have a theoretical limit of 126 non-dot characters.

Dennis
  • 14,264
  • 2
  • 48
  • 57
1

Apparently it is like Joel and Dennis explained. .Net is not capable of resolving names longer than 126 chars.

However if somebody has the same problem, take a look here at DNS Plus: http://www.simpledns.com/dns-client-lib.aspx#download

FinalNotriX
  • 385
  • 2
  • 13