示例#1
0
        public async Task ResolveService_WithCnameRef()
        {
            var    ns          = new NameServer(IPAddress.Loopback, 8600);
            var    serviceName = "myservice";
            var    baseName    = "service.consul";
            var    fullQuery   = $"{serviceName}.{baseName}";
            ushort prio        = 99;
            ushort weight      = 69;
            ushort port        = 88;

            var response = new DnsResponseMessage(new DnsResponseHeader(1234, (int)DnsResponseCode.NoError, 0, 0, 0, 0), 0);

            response.AddAnswer(
                new SrvRecord(
                    new ResourceRecordInfo(fullQuery, ResourceRecordType.SRV, QueryClass.IN, 1000, 0),
                    prio,
                    weight,
                    port,
                    DnsString.Parse(serviceName)));

            var targetHost = DnsString.Parse("myservice.localhost.net");

            response.AddAdditional(
                new CNameRecord(
                    new ResourceRecordInfo(serviceName, ResourceRecordType.CNAME, QueryClass.IN, 1000, 0),
                    targetHost));

            var client = new LookupClient(ns);

            var mock = new Mock <IDnsQuery>();

            mock.Setup(p => p.QueryAsync(It.IsAny <string>(), It.IsAny <QueryType>(), It.IsAny <QueryClass>(), It.IsAny <CancellationToken>()))
            .Returns(() => Task.FromResult <IDnsQueryResponse>(response.AsQueryResponse(ns, client.Settings)));

            var mockClient = mock.Object;

            var result = await mockClient.ResolveServiceAsync(baseName, serviceName);

            Assert.Single(result);
            var first = result.First();

            Assert.Equal(targetHost.ToString(), first.HostName);
            Assert.Equal((int)port, first.Port);
            Assert.Equal((int)prio, first.Priority);
            Assert.Equal((int)weight, first.Weight);
        }
示例#2
0
        public void Cache_GetOrAdd()
        {
            var cache    = new ResponseCache(true);
            var record   = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 100, 100));
            var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0)
            {
                Audit = new LookupClientAudit()
            };

            response.AddAnswer(record);

            cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));
            var item = cache.Get("key", out double?effectiveTtl);

            Assert.Equal(item, response.AsQueryResponse(new NameServer(IPAddress.Any)));
            Assert.Equal(100 * 1000, effectiveTtl);
        }
示例#3
0
        public void Cache_DoesCacheWithMinimumDefined()
        {
            var minTtl   = 2000;
            var cache    = new ResponseCache(true, TimeSpan.FromMilliseconds(minTtl));
            var record   = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 0, 100));
            var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0);

            response.AddAnswer(record);

            cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any), null));

            var item = cache.Get("key", out double?effectiveTtl);

            Assert.NotNull(item);
            Assert.Equal(0, item.Answers.First().TimeToLive);
            Assert.Equal(minTtl, effectiveTtl);
        }
            public IDnsQueryResponse GetResponse()
            {
                var elapsed = Elapsed();

                if (elapsed <= 0)
                {
                    return(_response);
                }

                var response = new DnsResponseMessage(
                    _response.Header,
                    _response.MessageSize)
                {
                    Audit = (_response as DnsQueryResponse)?.Audit ?? new LookupClientAudit()
                };

                foreach (var record in _response.Questions)
                {
                    response.AddQuestion(record);
                }

                foreach (var record in _response.Answers)
                {
                    var clone = record.Clone();
                    clone.TimeToLive = clone.TimeToLive - elapsed;
                    response.AddAnswer(clone);
                }

                foreach (var record in _response.Additionals)
                {
                    var clone = record.Clone();
                    clone.TimeToLive = clone.TimeToLive - elapsed;
                    response.AddAnswer(clone);
                }

                foreach (var record in _response.Authorities)
                {
                    var clone = record.Clone();
                    clone.TimeToLive = clone.TimeToLive - elapsed;
                    response.AddAnswer(clone);
                }

                var qr = response.AsQueryResponse(_response.NameServer);

                return(qr);
            }
示例#5
0
        public void Cache_GetOrAddExists()
        {
            var cache    = new ResponseCache(true);
            var record   = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 100, 100));
            var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0);

            response.AddAnswer(record);

            var success = cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));

            Assert.True(success);

            response.AddAnswer(new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 100, 100)));
            var fail = cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));

            Assert.False(fail);
        }
示例#6
0
        public void Cache_SupportsInfinite()
        {
            var cache    = new ResponseCache(true, Timeout.InfiniteTimeSpan);
            var record   = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 0, 100));
            var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0)
            {
                Audit = new LookupClientAudit()
            };

            response.AddAnswer(record);

            cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));
            var item = cache.Get("key", out double?effectiveTtl);

            // should not be null although TTL is zero, mimimum timeout is set to infinite
            Assert.Equal(item, response.AsQueryResponse(new NameServer(IPAddress.Any)));
            Assert.Equal(int.MaxValue, effectiveTtl);
        }
示例#7
0
        public void Cache_DoesNotCacheIfDisabled()
        {
            var cache    = new ResponseCache(false);
            var record   = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 100, 100));
            var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0)
            {
                Audit = new LookupClientAudit()
            };

            response.AddAnswer(record);

            cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));
            var item = cache.Get("key", out double?effectiveTtl);

            // should be null because cache is disabled and we create null in the second call of GetOrAdd
            Assert.Null(item);
            Assert.Null(effectiveTtl);
        }
示例#8
0
        public void Cache_EntriesLowestTTLWins()
        {
            var cache    = new ResponseCache(true);
            var record   = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 1000, 100));
            var recordB  = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 100, 100));
            var recordC  = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 0, 100));
            var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0);

            response.AddAnswer(record);
            response.AddAdditional(recordB);
            response.AddAuthority(recordC);

            cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));
            var item = cache.Get("key");

            // should be null because recordC has zero TTL which wins
            Assert.Null(item);
        }
示例#9
0
        public void Cache_DoesNotCacheIfZeroTTL()
        {
            var cache    = new ResponseCache(true);
            var record   = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 0, 100));
            var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0)
            {
                Audit = new LookupClientAudit()
            };

            response.AddAnswer(record);

            cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));
            var item = cache.Get("key", out double?effectiveTtl);

            // should be null because ttl of the record is 0 which disables caching for this record
            Assert.Null(item);
            Assert.Null(effectiveTtl);
        }
示例#10
0
        public void Cache_RespectsMaximumTtl()
        {
            var maxTtl   = 2000;
            var cache    = new ResponseCache(true, maximumTimeout: TimeSpan.FromMilliseconds(maxTtl));
            var record   = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 60 * 60 * 24, 100));
            var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0);

            response.AddAnswer(record);

            cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any), null));

            var item = cache.Get("key", out double?effectiveTtl);

            Assert.NotNull(item);
            Assert.Equal(1, cache.Count);
            Assert.Equal(60 * 60 * 24, item.Answers.First().TimeToLive);
            Assert.Equal(maxTtl, effectiveTtl);
        }
示例#11
0
        public void Cache_GetOrAddExists()
        {
            var cache    = new ResponseCache();
            var record   = new EmptyRecord(new ResourceRecord(DnsString.Parse("a"), ARecord.ResourceRecordType, QueryClass.In, 100, 100));
            var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0)
            {
                Audit = new LookupClientAudit()
            };

            response.AddAnswer(record);

            var success = cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));

            Assert.True(success);

            response.AddAnswer(new EmptyRecord(new ResourceRecord(DnsString.Parse("a"), ARecord.ResourceRecordType, QueryClass.In, 100, 100)));
            var fail = cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));

            Assert.False(fail);
        }
示例#12
0
        private async void HandleRequest(byte[] data, IPEndPoint remote)
        {
            DnsRequestMessage request = null;

            try
            {
                request = DnsRequestMessage.FromArray(data);

                OnEvent(OnRequested, new RequestedEventArgs(request, data, remote));

                IResponse response = await _coder.Code(request);

                OnEvent(OnResponded, new RespondedEventArgs(request, response, data, remote));

                await _udp.SendAsync(response.ToArray(), response.Size, remote).WithCancellationTimeout(TimeSpan.FromMilliseconds(UDP_TIMEOUT));
            }
            catch (SocketException e) { OnError(e); }
            catch (ArgumentException e) { OnError(e); }
            catch (IndexOutOfRangeException e) { OnError(e); }
            catch (OperationCanceledException e) { OnError(e); }
            catch (IOException e) { OnError(e); }
            catch (ObjectDisposedException e) { OnError(e); }
            catch (Model.ResponseException e)
            {
                IResponse response = e.Response;

                if (response == null)
                {
                    response = DnsResponseMessage.FromRequest(request);
                }

                try
                {
                    await _udp.SendAsync(response.ToArray(), response.Size, remote).WithCancellationTimeout(TimeSpan.FromMilliseconds(UDP_TIMEOUT));
                }
                catch (SocketException) { }
                catch (OperationCanceledException) { }
                finally { OnError(e); }
            }
        }
示例#13
0
        private async void HandleRequest(string sessionID, byte[] data)
        {
            DnsRequestMessage request = null;

            try
            {
                request = DnsRequestMessage.FromArray(data);

                OnEvent(OnRequested, new RequestedEventArgs(request, data));

                IResponse response = await _coder.Code(request);

                OnEvent(OnResponded, new RespondedEventArgs(request, response, data));

                _udpServer.SendAsync(sessionID, response.ToArray());
            }
            catch (SocketException e) { OnError(e); }
            catch (ArgumentException e) { OnError(e); }
            catch (IndexOutOfRangeException e) { OnError(e); }
            catch (OperationCanceledException e) { OnError(e); }
            catch (IOException e) { OnError(e); }
            catch (ObjectDisposedException e) { OnError(e); }
            catch (ResponseException e)
            {
                IResponse response = e.Response;

                if (response == null)
                {
                    response = DnsResponseMessage.FromRequest(request);
                }

                try
                {
                    _udpServer.SendAsync(sessionID, response.ToArray());
                }
                catch (SocketException) { }
                catch (OperationCanceledException) { }
                finally { OnError(e); }
            }
        }
示例#14
0
        public void Cache_EntriesLowestTTLWins()
        {
            var cache    = new ResponseCache();
            var record   = new EmptyRecord(new ResourceRecord(DnsString.Parse("a"), ARecord.ResourceRecordType, QueryClass.In, 1000, 100));
            var recordB  = new EmptyRecord(new ResourceRecord(DnsString.Parse("a"), ARecord.ResourceRecordType, QueryClass.In, 100, 100));
            var recordC  = new EmptyRecord(new ResourceRecord(DnsString.Parse("a"), ARecord.ResourceRecordType, QueryClass.In, 0, 100));
            var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0)
            {
                Audit = new LookupClientAudit()
            };

            response.AddAnswer(record);
            response.AddAdditional(recordB);
            response.AddAuthority(recordC);

            cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));
            var item = cache.Get("key", out var effectiveTtl);

            // should be null because recordC has zero TTL which wins
            Assert.Null(item);
            Assert.Null(effectiveTtl);
        }
        public void Resolve_overload_with_IPEndpoint_and_DnsRequetMessage_should_throw_DnsResponseException_when_header_ids_dont_match()
        {
            // Arrange.
            const string domainNameToResolve     = "www.A-Dummy-Domain.com";
            string       domainNameToResolveRoot = domainNameToResolve + ".";
            const ushort headerId = 123; // because we are *only* setting this up in the request header, it should not match with the response header.

            DnsRequestHeader  header            = new DnsRequestHeader(headerId, true, DnsOpCode.Query);
            DnsQuestion       question          = new DnsQuestion(mockDnsString.Object, QueryType.A, QueryClass.IN);
            DnsRequestMessage dnsRequestMessage = new DnsRequestMessage(header, question);
            IPEndPoint        dnsServerIP       = new IPEndPoint(IPAddress.Parse("10.0.0.10"), dnsPort53);

            mockDnsString.Setup(m => m.Value).Returns(domainNameToResolveRoot);
            DnsResponseMessage responseMessage = GetDnsResponseMessage();

            mockMessageProcessor.Setup(m => m.ProcessResponse(It.IsAny <ArraySegment <byte> >())).Returns(responseMessage);
            IDnsResolver resolver = new DnsResolver(mockCommunicator.Object, mockMessageProcessor.Object);

            // Act => Act.

            Assert.Throws <DnsResponseException>(() => resolver.Resolve(dnsServerIP, dnsRequestMessage), "Header id mismatch.");
        }
示例#16
0
        public async Task Cache_EntriesLowestTT_Expires()
        {
            var cache    = new ResponseCache(true);
            var record   = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 1000, 100));
            var recordB  = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 100, 100));
            var recordC  = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 1, 100));
            var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0);

            response.AddAnswer(record);
            response.AddAdditional(recordB);
            response.AddAuthority(recordC);

            cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));
            var item = cache.Get("key");

            Assert.NotNull(item);

            await Task.Delay(1100);

            var item3 = cache.Get("key");

            Assert.Null(item3);
        }
示例#17
0
        public async Task Cache_DoesCacheWithMinimumDefined()
        {
            var minTtl   = 2000;
            var cache    = new ResponseCache(true, TimeSpan.FromMilliseconds(minTtl));
            var record   = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 1, 100));
            var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0)
            {
                Audit = new LookupClientAudit()
            };

            response.AddAnswer(record);

            cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));

            await Task.Delay(1200);

            var item = cache.Get("key", out double?effectiveTtl);

            // should not be null although TTL is zero, mimimum timeout is set to 2000ms
            // TTL of the record should be zero because the initial TTL is 100
            Assert.Equal(0, item.Answers.First().TimeToLive);
            Assert.Equal(minTtl, effectiveTtl);
        }
示例#18
0
        public static DnsClientResponse FromArray(IRequest request, byte[] message)
        {
            DnsResponseMessage response = DnsResponseMessage.FromArray(message);

            return(new DnsClientResponse(request, response, message));
        }
示例#19
0
        public void ProcessResponse_should_return_DnsResponseMessage_object_with_2_answers_1_question_only_successfully()
        {
            // Arrange.
            const string domainNameToResolve     = "www.microsoft.com";
            const string domainNameToResolveRoot = domainNameToResolve + ".";
            const string ipAddress  = "10.1.1.100";
            const string ipAddress1 = "101.0.0.101";
            const ushort headerId   = 1001;
            IDnsString   dnsString  = new DnsString(domainNameToResolve, domainNameToResolveRoot);

            ArraySegment <byte> responseData = GetSampleData(ResponseDataSampleFile.QuestionAndAnswerQuery);

            mockReader.SetupSequence(m => m.ReadUInt16NetworkOrder(responseData))
            .Returns(headerId) // id
            .Returns(33152)    // flags
            .Returns(1)        // questionCount
            .Returns(2)        // answerCount
            .Returns(0)        // nameServerCount - setting it to zero for this unit test
            .Returns(0)        // additionCount
            .Returns(1)        // QueryType
            .Returns(1)        // QueryClass

            // BaseResourceRecordInfo - answer 1
            .Returns(1)     // record type
            .Returns(1)     // query class
            .Returns(4)     // RDLength

            // BaseResourceRecordInfo - answer 2
            .Returns(1)                                                                // record type
            .Returns(1)                                                                //query class
            .Returns(4);                                                               //// RDLength

            mockReader.Setup(m => m.ReadUInt32NetworkOrder(responseData)).Returns(12); // ttl - 32bit!!

            // question
            mockReader.SetupSequence(m => m.ReadQuestionQueryString(responseData))
            .Returns(dnsString)                    // question
            .Returns(dnsString)                    // ReadRecordInfo for answer 1
            .Returns(dnsString);                   // ReadRecordInfo for answer 2
            mockReader.SetupSequence(m => m.ReadIPAddress(responseData))
            .Returns(IPAddress.Parse(ipAddress))   // answer 1
            .Returns(IPAddress.Parse(ipAddress1)); // answer 2

            mockReader.SetupSequence(m => m.Index)
            .Returns(8).Returns(12)     // answer 1
            .Returns(8).Returns(12);    // answer 2

            INetworkMessageProcessor messageProcessor = new DnsQueryMessageProcessor(mockReader.Object, mockDnsString.Object);

            // Act.
            DnsResponseMessage response = messageProcessor.ProcessResponse(responseData);

            // Assert.

            Assert.AreEqual(2, response.Answers.Count);
            Assert.AreEqual(1, response.Questions.Count);

            Assert.AreEqual(0, response.Additionals.Count);
            Assert.AreEqual(0, response.Authorities.Count);

            Assert.AreEqual(headerId, response.Header.Identifier);
            Assert.IsInstanceOf <ARecord>(response.Answers[0]); // first answer record.
            Assert.IsInstanceOf <ARecord>(response.Answers[1]); // second answer record.

            // second Answer check
            ARecord arecord = response.Answers[1] as ARecord;

            Assert.AreEqual(domainNameToResolveRoot, response.Answers[1].DomainName.Value);
            Assert.AreEqual(ipAddress1, arecord.Address.ToString());

            // question check
            Assert.AreEqual(QueryClass.IN, response.Questions[0].QuestionClass);
            Assert.AreEqual(QueryType.A, response.Questions[0].QuestionType);
            Assert.AreEqual(domainNameToResolveRoot, response.Questions[0].QueryName.Value);
        }