public void DnsRecordFactory_ResolveARecord() { var header = new DnsResponseHeader(42, 256, 0, 1, 0, 0); var responseMessage = new DnsResponseMessage(header, 0); var info = new ResourceRecordInfo("query", ResourceRecordType.A, QueryClass.IN, 100, 4); var ip = IPAddress.Parse("123.45.67.9"); var answer = new ARecord(info, ip); responseMessage.AddAnswer(answer); var response = responseMessage.AsQueryResponse(new NameServer(ip)); var answerBytes = ip.GetAddressBytes(); var raw = GetResponseBytes(response, answerBytes); var handle = new DnsUdpMessageHandler(true); var result = handle.GetResponseMessage(new System.ArraySegment <byte>(raw)).AsQueryResponse(new NameServer(ip)); Assert.Equal(result.Answers.Count, 1); var resultAnswer = result.Answers.OfType <ARecord>().First(); Assert.Equal(resultAnswer.Address.ToString(), ip.ToString()); Assert.Equal(resultAnswer.DomainName.Value, "query."); Assert.Equal(resultAnswer.RawDataLength, 4); Assert.Equal(resultAnswer.RecordClass, QueryClass.IN); Assert.Equal(resultAnswer.RecordType, ResourceRecordType.A); Assert.True(resultAnswer.TimeToLive == 100); Assert.True(result.Header.Id == 42); Assert.True(result.Header.AnswerCount == 1); }
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), null)); await Task.Delay(200); var item = cache.Get("key", out double?effectiveTtl); Assert.NotNull(item); Assert.Equal(1 * 1000, effectiveTtl); await Task.Delay(1100); var item3 = cache.Get("key", out double?effectiveTtl2); Assert.Null(item3); }
public async Task Cache_EntriesLowestTT_Expires() { 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, 1, 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))); await Task.Delay(200); var item = cache.Get("key", out var effectiveTtl); Assert.NotNull(item); Assert.Equal(1 * 1000, effectiveTtl); await Task.Delay(1100); var item3 = cache.Get("key", out _); Assert.Null(item3); }
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); }
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); }
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); }
/// <summary> Constructs the response object based upon the data received from the DNS server. </summary> /// <param name="responseData">The data (byte[]) from the DNS server.</param> /// <returns>Response message object.</returns> public DnsResponseMessage ProcessResponse(ArraySegment <byte> responseData) { IDnsRecordFactory factory = new DnsRecordFactory(reader); /* * From index 0 till 11 bytes in the responseData array, we have the header items. */ ushort id = reader.ReadUInt16NetworkOrder(responseData); ushort flags = reader.ReadUInt16NetworkOrder(responseData); ushort questionCount = reader.ReadUInt16NetworkOrder(responseData); ushort answerCount = reader.ReadUInt16NetworkOrder(responseData); ushort nameServerCount = reader.ReadUInt16NetworkOrder(responseData); ushort additionalCount = reader.ReadUInt16NetworkOrder(responseData); /* * We have got above data, now build the response header. */ DnsResponseHeader header = new DnsResponseHeader(id, flags, questionCount, answerCount, additionalCount, nameServerCount); DnsResponseMessage response = new DnsResponseMessage(header, responseData.Count); /* * Next item in the response data is question that we sent to the DNS server which the server has copied onto the response message. */ for (int questionIndex = 0; questionIndex < questionCount; questionIndex++) { IDnsString questionString = reader.ReadQuestionQueryString(responseData); DnsQuestion question = new DnsQuestion(questionString, (QueryType)reader.ReadUInt16NetworkOrder(responseData), (QueryClass)reader.ReadUInt16NetworkOrder(responseData)); response.AddQuestion(question); } for (int answerIndex = 0; answerIndex < answerCount; answerIndex++) { BaseResourceRecordInfo info = factory.ReadRecordInfo(responseData); DnsResourceRecord record = factory.GetRecord(info, responseData); response.AddAnswer(record); } for (int serverIndex = 0; serverIndex < nameServerCount; serverIndex++) { BaseResourceRecordInfo info = factory.ReadRecordInfo(responseData); DnsResourceRecord record = factory.GetRecord(info, responseData); response.AddAuthority(record); } for (int additionalIndex = 0; additionalIndex < additionalCount; additionalIndex++) { BaseResourceRecordInfo info = factory.ReadRecordInfo(responseData); DnsResourceRecord record = factory.GetRecord(info, responseData); response.AddAdditional(record); } return(response); }
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); response.AddAnswer(record); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key"); Assert.Equal(item, response.AsQueryResponse(new NameServer(IPAddress.Any))); }
public void Cache_DoesCacheWithMinimumDefined() { var cache = new ResponseCache(true, TimeSpan.FromMilliseconds(100)); 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))); var item = cache.Get("key"); // should not be null although TTL is zero, mimimum timeout is set to 100ms Assert.Equal(item, response.AsQueryResponse(new NameServer(IPAddress.Any))); }
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); response.AddAnswer(record); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key"); // should be null because ttl of the record is 0 which disables caching for this record Assert.Null(item); }
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); response.AddAnswer(record); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key"); // should be null because cache is disabled and we create null in the second call of GetOrAdd Assert.Null(item); }
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); response.AddAnswer(record); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any), null)); var item = cache.Get("key", out double?effectiveTtl); // should not be null although TTL is zero, minimum timeout is set to infinite Assert.Equal(item, response.AsQueryResponse(new NameServer(IPAddress.Any), null)); Assert.Equal(int.MaxValue, effectiveTtl); }
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); }
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 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); }
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); }
public void Cache_DoesNotCacheIfZeroTTLWithZeroMinTtl() { var cache = new ResponseCache(true, TimeSpan.Zero); 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); }
public void Cache_SupportsInfinite() { var cache = new ResponseCache(true, Timeout.InfiniteTimeSpan); var record = 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); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key", out var 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); }
public void Cache_DoesNotCacheIfZeroTTL() { var cache = new ResponseCache(); var record = 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); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key", out var effectiveTtl); // should be null because ttl of the record is 0 which disables caching for this record Assert.Null(item); Assert.Null(effectiveTtl); }
public void Cache_DoesNotCacheIfDisabled() { var cache = new ResponseCache(false); 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); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key", out var effectiveTtl); // should be null because cache is disabled and we create null in the second call of GetOrAdd Assert.Null(item); Assert.Null(effectiveTtl); }
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); }
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 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); }