diff --git a/DnsServerCore/Dns/DnsServer.cs b/DnsServerCore/Dns/DnsServer.cs index 534a74bf..67c977e1 100644 --- a/DnsServerCore/Dns/DnsServer.cs +++ b/DnsServerCore/Dns/DnsServer.cs @@ -82,6 +82,8 @@ namespace DnsServerCore.Dns readonly BlockListZoneManager _blockListZoneManager; readonly CacheZoneManager _cacheZoneManager = new CacheZoneManager(); + readonly ResolverDnsCache _dnsCache; + readonly DnsARecord _aRecord = new DnsARecord(IPAddress.Any); readonly DnsAAAARecord _aaaaRecord = new DnsAAAARecord(IPAddress.IPv6Any); readonly DnsTXTRecord _txtRecord = new DnsTXTRecord("blockList=custom"); @@ -163,6 +165,8 @@ namespace DnsServerCore.Dns _blockedZoneManager = new BlockedZoneManager(this); _blockListZoneManager = new BlockListZoneManager(this); + _dnsCache = new ResolverDnsCache(_authZoneManager, _cacheZoneManager); + //init stats string statsFolder = Path.Combine(_configFolder, "stats"); @@ -847,7 +851,7 @@ namespace DnsServerCore.Dns { try { - string statusString = statusCode + " " + GetStatusString((HttpStatusCode)statusCode); + string statusString = statusCode + " " + GetHttpStatusString((HttpStatusCode)statusCode); byte[] bufferContent = Encoding.UTF8.GetBytes("" + statusString + "

" + statusString + "

" + (message == null ? "" : "

" + message + "

") + ""); byte[] bufferHeader = Encoding.UTF8.GetBytes("HTTP/1.1 " + statusString + "\r\nDate: " + DateTime.UtcNow.ToString("r") + "\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: " + bufferContent.Length + "\r\nX-Robots-Tag: noindex, nofollow\r\n\r\n"); @@ -859,7 +863,7 @@ namespace DnsServerCore.Dns { } } - internal static string GetStatusString(HttpStatusCode statusCode) + internal static string GetHttpStatusString(HttpStatusCode statusCode) { StringBuilder sb = new StringBuilder(); @@ -924,15 +928,10 @@ namespace DnsServerCore.Dns return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, isRecursionAllowed, false, false, DnsResponseCode.NotImplemented, request.Question); default: - //query authoritative zone - DnsDatagram response = ProcessAuthoritativeQuery(request, isRecursionAllowed); - - if ((response.RCODE != DnsResponseCode.Refused) || !request.RecursionDesired || !isRecursionAllowed) - return response; + DnsDatagram response; //check in allowed zone bool inAllowedZone = _allowedZoneManager.Query(request).RCODE != DnsResponseCode.Refused; - if (!inAllowedZone) { //check in blocked zone and block list zone @@ -941,8 +940,14 @@ namespace DnsServerCore.Dns return response; } + //query authoritative zone + response = ProcessAuthoritativeQuery(request, isRecursionAllowed); + + if ((response.RCODE != DnsResponseCode.Refused) || !request.RecursionDesired || !isRecursionAllowed) + return response; + //do recursive query - return ProcessRecursiveQuery(request, !inAllowedZone, null, null, false); + return ProcessRecursiveQuery(request, null, null, !inAllowedZone, false); } } catch (Exception ex) @@ -1190,81 +1195,7 @@ namespace DnsServerCore.Dns switch (lastRR.Type) { case DnsResourceRecordType.CNAME: - List responseAnswer = new List(); - responseAnswer.AddRange(response.Answer); - - DnsDatagram lastResponse; - - int queryCount = 0; - do - { - DnsDatagram newRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord((lastRR.RDATA as DnsCNAMERecord).Domain, questionType, request.Question[0].Class) }); - - //query authoritative zone first - lastResponse = _authZoneManager.Query(newRequest); - - if (lastResponse.RCODE == DnsResponseCode.Refused) - { - //not found in auth zone - if (newRequest.RecursionDesired && isRecursionAllowed) - { - //do recursion - lastResponse = ProcessRecursiveQuery(newRequest, false, null, null, false); - } - else - { - lastResponse = response; //response is logically last valid response - break; //break since no recursion allowed/desired - } - } - else if ((lastResponse.Answer.Count > 0) && (lastResponse.Answer[0].Type == DnsResourceRecordType.ANAME)) - { - lastResponse = ProcessANAME(request, lastResponse, isRecursionAllowed); - } - else if ((lastResponse.Answer.Count == 0) && (lastResponse.Authority.Count > 0)) - { - //found delegated/forwarded zone - lastResponse = ProcessAuthoritySection(newRequest, lastResponse, isRecursionAllowed); - } - - //check last response - if (lastResponse.Answer.Count == 0) - break; //cannot proceed to resolve cname further - - responseAnswer.AddRange(lastResponse.Answer); - - lastRR = lastResponse.Answer[lastResponse.Answer.Count - 1]; - - if (lastRR.Type != DnsResourceRecordType.CNAME) - break; //cname was resolved - } - while (++queryCount < MAX_CNAME_HOPS); - - DnsResponseCode rcode; - IReadOnlyList authority = null; - IReadOnlyList additional = null; - - if ((lastResponse.RCODE == DnsResponseCode.Refused) && !(request.RecursionDesired && isRecursionAllowed)) - { - rcode = DnsResponseCode.NoError; - } - else - { - rcode = lastResponse.RCODE; - - if (lastResponse.AuthoritativeAnswer) - { - authority = lastResponse.Authority; - additional = lastResponse.Additional; - } - else - { - if ((lastResponse.Authority.Count > 0) && (lastResponse.Authority[0].Type == DnsResourceRecordType.SOA)) - authority = lastResponse.Authority; - } - } - - return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, lastResponse.AuthoritativeAnswer, false, request.RecursionDesired, isRecursionAllowed, false, false, rcode, request.Question, responseAnswer, authority, additional) { Tag = response.Tag }; + return ProcessCNAME(request, response, isRecursionAllowed, false); case DnsResourceRecordType.ANAME: return ProcessANAME(request, response, isRecursionAllowed); @@ -1273,13 +1204,166 @@ namespace DnsServerCore.Dns } else if (response.Authority.Count > 0) { - return ProcessAuthoritySection(request, response, isRecursionAllowed); + switch (response.Authority[0].Type) + { + case DnsResourceRecordType.NS: + if (request.RecursionDesired && isRecursionAllowed) + { + //do recursive resolution using response authority name servers + List nameServers = NameServerAddress.GetNameServersFromResponse(response, _preferIPv6, false); + + return ProcessRecursiveQuery(request, nameServers, null, false, false); + } + + break; + + case DnsResourceRecordType.FWD: + if ((response.Authority.Count == 1) && (response.Authority[0].RDATA as DnsForwarderRecord).Forwarder.Equals("this-server", StringComparison.OrdinalIgnoreCase)) + { + //do conditional forwarding via "this-server" + return ProcessRecursiveQuery(request, null, null, false, false); + } + else + { + //do conditional forwarding + List forwarders = new List(response.Authority.Count); + + foreach (DnsResourceRecord rr in response.Authority) + { + if (rr.Type == DnsResourceRecordType.FWD) + forwarders.Add((rr.RDATA as DnsForwarderRecord).NameServer); + } + + return ProcessRecursiveQuery(request, null, forwarders, false, false); + } + } } } return response; } + private DnsDatagram ProcessCNAME(DnsDatagram request, DnsDatagram response, bool isRecursionAllowed, bool cacheRefreshOperation) + { + List responseAnswer = new List(); + responseAnswer.AddRange(response.Answer); + + DnsDatagram lastResponse; + bool isAuthoritativeAnswer = response.AuthoritativeAnswer; + string lastDomain = (response.Answer[response.Answer.Count - 1].RDATA as DnsCNAMERecord).Domain; + + int queryCount = 0; + do + { + DnsDatagram newRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord(lastDomain, request.Question[0].Type, request.Question[0].Class) }); + + //query authoritative zone first + lastResponse = _authZoneManager.Query(newRequest); + + if (lastResponse.RCODE == DnsResponseCode.Refused) + { + //not found in auth zone + if (newRequest.RecursionDesired && isRecursionAllowed) + { + //do recursion + lastResponse = RecursiveResolve(newRequest, null, null, false, cacheRefreshOperation); + isAuthoritativeAnswer = false; + } + else + { + //break since no recursion allowed/desired + break; + } + } + else if ((lastResponse.Answer.Count > 0) && (lastResponse.Answer[0].Type == DnsResourceRecordType.ANAME)) + { + lastResponse = ProcessANAME(request, lastResponse, isRecursionAllowed); + } + else if ((lastResponse.Answer.Count == 0) && (lastResponse.Authority.Count > 0)) + { + //found delegated/forwarded zone + switch (lastResponse.Authority[0].Type) + { + case DnsResourceRecordType.NS: + if (newRequest.RecursionDesired && isRecursionAllowed) + { + //do recursive resolution using last response authority name servers + List nameServers = NameServerAddress.GetNameServersFromResponse(lastResponse, _preferIPv6, false); + + lastResponse = RecursiveResolve(newRequest, nameServers, null, false, false); + isAuthoritativeAnswer = false; + } + + break; + + case DnsResourceRecordType.FWD: + if ((lastResponse.Authority.Count == 1) && (lastResponse.Authority[0].RDATA as DnsForwarderRecord).Forwarder.Equals("this-server", StringComparison.OrdinalIgnoreCase)) + { + //do conditional forwarding via "this-server" + lastResponse = RecursiveResolve(newRequest, null, null, false, false); + isAuthoritativeAnswer = false; + } + else + { + //do conditional forwarding + List forwarders = new List(lastResponse.Authority.Count); + + foreach (DnsResourceRecord rr in lastResponse.Authority) + { + if (rr.Type == DnsResourceRecordType.FWD) + forwarders.Add((rr.RDATA as DnsForwarderRecord).NameServer); + } + + lastResponse = RecursiveResolve(newRequest, null, forwarders, false, false); + isAuthoritativeAnswer = false; + } + + break; + } + } + + //check last response + if (lastResponse.Answer.Count == 0) + break; //cannot proceed to resolve further + + responseAnswer.AddRange(lastResponse.Answer); + + DnsResourceRecord lastRR = lastResponse.Answer[lastResponse.Answer.Count - 1]; + + if (lastRR.Type != DnsResourceRecordType.CNAME) + break; //cname was resolved + + lastDomain = (lastRR.RDATA as DnsCNAMERecord).Domain; + } + while (++queryCount < MAX_CNAME_HOPS); + + DnsResponseCode rcode; + IReadOnlyList authority = null; + IReadOnlyList additional = null; + + if ((lastResponse.RCODE == DnsResponseCode.Refused) && !(request.RecursionDesired && isRecursionAllowed)) + { + rcode = DnsResponseCode.NoError; + } + else + { + rcode = lastResponse.RCODE; + + if (isAuthoritativeAnswer) + { + authority = response.Authority; + additional = response.Additional; + } + else + { + if ((lastResponse.Authority.Count > 0) && (lastResponse.Authority[0].Type == DnsResourceRecordType.SOA)) + authority = lastResponse.Authority; + } + } + + return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, isAuthoritativeAnswer, false, request.RecursionDesired, isRecursionAllowed, false, false, rcode, request.Question, responseAnswer, authority, additional) { Tag = response.Tag }; + } + private DnsDatagram ProcessANAME(DnsDatagram request, DnsDatagram response, bool isRecursionAllowed) { List responseAnswer = new List(); @@ -1302,12 +1386,42 @@ namespace DnsServerCore.Dns if (lastResponse.RCODE == DnsResponseCode.Refused) { //not found in auth zone; do recursion - lastResponse = ProcessRecursiveQuery(newRequest, false, null, null, false); + lastResponse = RecursiveResolve(newRequest, null, null, false, false); } else if ((lastResponse.Answer.Count == 0) && (lastResponse.Authority.Count > 0)) { //found delegated/forwarded zone - lastResponse = ProcessAuthoritySection(newRequest, lastResponse, true); + switch (lastResponse.Authority[0].Type) + { + case DnsResourceRecordType.NS: + //do recursive resolution using last response authority name servers + List nameServers = NameServerAddress.GetNameServersFromResponse(lastResponse, _preferIPv6, false); + + lastResponse = RecursiveResolve(newRequest, nameServers, null, false, false); + break; + + case DnsResourceRecordType.FWD: + if ((lastResponse.Authority.Count == 1) && (lastResponse.Authority[0].RDATA as DnsForwarderRecord).Forwarder.Equals("this-server", StringComparison.OrdinalIgnoreCase)) + { + //do conditional forwarding via "this-server" + lastResponse = RecursiveResolve(newRequest, null, null, false, false); + } + else + { + //do conditional forwarding + List forwarders = new List(lastResponse.Authority.Count); + + foreach (DnsResourceRecord rr in lastResponse.Authority) + { + if (rr.Type == DnsResourceRecordType.FWD) + forwarders.Add((rr.RDATA as DnsForwarderRecord).NameServer); + } + + lastResponse = RecursiveResolve(newRequest, null, forwarders, false, false); + } + + break; + } } //check last response @@ -1346,45 +1460,6 @@ namespace DnsServerCore.Dns return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, true, false, request.RecursionDesired, isRecursionAllowed, false, false, rcode, request.Question, responseAnswer, response.Authority, response.Additional) { Tag = response.Tag }; } - private DnsDatagram ProcessAuthoritySection(DnsDatagram request, DnsDatagram response, bool isRecursionAllowed) - { - switch (response.Authority[0].Type) - { - case DnsResourceRecordType.NS: - if (request.RecursionDesired && isRecursionAllowed) - { - //do recursive resolution using response authority name servers - List nameServers = NameServerAddress.GetNameServersFromResponse(response, _preferIPv6, false); - - return ProcessRecursiveQuery(request, false, nameServers, null, false); - } - - break; - - case DnsResourceRecordType.FWD: - if ((response.Authority.Count == 1) && (response.Authority[0].RDATA as DnsForwarderRecord).Forwarder.Equals("this-server", StringComparison.OrdinalIgnoreCase)) - { - //do conditional forwarding via "this-server" - return ProcessRecursiveQuery(request, false, null, null, false); - } - else - { - //do conditional forwarding - List forwarders = new List(response.Authority.Count); - - foreach (DnsResourceRecord rr in response.Authority) - { - if (rr.Type == DnsResourceRecordType.FWD) - forwarders.Add((rr.RDATA as DnsForwarderRecord).NameServer); - } - - return ProcessRecursiveQuery(request, false, null, forwarders, false); - } - } - - return response; - } - private DnsDatagram ProcessBlockedQuery(DnsDatagram request) { DnsDatagram response = _blockedZoneManager.Query(request); @@ -1431,113 +1506,61 @@ namespace DnsServerCore.Dns return response; } - private DnsDatagram ProcessRecursiveQuery(DnsDatagram request, bool checkForCnameCloaking, IReadOnlyList viaNameServers, IReadOnlyList viaForwarders, bool cacheRefreshOperation) + private DnsDatagram ProcessRecursiveQuery(DnsDatagram request, IReadOnlyList viaNameServers, IReadOnlyList viaForwarders, bool checkForCnameCloaking, bool cacheRefreshOperation) { DnsDatagram response = RecursiveResolve(request, viaNameServers, viaForwarders, false, cacheRefreshOperation); - DnsResponseCode rcode = response.RCODE; - IReadOnlyList answer = response.Answer; - IReadOnlyList authority = null; - IReadOnlyList additional = null; - if (response.Answer.Count > 0) { - bool cnameCheckPassed = true; + DnsResourceRecordType questionType = request.Question[0].Type; + DnsResourceRecord lastRR = response.Answer[response.Answer.Count - 1]; + + if ((lastRR.Type != questionType) && (lastRR.Type == DnsResourceRecordType.CNAME) && (questionType != DnsResourceRecordType.ANY)) + response = ProcessCNAME(request, response, true, cacheRefreshOperation); if (checkForCnameCloaking && (response.Answer.Count > 1)) { - List responseAnswer = new List(); - - foreach (DnsResourceRecord record in response.Answer) + for (int i = 0; i < response.Answer.Count; i++) { - responseAnswer.Add(record); + DnsResourceRecord record = response.Answer[i]; - if (record.Type == DnsResourceRecordType.CNAME) + if (record.Type != DnsResourceRecordType.CNAME) + break; //no further CNAME records exists + + DnsDatagram newRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord((record.RDATA as DnsCNAMERecord).Domain, request.Question[0].Type, request.Question[0].Class) }); + DnsDatagram lastResponse = ProcessBlockedQuery(newRequest); + if (lastResponse != null) { - DnsDatagram newRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord((record.RDATA as DnsCNAMERecord).Domain, request.Question[0].Type, request.Question[0].Class) }); - DnsDatagram lastResponse = ProcessBlockedQuery(newRequest); - if (lastResponse != null) - { - //found cname cloaking - cnameCheckPassed = false; - responseAnswer.AddRange(lastResponse.Answer); + //found cname cloaking + List answer = new List(); - rcode = lastResponse.RCODE; - answer = responseAnswer; + //copy previous CNAME records + for (int j = 0; j < i; j++) + answer.Add(record); - if ((lastResponse.Authority.Count > 0) && (lastResponse.Authority[0].Type == DnsResourceRecordType.SOA)) - authority = lastResponse.Authority; + //copy last response answers + answer.AddRange(lastResponse.Answer); - response.Tag = lastResponse.Tag; - break; - } + IReadOnlyList authority = null; + + if ((lastResponse.Authority.Count > 0) && (lastResponse.Authority[0].Type == DnsResourceRecordType.SOA)) + authority = lastResponse.Authority; + + return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, true, true, false, false, DnsResponseCode.NoError, request.Question, answer, authority) { Tag = lastResponse.Tag }; } } } - - if (cnameCheckPassed) - { - DnsResourceRecordType questionType = request.Question[0].Type; - DnsResourceRecord lastRR = response.Answer[response.Answer.Count - 1]; - - if ((lastRR.Type != questionType) && (lastRR.Type == DnsResourceRecordType.CNAME) && (questionType != DnsResourceRecordType.ANY)) - { - List responseAnswer = new List(); - responseAnswer.AddRange(response.Answer); - - DnsDatagram lastResponse; - int queryCount = 0; - - do - { - DnsDatagram newRequest = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { new DnsQuestionRecord((lastRR.RDATA as DnsCNAMERecord).Domain, request.Question[0].Type, request.Question[0].Class) }); - - if (checkForCnameCloaking) - { - //check if cname domain is blocked to prevent cname cloaking - lastResponse = ProcessBlockedQuery(newRequest); - if (lastResponse == null) - lastResponse = RecursiveResolve(newRequest, null, null, false, cacheRefreshOperation); //cname is not blocked; so do recursive query - } - else - { - //do recursive query for cname - lastResponse = RecursiveResolve(newRequest, null, null, false, cacheRefreshOperation); - } - - if (lastResponse.Answer.Count == 0) - break; - - responseAnswer.AddRange(lastResponse.Answer); - - lastRR = lastResponse.Answer[lastResponse.Answer.Count - 1]; - - if (lastRR.Type == questionType) - break; - - if (lastRR.Type != DnsResourceRecordType.CNAME) - throw new DnsServerException("Invalid response received from DNS server."); - } - while (++queryCount < MAX_CNAME_HOPS); - - rcode = lastResponse.RCODE; - answer = responseAnswer; - - if ((lastResponse.Authority.Count > 0) && (lastResponse.Authority[0].Type == DnsResourceRecordType.SOA)) - authority = lastResponse.Authority; - - response.Tag = lastResponse.Tag; - } - } } - if ((authority == null) && (response.Authority.Count > 0) && (response.Authority[0].Type == DnsResourceRecordType.SOA)) - authority = response.Authority; + //return response + { + IReadOnlyList authority = null; - if ((response.Additional.Count > 0) && (request.Question[0].Type == DnsResourceRecordType.MX)) - additional = response.Additional; + if ((authority == null) && (response.Authority.Count > 0) && (response.Authority[0].Type == DnsResourceRecordType.SOA)) + authority = response.Authority; - return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, true, true, false, false, rcode, request.Question, answer, authority, additional) { Tag = response.Tag }; + return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, true, true, false, false, response.RCODE, request.Question, response.Answer, authority) { Tag = response.Tag }; + } } private DnsDatagram RecursiveResolve(DnsDatagram request, IReadOnlyList viaNameServers, IReadOnlyList viaForwarders, bool cachePrefetchOperation, bool cacheRefreshOperation) @@ -1595,8 +1618,7 @@ namespace DnsServerCore.Dns return null; //return null as prefetch worker thread does not need valid response and thus does not need to wait //wait till short timeout for response - bool signalled = queryHandle.WaitForResponse(1800, out DnsDatagram response); //1.8 sec wait as per draft-ietf-dnsop-serve-stale-04 - if (signalled) + if (queryHandle.WaitForResponse(1800, out DnsDatagram response)) //1.8 sec wait as per draft-ietf-dnsop-serve-stale-04 { //resolver signaled if (response != null) @@ -1620,11 +1642,11 @@ namespace DnsServerCore.Dns if (response != null) return response; - //no response available from resolver + //no response available from resolver or resolver had exception and no stale record was found } } - //no response available respond with ServerFailure + //no response available; respond with ServerFailure return new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, DnsResponseCode.ServerFailure, request.Question); } @@ -1655,7 +1677,7 @@ namespace DnsServerCore.Dns foreach (NameServerAddress nameServerAddress in forwarders) { if (nameServerAddress.IsIPEndPointStale) //refresh forwarder IPEndPoint if stale - nameServerAddress.RecursiveResolveIPAddress(_cacheZoneManager, null, _preferIPv6, _retries, _timeout); + nameServerAddress.RecursiveResolveIPAddress(_dnsCache, null, _preferIPv6, _retries, _timeout); } } @@ -1679,9 +1701,9 @@ namespace DnsServerCore.Dns IDnsCache dnsCache; if (cachePrefetchOperation || cacheRefreshOperation) - dnsCache = new ResolverPrefetchDnsCache(_cacheZoneManager, request.Question[0]); + dnsCache = new ResolverPrefetchDnsCache(_authZoneManager, _cacheZoneManager, request.Question[0]); else - dnsCache = _cacheZoneManager; + dnsCache = _dnsCache; DnsDatagram response = DnsClient.RecursiveResolve(request.Question[0], viaNameServers, dnsCache, _proxy, _preferIPv6, _retries, _timeout, _maxStackCount); queryHandle.Set(response); @@ -1720,21 +1742,10 @@ namespace DnsServerCore.Dns //fetch stale record DnsDatagram cacheResponse = QueryCache(request, true); - if ((cacheResponse == null) || ((cacheResponse.Answer.Count == 0) && (cacheResponse.Authority.Count == 0))) + if (cacheResponse == null) { - //no stale record or empty record found; cache new empty record to avoid frequent retries by the resolver - DnsResponseCode rcode; - - if (cacheResponse == null) - rcode = DnsResponseCode.ServerFailure; - else - rcode = cacheResponse.RCODE; - - DnsDatagram failureResponse = new DnsDatagram(request.Identifier, true, DnsOpcode.StandardQuery, false, false, request.RecursionDesired, true, false, false, rcode, request.Question); - - _cacheZoneManager.CacheResponse(failureResponse); - - queryHandle.Set(failureResponse); + //no stale record was found; signal null response to release waiting threads + queryHandle.Set(null); } else { @@ -1844,9 +1855,16 @@ namespace DnsServerCore.Dns AuthZoneInfo zoneInfo = _authZoneManager.GetAuthZoneInfo(query.Key.Name); if (zoneInfo != null) { - //zone is hosted - if (!zoneInfo.Disabled) - continue; //no cache refresh for zone that is hosted and enabled + switch (zoneInfo.Type) + { + case AuthZoneType.Primary: + case AuthZoneType.Secondary: + //zone is hosted + if (!zoneInfo.Disabled) + continue; //no cache refresh for zone that is hosted and enabled + + break; + } } if (query.Key.Type == DnsResourceRecordType.ANY) @@ -1903,7 +1921,7 @@ namespace DnsServerCore.Dns { //refresh cache DnsDatagram request = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { sampleQuestion }); - DnsDatagram response = ProcessRecursiveQuery(request, false, null, null, true); + DnsDatagram response = ProcessRecursiveQuery(request, null, null, false, true); bool removeFromSampleList = true; @@ -2449,6 +2467,9 @@ namespace DnsServerCore.Dns public CacheZoneManager CacheZoneManager { get { return _cacheZoneManager; } } + public IDnsCache DnsCache + { get { return _dnsCache; } } + public bool AllowRecursion { get { return _allowRecursion; }