예제 #1
0
        public DnsDatagram(Stream s, NameServerAddress server = null, ProtocolType protocol = ProtocolType.Udp, double rtt = 0)
        {
            _server   = server;
            _protocol = protocol;
            _size     = s.Length;
            _rtt      = rtt;
            _header   = new DnsHeader(s);

            _question = new DnsQuestionRecord[_header.QDCOUNT];
            for (int i = 0; i < _header.QDCOUNT; i++)
            {
                _question[i] = new DnsQuestionRecord(s);
            }

            _answer = new DnsResourceRecord[_header.ANCOUNT];
            for (int i = 0; i < _header.ANCOUNT; i++)
            {
                _answer[i] = new DnsResourceRecord(s);
            }

            _authority = new DnsResourceRecord[_header.NSCOUNT];
            for (int i = 0; i < _header.NSCOUNT; i++)
            {
                _authority[i] = new DnsResourceRecord(s);
            }

            _additional = new DnsResourceRecord[_header.ARCOUNT];
            for (int i = 0; i < _header.ARCOUNT; i++)
            {
                _additional[i] = new DnsResourceRecord(s);
            }
        }
        public DnsDatagramMetadata(NameServerAddress server, DnsTransportProtocol protocol, int size, double rtt)
        {
            _server   = server;
            _protocol = protocol;
            _size     = size;
            _rtt      = rtt;

            if (_rtt < 0.1)
            {
                _rtt = 0.1;
            }
        }
예제 #3
0
        public DnsClient(IPAddress[] servers)
        {
            if (servers.Length == 0)
            {
                throw new DnsClientException("Atleast one name server must be available for DnsClient.");
            }

            _servers = new NameServerAddress[servers.Length];

            for (int i = 0; i < servers.Length; i++)
            {
                _servers[i] = new NameServerAddress(servers[i]);
            }
        }
예제 #4
0
        public DnsClient(bool preferIPv6 = false)
        {
            _preferIPv6 = preferIPv6;

            NetworkInfo defaultNetworkInfo;

            if (_preferIPv6)
            {
                defaultNetworkInfo = NetUtilities.GetDefaultIPv6NetworkInfo();

                if ((defaultNetworkInfo == null) || (defaultNetworkInfo.Interface.GetIPProperties().DnsAddresses.Count == 0))
                {
                    defaultNetworkInfo = NetUtilities.GetDefaultIPv4NetworkInfo();
                }
            }
            else
            {
                defaultNetworkInfo = NetUtilities.GetDefaultIPv4NetworkInfo();
            }

            if (defaultNetworkInfo == null)
            {
                throw new DnsClientException("No default network connection was found on this computer.");
            }

            IPAddressCollection servers = defaultNetworkInfo.Interface.GetIPProperties().DnsAddresses;

            if (servers.Count == 0)
            {
                throw new DnsClientException("Default network does not have any DNS server configured.");
            }

            _servers = new NameServerAddress[servers.Count];

            for (int i = 0; i < servers.Count; i++)
            {
                _servers[i] = new NameServerAddress(servers[i]);
            }
        }
예제 #5
0
        public static DnsDatagram ResolveViaNameServers(DnsQuestionRecord question, NameServerAddress[] nameServers = null, IDnsCache cache = null, NetProxy proxy = null, bool preferIPv6 = false, bool tcp = false, int retries = 2, int maxStackCount = 10)
        {
            if ((nameServers != null) && (nameServers.Length > 0))
            {
                //create copy of name servers array so that the values in original array are not messed due to shuffling feature
                NameServerAddress[] nameServersCopy = new NameServerAddress[nameServers.Length];
                Array.Copy(nameServers, nameServersCopy, nameServers.Length);
                nameServers = nameServersCopy;
            }

            Stack <ResolverData> resolverStack = new Stack <ResolverData>();
            int stackNameServerIndex           = 0;

            while (true) //stack loop
            {
                if (resolverStack.Count > maxStackCount)
                {
                    while (resolverStack.Count > 0)
                    {
                        ResolverData data = resolverStack.Pop();

                        question = data.Question;
                    }

                    throw new DnsClientException("DnsClient exceeded the maximum stack count to resolve the domain: " + question.Name);
                }

                if (cache != null)
                {
                    DnsDatagram request       = new DnsDatagram(new DnsHeader(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, 1, 0, 0, 0), new DnsQuestionRecord[] { question }, null, null, null);
                    DnsDatagram cacheResponse = cache.Query(request);

                    switch (cacheResponse.Header.RCODE)
                    {
                    case DnsResponseCode.NoError:
                        if (cacheResponse.Answer.Length > 0)
                        {
                            if (resolverStack.Count == 0)
                            {
                                return(cacheResponse);
                            }
                            else
                            {
                                ResolverData data = resolverStack.Pop();

                                question             = data.Question;
                                nameServers          = data.NameServers;
                                stackNameServerIndex = data.NameServerIndex;

                                switch (cacheResponse.Answer[0].Type)
                                {
                                case DnsResourceRecordType.AAAA:
                                    nameServers[stackNameServerIndex] = new NameServerAddress(nameServers[stackNameServerIndex].Domain, (cacheResponse.Answer[0].RDATA as DnsAAAARecord).Address);
                                    break;

                                case DnsResourceRecordType.A:
                                    nameServers[stackNameServerIndex] = new NameServerAddress(nameServers[stackNameServerIndex].Domain, (cacheResponse.Answer[0].RDATA as DnsARecord).Address);
                                    break;

                                default:
                                    //didnt find IP for current name server
                                    stackNameServerIndex++;         //increment to skip current name server
                                    break;
                                }

                                continue;     //stack loop
                            }
                        }

                        if (cacheResponse.Authority.Length > 0)
                        {
                            if (cacheResponse.Authority[0].Type == DnsResourceRecordType.SOA)
                            {
                                if (resolverStack.Count == 0)
                                {
                                    return(cacheResponse);
                                }
                                else
                                {
                                    if (question.Type == DnsResourceRecordType.AAAA)
                                    {
                                        question = new DnsQuestionRecord(question.Name, DnsResourceRecordType.A, question.Class);
                                    }
                                    else
                                    {
                                        //didnt find IP for current name server
                                        //pop and try next name server
                                        ResolverData data = resolverStack.Pop();

                                        question             = data.Question;
                                        nameServers          = data.NameServers;
                                        stackNameServerIndex = data.NameServerIndex + 1;     //increment to skip current name server
                                    }

                                    continue;     //to stack loop
                                }
                            }

                            if ((nameServers == null) || (nameServers.Length == 0))
                            {
                                NameServerAddress[] cacheNameServers = NameServerAddress.GetNameServersFromResponse(cacheResponse, preferIPv6, true);

                                if (cacheNameServers.Length > 0)
                                {
                                    nameServers = cacheNameServers;
                                }
                            }
                        }

                        break;

                    case DnsResponseCode.NameError:
                        if (resolverStack.Count == 0)
                        {
                            return(cacheResponse);
                        }
                        else
                        {
                            //current name server domain doesnt exists
                            //pop and try next name server
                            ResolverData data = resolverStack.Pop();

                            question             = data.Question;
                            nameServers          = data.NameServers;
                            stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server

                            continue;                                        //stack loop
                        }
                    }
                }

                if ((nameServers == null) || (nameServers.Length == 0))
                {
                    //create copy of root name servers array so that the values in original array are not messed due to shuffling feature
                    if (preferIPv6)
                    {
                        nameServers = new NameServerAddress[ROOT_NAME_SERVERS_IPv6.Length];
                        Array.Copy(ROOT_NAME_SERVERS_IPv6, nameServers, ROOT_NAME_SERVERS_IPv6.Length);
                    }
                    else
                    {
                        nameServers = new NameServerAddress[ROOT_NAME_SERVERS_IPv4.Length];
                        Array.Copy(ROOT_NAME_SERVERS_IPv4, nameServers, ROOT_NAME_SERVERS_IPv4.Length);
                    }
                }

                NameServerAddress.Shuffle(nameServers);

                int hopCount = 0;
                while ((hopCount++) < MAX_HOPS) //resolver loop
                {
                    //copy and reset stack name server index since its one time use only after stack pop
                    int i = stackNameServerIndex;
                    stackNameServerIndex = 0;

                    //query name servers one by one
                    for (; i < nameServers.Length; i++) //retry next server loop
                    {
                        NameServerAddress currentNameServer = nameServers[i];

                        if (question.Name == currentNameServer.Domain)
                        {
                            continue; //obvious!
                        }
                        if (currentNameServer.EndPoint == null)
                        {
                            resolverStack.Push(new ResolverData(question, nameServers, i));

                            if (preferIPv6)
                            {
                                question = new DnsQuestionRecord(currentNameServer.Domain, DnsResourceRecordType.AAAA, question.Class);
                            }
                            else
                            {
                                question = new DnsQuestionRecord(currentNameServer.Domain, DnsResourceRecordType.A, question.Class);
                            }

                            nameServers = null;
                            goto stackLoop;
                        }

                        DnsClient client = new DnsClient(currentNameServer);

                        client._proxy      = proxy;
                        client._preferIPv6 = preferIPv6;
                        client._tcp        = tcp;
                        client._retries    = retries;

                        DnsDatagram request = new DnsDatagram(new DnsHeader(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, 1, 0, 0, 0), new DnsQuestionRecord[] { question }, null, null, null);
                        DnsDatagram response;

                        try
                        {
                            response = client.Resolve(request);
                        }
                        catch (DnsClientException)
                        {
                            continue; //resolver loop
                        }

                        if (response.Header.Truncation)
                        {
                            if (tcp)
                            {
                                return(response);
                            }

                            client._tcp = true;
                            response    = client.Resolve(request);
                        }

                        if (cache != null)
                        {
                            cache.CacheResponse(response);
                        }

                        switch (response.Header.RCODE)
                        {
                        case DnsResponseCode.NoError:
                            if (response.Answer.Length > 0)
                            {
                                if (!response.Answer[0].Name.Equals(question.Name, StringComparison.CurrentCultureIgnoreCase))
                                {
                                    continue;     //continue to next name server since current name server may be misconfigured
                                }
                                if (resolverStack.Count == 0)
                                {
                                    return(response);
                                }
                                else
                                {
                                    ResolverData data = resolverStack.Pop();

                                    question             = data.Question;
                                    nameServers          = data.NameServers;
                                    stackNameServerIndex = data.NameServerIndex;

                                    switch (response.Answer[0].Type)
                                    {
                                    case DnsResourceRecordType.AAAA:
                                        nameServers[stackNameServerIndex] = new NameServerAddress(nameServers[stackNameServerIndex].Domain, (response.Answer[0].RDATA as DnsAAAARecord).Address);
                                        break;

                                    case DnsResourceRecordType.A:
                                        nameServers[stackNameServerIndex] = new NameServerAddress(nameServers[stackNameServerIndex].Domain, (response.Answer[0].RDATA as DnsARecord).Address);
                                        break;

                                    default:
                                        //didnt find IP for current name server
                                        stackNameServerIndex++;         //increment to skip current name server
                                        break;
                                    }

                                    goto resolverLoop;
                                }
                            }

                            if (response.Authority.Length == 0)
                            {
                                continue;     //continue to next name server since current name server may be misconfigured
                            }
                            if (response.Authority[0].Type == DnsResourceRecordType.SOA)
                            {
                                //no entry for given type
                                if (resolverStack.Count == 0)
                                {
                                    return(response);
                                }
                                else
                                {
                                    if (question.Type == DnsResourceRecordType.AAAA)
                                    {
                                        question = new DnsQuestionRecord(question.Name, DnsResourceRecordType.A, question.Class);
                                    }
                                    else
                                    {
                                        //didnt find IP for current name server
                                        //pop and try next name server
                                        ResolverData data = resolverStack.Pop();

                                        question             = data.Question;
                                        nameServers          = data.NameServers;
                                        stackNameServerIndex = data.NameServerIndex + 1;     //increment to skip current name server
                                    }

                                    goto stackLoop;     //goto stack loop
                                }
                            }

                            nameServers = NameServerAddress.GetNameServersFromResponse(response, preferIPv6, false);

                            if (nameServers.Length == 0)
                            {
                                continue;     //continue to next name server since current name server may be misconfigured
                            }
                            goto resolverLoop;

                        case DnsResponseCode.NameError:
                            if (resolverStack.Count == 0)
                            {
                                return(response);
                            }
                            else
                            {
                                //current name server domain doesnt exists
                                //pop and try next name server
                                ResolverData data = resolverStack.Pop();

                                question             = data.Question;
                                nameServers          = data.NameServers;
                                stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server

                                goto stackLoop;                                  //goto stack loop
                            }

                        default:
                            continue;     //continue to next name server since current name server may be misconfigured
                        }
                    }

                    if (resolverStack.Count == 0)
                    {
                        throw new DnsClientException("DnsClient failed to resolve the request: no response from name servers.");
                    }
                    else
                    {
                        //didnt find IP for current name server
                        //pop and try next name server
                        ResolverData data = resolverStack.Pop();

                        question             = data.Question;
                        nameServers          = data.NameServers;
                        stackNameServerIndex = data.NameServerIndex + 1; //increment to skip current name server

                        break;                                           //to stack loop
                    }

                    resolverLoop :;
                }

                stackLoop :;
            }
        }
예제 #6
0
 public DnsClient(NameServerAddress server)
 {
     _servers = new NameServerAddress[] { server };
 }