Exemple #1
0
        public void GetRecord_should_throw_InvalidOperationException_when_Record_reader_index_becomes_out_of_sync()
        {
            // Arrange.
            const string             query      = "www.msn.com";
            const string             queryRoot  = query + ".";
            const ResourceRecordType recordType = ResourceRecordType.A;
            const QueryClass         queryClass = QueryClass.IN; // IN
            const int timeToLive = 1000;
            const int rawDataLen = 10;
            IPAddress ipaddress  = IPAddress.Parse("10.1.1.100");

            IDnsString dnsString = new DnsString(query, queryRoot);

            BaseResourceRecordInfo info         = new BaseResourceRecordInfo(recordType, queryClass, timeToLive, rawDataLen, dnsString);
            ArraySegment <byte>    responseData = GetSampleData(ResponseDataSampleFile.QuestionAndAnswerQuery);

            mockReader.Setup(r => r.Index).Returns(100);
            mockReader.Setup(r => r.ReadIPAddress(responseData)).Returns(ipaddress);

            IDnsRecordFactory factory = new DnsRecordFactory(mockReader.Object);

            // Act.

            Assert.Throws <InvalidOperationException>(() => factory.GetRecord(info, responseData), "Record reader index out of sync.");
        }
Exemple #2
0
        /**
         * Gets the records from the cache that match the given domain, class
         * and type. For class and type, UNSUPPORTED are considered wildcards.
         */
        public HashSet <DNSRecord> Query(Domain domain, AddressClass cls, ResourceRecordType type)
        {
            var check_class = cls != AddressClass.UNSUPPORTED;
            var check_type  = type != ResourceRecordType.UNSUPPORTED;
            var output      = new HashSet <DNSRecord>();

            logger.Trace("Cache asked for domain {0}, class {1}, rtype {2}", domain, cls, type);

            // Avoid going over any records which are out of date
            CleanTTL();

            foreach (var record in complete_cache)
            {
                if (record.Name != domain ||
                    (check_class && record.AddressClass != cls) ||
                    (check_type && record.Resource.Type != type))
                {
                    continue;
                }

                output.Add(record);
            }

            logger.Trace("Found {0} records", output.Count);
            return(output);
        }
Exemple #3
0
        public void DnsRecordFactory_McnetValidateSupport()
        {
            var types  = (ResourceRecordType[])Enum.GetValues(typeof(ResourceRecordType));
            var result = _client.Query(s_question);

            var ignore = new ResourceRecordType[]
            {
#pragma warning disable CS0618 // Type or member is obsolete
                ResourceRecordType.MD,
                ResourceRecordType.MF,
#pragma warning restore CS0618 // Type or member is obsolete
                ResourceRecordType.RRSIG,
                ResourceRecordType.TLSA,
                ResourceRecordType.NSEC,
                ResourceRecordType.SPF,
                ResourceRecordType.DNSKEY,
                ResourceRecordType.DS
            };

            foreach (var t in types)
            {
                if (ignore.Contains(t))
                {
                    continue;
                }

                var numRecords = result.AllRecords.OfRecordType(t).Count();
                Assert.True(numRecords > 0, $"{t} should have records");
            }
        }
Exemple #4
0
        private String GenerateQuery(String name, String serverURI, ResourceRecordType queryType)
        {
            var fields = new Dictionary <String, String>()
            {
                { "name", name },
                { "type", ((Int32)queryType).ToString() },
                { "ct", JsonContentType },
                { "cd", RequireDNSSEC ? "false" : "true" },
            };

            if (RequestNoGeolocation)
            {
                fields.Add("edns_client_subnet", "0.0.0.0/0");
            }

            const Int32 padtoLength = 250;

            String uri = $"{serverURI}?{Join("&", fields.Select(f => f.Key + "=" + f.Value))}";

            if (uri.Length - 16 < padtoLength && UseRandomPadding)
            {
                uri += $"&random_padding={GeneratePadding(padtoLength-uri.Length-16)}";
            }
            return(uri);
        }
Exemple #5
0
        public static ResourceRecord CreateRecord(ResourceRecordType type)
        {
            switch (type)
            {
            case ResourceRecordType.A: return(new AResourceRecord());

            case ResourceRecordType.AAAA: return(new AaaaResourceRecord());

            case ResourceRecordType.NS: return(new NsResourceRecord());

            //case ResourceRecordType.MD: return ResourceRecordType.MD;
            //case ResourceRecordType.MF: return ResourceRecordType.MF;
            case ResourceRecordType.CNAME: return(new CNameResourceRecord());

            case ResourceRecordType.SOA: return(new SoaResourceRecord());

            //case ResourceRecordType.MB: return ResourceRecordType.MB;
            //case ResourceRecordType.MG: return ResourceRecordType.MG;
            //case ResourceRecordType.MR: return ResourceRecordType.MR;
            //case ResourceRecordType.NULL: return ResourceRecordType.NULL;
            //case ResourceRecordType.WKS: return ResourceRecordType.WKS;
            case ResourceRecordType.PTR: return(new PtrResourceRecord());

            case ResourceRecordType.SRV: return(new SrvResourceRecord());

            //case ResourceRecordType.HINFO: return ResourceRecordType.HINFO;
            case ResourceRecordType.MX: return(new MxResourceRecord());

            case ResourceRecordType.TXT: return(new TxtResourceRecord());

            default:
                throw new NotSupportedException($"unsupported resource record type {type}");
            }
        }
Exemple #6
0
        public void GetRecord_should_return_EmptyRecord_type_when_unknown_recordType_is_found()
        {
            // Arrange.
            const string             query      = "www.msn.com";
            const string             queryRoot  = query + ".";
            const ResourceRecordType recordType = ResourceRecordType.OPT; // possibly make it to default case in the switch statement.
            const QueryClass         queryClass = QueryClass.IN;          // IN
            const int timeToLive = 1000;
            const int rawDataLen = 10;
            IPAddress ipaddress  = IPAddress.Parse("10.1.1.100");

            IDnsString dnsString = new DnsString(query, queryRoot);

            BaseResourceRecordInfo info         = new BaseResourceRecordInfo(recordType, queryClass, timeToLive, rawDataLen, dnsString);
            ArraySegment <byte>    responseData = GetSampleData(ResponseDataSampleFile.QuestionAndAnswerQuery);

            mockReader.SetupSequence(r => r.Index).Returns(100).Returns(100 + rawDataLen);
            mockReader.Setup(r => r.ReadIPAddress(responseData)).Returns(ipaddress);

            IDnsRecordFactory factory = new DnsRecordFactory(mockReader.Object);

            // Act.
            DnsResourceRecord result = factory.GetRecord(info, responseData);

            // Assert.

            Assert.IsInstanceOf(typeof(EmptyRecord), result);
            EmptyRecord record = (EmptyRecord)result;
        }
Exemple #7
0
        public void DnsRecordFactory_McnetValidateSupport()
        {
            var types  = (ResourceRecordType[])Enum.GetValues(typeof(ResourceRecordType));
            var result = _client.ResolveQuery(_client.NameServers, new TestMessageHandler(), _nullRequestMessage, false);

            var ignore = new ResourceRecordType[]
            {
#pragma warning disable CS0618 // Type or member is obsolete
                ResourceRecordType.MD,
                ResourceRecordType.MF,
#pragma warning restore CS0618 // Type or member is obsolete
                ResourceRecordType.OPT,
                ResourceRecordType.RRSIG
            };

            foreach (var t in types)
            {
                if (ignore.Contains(t))
                {
                    continue;
                }

                var numRecords = result.AllRecords.OfRecordType(t).Count();
                Assert.True(numRecords > 0, $"{t} should have records");
            }
        }
 public ResourceRecordSetChange(ChangeAction action, ResourceRecordType type, string name, string value, int ttl)
 {
     Action            = action;
     ResourceRecordSet = new ResourceRecordSet(type, name, new ResourceRecord(value))
     {
         TTL = ttl
     };
 }
Exemple #9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ResourceRecordInfo" /> class.
 /// </summary>
 /// <param name="domainName">The <see cref="DnsString" /> used by the query.</param>
 /// <param name="recordType">Type of the record.</param>
 /// <param name="recordClass">The record class.</param>
 /// <param name="timeToLive">The time to live.</param>
 /// <param name="rawDataLength">Length of the raw data.</param>
 /// <exception cref="System.ArgumentNullException">If <paramref name="domainName" /> is null or empty.</exception>
 public ResourceRecordInfo(DnsString domainName, ResourceRecordType recordType, QueryClass recordClass, int timeToLive, int rawDataLength)
 {
     DomainName    = domainName ?? throw new ArgumentNullException(nameof(domainName));
     RecordType    = recordType;
     RecordClass   = recordClass;
     TimeToLive    = timeToLive;
     RawDataLength = rawDataLength;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ResourceRecordInfo" /> class.
 /// </summary>
 /// <param name="domainName">The <see cref="DnsString" /> used by the query.</param>
 /// <param name="recordType">Type of the record.</param>
 /// <param name="recordClass">The record class.</param>
 /// <param name="timeToLive">The time to live.</param>
 /// <param name="rawDataLength">Length of the raw data.</param>
 /// <exception cref="System.ArgumentNullException">If <paramref name="domainName" /> is null or empty.</exception>
 public ResourceRecordInfo(DnsString domainName, ResourceRecordType recordType, QueryClass recordClass, int timeToLive, int rawDataLength)
 {
     DomainName        = domainName ?? throw new ArgumentNullException(nameof(domainName));
     RecordType        = recordType;
     RecordClass       = recordClass;
     RawDataLength     = rawDataLength;
     InitialTimeToLive = timeToLive;
     _ticks            = (int)(Environment.TickCount / 1000d);
 }
Exemple #11
0
 public LookupCallbackMessagePayload(CallbackMessageBaseValues baseValues, string hostName, ResourceRecordType rrType,
                                     ushort rrClass, byte[] rrData, uint ttl) : base(baseValues)
 {
     HostName    = hostName ?? string.Empty;
     RecordType  = rrType;
     RecordClass = rrClass;
     RecordData  = rrData;
     TimeToLive  = ttl;
 }
 public DNSLookupRecordArgs(string domainName, int ttl, QueryClass queryClass, ResourceRecordType queryType, string result, IPEndPoint dnsServer)
 {
     DomainName = domainName;
     TTL        = ttl;
     Class      = queryClass;
     Type       = queryType;
     Result     = result;
     DNSServer  = dnsServer;
 }
Exemple #13
0
        public DNSQuestion(Domain name, ResourceRecordType type, AddressClass address_class)
        {
            Name         = name;
            QueryType    = type.Normalize();
            AddressClass = address_class.Normalize();

            raw_query_type    = type;
            raw_address_class = address_class;
        }
Exemple #14
0
 /// <summary>Initializes a new instance of BaseResourceRecordInfo class.</summary>
 /// <param name="domainName">The <see cref="DnsString" /> used by the query.</param>
 /// <param name="recordType">Type of the record.</param>
 /// <param name="recordClass">The record class.</param>
 /// <param name="timeToLive">The time to live.</param>
 /// <param name="rawDataLength">Length of the raw data.</param>
 public BaseResourceRecordInfo(ResourceRecordType recordType, QueryClass recordClass, int timeToLive, int rawDataLength, IDnsString domainName)
 {
     DomainName        = domainName;
     RecordType        = recordType;
     RecordClass       = recordClass;
     RawDataLength     = rawDataLength;
     InitialTimeToLive = timeToLive;
     ticks             = Environment.TickCount;
 }
Exemple #15
0
        public static ResourceRecord FromBinaryReader(BinaryReader reader)
        {
            // Hostname
            string hostname = BonjourUtility.ReadHostnameFromBytes(reader);

            // Record Type
            ResourceRecordType type = (ResourceRecordType)reader.ReadNetworkOrderUInt16();

            ResourceRecord record;

            switch (type)
            {
            case ResourceRecordType.A:
                record = new ARecord();
                break;

            case ResourceRecordType.PTR:
                record = new PTRRecord();
                break;

            case ResourceRecordType.SRV:
                record = new SRVRecord();
                break;

            case ResourceRecordType.TXT:
                record = new TXTRecord();
                break;

            default:
                record      = new ResourceRecord();
                record.Type = type;
                break;
            }

            record.Name = hostname;

            // Class and Cache Flush bit
            ushort rrclass = reader.ReadNetworkOrderUInt16();

            record.Class      = (rrclass & 0x7fff);
            record.CacheFlush = rrclass.GetBit(15);

            // TTL
            record.TimeToLive = TimeSpan.FromSeconds(reader.ReadNetworkOrderInt32());

            // Data
            ushort dataLength = reader.ReadNetworkOrderUInt16();

            record.SetDataFromReader(reader, dataLength);

            return(record);
        }
Exemple #16
0
        public ResourceRecordInfo(DnsString queryName, ResourceRecordType recordType, QueryClass recordClass, int ttl, int length)
        {
            if (queryName == null)
            {
                throw new ArgumentNullException(nameof(queryName));
            }

            DomainName    = queryName;
            RecordType    = recordType;
            RecordClass   = recordClass;
            TimeToLive    = ttl;
            RawDataLength = length;
        }
Exemple #17
0
        private async Task <IEnumerable <DNSAnswer> > SingleLookup(String name, ResourceRecordType recordType, String serverURI)
        {
            String uri = GenerateQuery(name, serverURI, recordType);

            HttpResponseMessage response = await _client.GetAsync(uri);

            if (!response.IsSuccessStatusCode)
            {
                throw new DNSLookupException($"Error contacting DNS server (HTTP {response.StatusCode} {response.ReasonPhrase})");
            }

            String content = await response.Content.ReadAsStringAsync();

            return(HandleJSONResponse(content, RequireDNSSEC));
        }
Exemple #18
0
        public static string FormatResourceRecordType(ResourceRecordType val)
        {
            switch (val)
            {
            case ResourceRecordType.A: return("A");

            case ResourceRecordType.AAAA: return("AAAA");

            case ResourceRecordType.NS: return("NS");

            case ResourceRecordType.MD: return("MD");

            case ResourceRecordType.MF: return("MF");

            case ResourceRecordType.CNAME: return("CNAME");

            case ResourceRecordType.SOA: return("SOA");

            case ResourceRecordType.MB: return("MB");

            case ResourceRecordType.MG: return("MG");

            case ResourceRecordType.MR: return("MR");

            case ResourceRecordType.NULL: return("NULL");

            case ResourceRecordType.WKS: return("WKS");

            case ResourceRecordType.PTR: return("PTR");

            case ResourceRecordType.SRV: return("SRV");

            case ResourceRecordType.HINFO: return("HINFO");

            case ResourceRecordType.MX: return("MX");

            case ResourceRecordType.TXT: return("TXT");

            case ResourceRecordType.CAA: return("CAA");

            case ResourceRecordType.TLSA: return("TLSA");

            case ResourceRecordType.SSHFP: return("SSHFP");

            default:
                throw new NotSupportedException($"unsupported resource record type {val}");
            }
        }
Exemple #19
0
        /**
         * Gets all records with the given domain and record type in the zone.
         */
        public IEnumerable <DNSRecord> Query(Domain domain, ResourceRecordType rtype, AddressClass addr_class)
        {
            var key = Tuple.Create(domain, rtype, addr_class);
            HashSet <DNSRecord> records;

            zone_records.TryGetValue(key, out records);

            if (records == null)
            {
                return(new HashSet <DNSRecord>());
            }
            else
            {
                return(records);
            }
        }
        /*
         * 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
         +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         |                                               |
         | /                                               /
         | /                      NAME                     /
         |                                               |
         +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         |                      TYPE                     |
         +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         |                     CLASS                     |
         +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         |                      TTL                      |
         |                                               |
         +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         |                   RDLENGTH                    |
         +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
         | /                     RDATA                     /
         | /                                               /
         +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
         */

        public BaseResourceRecordInfo ReadRecordInfo(ArraySegment <byte> data)
        {
            IDnsString         domainName = _reader.ReadQuestionQueryString(data);                      // domain name
            ResourceRecordType recordType = (ResourceRecordType)_reader.ReadUInt16NetworkOrder(data);   // record type
            QueryClass         queryClass = (QueryClass)_reader.ReadUInt16NetworkOrder(data);           // query class
            int timeToLive    = (int)_reader.ReadUInt32NetworkOrder(data);                              // ttl - 32bit!!
            int rawDataLength = _reader.ReadUInt16NetworkOrder(data);                                   // RDLength

            return(new BaseResourceRecordInfo(
                       recordType,    // record type
                       queryClass,    // query class
                       timeToLive,    // ttl - 32bit!!
                       rawDataLength, // RDLength
                       domainName     // domain name
                       ));
        }
Exemple #21
0
        public static ResourceRecordType Normalize(this ResourceRecordType resource)
        {
            switch (resource)
            {
            case ResourceRecordType.CANONICAL_NAME:
            case ResourceRecordType.HOST_ADDRESS:
            case ResourceRecordType.MAIL_EXCHANGE:
            case ResourceRecordType.NAME_SERVER:
            case ResourceRecordType.START_OF_AUTHORITY:
            case ResourceRecordType.POINTER:
            case ResourceRecordType.HOST_6ADDRESS:
                return(resource);

            default:
                return(ResourceRecordType.UNSUPPORTED);
            }
        }
        public void LookupCallbackMessageSerializationTest()
        {
            const string             hostName = "RPI.local";
            const ResourceRecordType rrType   = ResourceRecordType.A;
            const ushort             rrClass  = 1; // IN
            var        rrData = IPAddress.Parse("127.0.0.1").GetAddressBytes();
            const uint ttl    = 15;

            var sm = new LookupCallbackMessage(CallbackMessageTestHelper.BaseValues, hostName, rrType, rrClass, rrData, ttl);

            var dm = CallbackMessageTestHelper.SerializeDeserializeTest(sm);

            dm.Payload.HostName.Should().Be(hostName);
            dm.Payload.RecordType.Should().Be(rrType);
            dm.Payload.RecordClass.Should().Be(rrClass);
            dm.Payload.RecordData.Should().BeEquivalentTo(rrData);
            dm.Payload.TimeToLive.Should().Be(ttl);
        }
Exemple #23
0
        public async Task <IEnumerable <DNSAnswer> > LookupAsync(String name, ResourceRecordType recordType)
        {
            var queryParams = new DNSQueryParameters(name, recordType);

            if (_answersCache.ContainsKey(queryParams))
            {
                DNSCacheEntry hit = _answersCache[queryParams];
                if (hit.ExpireTime <= DateTime.Now)
                {
                    _answersCache.TryRemove(queryParams, out DNSCacheEntry entry);
                }
                else
                {
                    return(hit.Answers);
                }
            }

            var storedExceptions = new ConcurrentBag <DNSLookupException>();

            foreach (String endpoint in _endpointList)
            {
                try
                {
                    Task <IEnumerable <DNSAnswer> > lookupTask = SingleLookup(name, recordType, endpoint);
                    DNSAnswer[] answers = (await lookupTask).ToArray();
                    if (answers.Any() && !_answersCache.ContainsKey(queryParams))
                    {
                        _answersCache.TryAdd(queryParams, new DNSCacheEntry(answers));
                    }
                    return(answers);
                }
                catch (DNSLookupException ex)
                {
                    storedExceptions.Add(ex);
                }
            }
            throw new DNSLookupException("Unable to perform DNS lookup due to lookup errors", storedExceptions);
        }
Exemple #24
0
        /**
         * Tries to resolve a question against the cache, and possibly several
         * servers. Throws a ResolverException if both methods fail.
         */
        public DNSPacket QueryServers(Domain domain, ResourceRecordType record_kind, AddressClass addr_class, EndPoint[] servers)
        {
            var question = new DNSQuestion(domain, record_kind, addr_class);

            foreach (var server in servers)
            {
                try
                {
                    var response = send_query(server, question, true);
                    if (response.ResponseType == ResponseType.NO_ERROR)
                    {
                        logger.Trace("Accepting response {0} from {1}", response, server);
                        return(response);
                    }
                }
                catch (SocketException error)
                {
                    logger.Trace("Recoverable error: " + error);
                }
            }

            throw new ResolverException(question.Name, "Cannot resolve query " + question);
        }
Exemple #25
0
        public void GetRecord_should_return_RecordTypeA()
        {
            // Arrange.
            const string             query      = "www.msn.com";
            const string             queryRoot  = query + ".";
            const ResourceRecordType recordType = ResourceRecordType.A; // A - Host Address.
            const QueryClass         queryClass = QueryClass.IN;        // IN
            const int timeToLive = 1000;
            const int rawDataLen = 10;
            IPAddress ipaddress  = IPAddress.Parse("10.1.1.100");

            IDnsString dnsString = new DnsString(query, queryRoot);

            BaseResourceRecordInfo info         = new BaseResourceRecordInfo(recordType, queryClass, timeToLive, rawDataLen, dnsString);
            ArraySegment <byte>    responseData = GetSampleData(ResponseDataSampleFile.QuestionAndAnswerQuery);

            mockReader.SetupSequence(r => r.Index).Returns(100).Returns(100 + rawDataLen);
            mockReader.Setup(r => r.ReadIPAddress(responseData)).Returns(ipaddress);

            IDnsRecordFactory factory = new DnsRecordFactory(mockReader.Object);

            // Act.

            DnsResourceRecord result = factory.GetRecord(info, responseData);

            // Assert.

            Assert.IsInstanceOf(typeof(ARecord), result);
            ARecord record = (ARecord)result;

            Assert.AreEqual(queryRoot, record.DomainName.ToString());
            Assert.AreEqual(ipaddress.ToString(), record.Address.ToString());
            Assert.AreEqual(recordType, record.RecordType);
            Assert.AreEqual(queryClass, record.RecordClass);
            Assert.AreEqual(timeToLive, record.TimeToLive);
            Assert.AreEqual(rawDataLen, record.RawDataLength);
        }
Exemple #26
0
 public LookupCallbackMessage(CallbackMessageBaseValues baseValues, string hostName, ResourceRecordType rrType, ushort rrClass, byte[] rrData, uint ttl)
     : this(new ServiceMessageHeader(OperationCode.AddressInfoReply),
            new LookupCallbackMessagePayload(baseValues, hostName, rrType, rrClass, rrData, ttl))
 {
 }
Exemple #27
0
 public ResourceRecordInfo(string query, ResourceRecordType recordType, QueryClass recordClass, int ttl, int length)
     : this(DnsString.ParseQueryString(query), recordType, recordClass, ttl, length)
 {
 }
Exemple #28
0
        /**
         * Resolves the given query, returning a QueryResult that contains
         * everything we found while doing the resolution.
         */
        public QueryResult Execute(Domain domain, ResourceRecordType rtype, AddressClass addr_class, bool recursive)
        {
            logger.Trace("Executing query on {0} for type {1} with recursion {2}",
                         domain, rtype, recursive);

            if (zone.IsAuthorityFor(domain))
            {
                var records = zone.Query(domain, rtype, addr_class).ToList();

                // It is possible that there is a CNAME that we should be aware of - in that case, check
                // it and see if we can find one.
                if (records.Count == 0)
                {
                    var cname_records = zone.Query(domain, ResourceRecordType.CANONICAL_NAME, addr_class).ToArray();

                    if (cname_records.Length != 0)
                    {
                        logger.Trace("Authoritative for CNAMEs, re-executing");

                        // In this case, try again with the alias
                        var alias         = ((CNAMEResource)cname_records[0].Resource).Alias;
                        var alias_results = Execute(alias, rtype, addr_class, recursive);

                        // The RFC directs us to return any intermediate CNAMEs, which we do
                        alias_results.Answers.InsertRange(0, cname_records);

                        return(alias_results);
                    }
                }

                var result = new QueryResult();
                result.IsAuthority = true;
                result.FoundAnswer = true;
                result.Answers     = new List <DNSRecord>();
                result.Authority   = new List <DNSRecord>();
                result.Additional  = new List <DNSRecord>();

                result.Answers.AddRange(records);
                result.Authority.Add(zone.StartOfAuthority);
                return(result);
            }
            else
            {
                var owning_subzone = zone.FindSubZone(domain);
                if (owning_subzone != null)
                {
                    logger.Trace("Subzone {0} is authoritative", owning_subzone);

                    // We can punt on the computation to our subzone delgation
                    var subzone_nameservers             = zone.Query(owning_subzone, ResourceRecordType.NAME_SERVER, addr_class);
                    var subzone_nameserver_addr_records = subzone_nameservers
                                                          .SelectMany(ns => zone.Query(ns.Name, ResourceRecordType.HOST_ADDRESS, addr_class));
                    var subzone_nameserver_addrs = subzone_nameserver_addr_records.Select(
                        record => new IPEndPoint(((AResource)record.Resource).Address, 53)
                        ).ToArray();

                    IEnumerable <DNSRecord> response = null;
                    try
                    {
                        var info = resolver.Resolve(domain, ResourceRecordType.HOST_ADDRESS, addr_class, subzone_nameserver_addrs);
                        response = info.aliases.Concat(info.answers).ToList();
                    }
                    catch (ResolverException err)
                    {
                        logger.Trace("Could not resolve from subzone: {0}", err);
                        response = new DNSRecord[] { };
                    }

                    var result = new QueryResult();
                    result.IsAuthority = false;
                    result.FoundAnswer = response.Count() > 0;
                    result.Answers     = new List <DNSRecord>(response);
                    result.Authority   = new List <DNSRecord>(subzone_nameservers);
                    result.Additional  = new List <DNSRecord>(subzone_nameserver_addr_records);
                    return(result);
                }
                else if (recursive)
                {
                    // We'll have to go outside our zone and use the general-purpose resolver
                    ResolverResult response;
                    logger.Trace("No authoritative server is local, executing recursive resolver");

                    try
                    {
                        response = resolver.Resolve(domain, rtype, addr_class, zone.Relays);
                    }
                    catch (ResolverException err)
                    {
                        logger.Trace("Could not resolve: {0}", err);

                        response                     = new ResolverResult();
                        response.answers             = new List <DNSRecord>();
                        response.aliases             = new List <DNSRecord>();
                        response.referrals           = new List <DNSRecord>();
                        response.referral_additional = new List <DNSRecord>();
                    }

                    var result = new QueryResult();
                    result.IsAuthority = false;
                    result.FoundAnswer = response.answers.Count() > 0;
                    result.Answers     = response.aliases.Concat(response.answers).ToList();
                    result.Authority   = response.referrals.ToList();
                    result.Additional  = response.referral_additional.ToList();
                    return(result);
                }
                else
                {
                    var cached_responses = cache.Query(domain, AddressClass.INTERNET, rtype);
                    if (cached_responses.Count > 0)
                    {
                        logger.Trace("Non-recursive search found {0} cached results", cached_responses.Count);

                        var cached_result = new QueryResult();
                        cached_result.IsAuthority = false;
                        cached_result.FoundAnswer = true;
                        cached_result.Answers     = cached_responses.ToList();
                        cached_result.Additional  = new List <DNSRecord>();
                        cached_result.Authority   = new List <DNSRecord>();
                        return(cached_result);
                    }

                    // If we can't recurse, and our cache knows nothing, then punt onto the forwarder
                    logger.Trace("Executing limited-case non-recursive resolver");

                    var question = new DNSQuestion(domain, rtype, AddressClass.INTERNET);

                    foreach (var forwarder in zone.Relays)
                    {
                        try
                        {
                            var forward_result = ResolverUtils.SendQuery(forwarder, question, false);

                            // If the server doesn't like our request, then pass it to something else
                            if (forward_result.ResponseType != ResponseType.NO_ERROR &&
                                forward_result.ResponseType != ResponseType.NAME_ERROR)
                            {
                                continue;
                            }

                            var forward_return = new QueryResult();
                            forward_return.FoundAnswer = forward_result.ResponseType == ResponseType.NO_ERROR;
                            forward_return.IsAuthority = false;
                            forward_return.Answers     = forward_result.Answers.ToList();
                            forward_return.Additional  = forward_result.AdditionalRecords.ToList();
                            forward_return.Authority   = forward_result.AuthoritativeAnswers.ToList();
                            return(forward_return);
                        }
                        catch (SocketException err)
                        {
                            // We can safely punt onto the next forwarder if one bails
                            logger.Trace("Could not request from {0}: {1}", forwarder, err);
                        }
                    }

                    // We can't do anything else here, so there is no such host, as far as we knot
                    var result = new QueryResult();
                    result.FoundAnswer = false;
                    result.IsAuthority = false;
                    result.Answers     = new List <DNSRecord>();
                    result.Authority   = new List <DNSRecord>();
                    result.Additional  = new List <DNSRecord>();
                    return(result);
                }
            }
        }
Exemple #29
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ResourceRecordInfo" /> class.
 /// </summary>
 /// <param name="domainName">The domain name used by the query.</param>
 /// <param name="recordType">Type of the record.</param>
 /// <param name="recordClass">The record class.</param>
 /// <param name="timeToLive">The time to live.</param>
 /// <param name="rawDataLength">Length of the raw data.</param>
 /// <exception cref="ArgumentNullException">If <paramref name="domainName"/> is null.</exception>
 public ResourceRecordInfo(string domainName, ResourceRecordType recordType, QueryClass recordClass, int timeToLive, int rawDataLength)
     : this(DnsString.Parse(domainName), recordType, recordClass, timeToLive, rawDataLength)
 {
 }
Exemple #30
0
 /// <summary>
 /// Filters the elements of an <see cref="IEnumerable{T}"/> to return <see cref="DnsResourceRecord"/>s
 /// which have the <paramref name="type"/>.
 /// </summary>
 /// <param name="records">The records.</param>
 /// <param name="type">The <see cref="ResourceRecordType"/> to filter for.</param>
 /// <returns>The list of <see cref="ARecord"/>.</returns>
 public static IEnumerable <DnsResourceRecord> OfRecordType(this IEnumerable <DnsResourceRecord> records, ResourceRecordType type)
 {
     return(records.Where(p => p.RecordType == type));
 }