summaryrefslogtreecommitdiffstats
path: root/mDNSResponder/mDNSCore/mDNS.c
diff options
context:
space:
mode:
Diffstat (limited to 'mDNSResponder/mDNSCore/mDNS.c')
-rwxr-xr-xmDNSResponder/mDNSCore/mDNS.c801
1 files changed, 407 insertions, 394 deletions
diff --git a/mDNSResponder/mDNSCore/mDNS.c b/mDNSResponder/mDNSCore/mDNS.c
index a58a6c1a..0d4d8ae4 100755
--- a/mDNSResponder/mDNSCore/mDNS.c
+++ b/mDNSResponder/mDNSCore/mDNS.c
@@ -45,6 +45,7 @@
#endif
#include "dns_sd.h" // for kDNSServiceFlags* definitions
+#include "dns_sd_internal.h"
#if APPLE_OSX_mDNSResponder
#include <WebFilterDNS/WebFilterDNS.h>
@@ -65,15 +66,22 @@ void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import));
#define NO_WCF 1
#endif // APPLE_OSX_mDNSResponder
-#if TARGET_OS_EMBEDDED
+#if AWD_METRICS
#include "Metrics.h"
#endif
+#if USE_DNS64
+#include "DNS64.h"
+#endif
+
+#ifdef UNIT_TEST
+#include "unittest.h"
+#endif
+
// Forward declarations
mDNSlocal void BeginSleepProcessing(mDNS *const m);
mDNSlocal void RetrySPSRegistrations(mDNS *const m);
mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly);
-mDNSlocal mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q);
mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q);
mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q);
mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q);
@@ -109,6 +117,10 @@ mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *et
#define NR_AnswerMulticast (mDNSu8*)~0
#define NR_AnswerUnicast (mDNSu8*)~1
+// Question default timeout values
+#define DEFAULT_MCAST_TIMEOUT 5
+#define DEFAULT_LO_OR_P2P_TIMEOUT 5
+
// The code (see SendQueries() and BuildQuestion()) needs to have the
// RequestUnicast value set to a value one greater than the number of times you want the query
// sent with the "request unicast response" (QU) bit set.
@@ -274,24 +286,27 @@ mDNSlocal AuthEntity *GetAuthEntity(AuthHash *r, const AuthGroup *const Preserve
return(e);
}
-mDNSexport AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name)
+mDNSexport AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 namehash, const domainname *const name)
{
AuthGroup *ag;
+ const mDNSu32 slot = namehash % AUTH_HASH_SLOTS;
+
for (ag = r->rrauth_hash[slot]; ag; ag=ag->next)
if (ag->namehash == namehash && SameDomainName(ag->name, name))
break;
return(ag);
}
-mDNSexport AuthGroup *AuthGroupForRecord(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr)
+mDNSexport AuthGroup *AuthGroupForRecord(AuthHash *r, const ResourceRecord *const rr)
{
- return(AuthGroupForName(r, slot, rr->namehash, rr->name));
+ return(AuthGroupForName(r, rr->namehash, rr->name));
}
-mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr)
+mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const ResourceRecord *const rr)
{
mDNSu16 namelen = DomainNameLength(rr->name);
AuthGroup *ag = (AuthGroup*)GetAuthEntity(r, mDNSNULL);
+ const mDNSu32 slot = rr->namehash % AUTH_HASH_SLOTS;
if (!ag) { LogMsg("GetAuthGroup: Failed to allocate memory for %##s", rr->name->c); return(mDNSNULL); }
ag->next = r->rrauth_hash[slot];
ag->namehash = rr->namehash;
@@ -310,9 +325,9 @@ mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const mDNSu32 slot, const Resourc
}
AssignDomainName(ag->name, rr->name);
- if (AuthGroupForRecord(r, slot, rr)) LogMsg("GetAuthGroup: Already have AuthGroup for %##s", rr->name->c);
+ if (AuthGroupForRecord(r, rr)) LogMsg("GetAuthGroup: Already have AuthGroup for %##s", rr->name->c);
r->rrauth_hash[slot] = ag;
- if (AuthGroupForRecord(r, slot, rr) != ag) LogMsg("GetAuthGroup: Not finding AuthGroup for %##s", rr->name->c);
+ if (AuthGroupForRecord(r, rr) != ag) LogMsg("GetAuthGroup: Not finding AuthGroup for %##s", rr->name->c);
return(ag);
}
@@ -320,11 +335,11 @@ mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const mDNSu32 slot, const Resourc
// Returns the AuthGroup in which the AuthRecord was inserted
mDNSexport AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr)
{
- (void)m;
AuthGroup *ag;
- const mDNSu32 slot = AuthHashSlot(rr->resrec.name);
- ag = AuthGroupForRecord(r, slot, &rr->resrec);
- if (!ag) ag = GetAuthGroup(r, slot, &rr->resrec); // If we don't have a AuthGroup for this name, make one now
+
+ (void)m;
+ ag = AuthGroupForRecord(r, &rr->resrec);
+ if (!ag) ag = GetAuthGroup(r, &rr->resrec); // If we don't have a AuthGroup for this name, make one now
if (ag)
{
*(ag->rrauth_tail) = rr; // Append this record to tail of cache slot list
@@ -337,9 +352,8 @@ mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *r
{
AuthGroup *a;
AuthRecord **rp;
- const mDNSu32 slot = AuthHashSlot(rr->resrec.name);
- a = AuthGroupForRecord(r, slot, &rr->resrec);
+ a = AuthGroupForRecord(r, &rr->resrec);
if (!a) { LogMsg("RemoveAuthRecord: ERROR!! AuthGroup not found for %s", ARDisplayString(m, rr)); return mDNSNULL; }
rp = &a->members;
while (*rp)
@@ -359,18 +373,19 @@ mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *r
return a;
}
-mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name)
+mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 namehash, const domainname *const name)
{
CacheGroup *cg;
+ mDNSu32 slot = HashSlotFromNameHash(namehash);
for (cg = m->rrcache_hash[slot]; cg; cg=cg->next)
if (cg->namehash == namehash && SameDomainName(cg->name, name))
break;
return(cg);
}
-mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const mDNSu32 slot, const ResourceRecord *const rr)
+mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const ResourceRecord *const rr)
{
- return(CacheGroupForName(m, slot, rr->namehash, rr->name));
+ return(CacheGroupForName(m, rr->namehash, rr->name));
}
mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr)
@@ -472,7 +487,7 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re
const mDNSu32 c = q->CNAMEReferrals + 1; // Stash a copy of the new q->CNAMEReferrals value
UDPSocket *sock = q->LocalSocket;
mDNSOpaque16 id = q->TargetQID;
-#if TARGET_OS_EMBEDDED
+#if AWD_METRICS
uDNSMetrics metrics;
#endif
@@ -496,7 +511,7 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re
LogInfo("AnswerQuestionByFollowingCNAME: %p %##s (%s) following CNAME referral %d for %s",
q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, RRDisplayString(m, rr));
-#if TARGET_OS_EMBEDDED
+#if AWD_METRICS
if ((q->CNAMEReferrals == 0) && !q->metrics.originalQName)
{
domainname * qName;
@@ -532,7 +547,7 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re
// Record how many times we've done this. We need to do this *after* mDNS_StartQuery_internal,
// because mDNS_StartQuery_internal re-initializes CNAMEReferrals to zero
q->CNAMEReferrals = c;
-#if TARGET_OS_EMBEDDED
+#if AWD_METRICS
q->metrics = metrics;
#endif
if (sock)
@@ -787,7 +802,6 @@ mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRec
(X) &kDNSRecordTypeActiveUniqueMask ? DefaultAnnounceIntervalForTypeUnique : 0)
#define TimeToAnnounceThisRecord(RR,time) ((RR)->AnnounceCount && (time) - ((RR)->LastAPTime + (RR)->ThisAPInterval) >= 0)
-#define TimeToSendThisRecord(RR,time) ((TimeToAnnounceThisRecord(RR,time) || (RR)->ImmedAnswer) && ResourceRecordIsValidAnswer(RR))
#define TicksTTL(RR) ((mDNSs32)(RR)->resrec.rroriginalttl * mDNSPlatformOneSecond)
#define RRExpireTime(RR) ((RR)->TimeRcvd + TicksTTL(RR))
@@ -962,9 +976,9 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
}
rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval;
}
- // Skip kDNSRecordTypeKnownUnique records here and set their LastAPTime in the "else" block below so that they get announced immediately,
- // otherwise, their announcement would be delayed until all other record probes complete.
- else if ((rr->resrec.RecordType != kDNSRecordTypeKnownUnique) && m->SuppressProbes && m->SuppressProbes - m->timenow >= 0)
+ // Skip kDNSRecordTypeKnownUnique and kDNSRecordTypeShared records here and set their LastAPTime in the "else" block below so
+ // that they get announced immediately, otherwise, their announcement would be delayed until the based on the SuppressProbes value.
+ else if ((rr->resrec.RecordType != kDNSRecordTypeKnownUnique) && (rr->resrec.RecordType != kDNSRecordTypeShared) && m->SuppressProbes && (m->SuppressProbes - m->timenow >= 0))
rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval + DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2;
else
rr->LastAPTime = m->timenow - rr->ThisAPInterval;
@@ -1155,9 +1169,8 @@ mDNSlocal AuthRecord *CheckAuthIdenticalRecord(AuthHash *r, AuthRecord *rr)
{
const AuthGroup *a;
AuthRecord *rp;
- const mDNSu32 slot = AuthHashSlot(rr->resrec.name);
- a = AuthGroupForRecord(r, slot, &rr->resrec);
+ a = AuthGroupForRecord(r, &rr->resrec);
if (!a) return mDNSNULL;
rp = a->members;
while (rp)
@@ -1181,9 +1194,8 @@ mDNSlocal mDNSBool CheckAuthRecordConflict(AuthHash *r, AuthRecord *rr)
{
const AuthGroup *a;
const AuthRecord *rp;
- const mDNSu32 slot = AuthHashSlot(rr->resrec.name);
- a = AuthGroupForRecord(r, slot, &rr->resrec);
+ a = AuthGroupForRecord(r, &rr->resrec);
if (!a) return mDNSfalse;
rp = a->members;
while (rp)
@@ -1203,9 +1215,8 @@ mDNSlocal AuthRecord *CheckAuthSameRecord(AuthHash *r, AuthRecord *rr)
{
const AuthGroup *a;
AuthRecord *rp;
- const mDNSu32 slot = AuthHashSlot(rr->resrec.name);
- a = AuthGroupForRecord(r, slot, &rr->resrec);
+ a = AuthGroupForRecord(r, &rr->resrec);
if (!a) return mDNSNULL;
rp = a->members;
while (rp)
@@ -1386,9 +1397,9 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
{
if (rr->resrec.RecordType == kDNSRecordTypeUnique)
rr->resrec.RecordType = kDNSRecordTypeVerified;
- else
+ else if (rr->resrec.RecordType != kDNSRecordTypeKnownUnique)
{
- LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique",
+ LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique or kDNSRecordTypeKnownUnique",
rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
return(mStatus_Invalid);
}
@@ -1630,7 +1641,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
getKeepaliveRaddr(m, rr, &raddr);
// This is an asynchronous call. Once the remote MAC address is available, helper will schedule an
// asynchronous task to update the resource record
- mDNSPlatformGetRemoteMacAddr(m, &raddr);
+ mDNSPlatformGetRemoteMacAddr(&raddr);
}
return(mStatus_NoError);
@@ -1679,9 +1690,8 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr,
{
AuthGroup *a;
AuthRecord **rp;
- const mDNSu32 slot = AuthHashSlot(rr->resrec.name);
- a = AuthGroupForRecord(&m->rrauth, slot, &rr->resrec);
+ a = AuthGroupForRecord(&m->rrauth, &rr->resrec);
if (!a) return mDNSfalse;
rp = &a->members;
while (*rp && *rp != rr) rp=&(*rp)->next;
@@ -1954,6 +1964,27 @@ mDNSlocal void AddRecordToResponseList(AuthRecord ***nrpp, AuthRecord *rr, AuthR
debugf("AddRecordToResponseList: %##s (%s) already in list", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
}
+mDNSlocal void AddRRSetAdditionalsToResponseList(mDNS *const m, AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *additional, const mDNSInterfaceID InterfaceID)
+{
+ AuthRecord *rr2;
+ if (additional->resrec.RecordType & kDNSRecordTypeUniqueMask)
+ {
+ for (rr2 = m->ResourceRecords; rr2; rr2 = rr2->next)
+ {
+ if ((rr2->resrec.namehash == additional->resrec.namehash) &&
+ (rr2->resrec.rrtype == additional->resrec.rrtype) &&
+ (rr2 != additional) &&
+ (rr2->resrec.RecordType & kDNSRecordTypeUniqueMask) &&
+ (rr2->resrec.rrclass == additional->resrec.rrclass) &&
+ ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&
+ SameDomainName(rr2->resrec.name, additional->resrec.name))
+ {
+ AddRecordToResponseList(nrpp, rr2, rr);
+ }
+ }
+ }
+}
+
mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseRecords, AuthRecord ***nrpp, const mDNSInterfaceID InterfaceID)
{
AuthRecord *rr, *rr2;
@@ -1962,10 +1993,16 @@ mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseR
// (Note: This is an "if", not a "while". If we add a record, we'll find it again
// later in the "for" loop, and we will follow further "additional" links then.)
if (rr->Additional1 && ResourceRecordIsValidInterfaceAnswer(rr->Additional1, InterfaceID))
+ {
AddRecordToResponseList(nrpp, rr->Additional1, rr);
+ AddRRSetAdditionalsToResponseList(m, nrpp, rr, rr->Additional1, InterfaceID);
+ }
if (rr->Additional2 && ResourceRecordIsValidInterfaceAnswer(rr->Additional2, InterfaceID))
+ {
AddRecordToResponseList(nrpp, rr->Additional2, rr);
+ AddRRSetAdditionalsToResponseList(m, nrpp, rr, rr->Additional2, InterfaceID);
+ }
// For SRV records, automatically add the Address record(s) for the target host
if (rr->resrec.rrtype == kDNSType_SRV)
@@ -2485,7 +2522,7 @@ mDNSlocal void SendResponses(mDNS *const m)
mDNSs32 maxExistingAnnounceInterval = 0;
const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
- m->NextScheduledResponse = m->timenow + 0x78000000;
+ m->NextScheduledResponse = m->timenow + FutureTime;
if (m->SleepState == SleepState_Transferring) RetrySPSRegistrations(m);
@@ -3059,13 +3096,18 @@ mDNSexport void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const
verbosedebugf("SetNextCacheCheckTimeForRecord: NextRequiredQuery in %ld sec CacheCheckGracePeriod %d ticks for %s",
(rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr), CRDisplayString(m,rr));
}
- ScheduleNextCacheCheckTime(m, HashSlot(rr->resrec.name), NextCacheCheckEvent(rr));
+ ScheduleNextCacheCheckTime(m, HashSlotFromNameHash(rr->resrec.namehash), NextCacheCheckEvent(rr));
}
#define kMinimumReconfirmTime ((mDNSu32)mDNSPlatformOneSecond * 5)
#define kDefaultReconfirmTimeForWake ((mDNSu32)mDNSPlatformOneSecond * 5)
#define kDefaultReconfirmTimeForNoAnswer ((mDNSu32)mDNSPlatformOneSecond * 5)
-#define kDefaultReconfirmTimeForFlappingInterface ((mDNSu32)mDNSPlatformOneSecond * 5)
+
+// Delay before restarting questions on a flapping interface.
+#define kDefaultQueryDelayTimeForFlappingInterface ((mDNSu32)mDNSPlatformOneSecond * 3)
+// After kDefaultQueryDelayTimeForFlappingInterface seconds, allow enough time for up to three queries (0, 1, and 4 seconds)
+// plus three seconds for "response delay" before removing the reconfirmed records from the cache.
+#define kDefaultReconfirmTimeForFlappingInterface (kDefaultQueryDelayTimeForFlappingInterface + ((mDNSu32)mDNSPlatformOneSecond * 7))
mDNSexport mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval)
{
@@ -3080,7 +3122,7 @@ mDNSexport mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr,
// Add a 33% random amount to the interval, to avoid synchronization between multiple hosts
// For all the reconfirmations in a given batch, we want to use the same random value
// so that the reconfirmation questions can be grouped into a single query packet
- if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(0x3FFFFFFF);
+ if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(FutureTime);
interval += m->RandomReconfirmDelay % ((interval/3) + 1);
rr->TimeRcvd = m->timenow - (mDNSs32)interval * 3;
rr->resrec.rroriginalttl = (interval * 4 + mDNSPlatformOneSecond - 1) / mDNSPlatformOneSecond;
@@ -3110,8 +3152,7 @@ mDNSlocal mDNSBool BuildQuestion(mDNS *const m, const NetworkInterfaceInfo *intf
else
{
mDNSu32 forecast = *answerforecast + anoninfo_space;
- const mDNSu32 slot = HashSlot(&q->qname);
- const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+ const CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
CacheRecord *rr;
CacheRecord **ka = *kalistptrptr; // Make a working copy of the pointer we're going to update
@@ -3204,7 +3245,7 @@ mDNSlocal void ReconfirmAntecedents(mDNS *const m, const domainname *const name,
// to get a AAAA response is not grounds to doubt the PTR/SRV chain that lead us to that name.
mDNSlocal const CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const domainname *const name, const mDNSu32 namehash)
{
- CacheGroup *const cg = CacheGroupForName(m, HashSlot(name), namehash, name);
+ CacheGroup *const cg = CacheGroupForName(m, namehash, name);
const CacheRecord *cr = cg ? cg->members : mDNSNULL;
while (cr && !RRTypeIsAddressType(cr->resrec.rrtype)) cr=cr->next;
return(cr);
@@ -3214,7 +3255,7 @@ mDNSlocal const CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const dom
mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *const q, const CacheRecord *const c0, const CacheRecord *const c1)
{
#ifndef SPC_DISABLED
- CacheGroup *const cg = CacheGroupForName(m, HashSlot(&q->qname), q->qnamehash, &q->qname);
+ CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
const CacheRecord *cr, *bestcr = mDNSNULL;
mDNSu32 bestmetric = 1000000;
for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
@@ -3365,7 +3406,7 @@ mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q)
mDNSPlatformMemCopy(IPAddr, &d->c[i + 1], len - i);
IPAddr[len - i] = 0;
m->mDNSStats.WakeOnResolves++;
- mDNSPlatformSendWakeupPacket(m, InterfaceID, EthAddr, IPAddr, InitialWakeOnResolveCount - q->WakeOnResolveCount);
+ mDNSPlatformSendWakeupPacket(InterfaceID, EthAddr, IPAddr, InitialWakeOnResolveCount - q->WakeOnResolveCount);
return;
}
else if (d->c[i] == ':')
@@ -3386,8 +3427,7 @@ mDNSlocal mDNSBool AccelerateThisQuery(mDNS *const m, DNSQuestion *q)
{
// We forecast: qname (n) type (2) class (2)
mDNSu32 forecast = (mDNSu32)DomainNameLength(&q->qname) + 4;
- const mDNSu32 slot = HashSlot(&q->qname);
- const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+ const CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
const CacheRecord *rr;
for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) // If we have a resource record in our cache,
if (rr->resrec.rdlength <= SmallRecordLimit && // which is small enough to sensibly fit in the packet
@@ -3490,7 +3530,7 @@ mDNSlocal void SendQueries(mDNS *const m)
const mDNSu8 *const limit = m->omsg.data + sizeof(m->omsg.data);
// If we fail to get a new on-demand socket (should only happen cases of the most extreme resource exhaustion), we'll try again next time
- if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort);
+ if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(zeroIPPort);
if (q->LocalSocket)
{
InitializeDNSMessage(&m->omsg.h, q->TargetQID, QueryFlags);
@@ -3531,7 +3571,7 @@ mDNSlocal void SendQueries(mDNS *const m)
// Note: Don't set NextScheduledQuery until here, because uDNS_CheckCurrentQuestion in the loop above can add new questions to the list,
// which causes NextScheduledQuery to get (incorrectly) set to m->timenow. Setting it here is the right place, because the very
// next thing we do is scan the list and call SetNextQueryTime() for every question we find, so we know we end up with the right value.
- m->NextScheduledQuery = m->timenow + 0x78000000;
+ m->NextScheduledQuery = m->timenow + FutureTime;
for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
{
if (mDNSOpaque16IsZero(q->TargetQID)
@@ -3610,7 +3650,7 @@ mDNSlocal void SendQueries(mDNS *const m)
// 2. Scan our authoritative RR list to see what probes we might need to send
- m->NextScheduledProbe = m->timenow + 0x78000000;
+ m->NextScheduledProbe = m->timenow + FutureTime;
if (m->CurrentRecord)
LogMsg("SendQueries ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
@@ -4110,7 +4150,7 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco
return;
}
-#if TARGET_OS_EMBEDDED
+#if AWD_METRICS
if ((AddRecord == QC_add) && Question_uDNS(q) && !followcname)
{
const domainname * queryName;
@@ -4169,6 +4209,11 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco
if (rr->DelayDelivery) return; // We'll come back later when CacheRecordDeferredAdd() calls us
+#if USE_DNS64
+ // If DNS64StateMachine() returns true, then the question was restarted as a different question, so return.
+ if (!mDNSOpaque16IsZero(q->TargetQID) && DNS64StateMachine(m, q, &rr->resrec, AddRecord)) return;
+#endif
+
#ifdef USE_LIBIDN
if (rr->resrec.RecordType == kDNSRecordTypePacketNegative) // If negative answer, check if we need to try Punycode conversion
{
@@ -4209,7 +4254,18 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco
q->QuestionCallback(m, q, &neg.resrec, AddRecord);
}
else
- q->QuestionCallback(m, q, &rr->resrec, AddRecord);
+ {
+#if USE_DNS64
+ if (DNS64ShouldAnswerQuestion(q, &rr->resrec))
+ {
+ DNS64AnswerQuestion(m, q, &rr->resrec, AddRecord);
+ }
+ else
+#endif
+ {
+ q->QuestionCallback(m, q, &rr->resrec, AddRecord);
+ }
+ }
mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again
}
// If this is an "Add" operation and this question needs validation, validate the response.
@@ -4265,12 +4321,12 @@ mDNSlocal void CacheRecordDeferredAdd(mDNS *const m, CacheRecord *rr)
m->CurrentQuestion = mDNSNULL;
}
-mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const mDNSu32 slot, mDNSBool *purge)
+mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash, mDNSBool *purge)
{
const mDNSs32 threshhold = m->timenow + mDNSPlatformOneSecond; // See if there are any records expiring within one second
const mDNSs32 start = m->timenow - 0x10000000;
mDNSs32 delay = start;
- CacheGroup *cg = CacheGroupForName(m, slot, namehash, name);
+ CacheGroup *cg = CacheGroupForName(m, namehash, name);
const CacheRecord *rr;
if (purge)
@@ -4559,13 +4615,12 @@ mDNSlocal void ReleaseAdditionalCacheRecords(mDNS *const m, CacheRecord **rp)
mDNSexport void ReleaseCacheRecord(mDNS *const m, CacheRecord *r)
{
CacheGroup *cg;
- const mDNSu32 slot = HashSlot(r->resrec.name);
//LogMsg("ReleaseCacheRecord: Releasing %s", CRDisplayString(m, r));
if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->smallrdatastorage) mDNSPlatformMemFree(r->resrec.rdata);
r->resrec.rdata = mDNSNULL;
- cg = CacheGroupForRecord(m, slot, &r->resrec);
+ cg = CacheGroupForRecord(m, &r->resrec);
if (!cg)
{
@@ -4662,7 +4717,7 @@ mDNSlocal void CheckCacheExpiration(mDNS *const m, const mDNSu32 slot, CacheGrou
m->NextScheduledQuery = m->timenow;
// After sending the query we'll increment UnansweredQueries and call SetNextCacheCheckTimeForRecord(),
// which will correctly update m->NextCacheCheck for us.
- event = m->timenow + 0x3FFFFFFF;
+ event = m->timenow + FutureTime;
}
}
}
@@ -4687,15 +4742,13 @@ mDNSlocal void CheckCacheExpiration(mDNS *const m, const mDNSu32 slot, CacheGrou
// returns true to indicate the same.
mDNSlocal mDNSBool AnswerQuestionWithLORecord(mDNS *const m, DNSQuestion *q, mDNSBool checkOnly)
{
- mDNSu32 slot;
AuthRecord *lr;
AuthGroup *ag;
if (m->CurrentRecord)
LogMsg("AnswerQuestionWithLORecord ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
- slot = AuthHashSlot(&q->qname);
- ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname);
+ ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname);
if (ag)
{
m->CurrentRecord = ag->members;
@@ -4772,8 +4825,19 @@ mDNSlocal mDNSBool AnswerQuestionWithLORecord(mDNS *const m, DNSQuestion *q, mDN
// reasons for suppressing the query, this function should be updated.
mDNSlocal void AnswerSuppressedQuestion(mDNS *const m, DNSQuestion *q)
{
- mDNSBool SuppressQuery = q->SuppressQuery;
- mDNSBool DisallowPID = q->DisallowPID;
+ mDNSBool SuppressQuery;
+ mDNSBool DisallowPID;
+
+ // If the client did not set the kDNSServiceFlagsReturnIntermediates flag, then don't generate a negative response, just
+ // deactivate the DNSQuestion.
+ if (!q->ReturnIntermed)
+ {
+ q->ThisQInterval = 0;
+ return;
+ }
+
+ SuppressQuery = q->SuppressQuery;
+ DisallowPID = q->DisallowPID;
// make sure that QuerySuppressed() returns false
q->SuppressQuery = mDNSfalse;
@@ -4789,13 +4853,15 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m)
{
mDNSBool ShouldQueryImmediately = mDNStrue;
DNSQuestion *const q = m->NewQuestions; // Grab the question we're going to answer
- mDNSu32 slot = HashSlot(&q->qname);
- CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+#if USE_DNS64
+ if (!mDNSOpaque16IsZero(q->TargetQID)) DNS64HandleNewQuestion(m, q);
+#endif
+ CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
mDNSBool AnsweredFromCache = mDNSfalse;
verbosedebugf("AnswerNewQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
- if (cg) CheckCacheExpiration(m, slot, cg);
+ if (cg) CheckCacheExpiration(m, HashSlotFromNameHash(q->qnamehash), cg);
if (m->NewQuestions != q) { LogInfo("AnswerNewQuestion: Question deleted while doing CheckCacheExpiration"); goto exit; }
m->NewQuestions = q->next;
// Advance NewQuestions to the next *after* calling CheckCacheExpiration, because if we advance it first
@@ -4935,11 +5001,10 @@ exit:
// appropriate answers, stopping if it reaches a NewLocalOnlyRecord -- these will be handled by AnswerAllLocalQuestionsWithLocalAuthRecord
mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m)
{
- mDNSu32 slot;
AuthGroup *ag;
DNSQuestion *q = m->NewLocalOnlyQuestions; // Grab the question we're going to answer
- m->NewLocalOnlyQuestions = q->next; // Advance NewLocalOnlyQuestions to the next (if any)
mDNSBool retEv = mDNSfalse;
+ m->NewLocalOnlyQuestions = q->next; // Advance NewLocalOnlyQuestions to the next (if any)
debugf("AnswerNewLocalOnlyQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
@@ -4954,8 +5019,7 @@ mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m)
// 1. First walk the LocalOnly records answering the LocalOnly question
// 2. As LocalOnly questions should also be answered by any other Auth records local to the machine,
// walk the ResourceRecords list delivering the answers
- slot = AuthHashSlot(&q->qname);
- ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname);
+ ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname);
if (ag)
{
m->CurrentRecord = ag->members;
@@ -5120,9 +5184,9 @@ mDNSlocal CacheGroup *GetCacheGroup(mDNS *const m, const mDNSu32 slot, const Res
}
AssignDomainName(cg->name, rr->name);
- if (CacheGroupForRecord(m, slot, rr)) LogMsg("GetCacheGroup: Already have CacheGroup for %##s", rr->name->c);
+ if (CacheGroupForRecord(m, rr)) LogMsg("GetCacheGroup: Already have CacheGroup for %##s", rr->name->c);
m->rrcache_hash[slot] = cg;
- if (CacheGroupForRecord(m, slot, rr) != cg) LogMsg("GetCacheGroup: Not finding CacheGroup for %##s", rr->name->c);
+ if (CacheGroupForRecord(m, rr) != cg) LogMsg("GetCacheGroup: Not finding CacheGroup for %##s", rr->name->c);
return(cg);
}
@@ -5162,7 +5226,7 @@ mDNSexport mDNSs32 mDNS_TimeNow(const mDNS *const m)
// had its Sleep Proxy client list change, and defer to actual BPF reconfiguration to mDNS_Execute().
// (GetNextScheduledEvent() returns "now" when m->SPSProxyListChanged is set)
#define SetSPSProxyListChanged(X) do { \
- if (m->SPSProxyListChanged && m->SPSProxyListChanged != (X)) mDNSPlatformUpdateProxyList(m, m->SPSProxyListChanged); \
+ if (m->SPSProxyListChanged && m->SPSProxyListChanged != (X)) mDNSPlatformUpdateProxyList(m->SPSProxyListChanged); \
m->SPSProxyListChanged = (X); } while(0)
// Called from mDNS_Execute() to expire stale proxy records
@@ -5221,13 +5285,12 @@ mDNSlocal void CheckRmvEventsForLocalRecords(mDNS *const m)
}
}
-mDNSlocal void TimeoutQuestions(mDNS *const m)
+mDNSlocal void TimeoutQuestions_internal(mDNS *const m, DNSQuestion* questions, mDNSInterfaceID InterfaceID)
{
- m->NextScheduledStopTime = m->timenow + 0x3FFFFFFF;
if (m->CurrentQuestion)
LogMsg("TimeoutQuestions ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c,
DNSTypeName(m->CurrentQuestion->qtype));
- m->CurrentQuestion = m->Questions;
+ m->CurrentQuestion = questions;
while (m->CurrentQuestion)
{
DNSQuestion *const q = m->CurrentQuestion;
@@ -5239,7 +5302,8 @@ mDNSlocal void TimeoutQuestions(mDNS *const m)
if (m->timenow - q->StopTime >= 0)
{
LogInfo("TimeoutQuestions: question %p %##s timed out, time %d", q, q->qname.c, m->timenow - q->StopTime);
- GenerateNegativeResponse(m, mDNSInterface_Any, QC_forceresponse);
+ q->LOAddressAnswers = 0; // unset since timing out the question
+ GenerateNegativeResponse(m, InterfaceID, QC_forceresponse);
if (m->CurrentQuestion == q) q->StopTime = 0;
}
else
@@ -5257,6 +5321,13 @@ mDNSlocal void TimeoutQuestions(mDNS *const m)
m->CurrentQuestion = mDNSNULL;
}
+mDNSlocal void TimeoutQuestions(mDNS *const m)
+{
+ m->NextScheduledStopTime = m->timenow + FutureTime; // push reschedule of TimeoutQuestions to way off into the future
+ TimeoutQuestions_internal(m, m->Questions, mDNSInterface_Any);
+ TimeoutQuestions_internal(m, m->LocalOnlyQuestions, mDNSInterface_LocalOnly);
+}
+
mDNSlocal void mDNSCoreFreeProxyRR(mDNS *const m)
{
AuthRecord *rrPtr = m->SPSRRSet, *rrNext = mDNSNULL;
@@ -5274,10 +5345,6 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
{
mDNS_Lock(m); // Must grab lock before trying to read m->timenow
-#if APPLE_OSX_mDNSResponder
- mDNSLogStatistics(m);
-#endif // APPLE_OSX_mDNSResponder
-
if (m->timenow - m->NextScheduledEvent >= 0)
{
int i;
@@ -5304,13 +5371,13 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
if (m->rrcache_size && m->timenow - m->NextCacheCheck >= 0)
{
mDNSu32 numchecked = 0;
- m->NextCacheCheck = m->timenow + 0x3FFFFFFF;
+ m->NextCacheCheck = m->timenow + FutureTime;
for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
{
if (m->timenow - m->rrcache_nextcheck[slot] >= 0)
{
CacheGroup **cp = &m->rrcache_hash[slot];
- m->rrcache_nextcheck[slot] = m->timenow + 0x3FFFFFFF;
+ m->rrcache_nextcheck[slot] = m->timenow + FutureTime;
while (*cp)
{
debugf("m->NextCacheCheck %4d Slot %3d %##s", numchecked, slot, *cp ? (*cp)->name : (domainname*)"\x04NULL");
@@ -5330,7 +5397,7 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
if (m->timenow - m->NextScheduledSPS >= 0)
{
- m->NextScheduledSPS = m->timenow + 0x3FFFFFFF;
+ m->NextScheduledSPS = m->timenow + FutureTime;
CheckProxyRecords(m, m->DuplicateRecords); // Clear m->DuplicateRecords first, then m->ResourceRecords
CheckProxyRecords(m, m->ResourceRecords);
}
@@ -5341,7 +5408,7 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
// as records could have expired during that check
if (m->timenow - m->NextScheduledKA >= 0)
{
- m->NextScheduledKA = m->timenow + 0x3FFFFFFF;
+ m->NextScheduledKA = m->timenow + FutureTime;
mDNS_SendKeepalives(m);
}
@@ -5525,16 +5592,17 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
m->RandomQueryDelay = 0;
m->RandomReconfirmDelay = 0;
+ // See if any questions (or local-only questions) have timed out
if (m->NextScheduledStopTime && m->timenow - m->NextScheduledStopTime >= 0) TimeoutQuestions(m);
#ifndef UNICAST_DISABLED
if (m->NextSRVUpdate && m->timenow - m->NextSRVUpdate >= 0) UpdateAllSRVRecords(m);
if (m->timenow - m->NextScheduledNATOp >= 0) CheckNATMappings(m);
if (m->timenow - m->NextuDNSEvent >= 0) uDNS_Tasks(m);
#endif
-#if APPLE_OSX_mDNSResponder
+#if APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
extern void serviceBLE();
if (m->NextBLEServiceTime && (m->timenow - m->NextBLEServiceTime >= 0)) serviceBLE();
-#endif // APPLE_OSX_mDNSResponder
+#endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR
}
// Note about multi-threaded systems:
@@ -5574,11 +5642,9 @@ mDNSlocal void SuspendLLQs(mDNS *m)
mDNSlocal mDNSBool QuestionHasLocalAnswers(mDNS *const m, DNSQuestion *q)
{
AuthRecord *rr;
- mDNSu32 slot;
AuthGroup *ag;
- slot = AuthHashSlot(&q->qname);
- ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname);
+ ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname);
if (ag)
{
for (rr = ag->members; rr; rr=rr->next)
@@ -5614,7 +5680,7 @@ mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question,
!SameDomainLabel(question->qname.c, (const mDNSu8 *)"\x0c_autotunnel6")&& question->QuestionCallback != AutoTunnelCallback)
{
question->NoAnswer = NoAnswer_Suspended;
- AddNewClientTunnel(m, question);
+ AddNewClientTunnel(question);
return;
}
#endif // APPLE_OSX_mDNSResponder
@@ -5890,7 +5956,7 @@ mDNSexport void mDNS_UpdateAllowSleep(mDNS *const m)
}
// Call the platform code to enable/disable sleep
- mDNSPlatformSetAllowSleep(m, allowSleep, reason);
+ mDNSPlatformSetAllowSleep(allowSleep, reason);
#else
(void) m;
#endif /* !defined(IDLESLEEPCONTROL_DISABLED) */
@@ -6001,7 +6067,7 @@ mDNSexport mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkIn
// now, then we don't update the DNS NULL record. But we do not prevent it from registering with the SPS. When SPS sees
// this DNS NULL record, it does not send any keepalives as it does not have all the information
mDNSPlatformMemZero(&mti, sizeof (mDNSTCPInfo));
- ret = mDNSPlatformRetrieveTCPInfo(m, &laddr, &lport, &raddr, &rport, &mti);
+ ret = mDNSPlatformRetrieveTCPInfo(&laddr, &lport, &raddr, &rport, &mti);
if (ret != mStatus_NoError)
{
LogMsg("mDNSPlatformRetrieveTCPInfo: mDNSPlatformRetrieveTCPInfo failed %d", ret);
@@ -6568,15 +6634,14 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m)
m->NextScheduledSPRetry = m->timenow;
+ // Clear out the SCDynamic entry that stores the external SPS information
+ mDNSPlatformClearSPSData();
+
if (!m->SystemWakeOnLANEnabled) LogSPS("BeginSleepProcessing: m->SystemWakeOnLANEnabled is false");
else if (!mDNSCoreHaveAdvertisedMulticastServices(m)) LogSPS("BeginSleepProcessing: No advertised services");
else // If we have at least one advertised service
{
NetworkInterfaceInfo *intf;
-
- // Clear out the SCDynamic entry that stores the external SPS information
- mDNSPlatformClearSPSData();
-
for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
{
// Intialize it to false. These values make sense only when SleepState is set to Sleeping.
@@ -6616,7 +6681,7 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m)
else if (SupportsInNICProxy(intf))
{
mDNSBool keepaliveOnly = mDNSfalse;
- if (ActivateLocalProxy(m, intf, &keepaliveOnly) == mStatus_NoError)
+ if (ActivateLocalProxy(intf, &keepaliveOnly) == mStatus_NoError)
{
SendGoodbyesForWakeOnlyService(m, &WakeOnlyService);
@@ -6833,11 +6898,6 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep)
// 2. Re-validate our cache records
currtime = mDNSPlatformUTC();
-#if APPLE_OSX_mDNSResponder
- // start time of this statistics gathering interval
- m->StatStartTime = currtime;
-#endif // APPLE_OSX_mDNSResponder
-
diff = currtime - m->TimeSlept;
FORALL_CACHERECORDS(slot, cg, cr)
{
@@ -6984,7 +7044,7 @@ mDNSexport mDNSBool mDNSCoreReadyForSleep(mDNS *m, mDNSs32 now)
if (rr->state == regState_Refresh && rr->tcp)
{ LogSPS("mDNSCoreReadyForSleep: waiting for Record updateIntID 0x%x 0x%x (updateid %d) %s", rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto notready; }
#if APPLE_OSX_mDNSResponder
- if (!RecordReadyForSleep(m, rr)) { LogSPS("mDNSCoreReadyForSleep: waiting for %s", ARDisplayString(m, rr)); goto notready; }
+ if (!RecordReadyForSleep(rr)) { LogSPS("mDNSCoreReadyForSleep: waiting for %s", ARDisplayString(m, rr)); goto notready; }
#endif
}
@@ -7315,8 +7375,7 @@ exit:
mDNSlocal CacheRecord *FindIdenticalRecordInCache(const mDNS *const m, const ResourceRecord *const pktrr)
{
- mDNSu32 slot = HashSlot(pktrr->name);
- CacheGroup *cg = CacheGroupForRecord(m, slot, pktrr);
+ CacheGroup *cg = CacheGroupForRecord(m, pktrr);
CacheRecord *rr;
mDNSBool match;
for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
@@ -7563,7 +7622,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
// We only mark this question for sending if it is at least one second since the last time we multicast it
// on this interface. If it is more than a second, or LastMCInterface is different, then we may multicast it.
// This is to guard against the case where someone blasts us with queries as fast as they can.
- if (m->timenow - (rr->LastMCTime + mDNSPlatformOneSecond) >= 0 ||
+ if ((mDNSu32)(m->timenow - rr->LastMCTime) >= (mDNSu32)mDNSPlatformOneSecond ||
(rr->LastMCInterface != mDNSInterfaceMark && rr->LastMCInterface != InterfaceID))
rr->NR_AnswerTo = NR_AnswerMulticast;
}
@@ -7592,44 +7651,25 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
if (query->h.flags.b[0] & kDNSFlag0_TC)
m->mDNSStats.KnownAnswerMultiplePkts++;
-#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
- if (QuestionNeedsMulticastResponse)
-#else
// We only do the following accelerated cache expiration and duplicate question suppression processing
// for non-truncated multicast queries with multicast responses.
// For any query generating a unicast response we don't do this because we can't assume we will see the response.
// For truncated queries we don't do this because a response we're expecting might be suppressed by a subsequent
// known-answer packet, and when there's packet loss we can't safely assume we'll receive *all* known-answer packets.
if (QuestionNeedsMulticastResponse && !(query->h.flags.b[0] & kDNSFlag0_TC))
-#endif
{
#if POOF_ENABLED
- const mDNSu32 slot = HashSlot(&pktq.qname);
- CacheGroup *cg = CacheGroupForName(m, slot, pktq.qnamehash, &pktq.qname);
+ CacheGroup *cg = CacheGroupForName(m, pktq.qnamehash, &pktq.qname);
CacheRecord *cr;
// Make a list indicating which of our own cache records we expect to see updated as a result of this query
// Note: Records larger than 1K are not habitually multicast, so don't expect those to be updated
-#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
- if (!(query->h.flags.b[0] & kDNSFlag0_TC))
-#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING
for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
if (SameNameRecordAnswersQuestion(&cr->resrec, &pktq) && cr->resrec.rdlength <= SmallRecordLimit)
if (!cr->NextInKAList && eap != &cr->NextInKAList)
{
*eap = cr;
eap = &cr->NextInKAList;
-#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
- if (cr->MPUnansweredQ == 0 || m->timenow - cr->MPLastUnansweredQT >= mDNSPlatformOneSecond)
- {
- // Although MPUnansweredQ is only really used for multi-packet query processing,
- // we increment it for both single-packet and multi-packet queries, so that it stays in sync
- // with the MPUnansweredKA value, which by necessity is incremented for both query types.
- cr->MPUnansweredQ++;
- cr->MPLastUnansweredQT = m->timenow;
- cr->MPExpectingKA = mDNStrue;
- }
-#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING
}
#endif // POOF_ENABLED
@@ -7637,9 +7677,6 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
// We only do this for non-truncated queries. Right now it would be too complicated to try
// to keep track of duplicate suppression state between multiple packets, especially when we
// can't guarantee to receive all of the Known Answer packets that go with a particular query.
-#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
- if (!(query->h.flags.b[0] & kDNSFlag0_TC))
-#endif
// For anonymous question, the duplicate suppressesion should happen if the
// question belongs in the same group. As the group is expected to be
// small, we don't do the optimization for now.
@@ -7723,16 +7760,6 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
ourcacherr = FindIdenticalRecordInCache(m, &m->rec.r.resrec);
- #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
- // See if this Known-Answer suppresses any answers we were expecting for our cache records. We do this always,
- // even if the TC bit is not set (the TC bit will *not* be set in the *last* packet of a multi-packet KA list).
- if (ourcacherr && ourcacherr->MPExpectingKA && m->timenow - ourcacherr->MPLastUnansweredQT < mDNSPlatformOneSecond)
- {
- ourcacherr->MPUnansweredKA++;
- ourcacherr->MPExpectingKA = mDNSfalse;
- }
- #endif
-
#if POOF_ENABLED
// Having built our ExpectedAnswers list from the questions in this packet, we then remove
// any records that are suppressed by the Known Answer list in this packet.
@@ -7779,13 +7806,9 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
mDNSBool SendMulticastResponse = mDNSfalse; // Send modern multicast response
mDNSBool SendUnicastResponse = mDNSfalse; // Send modern unicast response (not legacy unicast response)
-#if !TARGET_OS_EMBEDDED
- // always honor kDNSQClass_UnicastResponse in embedded environment to increase reliability
- // in high multicast packet loss environments.
-
// If it's been one TTL/4 since we multicast this, then send a multicast response
// for conflict detection, etc.
- if (m->timenow - (rr->LastMCTime + TicksTTL(rr)/4) >= 0)
+ if ((mDNSu32)(m->timenow - rr->LastMCTime) >= (mDNSu32)TicksTTL(rr)/4)
{
SendMulticastResponse = mDNStrue;
// If this record was marked for modern (delayed) unicast response, then mark it as promoted to
@@ -7797,7 +7820,6 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
rr->NR_AnswerTo = NR_AnswerMulticast;
}
}
-#endif // !TARGET_OS_EMBEDDED
// If the client insists on a multicast response, then we'd better send one
if (rr->NR_AnswerTo == NR_AnswerMulticast)
@@ -7925,12 +7947,7 @@ exit:
cr->UnansweredQueries++;
cr->LastUnansweredTime = m->timenow;
if (cr->UnansweredQueries > 1)
- #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
- debugf("ProcessQuery: (!TC) UAQ %lu MPQ %lu MPKA %lu %s",
- cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
- #else
debugf("ProcessQuery: UnansweredQueries %lu %s", cr->UnansweredQueries, CRDisplayString(m, cr));
- #endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING
SetNextCacheCheckTimeForRecord(m, cr);
}
@@ -7940,49 +7957,12 @@ exit:
{
// Only show debugging message if this record was not about to expire anyway
if (RRExpireTime(cr) - m->timenow > (mDNSs32) kDefaultReconfirmTimeForNoAnswer * 4 / 3 + mDNSPlatformOneSecond)
- #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
- debugf("ProcessQuery: (Max) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
- cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
- #else
- LogInfo("ProcessQuery: UnansweredQueries %lu TTL %lu mDNS_Reconfirm() for %s",
- cr->UnansweredQueries, (RRExpireTime(cr) - m->timenow + mDNSPlatformOneSecond-1) / mDNSPlatformOneSecond, CRDisplayString(m, cr));
- #endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING
+ LogInfo("ProcessQuery: UnansweredQueries %lu interface %lu TTL %lu mDNS_Reconfirm() for %s",
+ cr->UnansweredQueries, InterfaceID, (RRExpireTime(cr) - m->timenow + mDNSPlatformOneSecond-1) / mDNSPlatformOneSecond, CRDisplayString(m, cr));
m->mDNSStats.PoofCacheDeletions++;
mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
}
-#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
- // Make a guess, based on the multi-packet query / known answer counts, whether we think we
- // should have seen an answer for this. (We multiply MPQ by 4 and MPKA by 5, to allow for
- // possible packet loss of up to 20% of the additional KA packets.)
- else if (cr->MPUnansweredQ * 4 > cr->MPUnansweredKA * 5 + 8)
- {
- // We want to do this conservatively.
- // If there are so many machines on the network that they have to use multi-packet known-answer lists,
- // then we don't want them to all hit the network simultaneously with their final expiration queries.
- // By setting the record to expire in four minutes, we achieve two things:
- // (a) the 90-95% final expiration queries will be less bunched together
- // (b) we allow some time for us to witness enough other failed queries that we don't have to do our own
- mDNSu32 remain = (mDNSu32)(RRExpireTime(cr) - m->timenow) / 4;
- if (remain > 240 * (mDNSu32)mDNSPlatformOneSecond)
- remain = 240 * (mDNSu32)mDNSPlatformOneSecond;
-
- // Only show debugging message if this record was not about to expire anyway
- if (RRExpireTime(cr) - m->timenow > 4 * mDNSPlatformOneSecond)
- debugf("ProcessQuery: (MPQ) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
- cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
-
- if (remain <= 60 * (mDNSu32)mDNSPlatformOneSecond)
- cr->UnansweredQueries++; // Treat this as equivalent to one definite unanswered query
- cr->MPUnansweredQ = 0; // Clear MPQ/MPKA statistics
- cr->MPUnansweredKA = 0;
- cr->MPExpectingKA = mDNSfalse;
-
- if (remain < kDefaultReconfirmTimeForNoAnswer)
- remain = kDefaultReconfirmTimeForNoAnswer;
- mDNS_Reconfirm_internal(m, cr, remain);
- }
-#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING
}
#endif // POOF_ENABLED
@@ -8229,19 +8209,13 @@ mDNSlocal void RefreshCacheRecord(mDNS *const m, CacheRecord *rr, mDNSu32 ttl)
rr->TimeRcvd = m->timenow;
rr->resrec.rroriginalttl = ttl;
rr->UnansweredQueries = 0;
-#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
- rr->MPUnansweredQ = 0;
- rr->MPUnansweredKA = 0;
- rr->MPExpectingKA = mDNSfalse;
-#endif
SetNextCacheCheckTimeForRecord(m, rr);
}
mDNSexport void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease)
{
CacheRecord *rr;
- const mDNSu32 slot = HashSlot(&q->qname);
- CacheGroup *cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+ CacheGroup *cg = CacheGroupForName(m, q->qnamehash, &q->qname);
for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
if (rr->CRActiveQuestion == q)
{
@@ -8454,8 +8428,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage *
if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr)))
{
CacheRecord *rr, *neg = mDNSNULL;
- mDNSu32 slot = HashSlot(&q.qname);
- CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname);
+ CacheGroup *cg = CacheGroupForName(m, q.qnamehash, &q.qname);
for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
if (SameNameRecordAnswersQuestion(&rr->resrec, qptr))
{
@@ -8524,8 +8497,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage *
ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_SOA)
{
- const mDNSu32 s = HashSlot(m->rec.r.resrec.name);
- CacheGroup *cgSOA = CacheGroupForRecord(m, s, &m->rec.r.resrec);
+ CacheGroup *cgSOA = CacheGroupForRecord(m, &m->rec.r.resrec);
const rdataSOA *const soa = (const rdataSOA *)m->rec.r.resrec.rdata->u.data;
mDNSu32 ttl_s = soa->min;
// We use the lesser of the SOA.MIN field and the SOA record's TTL, *except*
@@ -8537,7 +8509,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage *
// Create the SOA record as we may have to return this to the questions
// that we are acting as a proxy for currently or in the future.
- SOARecord = CreateNewCacheEntry(m, s, cgSOA, 1, mDNSfalse, mDNSNULL);
+ SOARecord = CreateNewCacheEntry(m, HashSlotFromNameHash(m->rec.r.resrec.namehash), cgSOA, 1, mDNSfalse, mDNSNULL);
// Special check for SOA queries: If we queried for a.b.c.d.com, and got no answer,
// with an Authority Section SOA record for d.com, then this is a hint that the authority
@@ -8620,12 +8592,12 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage *
// been NULL. If we pass NULL cg to new cache entries that we create below,
// it will create additional cache groups for the same name. To avoid that,
// look up the cache group again to re-initialize cg again.
- cg = CacheGroupForName(m, slot, hash, name);
+ cg = CacheGroupForName(m, hash, name);
if (NSECRecords && DNSSECQuestion(qptr))
{
// Create the cache entry with delay and then add the NSEC records
// to it and add it immediately.
- negcr = CreateNewCacheEntry(m, slot, cg, 1, mDNStrue, mDNSNULL);
+ negcr = CreateNewCacheEntry(m, HashSlotFromNameHash(hash), cg, 1, mDNStrue, mDNSNULL);
if (negcr)
{
negcr->CRDNSSECQuestion = 0;
@@ -8650,7 +8622,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage *
else
{
// Need to add with a delay so that we can tag the SOA record
- negcr = CreateNewCacheEntry(m, slot, cg, 1, mDNStrue, mDNSNULL);
+ negcr = CreateNewCacheEntry(m, HashSlotFromNameHash(hash), cg, 1, mDNStrue, mDNSNULL);
if (negcr)
{
negcr->CRDNSSECQuestion = 0;
@@ -8674,9 +8646,6 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage *
repeat--;
name = (const domainname *)(name->c + 1 + name->c[0]);
hash = DomainNameHashValue(name);
- slot = HashSlot(name);
- // For now, we don't need to update cg here, because we'll do it again immediately, back up at the start of this loop
- //cg = CacheGroupForName(m, slot, hash, name);
}
}
}
@@ -8891,7 +8860,6 @@ mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const resp
}
for (i = 0; i < response->h.numAuthorities && ptr && ptr < end; i++)
{
- mDNSu32 slot;
CacheGroup *cg;
ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec);
@@ -8901,11 +8869,10 @@ mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const resp
m->rec.r.resrec.RecordType = 0;
continue;
}
- slot = HashSlot(m->rec.r.resrec.name);
- cg = CacheGroupForRecord(m, slot, &m->rec.r.resrec);
+ cg = CacheGroupForRecord(m, &m->rec.r.resrec);
// Create the cache entry but don't add it to the cache it. We need
// to cache this along with the main cache record.
- rr = CreateNewCacheEntry(m, slot, cg, 0, mDNSfalse, mDNSNULL);
+ rr = CreateNewCacheEntry(m, HashSlotFromNameHash(m->rec.r.resrec.namehash), cg, 0, mDNSfalse, mDNSNULL);
if (rr)
{
debugf("mDNSParseNSEC3Records: %s", CRDisplayString(m, rr));
@@ -9027,8 +8994,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
CacheRecord *rr;
// Remember the unicast question that we found, which we use to make caching
// decisions later on in this function
- const mDNSu32 slot = HashSlot(&q.qname);
- CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname);
+ CacheGroup *cg = CacheGroupForName(m, q.qnamehash, &q.qname);
if (!mDNSOpaque16IsZero(response->h.id))
{
unicastQuestion = qptr;
@@ -9401,7 +9367,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
// have any record(s) of the same type that we should re-assert to rescue them
// (see note about "multi-homing and bridged networks" at the end of this function).
else if (m->rec.r.resrec.rrtype == rr->resrec.rrtype)
- if ((m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) && m->timenow - rr->LastMCTime > mDNSPlatformOneSecond/2)
+ if ((m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) && (mDNSu32)(m->timenow - rr->LastMCTime) > (mDNSu32)mDNSPlatformOneSecond/2)
{ rr->ImmedAnswer = mDNSInterfaceMark; m->NextScheduledResponse = m->timenow; }
}
}
@@ -9420,8 +9386,8 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
if (!AcceptableResponse) LogInfo("mDNSCoreReceiveResponse ignoring %s", CRDisplayString(m, &m->rec.r));
if (m->rrcache_size && AcceptableResponse)
{
- const mDNSu32 slot = HashSlot(m->rec.r.resrec.name);
- CacheGroup *cg = CacheGroupForRecord(m, slot, &m->rec.r.resrec);
+ const mDNSu32 slot = HashSlotFromNameHash(m->rec.r.resrec.namehash);
+ CacheGroup *cg = CacheGroupForRecord(m, &m->rec.r.resrec);
CacheRecord *rr = mDNSNULL;
if (McastNSEC3Records)
@@ -9447,7 +9413,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
if (AddToCFList)
delay = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
else
- delay = CheckForSoonToExpireRecords(m, m->rec.r.resrec.name, m->rec.r.resrec.namehash, slot, mDNSNULL);
+ delay = CheckForSoonToExpireRecords(m, m->rec.r.resrec.name, m->rec.r.resrec.namehash, mDNSNULL);
// If unique, assume we may have to delay delivery of this 'add' event.
// Below, where we walk the CacheFlushRecords list, we either call CacheRecordDeferredAdd()
@@ -9513,8 +9479,8 @@ exit:
while (CacheFlushRecords != (CacheRecord*)1)
{
CacheRecord *r1 = CacheFlushRecords, *r2;
- const mDNSu32 slot = HashSlot(r1->resrec.name);
- const CacheGroup *cg = CacheGroupForRecord(m, slot, &r1->resrec);
+ const mDNSu32 slot = HashSlotFromNameHash(r1->resrec.namehash);
+ const CacheGroup *cg = CacheGroupForRecord(m, &r1->resrec);
CacheFlushRecords = CacheFlushRecords->NextInCFList;
r1->NextInCFList = mDNSNULL;
@@ -9664,7 +9630,7 @@ exit:
NSECRecords = mDNSNULL;
NSECCachePtr = mDNSNULL;
}
- r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash, slot, mDNSNULL);
+ r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash, mDNSNULL);
// If no longer delaying, deliver answer now, else schedule delivery for the appropriate time
if (!r1->DelayDelivery) CacheRecordDeferredAdd(m, r1);
else ScheduleNextCacheCheckTime(m, slot, r1->DelayDelivery);
@@ -10382,13 +10348,14 @@ mDNSlocal mDNSu32 mDNSGenerateOwnerOptForInterface(mDNS *const m, const mDNSInte
mDNSu8 *end = mDNSNULL;
mDNSu32 length = 0;
AuthRecord opt;
+ NetworkInterfaceInfo *intf;
mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
opt.resrec.rrclass = NormalMaxDNSMessageData;
opt.resrec.rdlength = sizeof(rdataOPT);
opt.resrec.rdestimate = sizeof(rdataOPT);
- NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
+ intf = FirstInterfaceForID(m, InterfaceID);
SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
LogSPS("Generated OPT record : %s", ARDisplayString(m, &opt));
@@ -10405,30 +10372,18 @@ mDNSlocal mDNSu32 mDNSGenerateOwnerOptForInterface(mDNS *const m, const mDNSInte
return length;
}
+// Note that this routine is called both for Sleep Proxy Registrations, and for Standard Dynamic
+// DNS registrations, but (currently) only has to handle the Sleep Proxy Registration reply case,
+// and should ignore Standard Dynamic DNS registration replies, because those are handled elsewhere.
+// Really, both should be unified and handled in one place.
mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *end, const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID)
{
if (InterfaceID)
{
- mDNSu32 updatelease = 60 * 60; // If SPS fails to indicate lease time, assume one hour
- const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space);
- mDNSAddr spsaddr;
- char *ifname;
- if (ptr)
- {
- ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec);
- if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_OPT)
- {
- const rdataOPT *o;
- const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength];
- for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++)
- if (o->opt == kDNSOpt_Lease)
- {
- updatelease = o->u.updatelease;
- LogSPS("Sleep Proxy granted lease time %4d seconds, updateid %d, InterfaceID %p", updatelease, mDNSVal16(msg->h.id), InterfaceID);
- }
- }
- m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it
- }
+ mDNSu32 pktlease = 0, spsupdates = 0;
+ const mDNSBool gotlease = GetPktLease(m, msg, end, &pktlease);
+ const mDNSu32 updatelease = gotlease ? pktlease : 60 * 60; // If SPS fails to indicate lease time, assume one hour
+ if (gotlease) LogSPS("DNS Update response contains lease option granting %4d seconds, updateid %d, InterfaceID %p", updatelease, mDNSVal16(msg->h.id), InterfaceID);
if (m->CurrentRecord)
LogMsg("mDNSCoreReceiveUpdateR ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
@@ -10447,7 +10402,8 @@ mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg
if (mDNSOpaque64IsZero(&rr->updateIntID))
rr->updateid = zeroID;
rr->expire = NonZeroTime(m->timenow + updatelease * mDNSPlatformOneSecond);
- LogSPS("Sleep Proxy %s record %5d 0x%x 0x%x (%d) %s", rr->WakeUp.HMAC.l[0] ? "transferred" : "registered", updatelease, rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr));
+ spsupdates++;
+ LogSPS("Sleep Proxy %s record %2d %5d 0x%x 0x%x (%d) %s", rr->WakeUp.HMAC.l[0] ? "transferred" : "registered", spsupdates, updatelease, rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr));
if (rr->WakeUp.HMAC.l[0])
{
rr->WakeUp.HMAC = zeroEthAddr; // Clear HMAC so that mDNS_Deregister_internal doesn't waste packets trying to wake this host
@@ -10460,22 +10416,26 @@ mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg
if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now
m->CurrentRecord = rr->next;
}
-
- // Update the dynamic store with the IP Address and MAC address of the sleep proxy
- ifname = InterfaceNameForID(m, InterfaceID);
- mDNSPlatformMemCopy(&spsaddr, srcaddr, sizeof (mDNSAddr));
- mDNSPlatformStoreSPSMACAddr(&spsaddr, ifname);
-
- // Store the Owner OPT record for this interface.
- // Configd may use the OPT record if it detects a conflict with the BSP when the system wakes up
- DNSMessage optMsg;
- int length = 0;
- InitializeDNSMessage(&optMsg.h, zeroID, ResponseFlags);
- length = mDNSGenerateOwnerOptForInterface(m, InterfaceID, &optMsg);
- if (length != 0)
+ if (spsupdates) // Only do this dynamic store stuff if this was, in fact, a Sleep Proxy Update response
{
- length += sizeof(DNSMessageHeader);
- mDNSPlatformStoreOwnerOptRecord(ifname, &optMsg, length);
+ char *ifname;
+ mDNSAddr spsaddr;
+ DNSMessage optMsg;
+ int length;
+ // Update the dynamic store with the IP Address and MAC address of the sleep proxy
+ ifname = InterfaceNameForID(m, InterfaceID);
+ mDNSPlatformMemCopy(&spsaddr, srcaddr, sizeof (mDNSAddr));
+ mDNSPlatformStoreSPSMACAddr(&spsaddr, ifname);
+
+ // Store the Owner OPT record for this interface.
+ // Configd may use the OPT record if it detects a conflict with the BSP when the system wakes up
+ InitializeDNSMessage(&optMsg.h, zeroID, ResponseFlags);
+ length = mDNSGenerateOwnerOptForInterface(m, InterfaceID, &optMsg);
+ if (length != 0)
+ {
+ length += sizeof(DNSMessageHeader);
+ mDNSPlatformStoreOwnerOptRecord(ifname, &optMsg, length);
+ }
}
}
// If we were waiting to go to sleep, then this SPS registration or wide-area record deletion
@@ -10512,12 +10472,6 @@ mDNSexport void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr,
cr->CRActiveQuestion = mDNSNULL;
cr->UnansweredQueries = 0;
cr->LastUnansweredTime = 0;
-#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
- cr->MPUnansweredQ = 0;
- cr->MPLastUnansweredQT = 0;
- cr->MPUnansweredKA = 0;
- cr->MPExpectingKA = mDNSfalse;
-#endif
cr->NextInCFList = mDNSNULL;
cr->nsec = mDNSNULL;
cr->soa = mDNSNULL;
@@ -10595,7 +10549,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNS
// Track the number of multicast packets received from a source outside our subnet.
// Check the destination address to avoid accounting for spurious packets that
// comes in with message id zero.
- if (!mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr) &&
+ if (!mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr) && dstaddr &&
mDNSAddressIsAllDNSLinkGroup(dstaddr))
{
m->RemoteSubnet++;
@@ -10624,8 +10578,8 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNS
{
static int msgCount = 0;
if (msgCount < 1000) {
- msgCount++;
int i = 0;
+ msgCount++;
LogInfo("Unknown DNS packet type %02X%02X from %#-15a:%-5d to %#-15a:%-5d length %d on %p (ignored)",
msg->h.flags.b[0], msg->h.flags.b[1], srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - pkt), InterfaceID);
while (i < (int)(end - pkt))
@@ -10658,6 +10612,11 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNS
#define SameQTarget(A,B) (((A)->Target.type == mDNSAddrType_None && (B)->Target.type == mDNSAddrType_None) || \
(mDNSSameAddress(& (A)->Target, & (B)->Target) && mDNSSameIPPort((A)->TargetPort, (B)->TargetPort)))
+// SameQuestionKind is true if *both* questions are either multicast or unicast
+// TargetQID is used for this determination.
+#define SameQuestionKind(A,B) ((mDNSOpaque16IsZero(A) && mDNSOpaque16IsZero(B)) || \
+ ((!mDNSOpaque16IsZero(A)) && (!mDNSOpaque16IsZero(B))))
+
// Note: We explicitly disallow making a public query be a duplicate of a private one. This is to avoid the
// circular deadlock where a client does a query for something like "dns-sd -Q _dns-query-tls._tcp.company.com SRV"
// and we have a key for company.com, so we try to locate the private query server for company.com, which necessarily entails
@@ -10701,8 +10660,9 @@ mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuest
(q->DisallowPID == question->DisallowPID) && // Disallowing a PID should not affect a PID that is allowed
(q->BrowseThreshold == question->BrowseThreshold) && // browse thresholds must match
q->qnamehash == question->qnamehash &&
- (IsAWDLIncluded(q) == IsAWDLIncluded(question)) && // Inclusion of AWDL interface must match
- SameDomainName(&q->qname, &question->qname)) // and name
+ (IsAWDLIncluded(q) == IsAWDLIncluded(question)) && // Inclusion of AWDL interface must match
+ SameQuestionKind(q->TargetQID, question->TargetQID) && // mDNS or uDNS must match
+ SameDomainName(&q->qname, &question->qname)) // and name
return(q);
return(mDNSNULL);
}
@@ -11007,7 +10967,7 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question)
mDNSu32 timeout = 0;
mDNSBool DEQuery;
- question->validDNSServers = zeroOpaque64;
+ question->validDNSServers = zeroOpaque128;
DEQuery = DomainEnumQuery(&question->qname);
for (curr = m->DNSServers; curr; curr = curr->next)
{
@@ -11036,6 +10996,7 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question)
currcount = CountLabels(&curr->domain);
if ((!curr->cellIntf || (!DEQuery && !(question->flags & kDNSServiceFlagsDenyCellular))) &&
+ (!curr->isExpensive || !(question->flags & kDNSServiceFlagsDenyExpensive)) &&
DNSServerMatch(curr, question->InterfaceID, question->ServiceID))
{
bettermatch = BetterMatchForName(&question->qname, namecount, &curr->domain, currcount, bestmatchlen);
@@ -11050,7 +11011,7 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question)
if (bettermatch)
{
debugf("SetValidDNSServers: Resetting all the bits");
- question->validDNSServers = zeroOpaque64;
+ question->validDNSServers = zeroOpaque128;
timeout = 0;
}
debugf("SetValidDNSServers: question %##s Setting the bit for DNS server Address %#a (Domain %##s), Scoped:%d index %d,"
@@ -11059,15 +11020,15 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question)
timeout += curr->timeout;
if (DEQuery)
debugf("DomainEnumQuery: Question %##s, DNSServer %#a, cell %d", question->qname.c, &curr->addr, curr->cellIntf);
- bit_set_opaque64(question->validDNSServers, index);
+ bit_set_opaque128(question->validDNSServers, index);
}
}
index++;
}
question->noServerResponse = 0;
- debugf("SetValidDNSServers: ValidDNSServer bits 0x%x%x for question %p %##s (%s)",
- question->validDNSServers.l[1], question->validDNSServers.l[0], question, question->qname.c, DNSTypeName(question->qtype));
+ debugf("SetValidDNSServers: ValidDNSServer bits 0x%x%x%x%x for question %p %##s (%s)",
+ question->validDNSServers.l[3], question->validDNSServers.l[2], question->validDNSServers.l[1], question->validDNSServers.l[0], question, question->qname.c, DNSTypeName(question->qtype));
// If there are no matching resolvers, then use the default timeout value.
// For ProxyQuestion, shorten the timeout so that dig does not timeout on us in case of no response.
return ((question->ProxyQuestion || question->ValidatingResponse) ? DEFAULT_UDNSSEC_TIMEOUT : timeout ? timeout : DEFAULT_UDNS_TIMEOUT);
@@ -11075,7 +11036,7 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question)
// Get the Best server that matches a name. If you find penalized servers, look for the one
// that will come out of the penalty box soon
-mDNSlocal DNSServer *GetBestServer(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID, mDNSs32 ServiceID, mDNSOpaque64 validBits,
+mDNSlocal DNSServer *GetBestServer(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID, mDNSs32 ServiceID, mDNSOpaque128 validBits,
int *selected, mDNSBool nameMatch)
{
DNSServer *curmatch = mDNSNULL;
@@ -11154,7 +11115,7 @@ mDNSlocal DNSServer *GetServerForName(mDNS *m, const domainname *name, mDNSInter
{
DNSServer *curmatch = mDNSNULL;
char *ifname = mDNSNULL; // for logging purposes only
- mDNSOpaque64 allValid;
+ mDNSOpaque128 allValid;
if ((InterfaceID == mDNSInterface_Unicast) || (InterfaceID == mDNSInterface_LocalOnly))
InterfaceID = mDNSNULL;
@@ -11162,7 +11123,7 @@ mDNSlocal DNSServer *GetServerForName(mDNS *m, const domainname *name, mDNSInter
if (InterfaceID) ifname = InterfaceNameForID(m, InterfaceID);
// By passing in all ones, we make sure that every DNS server is considered
- allValid.l[0] = allValid.l[1] = 0xFFFFFFFF;
+ allValid.l[0] = allValid.l[1] = allValid.l[2] = allValid.l[3] = 0xFFFFFFFF;
curmatch = GetBestServer(m, name, InterfaceID, ServiceID, allValid, mDNSNULL, mDNStrue);
@@ -11191,11 +11152,11 @@ mDNSexport DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question)
if (InterfaceID)
ifname = InterfaceNameForID(m, InterfaceID);
- if (!mDNSOpaque64IsZero(&question->validDNSServers))
+ if (!mDNSOpaque128IsZero(&question->validDNSServers))
{
curmatch = GetBestServer(m, name, InterfaceID, question->ServiceID, question->validDNSServers, &currindex, mDNSfalse);
if (currindex != -1)
- bit_clr_opaque64(question->validDNSServers, currindex);
+ bit_clr_opaque128(question->validDNSServers, currindex);
}
if (curmatch != mDNSNULL)
@@ -11289,6 +11250,13 @@ mDNSlocal mDNSBool ShouldSuppressUnicastQuery(mDNS *const m, DNSQuestion *q, DNS
DNSTypeName(q->qtype), d->domain.c, &d->addr, mDNSVal16(d->port));
return mDNSfalse;
}
+#if USE_DNS64
+ if (DNS64IsQueryingARecord(q->dns64.state))
+ {
+ LogInfo("ShouldSuppressUnicastQuery: DNS64 query not suppressed for %##s, qtype %s", q->qname.c, DNSTypeName(q->qtype));
+ return mDNSfalse;
+ }
+#endif
LogInfo("ShouldSuppressUnicastQuery: Query suppressed for %##s, qtype %s, since DNS Configuration does not allow (req_A is %s and req_AAAA is %s)",
q->qname.c, DNSTypeName(q->qtype), d->req_A ? "true" : "false", d->req_AAAA ? "true" : "false");
@@ -11384,11 +11352,9 @@ mDNSlocal mDNSBool ShouldSuppressQuery(mDNS *const m, DNSQuestion *q)
mDNSlocal void CacheRecordRmvEventsForCurrentQuestion(mDNS *const m, DNSQuestion *q)
{
CacheRecord *rr;
- mDNSu32 slot;
CacheGroup *cg;
- slot = HashSlot(&q->qname);
- cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+ cg = CacheGroupForName(m, q->qnamehash, &q->qname);
for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
{
// Don't deliver RMV events for negative records
@@ -11445,7 +11411,6 @@ mDNSlocal mDNSBool IsQuestionNew(mDNS *const m, DNSQuestion *question)
mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q)
{
AuthRecord *rr;
- mDNSu32 slot;
AuthGroup *ag;
if (m->CurrentQuestion)
@@ -11458,8 +11423,7 @@ mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q
return mDNStrue;
}
m->CurrentQuestion = q;
- slot = AuthHashSlot(&q->qname);
- ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname);
+ ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname);
if (ag)
{
for (rr = ag->members; rr; rr=rr->next)
@@ -11485,7 +11449,7 @@ mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q
// Returns false if the question got deleted while delivering the RMV events
// The caller should handle the case
-mDNSlocal mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q)
+mDNSexport mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q)
{
if (m->CurrentQuestion)
LogMsg("CacheRecordRmvEventsForQuestion: ERROR m->CurrentQuestion already set: %##s (%s)",
@@ -11684,33 +11648,29 @@ mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question)
{
// First reset all DNS Configuration
question->qDNSServer = mDNSNULL;
- question->validDNSServers = zeroOpaque64;
+ question->validDNSServers = zeroOpaque128;
question->triedAllServersOnce = 0;
question->noServerResponse = 0;
- question->StopTime = 0;
-#if TARGET_OS_EMBEDDED
+ question->StopTime = (question->TimeoutQuestion) ? question->StopTime : 0;
+#if AWD_METRICS
mDNSPlatformMemZero(&question->metrics, sizeof(question->metrics));
#endif
- // Need not initialize the DNS Configuration for Local Only OR P2P Questions
- if (LocalOnlyOrP2PInterface(question->InterfaceID))
+ // Need not initialize the DNS Configuration for Local Only OR P2P Questions when timeout not specified
+ if (LocalOnlyOrP2PInterface(question->InterfaceID) && !question->TimeoutQuestion)
return;
// Proceed to initialize DNS Configuration (some are set in SetValidDNSServers())
if (!mDNSOpaque16IsZero(question->TargetQID))
{
mDNSu32 timeout = SetValidDNSServers(m, question);
- // We set the timeout whenever mDNS_StartQuery_internal is called. This means if we have
- // a networking change/search domain change that calls this function again we keep
- // reinitializing the timeout value which means it may never timeout. If this becomes
- // a common case in the future, we can easily fix this by adding extra state that
- // indicates that we have already set the StopTime.
- //
- // Note that we set the timeout for all questions. If this turns out to be a duplicate,
+ // We set the timeout value the first time mDNS_StartQuery_internal is called for a question.
+ // So if a question is restarted when a network change occurs, the StopTime is not reset.
+ // Note that we set the timeout for all questions. If this turns out to be a duplicate,
// it gets a full timeout value even if the original question times out earlier.
- if (question->TimeoutQuestion)
+ if (question->TimeoutQuestion && !question->StopTime)
{
question->StopTime = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond);
- LogInfo("InitDNSConfig: Setting StopTime on question %p %##s (%s)", question, question->qname.c, DNSTypeName(question->qtype));
+ LogInfo("InitDNSConfig: Setting StopTime on the uDNS question %p %##s (%s)", question, question->qname.c, DNSTypeName(question->qtype));
}
question->qDNSServer = GetServerForQuestion(m, question);
@@ -11719,17 +11679,22 @@ mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question)
question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL,
mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort));
}
- else
+ else if (question->TimeoutQuestion && !question->StopTime)
{
- if (question->TimeoutQuestion)
- question->StopTime = NonZeroTime(m->timenow + GetTimeoutForMcastQuestion(m, question) * mDNSPlatformOneSecond);
+ // If the question is to be timed out and its a multicast, local-only or P2P case,
+ // then set it's stop time.
+ mDNSu32 timeout = LocalOnlyOrP2PInterface(question->InterfaceID) ?
+ DEFAULT_LO_OR_P2P_TIMEOUT : GetTimeoutForMcastQuestion(m, question);
+ question->StopTime = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond);
+ LogInfo("InitDNSConfig: Setting StopTime on question %p %##s (%s)", question, question->qname.c, DNSTypeName(question->qtype));
}
// Set StopTime here since it is a part of DNS Configuration
if (question->StopTime)
SetNextQueryStopTime(m, question);
- // SetNextQueryTime() need not be initialized for LocalOnly OR P2P Questions since those questions
- // will never be transmitted on the wire. Hence we call SetNextQueryTime() here.
- SetNextQueryTime(m,question);
+ // Don't call SetNextQueryTime() if a LocalOnly OR P2P Question since those questions
+ // will never be transmitted on the wire.
+ if (!(LocalOnlyOrP2PInterface(question->InterfaceID)))
+ SetNextQueryTime(m,question);
}
// InitCommonState() is called by mDNS_StartQuery_internal() to initialize the common(uDNS/mDNS) internal
@@ -11755,7 +11720,7 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question)
// turned ON which can allocate memory e.g., base64 encoding, in the case of DNSSEC.
question->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question
question->qnamehash = DomainNameHashValue(&question->qname);
- question->DelayAnswering = CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash, HashSlot(&question->qname), &purge);
+ question->DelayAnswering = CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash, &purge);
question->LastQTime = m->timenow;
question->ExpectUnicastResp = 0;
question->LastAnswerPktNum = m->PktNum;
@@ -11792,7 +11757,7 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question)
if (!(question->flags & kDNSServiceFlagsServiceIndex))
{
#if APPLE_OSX_mDNSResponder
- mDNSPlatformGetDNSRoutePolicy(m, question, &isBlocked);
+ mDNSPlatformGetDNSRoutePolicy(question, &isBlocked);
#else
question->ServiceID = -1;
#endif
@@ -11897,10 +11862,12 @@ mDNSlocal void InitLLQState(DNSQuestion *const question)
question->id = zeroOpaque64;
}
+#ifdef DNS_PUSH_ENABLED
mDNSlocal void InitDNSPNState(DNSQuestion *const question)
{
question->dnsPushState = DNSPUSH_INIT;
}
+#endif // DNS_PUSH_ENABLED
// InitDNSSECProxyState() is called by mDNS_StartQuery_internal() to initialize
// DNSSEC & DNS Proxy fields of the DNS Question.
@@ -11941,6 +11908,16 @@ mDNSlocal void FinalizeUnicastQuestion(mDNS *const m, DNSQuestion *question, mDN
if (question->DuplicateOf)
{
question->validDNSServers = question->DuplicateOf->validDNSServers;
+ // If current(dup) question has DNS Server assigned but the original question has no DNS Server assigned to it,
+ // then we log a line as it could indicate an issue
+ if (question->DuplicateOf->qDNSServer == mDNSNULL)
+ {
+ if (question->qDNSServer)
+ LogInfo("FinalizeUnicastQuestion: Current(dup) question %p has DNSServer(%#a:%d) but original question(%p) has no DNS Server! %##s (%s)",
+ question, question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL,
+ mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort),
+ question->DuplicateOf, question->qname.c, DNSTypeName(question->qtype));
+ }
question->qDNSServer = question->DuplicateOf->qDNSServer;
LogInfo("FinalizeUnicastQuestion: Duplicate question %p (%p) %##s (%s), DNS Server %#a:%d",
question, question->DuplicateOf, question->qname.c, DNSTypeName(question->qtype),
@@ -12031,7 +12008,9 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
purge = InitCommonState(m, question);
InitWABState(question);
InitLLQState(question);
+#ifdef DNS_PUSH_ENABLED
InitDNSPNState(question);
+#endif // DNS_PUSH_ENABLED
InitDNSSECProxyState(m, question);
// FindDuplicateQuestion should be called last after all the intialization
@@ -12108,8 +12087,7 @@ mDNSexport void CancelGetZoneData(mDNS *const m, ZoneData *nta)
mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question)
{
- const mDNSu32 slot = HashSlot(&question->qname);
- CacheGroup *cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname);
+ CacheGroup *cg = CacheGroupForName(m, question->qnamehash, &question->qname);
CacheRecord *rr;
DNSQuestion **qp = &m->Questions;
@@ -12139,24 +12117,16 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
}
#endif // BONJOUR_ON_DEMAND
-#if TARGET_OS_EMBEDDED
+#if AWD_METRICS
if (Question_uDNS(question) && !question->metrics.answered && (question->metrics.querySendCount > 0))
{
const domainname * queryName;
mDNSBool isForCell;
mDNSu32 durationMs;
- queryName = question->metrics.originalQName ? question->metrics.originalQName : &question->qname;
- isForCell = (question->qDNSServer && question->qDNSServer->cellIntf);
-
- if (question->metrics.querySendCount > 0)
- {
- durationMs = ((m->timenow - question->metrics.firstQueryTime) * 1000) / mDNSPlatformOneSecond;
- }
- else
- {
- durationMs = 0;
- }
+ queryName = question->metrics.originalQName ? question->metrics.originalQName : &question->qname;
+ isForCell = (question->qDNSServer && question->qDNSServer->cellIntf);
+ durationMs = ((m->timenow - question->metrics.firstQueryTime) * 1000) / mDNSPlatformOneSecond;
MetricsUpdateUDNSQueryStats(queryName, question->qtype, mDNSNULL, question->metrics.querySendCount, durationMs, isForCell);
}
#endif
@@ -12279,6 +12249,7 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
question->tcp = mDNSNULL;
}
}
+#ifdef DNS_PUSH_ENABLED
else if (question->dnsPushState == DNSPUSH_ESTABLISHED)
{
if (question->tcp)
@@ -12288,6 +12259,7 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
question->tcp = mDNSNULL;
}
}
+#endif // DNS_PUSH_ENABLED
#if APPLE_OSX_mDNSResponder
UpdateAutoTunnelDomainStatuses(m);
#endif
@@ -12306,7 +12278,7 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
FreeAnonInfo(question->AnonInfo);
question->AnonInfo = mDNSNULL;
}
-#if TARGET_OS_EMBEDDED
+#if AWD_METRICS
if (question->metrics.originalQName)
{
mDNSPlatformMemFree(question->metrics.originalQName);
@@ -12314,6 +12286,10 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
}
#endif
+#if USE_DNS64
+ DNS64ResetState(question);
+#endif
+
return(mStatus_NoError);
}
@@ -12352,8 +12328,7 @@ mDNSexport mStatus mDNS_StopQueryWithRemoves(mDNS *const m, DNSQuestion *const q
if (status == mStatus_NoError && !qq)
{
const CacheRecord *rr;
- const mDNSu32 slot = HashSlot(&question->qname);
- CacheGroup *const cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname);
+ CacheGroup *const cg = CacheGroupForName(m, question->qnamehash, &question->qname);
LogInfo("Generating terminal removes for %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
if (rr->resrec.RecordType != kDNSRecordTypePacketNegative && SameNameRecordAnswersQuestion(&rr->resrec, question))
@@ -12585,6 +12560,8 @@ mDNSlocal NetworkInterfaceInfo *FindFirstAdvertisedInterface(mDNS *const m)
return(intf);
}
+// The parameter "set" here refers to the set of AuthRecords used to advertise this interface.
+// (It's a set of records, not a set of interfaces.)
mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
{
char buffer[MAX_REVERSE_MAPPING_NAME];
@@ -12599,6 +12576,8 @@ mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
primary = FindFirstAdvertisedInterface(m);
if (!primary) primary = set; // If no existing advertised interface, this new NetworkInterfaceInfo becomes our new primary
+ // We should never have primary be NULL, because even if there is
+ // no other interface yet, we should always find ourself in the list.
// If interface is marked as a direct link, we can assume the address record is unique
// and does not need to go through the probe phase of the probe/announce packet sequence.
@@ -12608,9 +12587,9 @@ mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
LogInfo("AdvertiseInterface: Marking address record as kDNSRecordTypeKnownUnique for %s", set->ifname);
// Send dynamic update for non-linklocal IPv4 Addresses
- mDNS_SetupResourceRecord(&set->RR_A, mDNSNULL, set->InterfaceID, kDNSType_A, kHostNameTTL, recordType, AuthRecordAny, mDNS_HostNameCallback, set);
- mDNS_SetupResourceRecord(&set->RR_PTR, mDNSNULL, set->InterfaceID, kDNSType_PTR, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
- mDNS_SetupResourceRecord(&set->RR_HINFO, mDNSNULL, set->InterfaceID, kDNSType_HINFO, kHostNameTTL, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
+ mDNS_SetupResourceRecord(&set->RR_A, mDNSNULL, set->InterfaceID, kDNSType_A, kHostNameTTL, recordType, AuthRecordAny, mDNS_HostNameCallback, set);
+ mDNS_SetupResourceRecord(&set->RR_PTR, mDNSNULL, set->InterfaceID, kDNSType_PTR, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
+ mDNS_SetupResourceRecord(&set->RR_HINFO, mDNSNULL, set->InterfaceID, kDNSType_HINFO, kHostNameTTL, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
#if ANSWER_REMOTE_HOSTNAME_QUERIES
set->RR_A.AllowRemoteQuery = mDNStrue;
@@ -12907,7 +12886,7 @@ mDNSexport void mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceI
}
}
-mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping)
+mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed activationSpeed)
{
AuthRecord *rr;
mDNSBool FirstOfType = mDNStrue;
@@ -12978,32 +12957,56 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
// We don't want to do a probe, and then see a stale echo of an announcement we ourselves sent,
// and think it's a conflicting answer to our probe.
// In the case of a flapping interface, we pause for five seconds, and reduce the announcement count to one packet.
- const mDNSs32 probedelay = flapping ? mDNSPlatformOneSecond * 5 : mDNSPlatformOneSecond / 2;
- const mDNSu8 numannounce = flapping ? (mDNSu8)1 : InitialAnnounceCount;
+ mDNSs32 probedelay;
+ mDNSu8 numannounce;
+ switch (activationSpeed)
+ {
+ case FastActivation:
+ probedelay = (mDNSs32)0;
+ numannounce = InitialAnnounceCount;
+ LogMsg("mDNS_RegisterInterface: Using fast activation for DirectLink interface %s (%#a)", set->ifname, &set->ip);
+ break;
- // Use a small amount of randomness:
- // In the case of a network administrator turning on an Ethernet hub so that all the
- // connected machines establish link at exactly the same time, we don't want them all
- // to go and hit the network with identical queries at exactly the same moment.
- // We set a random delay of up to InitialQuestionInterval (1/3 second).
- // We must *never* set m->SuppressSending to more than that (or set it repeatedly in a way
- // that causes mDNSResponder to remain in a prolonged state of SuppressSending, because
- // suppressing packet sending for more than about 1/3 second can cause protocol correctness
- // to start to break down (e.g. we don't answer probes fast enough, and get name conflicts).
- // See <rdar://problem/4073853> mDNS: m->SuppressSending set too enthusiastically
- if (!m->SuppressSending) m->SuppressSending = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval);
+ case SlowActivation:
+ probedelay = mDNSPlatformOneSecond * 5;
+ numannounce = (mDNSu8)1;
+ LogMsg("mDNS_RegisterInterface: Frequent transitions for interface %s (%#a), doing slow activation", set->ifname, &set->ip);
+ m->mDNSStats.InterfaceUpFlap++;
+ break;
- if (flapping)
- {
- LogMsg("mDNS_RegisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip);
- m->mDNSStats.InterfaceUpFlap++;
+ case NormalActivation:
+ default:
+ probedelay = mDNSPlatformOneSecond / 2;
+ numannounce = InitialAnnounceCount;
+ break;
}
LogInfo("mDNS_RegisterInterface: %s (%#a) probedelay %d", set->ifname, &set->ip, probedelay);
- if (m->SuppressProbes == 0 ||
- m->SuppressProbes - NonZeroTime(m->timenow + probedelay) < 0)
- m->SuppressProbes = NonZeroTime(m->timenow + probedelay);
+ // No probe or sending suppression on DirectLink type interfaces.
+ if (activationSpeed == FastActivation)
+ {
+ m->SuppressSending = 0;
+ m->SuppressProbes = 0;
+ }
+ else
+ {
+ // Use a small amount of randomness:
+ // In the case of a network administrator turning on an Ethernet hub so that all the
+ // connected machines establish link at exactly the same time, we don't want them all
+ // to go and hit the network with identical queries at exactly the same moment.
+ // We set a random delay of up to InitialQuestionInterval (1/3 second).
+ // We must *never* set m->SuppressSending to more than that (or set it repeatedly in a way
+ // that causes mDNSResponder to remain in a prolonged state of SuppressSending, because
+ // suppressing packet sending for more than about 1/3 second can cause protocol correctness
+ // to start to break down (e.g. we don't answer probes fast enough, and get name conflicts).
+ // See <rdar://problem/4073853> mDNS: m->SuppressSending set too enthusiastically
+ if (!m->SuppressSending) m->SuppressSending = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval);
+
+ if (m->SuppressProbes == 0 ||
+ m->SuppressProbes - NonZeroTime(m->timenow + probedelay) < 0)
+ m->SuppressProbes = NonZeroTime(m->timenow + probedelay);
+ }
// Include OWNER option in packets for 60 seconds after connecting to the network. Setting
// it here also handles the wake up case as the network link comes UP after waking causing
@@ -13020,10 +13023,10 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
if (!q->InterfaceID || q->InterfaceID == set->InterfaceID) // If non-specific Q, or Q on this specific interface,
{ // then reactivate this question
// If flapping, delay between first and second queries is nine seconds instead of one second
- mDNSBool dodelay = flapping && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID);
+ mDNSBool dodelay = (activationSpeed == SlowActivation) && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID);
mDNSs32 initial = dodelay ? InitialQuestionInterval * QuestionIntervalStep2 : InitialQuestionInterval;
- mDNSs32 qdelay = dodelay ? mDNSPlatformOneSecond * 5 : 0;
- if (dodelay) LogInfo("No cache records expired for %##s (%s); okay to delay questions a little", q->qname.c, DNSTypeName(q->qtype));
+ mDNSs32 qdelay = dodelay ? kDefaultQueryDelayTimeForFlappingInterface : 0;
+ if (dodelay) LogInfo("No cache records expired for %##s (%s); delaying questions by %d seconds", q->qname.c, DNSTypeName(q->qtype), qdelay);
if (!q->ThisQInterval || q->ThisQInterval > initial)
{
@@ -13066,7 +13069,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
// Note: mDNS_DeregisterInterface calls mDNS_Deregister_internal which can call a user callback, which may change
// the record list and/or question list.
// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping)
+mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed activationSpeed)
{
NetworkInterfaceInfo **p = &m->HostInterfaces;
mDNSBool revalidate = mDNSfalse;
@@ -13126,7 +13129,7 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se
m->mDNSStats.InterfaceDown++;
- if (set->McastTxRx && flapping)
+ if (set->McastTxRx && (activationSpeed == SlowActivation))
{
LogMsg("mDNS_DeregisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip);
m->mDNSStats.InterfaceDownFlap++;
@@ -13152,9 +13155,10 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se
{
// If this interface is deemed flapping,
// postpone deleting the cache records in case the interface comes back again
- if (set->McastTxRx && flapping)
+ if (set->McastTxRx && (activationSpeed == SlowActivation))
{
- // For a flapping interface we want these record to go away after 30 seconds
+ // For a flapping interface we want these records to go away after
+ // kDefaultReconfirmTimeForFlappingInterface seconds if they are not reconfirmed.
mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface);
// We set UnansweredQueries = MaxUnansweredQueries so we don't waste time doing any queries for them --
// if the interface does come back, any relevant questions will be reactivated anyway
@@ -13314,10 +13318,7 @@ mDNSlocal void NSSCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
}
-// Derive AuthRecType from the coreFlag* values.
-// Note, this is not using the external flags values, kDNSServiceFlags*, defined in dns_sd.h.
-// It should be changed to do so once the use of coreFlag* is completely replaced with
-// the use the kDNSServiceFlags* definitions within mDNSResponder.
+// Derive AuthRecType from the kDNSServiceFlags* values.
mDNSlocal AuthRecType setAuthRecType(mDNSInterfaceID InterfaceID, mDNSu32 flags)
{
AuthRecType artype;
@@ -13326,12 +13327,12 @@ mDNSlocal AuthRecType setAuthRecType(mDNSInterfaceID InterfaceID, mDNSu32 flags)
artype = AuthRecordLocalOnly;
else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE)
artype = AuthRecordP2P;
- else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeP2P)
- && (flags & coreFlagIncludeAWDL))
+ else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P)
+ && (flags & kDNSServiceFlagsIncludeAWDL))
artype = AuthRecordAnyIncludeAWDLandP2P;
- else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeP2P))
+ else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P))
artype = AuthRecordAnyIncludeP2P;
- else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeAWDL))
+ else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeAWDL))
artype = AuthRecordAnyIncludeAWDL;
else
artype = AuthRecordAny;
@@ -13370,7 +13371,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
mDNSu32 i;
mDNSu32 hostTTL;
AuthRecType artype;
- mDNSu8 recordType = (flags & coreFlagKnownUnique) ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique;
+ mDNSu8 recordType = (flags & kDNSServiceFlagsKnownUnique) ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique;
sr->ServiceCallback = Callback;
sr->ServiceContext = Context;
@@ -13388,7 +13389,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
mDNS_SetupResourceRecord(&sr->RR_ADV, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeAdvisory, artype, ServiceCallback, sr);
mDNS_SetupResourceRecord(&sr->RR_PTR, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared, artype, ServiceCallback, sr);
- if (flags & coreFlagWakeOnly)
+ if (flags & kDNSServiceFlagsWakeOnlyService)
{
sr->RR_PTR.AuthFlags = AuthFlagsWakeOnly;
}
@@ -13399,7 +13400,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
hostTTL = kHostNameTTL;
mDNS_SetupResourceRecord(&sr->RR_SRV, mDNSNULL, InterfaceID, kDNSType_SRV, hostTTL, recordType, artype, ServiceCallback, sr);
- mDNS_SetupResourceRecord(&sr->RR_TXT, mDNSNULL, InterfaceID, kDNSType_TXT, kStandardTTL, kDNSRecordTypeUnique, artype, ServiceCallback, sr);
+ mDNS_SetupResourceRecord(&sr->RR_TXT, mDNSNULL, InterfaceID, kDNSType_TXT, kStandardTTL, recordType, artype, ServiceCallback, sr);
// If port number is zero, that means the client is really trying to do a RegisterNoSuchService
if (mDNSIPPortIsZero(port))
@@ -13841,7 +13842,7 @@ mDNSlocal void mDNSCoreReceiveRawARP(mDNS *const m, const ARP_EthIP *const arp,
}
else if (msg == msg3)
{
- mDNSPlatformSetLocalAddressCacheEntry(m, &rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID);
+ mDNSPlatformSetLocalAddressCacheEntry(&rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID);
}
else if (msg == msg4)
{
@@ -13947,7 +13948,7 @@ mDNSlocal void mDNSCoreReceiveRawND(mDNS *const m, const mDNSEthAddr *const sha,
LogSPS("Reached maximum number of restarts for probing - %s", ARDisplayString(m,rr));
}
else if (msg == msg3)
- mDNSPlatformSetLocalAddressCacheEntry(m, &rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID);
+ mDNSPlatformSetLocalAddressCacheEntry(&rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID);
else if (msg == msg4)
SendNDP(m, NDP_Adv, NDP_Solicited, rr, &ndp->target, mDNSNULL, spa, sha);
else if (msg == msg5)
@@ -14286,7 +14287,7 @@ mDNSexport void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, m
{
if (!m->SPSSocket)
{
- m->SPSSocket = mDNSPlatformUDPSocket(m, zeroIPPort);
+ m->SPSSocket = mDNSPlatformUDPSocket(zeroIPPort);
if (!m->SPSSocket) { LogMsg("mDNSCoreBeSleepProxyServer: Failed to allocate SPSSocket"); goto fail; }
}
#ifndef SPC_DISABLED
@@ -14328,9 +14329,9 @@ mDNSexport void mDNS_GrowCache(mDNS *const m, CacheEntity *storage, mDNSu32 numr
mDNS_Unlock(m);
}
-mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
- CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
- mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context)
+mDNSlocal mStatus mDNS_InitStorage(mDNS *const m, mDNS_PlatformSupport *const p,
+ CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
+ mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context)
{
mDNSu32 slot;
mDNSs32 timenow;
@@ -14370,14 +14371,14 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
m->timenow_last = timenow;
m->NextScheduledEvent = timenow;
m->SuppressSending = timenow;
- m->NextCacheCheck = timenow + 0x78000000;
- m->NextScheduledQuery = timenow + 0x78000000;
- m->NextScheduledProbe = timenow + 0x78000000;
- m->NextScheduledResponse = timenow + 0x78000000;
- m->NextScheduledNATOp = timenow + 0x78000000;
- m->NextScheduledSPS = timenow + 0x78000000;
- m->NextScheduledKA = timenow + 0x78000000;
- m->NextScheduledStopTime = timenow + 0x78000000;
+ m->NextCacheCheck = timenow + FutureTime;
+ m->NextScheduledQuery = timenow + FutureTime;
+ m->NextScheduledProbe = timenow + FutureTime;
+ m->NextScheduledResponse = timenow + FutureTime;
+ m->NextScheduledNATOp = timenow + FutureTime;
+ m->NextScheduledSPS = timenow + FutureTime;
+ m->NextScheduledKA = timenow + FutureTime;
+ m->NextScheduledStopTime = timenow + FutureTime;
m->NextBLEServiceTime = 0; // zero indicates inactive
#if BONJOUR_ON_DEMAND
@@ -14399,9 +14400,6 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
m->SleepLimit = 0;
#if APPLE_OSX_mDNSResponder
- m->StatStartTime = mDNSPlatformUTC();
- m->NextStatLogTime = m->StatStartTime + kDefaultNextStatsticsLogTime;
- m->ActiveStatTime = 0;
m->UnicastPacketsSent = 0;
m->MulticastPacketsSent = 0;
m->RemoteSubnet = 0;
@@ -14424,7 +14422,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
{
m->rrcache_hash[slot] = mDNSNULL;
- m->rrcache_nextcheck[slot] = timenow + 0x78000000;;
+ m->rrcache_nextcheck[slot] = timenow + FutureTime;;
}
mDNS_GrowCache_internal(m, rrcachestorage, rrcachesize);
@@ -14450,8 +14448,8 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
m->SuppressProbes = 0;
#ifndef UNICAST_DISABLED
- m->NextuDNSEvent = timenow + 0x78000000;
- m->NextSRVUpdate = timenow + 0x78000000;
+ m->NextuDNSEvent = timenow + FutureTime;
+ m->NextSRVUpdate = timenow + FutureTime;
m->DNSServers = mDNSNULL;
@@ -14482,7 +14480,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
m->NATTraversals = mDNSNULL;
m->CurrentNATTraversal = mDNSNULL;
m->retryIntervalGetAddr = 0; // delta between time sent and retry
- m->retryGetAddr = timenow + 0x78000000; // absolute time when we retry
+ m->retryGetAddr = timenow + FutureTime; // absolute time when we retry
m->ExtAddress = zerov4Addr;
m->PCPNonce[0] = mDNSRandom(-1);
m->PCPNonce[1] = mDNSRandom(-1);
@@ -14531,6 +14529,17 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
#endif
+ return(result);
+}
+
+mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
+ CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
+ mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context)
+{
+ mStatus result = mDNS_InitStorage(m, p, rrcachestorage, rrcachesize, AdvertiseLocalAddresses, Callback, Context);
+ if (result != mStatus_NoError)
+ return(result);
+
result = mDNSPlatformInit(m);
#ifndef UNICAST_DISABLED
@@ -14604,8 +14613,7 @@ mDNSlocal void PurgeOrReconfirmCacheRecord(mDNS *const m, CacheRecord *cr, const
mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q)
{
- const mDNSu32 slot = HashSlot(&q->qname);
- CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+ CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
CacheRecord *rp;
mDNSu8 validatingResponse = 0;
@@ -14640,8 +14648,7 @@ mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q)
// them.
mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q)
{
- const mDNSu32 slot = HashSlot(&q->qname);
- CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+ CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
CacheRecord *rp;
for (rp = cg ? cg->members : mDNSNULL; rp; rp = rp->next)
@@ -14664,8 +14671,7 @@ mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q)
mDNSexport mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16 qtype)
{
DNSQuestion question;
- const mDNSu32 slot = HashSlot(&q->qname);
- CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+ CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
CacheRecord *rp;
// Create an identical question but with qtype
@@ -14788,7 +14794,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
// hence we are ready to ack the configuration as this is the last call to mDNSPlatformSetConfig
// for the dns configuration change notification.
SetConfigState(m, mDNStrue);
- if (!mDNSPlatformSetDNSConfig(m, mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL, mDNStrue))
+ if (!mDNSPlatformSetDNSConfig(mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL, mDNStrue))
{
SetDynDNSHostNameIfChanged(m, &fqdn);
SetConfigState(m, mDNSfalse);
@@ -14844,6 +14850,9 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
// cache records and as the resGroupID is different, you can't use the cache record from the scoped DNSServer to answer the
// non-scoped question and vice versa.
//
+#if USE_DNS64
+ DNS64RestartQuestions(m);
+#endif
for (q = m->Questions; q; q=q->next)
{
if (!mDNSOpaque16IsZero(q->TargetQID))
@@ -15007,7 +15016,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
{
LogMsg("uDNS_SetupDNSConfig: ERROR!! Cache Record %s Active question %##s (%s) (scope:%p) pointing to DNSServer Address %#a"
" to be freed", CRDisplayString(m, cr), qptr->qname.c, DNSTypeName(qptr->qtype), qptr->InterfaceID, &ptr->addr);
- qptr->validDNSServers = zeroOpaque64;
+ qptr->validDNSServers = zeroOpaque128;
qptr->qDNSServer = mDNSNULL;
cr->resrec.rDNSServer = mDNSNULL;
}
@@ -15070,7 +15079,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
v4 = v6 = r = zeroAddr;
v4.type = r.type = mDNSAddrType_IPv4;
- if (mDNSPlatformGetPrimaryInterface(m, &v4, &v6, &r) == mStatus_NoError && !mDNSv4AddressIsLinkLocal(&v4.ip.v4))
+ if (mDNSPlatformGetPrimaryInterface(&v4, &v6, &r) == mStatus_NoError && !mDNSv4AddressIsLinkLocal(&v4.ip.v4))
{
mDNS_SetPrimaryInterfaceInfo(m,
!mDNSIPv4AddressIsZero(v4.ip.v4) ? &v4 : mDNSNULL,
@@ -15256,3 +15265,7 @@ mDNSexport void mDNS_FinalExit(mDNS *const m)
LogInfo("mDNS_FinalExit: done");
}
+
+#ifdef UNIT_TEST
+#include "../unittests/mdns_ut.c"
+#endif