diff --git a/DnsServerCore/Dns/DnsServer.cs b/DnsServerCore/Dns/DnsServer.cs
index c4d4813e..fd5ed4b9 100644
--- a/DnsServerCore/Dns/DnsServer.cs
+++ b/DnsServerCore/Dns/DnsServer.cs
@@ -17,6 +17,7 @@ along with this program. If not, see .
*/
+using DnsServerCore.Dns.ResourceRecords;
using DnsServerCore.Dns.ZoneManagers;
using DnsServerCore.Dns.Zones;
using Newtonsoft.Json;
@@ -119,7 +120,7 @@ namespace DnsServerCore.Dns
readonly object _cachePrefetchRefreshTimerLock = new object();
const int CACHE_PREFETCH_REFRESH_TIMER_INITIAL_INTEVAL = 60000;
DateTime _cachePrefetchSamplingTimerTriggersOn;
- IList _cachePrefetchSampleList;
+ IList _cacheRefreshSampleList;
Timer _cacheMaintenanceTimer;
const int CACHE_MAINTENANCE_TIMER_INITIAL_INTEVAL = 60 * 60 * 1000;
@@ -1705,13 +1706,13 @@ namespace DnsServerCore.Dns
}
}
- private async Task RefreshCacheAsync(IList cacheRefreshSampleList, DnsQuestionRecord sampleQuestion, int sampleQuestionIndex)
+ private async Task RefreshCacheAsync(IList cacheRefreshSampleList, CacheRefreshSample sample, int sampleQuestionIndex)
{
try
{
//refresh cache
- DnsDatagram request = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { sampleQuestion });
- DnsDatagram response = await ProcessRecursiveQueryAsync(request, null, null, false, true);
+ DnsDatagram request = new DnsDatagram(0, false, DnsOpcode.StandardQuery, false, false, true, false, false, false, DnsResponseCode.NoError, new DnsQuestionRecord[] { sample.SampleQuestion });
+ DnsDatagram response = await ProcessRecursiveQueryAsync(request, sample.ViaNameServers, sample.ViaForwarders, false, true);
bool removeFromSampleList = true;
DateTime utcNow = DateTime.UtcNow;
@@ -1801,22 +1802,77 @@ namespace DnsServerCore.Dns
if (stats != null)
{
List> eligibleQueries = stats.GetLastHourEligibleQueries(_cachePrefetchSampleEligibilityHitsPerHour);
- List cacheRefreshSampleList = new List(eligibleQueries.Count);
+ List cacheRefreshSampleList = new List(eligibleQueries.Count);
int cacheRefreshTrigger = (_cachePrefetchSampleIntervalInMinutes + 1) * 60;
foreach (KeyValuePair query in eligibleQueries)
{
+ IReadOnlyList viaNameServers = null;
+ IReadOnlyList viaForwarders = null;
+
AuthZoneInfo zoneInfo = _authZoneManager.GetAuthZoneInfo(query.Key.Name);
- if (zoneInfo != null)
+ if ((zoneInfo != null) && !zoneInfo.Disabled)
{
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
+ continue; //no cache refresh for hosted zones
+ case AuthZoneType.Stub: //stub zone refresh via its name servers
+ {
+ IReadOnlyList nsRecords = zoneInfo.GetRecords(DnsResourceRecordType.NS);
+
+ List nameServers = new List();
+
+ foreach (DnsResourceRecord nsRecord in nsRecords)
+ {
+ string nsDomain = (nsRecord.RDATA as DnsNSRecord).NameServer;
+
+ IReadOnlyList glueRecords = nsRecord.GetGlueRecords();
+ if (glueRecords.Count > 0)
+ {
+ foreach (DnsResourceRecord glueRecord in glueRecords)
+ {
+ switch (glueRecord.Type)
+ {
+ case DnsResourceRecordType.A:
+ nameServers.Add(new NameServerAddress(nsDomain, (glueRecord.RDATA as DnsARecord).Address));
+ break;
+
+ case DnsResourceRecordType.AAAA:
+ if (_preferIPv6)
+ nameServers.Add(new NameServerAddress(nsDomain, (glueRecord.RDATA as DnsAAAARecord).Address));
+
+ break;
+ }
+ }
+ }
+ else
+ {
+ nameServers.Add(new NameServerAddress(nsDomain));
+ }
+ }
+
+ viaNameServers = nameServers;
+ }
+ break;
+
+ case AuthZoneType.Forwarder: //forwarder zone refresh via its forwarders
+ {
+ IReadOnlyList fwdRecords = zoneInfo.GetRecords(DnsResourceRecordType.FWD);
+
+ List forwarders = new List();
+
+ foreach (DnsResourceRecord fwdRecord in fwdRecords)
+ {
+ if (!fwdRecord.IsDisabled())
+ forwarders.Add((fwdRecord.RDATA as DnsForwarderRecord).NameServer);
+ }
+
+ viaForwarders = forwarders;
+ }
break;
}
}
@@ -1826,10 +1882,19 @@ namespace DnsServerCore.Dns
DnsQuestionRecord refreshQuery = GetCacheRefreshNeededQuery(query.Key, cacheRefreshTrigger);
if (refreshQuery != null)
- cacheRefreshSampleList.Add(refreshQuery);
+ {
+ if ((viaNameServers != null) && !refreshQuery.Name.Equals(query.Key.Name, StringComparison.OrdinalIgnoreCase))
+ {
+ //stub zone case where refresh query is a CNAME of the original query
+ if (!refreshQuery.Name.Equals(zoneInfo.Name, StringComparison.OrdinalIgnoreCase) && !refreshQuery.Name.EndsWith("." + zoneInfo.Name, StringComparison.OrdinalIgnoreCase))
+ viaNameServers = null; //refresh query is a CNAME that is outside of the stub zone so do usual recursive resolution
+ }
+
+ cacheRefreshSampleList.Add(new CacheRefreshSample(refreshQuery, viaNameServers, viaForwarders));
+ }
}
- _cachePrefetchSampleList = cacheRefreshSampleList;
+ _cacheRefreshSampleList = cacheRefreshSampleList;
}
}
catch (Exception ex)
@@ -1844,7 +1909,7 @@ namespace DnsServerCore.Dns
{
if (_cachePrefetchSamplingTimer != null)
{
- _cachePrefetchSamplingTimer.Change(_cachePrefetchSampleIntervalInMinutes * 60 * 1000, System.Threading.Timeout.Infinite);
+ _cachePrefetchSamplingTimer.Change(_cachePrefetchSampleIntervalInMinutes * 60 * 1000, Timeout.Infinite);
_cachePrefetchSamplingTimerTriggersOn = DateTime.UtcNow.AddMinutes(_cachePrefetchSampleIntervalInMinutes);
}
}
@@ -1855,19 +1920,19 @@ namespace DnsServerCore.Dns
{
try
{
- IList cacheRefreshSampleList = _cachePrefetchSampleList;
+ IList cacheRefreshSampleList = _cacheRefreshSampleList;
if (cacheRefreshSampleList != null)
{
for (int i = 0; i < cacheRefreshSampleList.Count; i++)
{
- DnsQuestionRecord sampleQuestion = cacheRefreshSampleList[i];
- if (sampleQuestion == null)
+ CacheRefreshSample sample = cacheRefreshSampleList[i];
+ if (sample == null)
continue;
- if (!IsCacheRefreshNeeded(sampleQuestion, _cachePrefetchTrigger + 2))
+ if (!IsCacheRefreshNeeded(sample.SampleQuestion, _cachePrefetchTrigger + 2))
continue;
- _ = RefreshCacheAsync(cacheRefreshSampleList, sampleQuestion, i);
+ _ = RefreshCacheAsync(cacheRefreshSampleList, sample, i);
}
}
}
@@ -1908,13 +1973,13 @@ namespace DnsServerCore.Dns
lock (_cachePrefetchSamplingTimerLock)
{
if (_cachePrefetchSamplingTimer != null)
- _cachePrefetchSamplingTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
+ _cachePrefetchSamplingTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
lock (_cachePrefetchRefreshTimerLock)
{
if (_cachePrefetchRefreshTimer != null)
- _cachePrefetchRefreshTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
+ _cachePrefetchRefreshTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
}
else if (_state == ServiceState.Running)
@@ -1923,7 +1988,7 @@ namespace DnsServerCore.Dns
{
if (_cachePrefetchSamplingTimer != null)
{
- _cachePrefetchSamplingTimer.Change(_cachePrefetchSampleIntervalInMinutes * 60 * 1000, System.Threading.Timeout.Infinite);
+ _cachePrefetchSamplingTimer.Change(_cachePrefetchSampleIntervalInMinutes * 60 * 1000, Timeout.Infinite);
_cachePrefetchSamplingTimerTriggersOn = DateTime.UtcNow.AddMinutes(_cachePrefetchSampleIntervalInMinutes);
}
}
@@ -1931,10 +1996,9 @@ namespace DnsServerCore.Dns
lock (_cachePrefetchRefreshTimerLock)
{
if (_cachePrefetchRefreshTimer != null)
- _cachePrefetchRefreshTimer.Change(CACHE_PREFETCH_REFRESH_TIMER_INITIAL_INTEVAL, System.Threading.Timeout.Infinite);
+ _cachePrefetchRefreshTimer.Change(CACHE_PREFETCH_REFRESH_TIMER_INITIAL_INTEVAL, Timeout.Infinite);
}
}
-
}
private void UpdateThisServer()
@@ -2627,5 +2691,19 @@ namespace DnsServerCore.Dns
}
#endregion
+
+ class CacheRefreshSample
+ {
+ public CacheRefreshSample(DnsQuestionRecord sampleQuestion, IReadOnlyList viaNameServers, IReadOnlyList viaForwarders)
+ {
+ SampleQuestion = sampleQuestion;
+ ViaNameServers = viaNameServers;
+ ViaForwarders = viaForwarders;
+ }
+
+ public DnsQuestionRecord SampleQuestion { get; }
+ public IReadOnlyList ViaNameServers { get; }
+ public IReadOnlyList ViaForwarders { get; }
+ }
}
}