diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-19 08:52:21 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-20 11:23:32 +0200 |
commit | f761b290f135957f47e1c9af71b4a81c76c32b48 (patch) | |
tree | 2b7d273db4ff2388867efec5ad432fa49cd4047e /mDNSResponder/mDNSCore | |
parent | mDNSResponder: Update to v576.30.4 (diff) | |
download | rtems-libbsd-f761b290f135957f47e1c9af71b4a81c76c32b48.tar.bz2 |
mDNSResponder: Update to v625.41.2
The sources can be obtained via:
https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-625.41.2.tar.gz
Update #3522.
Diffstat (limited to 'mDNSResponder/mDNSCore')
-rw-r--r-- | mDNSResponder/mDNSCore/CryptoAlg.c | 2 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/CryptoAlg.h | 3 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/DNSCommon.c | 119 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/DNSCommon.h | 14 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/DNSDigest.c | 3 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/anonymous.c | 39 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/anonymous.h | 2 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/dnsproxy.c | 35 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/dnsproxy.h | 3 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/dnssec.c | 21 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/dnssec.h | 3 | ||||
-rwxr-xr-x | mDNSResponder/mDNSCore/mDNS.c | 935 | ||||
-rwxr-xr-x | mDNSResponder/mDNSCore/mDNSDebug.h | 10 | ||||
-rwxr-xr-x | mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h | 95 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/nsec.c | 14 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/nsec.h | 3 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/nsec3.c | 28 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/nsec3.h | 2 | ||||
-rwxr-xr-x | mDNSResponder/mDNSCore/uDNS.c | 66 |
19 files changed, 756 insertions, 641 deletions
diff --git a/mDNSResponder/mDNSCore/CryptoAlg.c b/mDNSResponder/mDNSCore/CryptoAlg.c index 38533fc8..0008405d 100644 --- a/mDNSResponder/mDNSCore/CryptoAlg.c +++ b/mDNSResponder/mDNSCore/CryptoAlg.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2012 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/mDNSResponder/mDNSCore/CryptoAlg.h b/mDNSResponder/mDNSCore/CryptoAlg.h index 6cb3dc9d..c21507e4 100644 --- a/mDNSResponder/mDNSCore/CryptoAlg.h +++ b/mDNSResponder/mDNSCore/CryptoAlg.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2012 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef __CRYPTO_ALG_H #define __CRYPTO_ALG_H diff --git a/mDNSResponder/mDNSCore/DNSCommon.c b/mDNSResponder/mDNSCore/DNSCommon.c index 249e3b23..d364ee02 100644 --- a/mDNSResponder/mDNSCore/DNSCommon.c +++ b/mDNSResponder/mDNSCore/DNSCommon.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -513,7 +513,7 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RD expTimeBuf, inceptTimeBuf, swap16(rrsig->keyTag), ((domainname *)(&rrsig->signerName))->c); len = DomainNameLength((domainname *)&rrsig->signerName); - length += baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + len + RRSIG_FIXED_SIZE), + baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + len + RRSIG_FIXED_SIZE), rr->rdlength - (len + RRSIG_FIXED_SIZE), ENC_BASE64); } break; @@ -521,7 +521,7 @@ mDNSexport char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RD rdataDNSKey *rrkey = (rdataDNSKey *)rd->data; length += mDNS_snprintf(buffer+length, RemSpc, "\t%d %d %s %u ", swap16(rrkey->flags), rrkey->proto, DNSSECAlgName(rrkey->alg), (unsigned int)keytag((mDNSu8 *)rrkey, rr->rdlength)); - length += baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + DNSKEY_FIXED_SIZE), + baseEncode(buffer + length, RemSpc, (const mDNSu8 *)(rd->data + DNSKEY_FIXED_SIZE), rr->rdlength - DNSKEY_FIXED_SIZE, ENC_BASE64); } break; @@ -1481,6 +1481,7 @@ mDNSexport void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID I q->qnameOrig = mDNSNULL; q->AnonInfo = mDNSNULL; q->pid = mDNSPlatformGetPID(); + q->euid = 0; q->DisallowPID = mDNSfalse; q->ServiceID = -1; q->QuestionCallback = callback; @@ -2357,13 +2358,9 @@ mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNS case kDNSType_NSEC: { // For NSEC records, rdlength represents the exact number of bytes // of in memory storage. - int len = rr->rdlength; mDNSu8 *nsec = (mDNSu8 *)rdb->data; domainname *name = (domainname *)nsec; - int dlen; - - dlen = DomainNameLength(name); - len -= dlen; + const int dlen = DomainNameLength(name); nsec += dlen; // This function is called when we are sending a NSEC record as part of mDNS, // or to copy the data to any other buffer needed which could be a mDNS or uDNS @@ -2376,7 +2373,6 @@ mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNS int i, j, wlen; wlen = *(nsec + 1); nsec += 2; // Skip the window number and len - len -= 2; // For our simplified use of NSEC synthetic records: // @@ -2406,6 +2402,7 @@ mDNSexport mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNS else { int win, wlen; + int len = rr->rdlength - dlen; // Sanity check whether the bitmap is good while (len) @@ -2607,7 +2604,7 @@ mDNSexport mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domain } // for dynamic updates -mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease) +mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease) { AuthRecord rr; mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); @@ -2616,13 +2613,13 @@ mDNSexport mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease) rr.resrec.rdestimate = sizeof(rdataOPT); rr.resrec.rdata->u.opt[0].opt = kDNSOpt_Lease; rr.resrec.rdata->u.opt[0].u.updatelease = lease; - end = PutResourceRecordTTLJumbo(msg, end, &msg->h.numAdditionals, &rr.resrec, 0); - if (!end) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTL"); return mDNSNULL; } - return end; + ptr = PutResourceRecordTTLJumbo(msg, ptr, &msg->h.numAdditionals, &rr.resrec, 0); + if (!ptr) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTL"); return mDNSNULL; } + return ptr; } // for dynamic updates -mDNSexport mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease, mDNSu8 *limit) +mDNSexport mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease, mDNSu8 *limit) { AuthRecord rr; mDNS_SetupResourceRecord(&rr, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); @@ -2631,9 +2628,9 @@ mDNSexport mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *end, mDNSu32 rr.resrec.rdestimate = sizeof(rdataOPT); rr.resrec.rdata->u.opt[0].opt = kDNSOpt_Lease; rr.resrec.rdata->u.opt[0].u.updatelease = lease; - end = PutResourceRecordTTLWithLimit(msg, end, &msg->h.numAdditionals, &rr.resrec, 0, limit); - if (!end) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTLWithLimit"); return mDNSNULL; } - return end; + ptr = PutResourceRecordTTLWithLimit(msg, ptr, &msg->h.numAdditionals, &rr.resrec, 0, limit); + if (!ptr) { LogMsg("ERROR: putUpdateLeaseWithLimit - PutResourceRecordTTLWithLimit"); return mDNSNULL; } + return ptr; } mDNSexport mDNSu8 *putDNSSECOption(DNSMessage *msg, mDNSu8 *end, mDNSu8 *limit) @@ -2650,7 +2647,7 @@ mDNSexport mDNSu8 *putDNSSECOption(DNSMessage *msg, mDNSu8 *end, mDNSu8 *limit) // set the DO bit ttl |= 0x8000; end = PutResourceRecordTTLWithLimit(msg, end, &msg->h.numAdditionals, &rr.resrec, ttl, limit); - if (!end) { LogMsg("ERROR: putUpdateLease - PutResourceRecordTTLWithLimit"); return mDNSNULL; } + if (!end) { LogMsg("ERROR: putDNSSECOption - PutResourceRecordTTLWithLimit"); return mDNSNULL; } return end; } @@ -3441,12 +3438,7 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage mDNSu16 pktrdlength; if (largecr == &m->rec && m->rec.r.resrec.RecordType) - { - LogMsg("GetLargeResourceRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r)); -#if ForceAlerts - *(long*)0 = 0; -#endif - } + LogFatalError("GetLargeResourceRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r)); rr->next = mDNSNULL; rr->resrec.name = &largecr->namestorage; @@ -3713,7 +3705,7 @@ mDNSexport void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *t } ptr = DumpRecords(m, msg, ptr, end, msg->h.numAnswers, IsUpdate ? "Prerequisites" : "Answers"); ptr = DumpRecords(m, msg, ptr, end, msg->h.numAuthorities, IsUpdate ? "Updates" : "Authorities"); - ptr = DumpRecords(m, msg, ptr, end, msg->h.numAdditionals, "Additionals"); + DumpRecords(m, msg, ptr, end, msg->h.numAdditionals, "Additionals"); LogMsg("--------------"); } @@ -3725,11 +3717,8 @@ mDNSexport void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *t // Stub definition of TCPSocket_struct so we can access flags field. (Rest of TCPSocket_struct is platform-dependent.) struct TCPSocket_struct { TCPSocketFlags flags; /* ... */ }; - -struct UDPSocket_struct -{ - mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port -}; +// Stub definition of UDPSocket_struct so we can access port field. (Rest of UDPSocket_struct is platform-dependent.) +struct UDPSocket_struct { mDNSIPPort port; /* ... */ }; // Note: When we sign a DNS message using DNSDigest_SignMessage(), the current real-time clock value is used, which // is why we generally defer signing until we send the message, to ensure the signature is as fresh as possible. @@ -3844,12 +3833,7 @@ mDNSexport void mDNS_Lock_(mDNS *const m, const char * const functionname) // If that client callback does mDNS API calls, mDNS_reentrancy and mDNS_busy will both be one // If mDNS_busy != mDNS_reentrancy that's a bad sign if (m->mDNS_busy != m->mDNS_reentrancy) - { - LogMsg("%s: mDNS_Lock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy); -#if ForceAlerts - *(long*)0 = 0; -#endif - } + LogFatalError("%s: mDNS_Lock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy); // If this is an initial entry into the mDNSCore code, set m->timenow // else, if this is a re-entrant entry into the mDNSCore code, m->timenow should already be set @@ -3930,82 +3914,89 @@ mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m) return(e); } +#define LogTSE TSE++,LogMsg + mDNSexport void ShowTaskSchedulingError(mDNS *const m) { + int TSE = 0; AuthRecord *rr; mDNS_Lock(m); - LogMsg("Task Scheduling Error: Continuously busy for more than a second"); + LogMsg("Task Scheduling Error: *** Continuously busy for more than a second"); // Note: To accurately diagnose *why* we're busy, the debugging code here needs to mirror the logic in GetNextScheduledEvent above if (m->NewQuestions && (!m->NewQuestions->DelayAnswering || m->timenow - m->NewQuestions->DelayAnswering >= 0)) - LogMsg("Task Scheduling Error: NewQuestion %##s (%s)", + LogTSE("Task Scheduling Error: NewQuestion %##s (%s)", m->NewQuestions->qname.c, DNSTypeName(m->NewQuestions->qtype)); if (m->NewLocalOnlyQuestions) - LogMsg("Task Scheduling Error: NewLocalOnlyQuestions %##s (%s)", + LogTSE("Task Scheduling Error: NewLocalOnlyQuestions %##s (%s)", m->NewLocalOnlyQuestions->qname.c, DNSTypeName(m->NewLocalOnlyQuestions->qtype)); if (m->NewLocalRecords) { rr = AnyLocalRecordReady(m); - if (rr) LogMsg("Task Scheduling Error: NewLocalRecords %s", ARDisplayString(m, rr)); + if (rr) LogTSE("Task Scheduling Error: NewLocalRecords %s", ARDisplayString(m, rr)); } - if (m->NewLocalOnlyRecords) LogMsg("Task Scheduling Error: NewLocalOnlyRecords"); + if (m->NewLocalOnlyRecords) LogTSE("Task Scheduling Error: NewLocalOnlyRecords"); - if (m->SPSProxyListChanged) LogMsg("Task Scheduling Error: SPSProxyListChanged"); - if (m->LocalRemoveEvents) LogMsg("Task Scheduling Error: LocalRemoveEvents"); + if (m->SPSProxyListChanged) LogTSE("Task Scheduling Error: SPSProxyListChanged"); - if (m->timenow - m->NextScheduledEvent >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledEvent %d", m->timenow - m->NextScheduledEvent); + if (m->LocalRemoveEvents) LogTSE("Task Scheduling Error: LocalRemoveEvents"); #ifndef UNICAST_DISABLED if (m->timenow - m->NextuDNSEvent >= 0) - LogMsg("Task Scheduling Error: m->NextuDNSEvent %d", m->timenow - m->NextuDNSEvent); + LogTSE("Task Scheduling Error: m->NextuDNSEvent %d", m->timenow - m->NextuDNSEvent); if (m->timenow - m->NextScheduledNATOp >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledNATOp %d", m->timenow - m->NextScheduledNATOp); + LogTSE("Task Scheduling Error: m->NextScheduledNATOp %d", m->timenow - m->NextScheduledNATOp); if (m->NextSRVUpdate && m->timenow - m->NextSRVUpdate >= 0) - LogMsg("Task Scheduling Error: m->NextSRVUpdate %d", m->timenow - m->NextSRVUpdate); + LogTSE("Task Scheduling Error: m->NextSRVUpdate %d", m->timenow - m->NextSRVUpdate); #endif if (m->timenow - m->NextCacheCheck >= 0) - LogMsg("Task Scheduling Error: m->NextCacheCheck %d", m->timenow - m->NextCacheCheck); + LogTSE("Task Scheduling Error: m->NextCacheCheck %d", m->timenow - m->NextCacheCheck); if (m->timenow - m->NextScheduledSPS >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledSPS %d", m->timenow - m->NextScheduledSPS); + LogTSE("Task Scheduling Error: m->NextScheduledSPS %d", m->timenow - m->NextScheduledSPS); if (m->timenow - m->NextScheduledKA >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledKA %d", m->timenow - m->NextScheduledKA); + LogTSE("Task Scheduling Error: m->NextScheduledKA %d", m->timenow - m->NextScheduledKA); if (!m->DelaySleep && m->SleepLimit && m->timenow - m->NextScheduledSPRetry >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledSPRetry %d", m->timenow - m->NextScheduledSPRetry); + LogTSE("Task Scheduling Error: m->NextScheduledSPRetry %d", m->timenow - m->NextScheduledSPRetry); if (m->DelaySleep && m->timenow - m->DelaySleep >= 0) - LogMsg("Task Scheduling Error: m->DelaySleep %d", m->timenow - m->DelaySleep); + LogTSE("Task Scheduling Error: m->DelaySleep %d", m->timenow - m->DelaySleep); if (m->SuppressSending && m->timenow - m->SuppressSending >= 0) - LogMsg("Task Scheduling Error: m->SuppressSending %d", m->timenow - m->SuppressSending); + LogTSE("Task Scheduling Error: m->SuppressSending %d", m->timenow - m->SuppressSending); if (m->timenow - m->NextScheduledQuery >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledQuery %d", m->timenow - m->NextScheduledQuery); + LogTSE("Task Scheduling Error: m->NextScheduledQuery %d", m->timenow - m->NextScheduledQuery); if (m->timenow - m->NextScheduledProbe >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledProbe %d", m->timenow - m->NextScheduledProbe); + LogTSE("Task Scheduling Error: m->NextScheduledProbe %d", m->timenow - m->NextScheduledProbe); if (m->timenow - m->NextScheduledResponse >= 0) - LogMsg("Task Scheduling Error: m->NextScheduledResponse %d", m->timenow - m->NextScheduledResponse); + LogTSE("Task Scheduling Error: m->NextScheduledResponse %d", m->timenow - m->NextScheduledResponse); + if (m->timenow - m->NextScheduledStopTime >= 0) + LogTSE("Task Scheduling Error: m->NextScheduledStopTime %d", m->timenow - m->NextScheduledStopTime); + + if (m->timenow - m->NextScheduledEvent >= 0) + LogTSE("Task Scheduling Error: m->NextScheduledEvent %d", m->timenow - m->NextScheduledEvent); + + if (m->NetworkChanged && m->timenow - m->NetworkChanged >= 0) + LogTSE("Task Scheduling Error: NetworkChanged %d", m->timenow - m->NetworkChanged); + + if (!TSE) LogMsg("Task Scheduling Error: *** No likely causes identified"); + else LogMsg("Task Scheduling Error: *** %d potential cause%s identified (significant only if the same cause consistently appears)", TSE, TSE > 1 ? "s" : ""); mDNS_Unlock(m); } -mDNSexport void mDNS_Unlock_(mDNS *const m, const char * const functionname) +mDNSexport void mDNS_Unlock_(mDNS *const m, const char *const functionname) { // Decrement mDNS_busy m->mDNS_busy--; // Check for locking failures if (m->mDNS_busy != m->mDNS_reentrancy) - { - LogMsg("%s: mDNS_Unlock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy); -#if ForceAlerts - *(long*)0 = 0; -#endif - } + LogFatalError("%s: mDNS_Unlock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", functionname, m->mDNS_busy, m->mDNS_reentrancy); // If this is a final exit from the mDNSCore code, set m->NextScheduledEvent and clear m->timenow if (m->mDNS_busy == 0) diff --git a/mDNSResponder/mDNSCore/DNSCommon.h b/mDNSResponder/mDNSCore/DNSCommon.h index b92f5a9a..e51b06dd 100644 --- a/mDNSResponder/mDNSCore/DNSCommon.h +++ b/mDNSResponder/mDNSCore/DNSCommon.h @@ -220,7 +220,7 @@ extern mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *r extern mDNSu8 *putDeletionRecordWithLimit(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr, mDNSu8 *limit); extern mDNSu8 *putDeleteRRSetWithLimit(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype, mDNSu8 *limit); extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name); -extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease); +extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease); extern mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease, mDNSu8 *limit); extern mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *ptr, DomainAuthInfo *authInfo, mDNSu8 *limit); @@ -297,16 +297,16 @@ extern void mDNS_Unlock_(mDNS *const m, const char * const functionname); #define mDNS_Unlock(X) mDNS_Unlock_((X), __func__) -#define mDNS_CheckLock(X) { if ((X)->mDNS_busy != (X)->mDNS_reentrancy+1) \ - LogMsg("%s: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", __func__, (X)->mDNS_busy, (X)->mDNS_reentrancy); } +#define mDNS_CheckLock(X) \ + if ((X)->mDNS_busy != (X)->mDNS_reentrancy+1) LogMsg("%s: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", __func__, (X)->mDNS_busy, (X)->mDNS_reentrancy) #define mDNS_DropLockBeforeCallback() do { m->mDNS_reentrancy++; \ - if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Locking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \ -} while (0) + if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Locking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \ + } while (0) #define mDNS_ReclaimLockAfterCallback() do { \ - if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Unlocking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \ - m->mDNS_reentrancy--; } while (0) + if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Unlocking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \ + m->mDNS_reentrancy--; } while (0) #ifdef __cplusplus } diff --git a/mDNSResponder/mDNSCore/DNSDigest.c b/mDNSResponder/mDNSCore/DNSDigest.c index 33798d38..57a40120 100644 --- a/mDNSResponder/mDNSCore/DNSDigest.c +++ b/mDNSResponder/mDNSCore/DNSDigest.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2011 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ * limitations under the License. */ - #ifdef __cplusplus extern "C" { #endif diff --git a/mDNSResponder/mDNSCore/anonymous.c b/mDNSResponder/mDNSCore/anonymous.c index 55a83175..779e4ea6 100644 --- a/mDNSResponder/mDNSCore/anonymous.c +++ b/mDNSResponder/mDNSCore/anonymous.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2012 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2012-2013 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,14 @@ #define ANON_NSEC3_ITERATIONS 1 +struct AnonInfoResourceRecord_struct +{ + ResourceRecord resrec; + RData rdatastorage; +}; + +typedef struct AnonInfoResourceRecord_struct AnonInfoResourceRecord; + mDNSlocal mDNSBool InitializeNSEC3Record(ResourceRecord *rr, const mDNSu8 *AnonData, int len, mDNSu32 salt) { const mDNSu8 *ptr; @@ -118,9 +126,10 @@ mDNSlocal ResourceRecord *ConstructNSEC3Record(const domainname *service, const mDNSlocal ResourceRecord *CopyNSEC3ResourceRecord(AnonymousInfo *si, const ResourceRecord *rr) { - int len; + AnonInfoResourceRecord *anonRR; domainname *name; - ResourceRecord *nsec3rr; + mDNSu32 neededLen; + mDNSu32 extraLen; if (rr->rdlength < MCAST_NSEC3_RDLENGTH) { @@ -128,22 +137,26 @@ mDNSlocal ResourceRecord *CopyNSEC3ResourceRecord(AnonymousInfo *si, const Resou return mDNSNULL; } // Allocate space for the name and the rdata along with the ResourceRecord - len = DomainNameLength(rr->name); - nsec3rr = mDNSPlatformMemAllocate(sizeof(ResourceRecord) + len + sizeof(RData)); - if (!nsec3rr) + neededLen = rr->rdlength + DomainNameLength(rr->name); + extraLen = (neededLen > sizeof(RDataBody)) ? (neededLen - sizeof(RDataBody)) : 0; + anonRR = (AnonInfoResourceRecord *)mDNSPlatformMemAllocate(sizeof(AnonInfoResourceRecord) + extraLen); + if (!anonRR) return mDNSNULL; - *nsec3rr = *rr; - name = (domainname *)((mDNSu8 *)nsec3rr + sizeof(ResourceRecord)); - nsec3rr->name = (const domainname *)name; + anonRR->resrec = *rr; + + anonRR->rdatastorage.MaxRDLength = rr->rdlength; + mDNSPlatformMemCopy(anonRR->rdatastorage.u.data, rr->rdata->u.data, rr->rdlength); + + name = (domainname *)(anonRR->rdatastorage.u.data + rr->rdlength); AssignDomainName(name, rr->name); - nsec3rr->rdata = (RData *)((mDNSu8 *)nsec3rr->name + len); - mDNSPlatformMemCopy(nsec3rr->rdata->u.data, rr->rdata->u.data, rr->rdlength); + anonRR->resrec.name = name; + anonRR->resrec.rdata = &anonRR->rdatastorage; - si->nsec3RR = nsec3rr; + si->nsec3RR = (ResourceRecord *)anonRR; - return nsec3rr; + return si->nsec3RR; } // When a service is started or a browse is started with the Anonymous data, we allocate a new random diff --git a/mDNSResponder/mDNSCore/anonymous.h b/mDNSResponder/mDNSCore/anonymous.h index 2f2b4f8c..b60812ea 100644 --- a/mDNSResponder/mDNSCore/anonymous.h +++ b/mDNSResponder/mDNSCore/anonymous.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2012 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2012 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/mDNSResponder/mDNSCore/dnsproxy.c b/mDNSResponder/mDNSCore/dnsproxy.c index 11bacc10..5b358864 100644 --- a/mDNSResponder/mDNSCore/dnsproxy.c +++ b/mDNSResponder/mDNSCore/dnsproxy.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2013 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -83,10 +83,6 @@ mDNSlocal void FreeDNSProxyClient(DNSProxyClient *pc) mDNSlocal mDNSBool ParseEDNS0(DNSProxyClient *pc, const mDNSu8 *ptr, int length, const mDNSu8 *limit) { - mDNSu16 rrtype, rrclass; - mDNSu8 rcode, version; - mDNSu16 flag; - if (ptr + length > limit) { LogInfo("ParseEDNS0: Not enough space in the packet"); @@ -94,18 +90,19 @@ mDNSlocal mDNSBool ParseEDNS0(DNSProxyClient *pc, const mDNSu8 *ptr, int length, } // Skip the root label ptr++; - rrtype = (mDNSu16) ((mDNSu16)ptr[0] << 8 | ptr[1]); + mDNSu16 rrtype = (mDNSu16) ((mDNSu16)ptr[0] << 8 | ptr[1]); if (rrtype != kDNSType_OPT) { LogInfo("ParseEDNS0: Not the right type %d", rrtype); return mDNSfalse; } - rrclass = (mDNSu16) ((mDNSu16)ptr[2] << 8 | ptr[3]); - rcode = ptr[4]; - version = ptr[5]; - flag = (mDNSu16) ((mDNSu16)ptr[6] << 8 | ptr[7]); - + mDNSu16 rrclass = (mDNSu16) ((mDNSu16)ptr[2] << 8 | ptr[3]); +#if MDNS_DEBUGMSGS + mDNSu8 rcode = ptr[4]; + mDNSu8 version = ptr[5]; + mDNSu16 flag = (mDNSu16) ((mDNSu16)ptr[6] << 8 | ptr[7]); debugf("rrtype is %s, length is %d, rcode %d, version %d, flag 0x%x", DNSTypeName(rrtype), rrclass, rcode, version, flag); +#endif pc->rcvBufSize = rrclass; pc->DNSSECOK = ptr[6] & 0x80; @@ -366,7 +363,7 @@ again: return mDNSNULL; } len += (ptr - orig); - orig = ptr; + // orig = ptr; Commented out to avoid ‘value never read’ error message } LogInfo("AddResourceRecord: Added %d bytes to the packet", len); return ptr; @@ -471,14 +468,16 @@ mDNSlocal void ProxyClientCallback(mDNS *const m, DNSQuestion *question, const R } } } + + debugf("ProxyClientCallback: InterfaceID is %p for response to client", pc->interfaceID); if (!pc->tcp) { - mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, (UDPSocket *)pc->socket, &pc->addr, pc->port, mDNSNULL, mDNSNULL, mDNSfalse); + mDNSSendDNSMessage(m, &m->omsg, ptr, pc->interfaceID, (UDPSocket *)pc->socket, &pc->addr, pc->port, mDNSNULL, mDNSNULL, mDNSfalse); } else { - mDNSSendDNSMessage(m, &m->omsg, ptr, mDNSInterface_Any, mDNSNULL, &pc->addr, pc->port, (TCPSocket *)pc->socket, mDNSNULL, mDNSfalse); + mDNSSendDNSMessage(m, &m->omsg, ptr, pc->interfaceID, mDNSNULL, &pc->addr, pc->port, (TCPSocket *)pc->socket, mDNSNULL, mDNSfalse); } done: @@ -502,8 +501,6 @@ mDNSlocal void SendError(mDNS *const m, void *socket, void *const pkt, const mDN int pktlen = (int)(end - (mDNSu8 *)pkt); DNSMessage *msg = (DNSMessage *)pkt; - (void) InterfaceID; - // RFC 1035 requires that we copy the question back and RFC 2136 is okay with sending nothing // in the body or send back whatever we get for updates. It is easy to return whatever we get // in the question back to the responder. We return as much as we can fit in our standard @@ -517,12 +514,12 @@ mDNSlocal void SendError(mDNS *const m, void *socket, void *const pkt, const mDN mDNSPlatformMemCopy(m->omsg.data, (mDNSu8 *)&msg->h.numQuestions, pktlen); if (!tcp) { - mDNSSendDNSMessage(m, &m->omsg, (mDNSu8 *)&m->omsg + pktlen, mDNSInterface_Any, socket, dstaddr, dstport, mDNSNULL, mDNSNULL, + mDNSSendDNSMessage(m, &m->omsg, (mDNSu8 *)&m->omsg + pktlen, InterfaceID, socket, dstaddr, dstport, mDNSNULL, mDNSNULL, mDNSfalse); } else { - mDNSSendDNSMessage(m, &m->omsg, (mDNSu8 *)&m->omsg + pktlen, mDNSInterface_Any, mDNSNULL, dstaddr, dstport, (TCPSocket *)socket, + mDNSSendDNSMessage(m, &m->omsg, (mDNSu8 *)&m->omsg + pktlen, InterfaceID, mDNSNULL, dstaddr, dstport, (TCPSocket *)socket, mDNSNULL, mDNSfalse); } mDNSPlatformDisposeProxyContext(context); @@ -576,7 +573,7 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, void *const pkt, const mDNSu8 *ptr; DNSQuestion q, *qptr; DNSProxyClient *pc; - const mDNSu8 *optRR; + const mDNSu8 *optRR = mDNSNULL; int optLen = 0; DNSProxyClient **ppc = &DNSProxyClients; diff --git a/mDNSResponder/mDNSCore/dnsproxy.h b/mDNSResponder/mDNSCore/dnsproxy.h index ed46a125..8aa3d007 100644 --- a/mDNSResponder/mDNSCore/dnsproxy.h +++ b/mDNSResponder/mDNSCore/dnsproxy.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2013 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef __DNS_PROXY_H #define __DNS_PROXY_H diff --git a/mDNSResponder/mDNSCore/dnssec.c b/mDNSResponder/mDNSCore/dnssec.c index c83b8413..bf9acfe8 100644 --- a/mDNSResponder/mDNSCore/dnssec.c +++ b/mDNSResponder/mDNSCore/dnssec.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2013 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "mDNSEmbeddedAPI.h" #include "DNSSECSupport.h" #include "DNSCommon.h" @@ -309,7 +310,7 @@ mDNSlocal AuthChain *AuthChainCopy(AuthChain *ae) rvfrom = ae->rrset; rvto = &ac->rrset; - while (rvfrom) + while (rvfrom && rvto) { *rvto = CopyRRVerifier(rvfrom); rvfrom = rvfrom->next; @@ -318,7 +319,7 @@ mDNSlocal AuthChain *AuthChainCopy(AuthChain *ae) rvfrom = ae->rrsig; rvto = &ac->rrsig; - while (rvfrom) + while (rvfrom && rvto) { *rvto = CopyRRVerifier(rvfrom); rvfrom = rvfrom->next; @@ -327,7 +328,7 @@ mDNSlocal AuthChain *AuthChainCopy(AuthChain *ae) rvfrom = ae->key; rvto = &ac->key; - while (rvfrom) + while (rvfrom && rvto) { *rvto = CopyRRVerifier(rvfrom); rvfrom = rvfrom->next; @@ -1065,7 +1066,6 @@ mDNSlocal mStatus CheckDSForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecord * return mStatus_NoError; else return mStatus_NoSuchRecord; - return (dv->ds ? mStatus_NoError : mStatus_NoSuchRecord); } // It returns mDNStrue if we have all the rrsets for verification and mDNSfalse otherwise. @@ -2335,8 +2335,6 @@ mDNSlocal void SetTTLRRSet(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus statu rdataRRSig *rrsig; mDNSu32 slot; CacheGroup *cg; - int sigNameLen, len; - mDNSu8 *ptr; mDNSu32 rrTTL, rrsigTTL, rrsigOrigTTL, rrsigTimeTTL; domainname *qname; mDNSu16 qtype; @@ -2400,17 +2398,11 @@ mDNSlocal void SetTTLRRSet(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus statu { rrsigv = dv->ac->rrsig; rrsig = (rdataRRSig *)rrsigv->rdata; - sigNameLen = DomainNameLength((domainname *)&rrsig->signerName); - // pointer to signature and the length - ptr = (mDNSu8 *)(rrsigv->rdata + sigNameLen + RRSIG_FIXED_SIZE); - len = rrsigv->rdlength - RRSIG_FIXED_SIZE - sigNameLen; } else { rrsigv = mDNSNULL; rrsig = mDNSNULL; - ptr = mDNSNULL; - sigNameLen = len = 0; } rrsigRR = mDNSNULL; @@ -3187,14 +3179,11 @@ mDNSexport void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion * mDNSlocal mDNSBool TrustedKeyPresent(mDNS *const m, DNSSECVerifier *dv) { - rdataRRSig *rrsig; rdataDS *ds; rdataDNSKey *key; TrustAnchor *ta; RRVerifier *keyv; - rrsig = (rdataRRSig *)dv->rrsig->rdata; - // Walk all our trusted DS Records to see if we have a matching DNS KEY record that verifies // the hash. If we find one, verify that this key was used to sign the KEY rrsets in // this zone. Loop till we find one. diff --git a/mDNSResponder/mDNSCore/dnssec.h b/mDNSResponder/mDNSCore/dnssec.h index 1a8d9535..b770af8d 100644 --- a/mDNSResponder/mDNSCore/dnssec.h +++ b/mDNSResponder/mDNSCore/dnssec.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2013 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef __DNSSEC_H #define __DNSSEC_H diff --git a/mDNSResponder/mDNSCore/mDNS.c b/mDNSResponder/mDNSCore/mDNS.c index e0af1f1a..6b02be46 100755 --- a/mDNSResponder/mDNSCore/mDNS.c +++ b/mDNSResponder/mDNSCore/mDNS.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,7 +47,6 @@ #include "dns_sd.h" // for kDNSServiceFlags* definitions #if APPLE_OSX_mDNSResponder - #include <WebFilterDNS/WebFilterDNS.h> #if !NO_WCF @@ -63,6 +62,10 @@ void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import)); #define NO_WCF 1 #endif // APPLE_OSX_mDNSResponder +#if TARGET_OS_EMBEDDED +#include "Metrics.h" +#endif + // Forward declarations mDNSlocal void BeginSleepProcessing(mDNS *const m); mDNSlocal void RetrySPSRegistrations(mDNS *const m); @@ -80,6 +83,7 @@ mDNSlocal void DeadvertiseAllInterfaceRecords(mDNS *const m); mDNSlocal void FreeNSECRecords(mDNS *const m, CacheRecord *NSECRecords); mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end, const mDNSInterfaceID InterfaceID, CacheRecord **NSEC3Records); +mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *eth); // *************************************************************************** @@ -146,10 +150,6 @@ mDNSlocal void SetNextQueryStopTime(mDNS *const m, const DNSQuestion *const q) { mDNS_CheckLock(m); -#if ForceAlerts - if (m->mDNS_busy != m->mDNS_reentrancy+1) *(long*)0 = 0; -#endif - if (m->NextScheduledStopTime - q->StopTime > 0) m->NextScheduledStopTime = q->StopTime; } @@ -158,10 +158,6 @@ mDNSexport void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q) { mDNS_CheckLock(m); -#if ForceAlerts - if (m->mDNS_busy != m->mDNS_reentrancy+1) *(long*)0 = 0; -#endif - if (ActiveQuestion(q)) { // Depending on whether this is a multicast or unicast question we want to set either: @@ -352,7 +348,7 @@ mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const mDNSu32 slo return(CacheGroupForName(m, slot, rr->namehash, rr->name)); } -mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr, mDNSBool *myself) +mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr) { NetworkInterfaceInfo *intf; @@ -363,44 +359,19 @@ mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterface for (intf = m->HostInterfaces; intf; intf = intf->next) if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx) if (((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) & intf->mask.ip.v4.NotAnInteger) == 0) - { - if (myself) - { - if (mDNSSameIPv4Address(intf->ip.ip.v4, addr->ip.v4)) - *myself = mDNStrue; - else - *myself = mDNSfalse; - if (*myself) - debugf("mDNS_AddressIsLocalSubnet: IPv4 %#a returning true", addr); - else - debugf("mDNS_AddressIsLocalSubnet: IPv4 %#a returning false", addr); - } return(mDNStrue); - } } if (addr->type == mDNSAddrType_IPv6) { + if (mDNSv6AddressIsLinkLocal(&addr->ip.v6)) return(mDNStrue); for (intf = m->HostInterfaces; intf; intf = intf->next) if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx) if ((((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) & intf->mask.ip.v6.l[0]) == 0) && (((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) & intf->mask.ip.v6.l[1]) == 0) && (((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) & intf->mask.ip.v6.l[2]) == 0) && (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) & intf->mask.ip.v6.l[3]) == 0)) - { - if (myself) - { - if (mDNSSameIPv6Address(intf->ip.ip.v6, addr->ip.v6)) - *myself = mDNStrue; - else - *myself = mDNSfalse; - if (*myself) - debugf("mDNS_AddressIsLocalSubnet: IPv6 %#a returning true", addr); - else - debugf("mDNS_AddressIsLocalSubnet: IPv6 %#a returning false", addr); - } return(mDNStrue); - } } return(mDNSfalse); @@ -475,11 +446,20 @@ 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 + domainname *originalQName; +#endif // if there is a message waiting at the socket, we want to process that instead // of throwing it away. If we have a CNAME response that answers // both A and AAAA question and while answering it we don't want to throw // away the response where the actual addresses are present. + // This is a stupid hack and we should get rid of it. + // The chance of there being a second unicast UDP packet already waiting in the kernel before we’ve + // finished processing the previous one is virtually nil, and will only happen by luck on very rare + // occasions when running on a machine with a fast network connection and a slow or busy processor. + // The idea that we’d rely for correctness on this random chance event occurring is ridiculous. + // -- SC if (mDNSPlatformPeekUDP(m, q->LocalSocket)) { LogInfo("AnswerQuestionByFollowingCNAME: Preserving UDP socket for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); @@ -508,6 +488,31 @@ 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 (q->metrics.originalQName) + { + originalQName = q->metrics.originalQName; + q->metrics.originalQName = mDNSNULL; + } + else + { + mDNSu16 qNameLen; + + qNameLen = DomainNameLength(&q->qname); + if ((qNameLen > 0) && (qNameLen <= MAX_DOMAIN_NAME)) + { + originalQName = mDNSPlatformMemAllocate(qNameLen); + if (originalQName) + { + mDNSPlatformMemCopy(originalQName->c, q->qname.c, qNameLen); + } + } + else + { + originalQName = mDNSNULL; + } + } +#endif mDNS_StopQuery_internal(m, q); // Stop old query AssignDomainName(&q->qname, &rr->rdata->u.name); // Update qname q->qnamehash = DomainNameHashValue(&q->qname); // and namehash @@ -524,6 +529,9 @@ 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 + q->metrics.originalQName = originalQName; +#endif if (sock) { // We have a message waiting and that should answer this question. @@ -933,7 +941,7 @@ mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr) { const domainname *const n = SetUnicastTargetToHostName(m, rr); if (n) newname = n; - else { target->c[0] = 0; SetNewRData(&rr->resrec, mDNSNULL, 0); return; } + else { if (target) target->c[0] = 0; SetNewRData(&rr->resrec, mDNSNULL, 0); return; } } if (target && SameDomainName(target, newname)) @@ -1133,26 +1141,61 @@ mDNSlocal AuthRecord *CheckAuthSameRecord(AuthHash *r, AuthRecord *rr) mDNSlocal void DecrementAutoTargetServices(mDNS *const m, AuthRecord *const rr) { + if (RRLocalOnly(rr)) + { + // A sanity check, this should be prevented in calling code. + LogInfo("DecrementAutoTargetServices: called for RRLocalOnly() record: %s", ARDisplayString(m, rr)); + return; + } + if (!AuthRecord_uDNS(rr) && rr->resrec.rrtype == kDNSType_SRV && rr->AutoTarget == Target_AutoHost) { - m->AutoTargetServices--; - LogInfo("DecrementAutoTargetServices: AutoService Record %s, AutoTargetServices %d", ARDisplayString(m, rr), m->AutoTargetServices); - if (!m->AutoTargetServices) + // If about to get rid of the last advertised service + if (m->AutoTargetServices == 1) DeadvertiseAllInterfaceRecords(m); + + m->AutoTargetServices--; + LogInfo("DecrementAutoTargetServices: AutoTargetServices %d Record %s", m->AutoTargetServices, ARDisplayString(m, rr)); + } + +#if TARGET_OS_WATCH + if (!AuthRecord_uDNS(rr)) + { + if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1) + m->NetworkChanged = m->timenow; + m->NumAllInterfaceRecords--; + LogInfo("DecrementAutoTargetServices: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %s", + m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr)); } +#endif } mDNSlocal void IncrementAutoTargetServices(mDNS *const m, AuthRecord *const rr) { - if (!AuthRecord_uDNS(rr) && rr->resrec.rrtype == kDNSType_SRV && rr->AutoTarget == Target_AutoHost) + if (RRLocalOnly(rr)) + { + // A sanity check, this should be prevented in calling code. + LogInfo("IncrementAutoTargetServices: called for RRLocalOnly() record: %s", ARDisplayString(m, rr)); + return; + } + +#if TARGET_OS_WATCH + if (!AuthRecord_uDNS(rr)) { - int count = m->AutoTargetServices; + m->NumAllInterfaceRecords++; + LogInfo("IncrementAutoTargetServices: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %s", + m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr)); + if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1) + m->NetworkChanged = m->timenow; + } +#endif - // Bump up before calling AdvertiseAllInterfaceRecords. AdvertiseInterface - // returns without doing anything if the count is zero. + if (!AuthRecord_uDNS(rr) && rr->resrec.rrtype == kDNSType_SRV && rr->AutoTarget == Target_AutoHost) + { m->AutoTargetServices++; - LogInfo("IncrementAutoTargetServices: AutoService Record %s, AutoTargetServices %d", ARDisplayString(m, rr), m->AutoTargetServices); - if (!count) + LogInfo("IncrementAutoTargetServices: AutoTargetServices %d Record %s", m->AutoTargetServices, ARDisplayString(m, rr)); + // If this is the first advertised service + if (m->AutoTargetServices == 1) AdvertiseAllInterfaceRecords(m); } } @@ -1378,6 +1421,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) // (kDNSRecordTypeDeregistering) so that we deliver RMV events to the application. But this causes more // complications and not clear whether there are any benefits. See rdar:9304275 for details. // Hence, just bail out. + // This comment is doesn’t make any sense. -- SC if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) { if (CheckAuthRecordConflict(&m->rrauth, rr)) @@ -1443,11 +1487,12 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) { AuthGroup *ag; ag = InsertAuthRecord(m, &m->rrauth, rr); - if (ag && !ag->NewLocalOnlyRecords) { + if (ag && !ag->NewLocalOnlyRecords) + { m->NewLocalOnlyRecords = mDNStrue; ag->NewLocalOnlyRecords = rr; } - // No probing for LocalOnly records, Acknowledge them right away + // No probing for LocalOnly records; acknowledge them right away if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified; AcknowledgeRecord(m, rr); return(mStatus_NoError); @@ -1459,15 +1504,15 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) } } - // If this is a keepalive record, fetch the MAC address of the remote host. + // If this is a non-sleep proxy keepalive record, fetch the MAC address of the remote host. // This is used by the in-NIC proxy to send the keepalive packets. - if (mDNS_KeepaliveRecord(&rr->resrec)) + if (!rr->WakeUp.HMAC.l[0] && mDNS_KeepaliveRecord(&rr->resrec)) { + mDNSAddr raddr; // Set the record type to known unique to prevent probing keep alive records. // Also make sure we do not announce the keepalive records. rr->resrec.RecordType = kDNSRecordTypeKnownUnique; rr->AnnounceCount = 0; - mDNSAddr raddr; 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 @@ -1476,8 +1521,9 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) if (!AuthRecord_uDNS(rr)) // This check is superfluous, given that for unicast records we (currently) bail out above { - // We have inserted the record in the list. See if we have to advertise the A/AAAA,HINFO,PTR records. + // We have inserted the record in the list. See if we have to advertise the A/AAAA, HINFO, PTR records. IncrementAutoTargetServices(m, rr); + // For records that are not going to probe, acknowledge them right away if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering) AcknowledgeRecord(m, rr); @@ -2361,8 +2407,8 @@ mDNSlocal void SendResponses(mDNS *const m) LogSPS("SendResponses: Sending wakeup %2d for %.6a %s", rr->AnnounceCount-3, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password); for (r2 = rr; r2; r2=r2->next) - if (r2->AnnounceCount && r2->resrec.InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&r2->WakeUp.IMAC, &rr->WakeUp.IMAC) && - !mDNSSameEthAddress(&zeroEthAddr, &r2->WakeUp.HMAC)) + if ((r2->resrec.RecordType == kDNSRecordTypeDeregistering) && r2->AnnounceCount && (r2->resrec.InterfaceID == rr->resrec.InterfaceID) && + mDNSSameEthAddress(&r2->WakeUp.IMAC, &rr->WakeUp.IMAC) && !mDNSSameEthAddress(&zeroEthAddr, &r2->WakeUp.HMAC)) { // For now we only want to send a single Unsolicited Neighbor Advertisement restoring the address to the original // owner, because these packets can cause some IPv6 stacks to falsely conclude that there's an address conflict. @@ -2532,7 +2578,7 @@ mDNSlocal void SendResponses(mDNS *const m) if ((rr->SendRNow == intf->InterfaceID) && ((rr->resrec.InterfaceID == mDNSInterface_Any) && !mDNSPlatformValidRecordForInterface(rr, intf))) { - LogInfo("SendResponses: Not sending %s, on %s", ARDisplayString(m, rr), InterfaceNameForID(m, rr->SendRNow)); + // LogInfo("SendResponses: Not sending %s, on %s", ARDisplayString(m, rr), InterfaceNameForID(m, rr->SendRNow)); rr->SendRNow = GetNextActiveInterfaceID(intf); } else if (rr->SendRNow == intf->InterfaceID) @@ -2917,10 +2963,10 @@ mDNSexport mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, // BuildQuestion puts a question into a DNS Query packet and if successful, updates the value of queryptr. // It also appends to the list of known answer records that need to be included, // and updates the forcast for the size of the known answer section. -mDNSlocal mDNSBool BuildQuestion(mDNS *const m, DNSMessage *query, mDNSu8 **queryptr, DNSQuestion *q, - CacheRecord ***kalistptrptr, mDNSu32 *answerforecast) +mDNSlocal mDNSBool BuildQuestion(mDNS *const m, const NetworkInterfaceInfo *intf, DNSMessage *query, mDNSu8 **queryptr, + DNSQuestion *q, CacheRecord ***kalistptrptr, mDNSu32 *answerforecast) { - mDNSBool ucast = (q->LargeAnswers || q->RequestUnicast) && m->CanReceiveUnicastOn5353; + mDNSBool ucast = (q->LargeAnswers || q->RequestUnicast) && m->CanReceiveUnicastOn5353 && intf->SupportsUnicastMDNSResponse; mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0); const mDNSu8 *const limit = query->data + NormalMaxDNSMessageData; mDNSu8 anoninfo_space = q->AnonInfo ? AnonInfoSpace(q->AnonInfo) : 0; @@ -3060,27 +3106,27 @@ mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *c #endif // SPC_DISABLED } -mDNSlocal void CheckAndSwapSPS(const CacheRecord *sps1, const CacheRecord *sps2) +mDNSlocal void CheckAndSwapSPS(const CacheRecord **sps1, const CacheRecord **sps2) { const CacheRecord *swap_sps; mDNSu32 metric1, metric2; - if (!sps1 || !sps2) return; - metric1 = SPSMetric(sps1->resrec.rdata->u.name.c); - metric2 = SPSMetric(sps2->resrec.rdata->u.name.c); - if (!SPSFeatures(sps1->resrec.rdata->u.name.c) && SPSFeatures(sps2->resrec.rdata->u.name.c) && (metric2 >= metric1)) + if (!(*sps1) || !(*sps2)) return; + metric1 = SPSMetric((*sps1)->resrec.rdata->u.name.c); + metric2 = SPSMetric((*sps2)->resrec.rdata->u.name.c); + if (!SPSFeatures((*sps1)->resrec.rdata->u.name.c) && SPSFeatures((*sps2)->resrec.rdata->u.name.c) && (metric2 >= metric1)) { - swap_sps = sps1; - sps1 = sps2; - sps2 = swap_sps; + swap_sps = *sps1; + *sps1 = *sps2; + *sps2 = swap_sps; } } mDNSlocal void ReorderSPSByFeature(const CacheRecord *sps[3]) { - CheckAndSwapSPS(sps[0], sps[1]); - CheckAndSwapSPS(sps[0], sps[2]); - CheckAndSwapSPS(sps[1], sps[2]); + CheckAndSwapSPS(&sps[0], &sps[1]); + CheckAndSwapSPS(&sps[0], &sps[2]); + CheckAndSwapSPS(&sps[1], &sps[2]); } @@ -3124,7 +3170,7 @@ mDNSlocal mDNSBool SuppressOnThisInterface(const DupSuppressInfo ds[DupSuppressI return(mDNSfalse); } -mDNSlocal int RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 Time, mDNSInterfaceID InterfaceID, mDNSs32 Type) +mDNSlocal void RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 Time, mDNSInterfaceID InterfaceID, mDNSs32 Type) { int i, j; @@ -3144,8 +3190,6 @@ mDNSlocal int RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDN ds[i].Time = Time; ds[i].InterfaceID = InterfaceID; ds[i].Type = Type; - - return(i); } mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q) @@ -3163,7 +3207,6 @@ mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q) // Split MAC@IPAddress and pass them separately len = d->c[0]; - i = 1; cnt = 0; for (i = 1; i < len; i++) { @@ -3558,7 +3601,7 @@ mDNSlocal void SendQueries(mDNS *const m) } // If we're suppressing this question, or we successfully put it, update its SendQNow state else if ((Suppress = SuppressOnThisInterface(q->DupSuppress, intf)) || - BuildQuestion(m, &m->omsg, &queryptr, q, &kalistptr, &answerforecast)) + BuildQuestion(m, intf, &m->omsg, &queryptr, q, &kalistptr, &answerforecast)) { // We successfully added the question to the packet. Make sure that // we also send the NSEC3 record if required. BuildQuestion accounted for @@ -3582,7 +3625,7 @@ mDNSlocal void SendQueries(mDNS *const m) q->WakeOnResolveCount--; } - // use brackground traffic class if any included question requires it + // use background traffic class if any included question requires it if (q->UseBackgroundTrafficClass) { useBackgroundTrafficClass = mDNStrue; @@ -3595,7 +3638,7 @@ mDNSlocal void SendQueries(mDNS *const m) for (ar = m->ResourceRecords; ar; ar=ar->next) if (ar->SendRNow == intf->InterfaceID) { - mDNSBool ucast = (ar->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353; + mDNSBool ucast = (ar->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353 && intf->SupportsUnicastMDNSResponse; mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0); const mDNSu8 *const limit = m->omsg.data + (m->omsg.h.numQuestions ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData); // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n) @@ -3893,6 +3936,31 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco return; } +#if TARGET_OS_EMBEDDED + if ((AddRecord == QC_add) && Question_uDNS(q) && (!q->metrics.answered || (q->metrics.querySendCount > 0))) + { + uDNSMetrics * metrics; + const domainname * queryName; + mDNSu32 responseLatencyMs; + mDNSBool isForCellular; + + metrics = &q->metrics; + queryName = metrics->originalQName ? metrics->originalQName : &q->qname; + if (metrics->querySendCount > 0) + { + responseLatencyMs = ((m->timenow - metrics->firstQueryTime) * 1000) / mDNSPlatformOneSecond; + } + else + { + responseLatencyMs = 0; + } + isForCellular = (q->qDNSServer && q->qDNSServer->cellIntf); + + MetricsUpdateUDNSStats(queryName, mDNStrue, metrics->querySendCount, responseLatencyMs, isForCellular); + metrics->answered = mDNStrue; + metrics->querySendCount = 0; + } +#endif // Note: Use caution here. In the case of records with rr->DelayDelivery set, AnswerCurrentQuestionWithResourceRecord(... mDNStrue) // may be called twice, once when the record is received, and again when it's time to notify local clients. // If any counters or similar are added here, care must be taken to ensure that they are not double-incremented by this. @@ -4884,7 +4952,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, m->SPSProxyListChanged); \ m->SPSProxyListChanged = (X); } while(0) // Called from mDNS_Execute() to expire stale proxy records @@ -5558,26 +5626,34 @@ mDNSexport void mDNS_UpdateAllowSleep(mDNS *const m) break; } - // Disallow sleep if there is no sleep proxy server - const CacheRecord *cr = FindSPSInCache1(m, &intf->NetWakeBrowse, mDNSNULL, mDNSNULL); - if ( cr == mDNSNULL) - { - allowSleep = mDNSfalse; - mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server on %s", intf->ifname); - LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server", intf->ifname); - break; - } - else if (m->SPSType != 0) + // If the interface can be an in-NIC Proxy, we should check if it can accomodate all the records + // that will be offloaded. If not, we should prevent sleep. + // This check will be possible once the lower layers provide an API to query the space available for offloads on the NIC. +#if APPLE_OSX_mDNSResponder + if (!SupportsInNICProxy(intf)) +#endif { - mDNSu32 mymetric = LocalSPSMetric(m); - mDNSu32 metric = SPSMetric(cr->resrec.rdata->u.name.c); - if (metric >= mymetric) + // Disallow sleep if there is no sleep proxy server + const CacheRecord *cr = FindSPSInCache1(m, &intf->NetWakeBrowse, mDNSNULL, mDNSNULL); + if ( cr == mDNSNULL) { allowSleep = mDNSfalse; - mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server with better metric on %s", intf->ifname); - LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server with a better metric", intf->ifname); + mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server on %s", intf->ifname); + LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server", intf->ifname); break; } + else if (m->SPSType != 0) + { + mDNSu32 mymetric = LocalSPSMetric(m); + mDNSu32 metric = SPSMetric(cr->resrec.rdata->u.name.c); + if (metric >= mymetric) + { + allowSleep = mDNSfalse; + mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server with better metric on %s", intf->ifname); + LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server with a better metric", intf->ifname); + break; + } + } } } } @@ -5608,7 +5684,7 @@ mDNSlocal mDNSBool mDNSUpdateOkToSend(mDNS *const m, AuthRecord *rr, NetworkInte // updateid and we should have returned from above. // // Note: scopeid is the same as intf->InterfaceID. It is passed in so that we don't have to call the - // platform function to extract the value from "intf" everytime. + // platform function to extract the value from "intf" every time. if ((scopeid >= (sizeof(rr->updateIntID) * mDNSNBBY) || bit_get_opaque64(rr->updateIntID, scopeid)) && (!rr->resrec.InterfaceID || rr->resrec.InterfaceID == intf->InterfaceID)) @@ -5619,35 +5695,41 @@ mDNSlocal mDNSBool mDNSUpdateOkToSend(mDNS *const m, AuthRecord *rr, NetworkInte mDNSexport void UpdateRMACCallback(mDNS *const m, void *context) { - IPAddressMACMapping *addrmap = (IPAddressMACMapping *)context ; - m->CurrentRecord = m->ResourceRecords; - - if (!addrmap) - { - LogMsg("UpdateRMACCallback: Address mapping is NULL"); - return; - } - - while (m->CurrentRecord) - { - AuthRecord *rr = m->CurrentRecord; - // If this is a keepalive record and the remote IP address matches, update the RData - if (mDNS_KeepaliveRecord(&rr->resrec)) - { - mDNSAddr raddr; - getKeepaliveRaddr(m, rr, &raddr); - if (mDNSSameAddress(&raddr, &addrmap->ipaddr)) - { - UpdateKeepaliveRData(m, rr, mDNSNULL, mDNStrue, (char *)(addrmap->ethaddr)); - } - } - m->CurrentRecord = rr->next; - } - - if (addrmap) - { - mDNSPlatformMemFree(addrmap); - } + IPAddressMACMapping *addrmap = (IPAddressMACMapping *)context ; + m->CurrentRecord = m->ResourceRecords; + + if (!addrmap) + { + LogMsg("UpdateRMACCallback: Address mapping is NULL"); + return; + } + + while (m->CurrentRecord) + { + AuthRecord *rr = m->CurrentRecord; + // If this is a non-sleep proxy keepalive record and the remote IP address matches, update the RData + if (!rr->WakeUp.HMAC.l[0] && mDNS_KeepaliveRecord(&rr->resrec)) + { + mDNSAddr raddr; + getKeepaliveRaddr(m, rr, &raddr); + if (mDNSSameAddress(&raddr, &addrmap->ipaddr)) + { + // Update the MAC address only if it is not a zero MAC address + mDNSEthAddr macAddr; + mDNSu8 *ptr = GetValueForMACAddr((mDNSu8 *)(addrmap->ethaddr), (mDNSu8 *) (addrmap->ethaddr + sizeof(addrmap->ethaddr)), &macAddr); + if (ptr != mDNSNULL && !mDNSEthAddressIsZero(macAddr)) + { + UpdateKeepaliveRData(m, rr, mDNSNULL, mDNStrue, (char *)(addrmap->ethaddr)); + } + } + } + m->CurrentRecord = rr->next; + } + + if (addrmap) + { + mDNSPlatformMemFree(addrmap); + } } mDNSexport mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSBool updateMac, char *ethAddr) @@ -6114,29 +6196,49 @@ mDNSexport mDNSBool mDNSCoreHaveAdvertisedMulticastServices(mDNS *const m) return mDNSfalse; } +#define WAKE_ONLY_SERVICE 1 +#define AC_ONLY_SERVICE 2 + #ifdef APPLE_OSX_mDNSResponder -// This function is used only in the case of local NIC proxy. For external -// sleep proxy server, we do this in SPSInitRecordsBeforeUpdate when we -// walk the resource records. -mDNSlocal void SendGoodbyesForWakeOnlyService(mDNS *const m, mDNSBool *WakeOnlyService) +mDNSlocal void SendGoodbyesForSelectServices(mDNS *const m, mDNSBool *servicePresent, mDNSu32 serviceType) { AuthRecord *rr; - - *WakeOnlyService = mDNSfalse; + *servicePresent = mDNSfalse; // Mark all the records we need to deregister and send them for (rr = m->ResourceRecords; rr; rr=rr->next) { - if ((rr->AuthFlags & AuthFlagsWakeOnly) && - rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye) + // If the service type is wake only service and the auth flags match and requires a goodbye + // OR if the service type is AC only and it is not a keepalive record, + // mark the records we need to deregister and send them + if ((serviceType == WAKE_ONLY_SERVICE && (rr->AuthFlags & AuthFlagsWakeOnly) && + rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye) || + (serviceType == AC_ONLY_SERVICE && !mDNS_KeepaliveRecord(&rr->resrec))) { rr->ImmedAnswer = mDNSInterfaceMark; - *WakeOnlyService = mDNStrue; + *servicePresent = mDNStrue; } } } +#endif + +#ifdef APPLE_OSX_mDNSResponder +// This function is used only in the case of local NIC proxy. For external +// sleep proxy server, we do this in SPSInitRecordsBeforeUpdate when we +// walk the resource records. +mDNSlocal void SendGoodbyesForWakeOnlyService(mDNS *const m, mDNSBool *WakeOnlyService) +{ + return SendGoodbyesForSelectServices(m, WakeOnlyService, WAKE_ONLY_SERVICE); +} #endif // APPLE_OSx_mDNSResponder +#ifdef APPLE_OSX_mDNSResponder +mDNSlocal void SendGoodbyesForACOnlyServices(mDNS *const m, mDNSBool *acOnlyService) +{ + return SendGoodbyesForSelectServices(m, acOnlyService, AC_ONLY_SERVICE); +} +#endif + mDNSlocal void SendSleepGoodbyes(mDNS *const m, mDNSBool AllInterfaces, mDNSBool unicast) { AuthRecord *rr; @@ -6232,6 +6334,7 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m) { mDNSBool SendGoodbyes = mDNStrue; mDNSBool WakeOnlyService = mDNSfalse; + mDNSBool ACOnlyService = mDNSfalse; mDNSBool invokeKACallback = mDNStrue; const CacheRecord *sps[3] = { mDNSNULL }; mDNSOpaque64 updateIntID = zeroOpaque64; @@ -6288,9 +6391,12 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m) #if APPLE_OSX_mDNSResponder else if (SupportsInNICProxy(intf)) { - if (ActivateLocalProxy(m, intf) == mStatus_NoError) + mDNSBool keepaliveOnly = mDNSfalse; + if (ActivateLocalProxy(m, intf, &keepaliveOnly) == mStatus_NoError) { SendGoodbyesForWakeOnlyService(m, &WakeOnlyService); + if (keepaliveOnly) + SendGoodbyesForACOnlyServices(m, &ACOnlyService); SendGoodbyes = mDNSfalse; invokeKACallback = mDNSfalse; LogSPS("BeginSleepProcessing: %-6s using local proxy", intf->ifname); @@ -6334,9 +6440,9 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m) { #if ForceAlerts if (intf->SPSAddr[i].type) - { LogMsg("BeginSleepProcessing: %s %d intf->SPSAddr[i].type %d", intf->ifname, i, intf->SPSAddr[i].type); *(long*)0 = 0; } + LogFatalError("BeginSleepProcessing: %s %d intf->SPSAddr[i].type %d", intf->ifname, i, intf->SPSAddr[i].type); if (intf->NetWakeResolve[i].ThisQInterval >= 0) - { LogMsg("BeginSleepProcessing: %s %d intf->NetWakeResolve[i].ThisQInterval %d", intf->ifname, i, intf->NetWakeResolve[i].ThisQInterval); *(long*)0 = 0; } + LogFatalError("BeginSleepProcessing: %s %d intf->NetWakeResolve[i].ThisQInterval %d", intf->ifname, i, intf->NetWakeResolve[i].ThisQInterval); #endif intf->SPSAddr[i].type = mDNSAddrType_None; if (intf->NetWakeResolve[i].ThisQInterval >= 0) mDNS_StopQuery(m, &intf->NetWakeResolve[i]); @@ -6396,10 +6502,10 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m) LogSPS("BeginSleepProcessing: Not registering with Sleep Proxy Server on all interfaces"); SendSleepGoodbyes(m, mDNSfalse, mDNSfalse); } - else if (WakeOnlyService) + else if (WakeOnlyService || ACOnlyService) { // If we saw WakeOnly service above, send the goodbyes now. - LogSPS("BeginSleepProcessing: Sending goodbyes for WakeOnlyServices"); + LogSPS("BeginSleepProcessing: Sending goodbyes for %s", WakeOnlyService? "WakeOnlyService" : "AC Only Service"); SendResponses(m); } } @@ -6473,11 +6579,7 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep) { m->SleepState = SleepState_Awake; m->SleepSeqNum++; - // If the machine wakes and then immediately tries to sleep again (e.g. a maintenance wake) - // then we enforce a minimum delay of 16 seconds before we begin sleep processing. - // This is to allow time for the Ethernet link to come up, DHCP to get an address, mDNS to issue queries, etc., - // before we make our determination of whether there's a Sleep Proxy out there we should register with. - m->DelaySleep = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 16); + m->DelaySleep = 0; } if (m->SPSState == 3) @@ -7103,7 +7205,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, mDNSBool QueryWasMulticast, mDNSBool QueryWasLocalUnicast, DNSMessage *const response) { - mDNSBool FromLocalSubnet = srcaddr && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr, mDNSNULL); + mDNSBool FromLocalSubnet = srcaddr && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr); AuthRecord *ResponseRecords = mDNSNULL; AuthRecord **nrp = &ResponseRecords; @@ -7653,9 +7755,9 @@ exit: DNSQuestion *q = DupQuestions; DupQuestions = q->NextInDQList; q->NextInDQList = mDNSNULL; - i = RecordDupSuppressInfo(q->DupSuppress, m->timenow, InterfaceID, srcaddr->type); - debugf("ProcessQuery: Recorded DSI for %##s (%s) on %p/%s %d", q->qname.c, DNSTypeName(q->qtype), InterfaceID, - srcaddr->type == mDNSAddrType_IPv4 ? "v4" : "v6", i); + RecordDupSuppressInfo(q->DupSuppress, m->timenow, InterfaceID, srcaddr->type); + debugf("ProcessQuery: Recorded DSI for %##s (%s) on %p/%s", q->qname.c, DNSTypeName(q->qtype), InterfaceID, + srcaddr->type == mDNSAddrType_IPv4 ? "v4" : "v6"); } if (McastNSEC3Records) @@ -7673,7 +7775,7 @@ mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg, { mDNSu8 *responseend = mDNSNULL; mDNSBool QueryWasLocalUnicast = srcaddr && dstaddr && - !mDNSAddrIsDNSMulticast(dstaddr) && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr, mDNSNULL); + !mDNSAddrIsDNSMulticast(dstaddr) && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr); if (!InterfaceID && dstaddr && mDNSAddrIsDNSMulticast(dstaddr)) { @@ -7791,111 +7893,6 @@ mDNSlocal DNSQuestion *ExpectingUnicastResponseForRecord(mDNS *const m, return(mDNSNULL); } -// Return a pointer to the primary service name, skipping subtype name if present. -mDNSlocal const domainname *getPrimaryServiceName(const domainname *domainName) -{ - const domainname *primaryName = domainName; - const domainname *subName = SkipLeadingLabels(domainName, 1); - - if (SameDomainLabel(subName->c, (const mDNSu8 *)mDNSSubTypeLabel)) - { - // skip "<sub type name>._sub" portion of name - primaryName = SkipLeadingLabels(domainName, 2); - debugf("getPrimaryServiceName: returning %##s for _sub type", primaryName); - } - - return primaryName; -} - -// This function is not called if the packet is from us, which implies that we accept all multicast packets coming from us. -mDNSlocal mDNSBool ExpectingMulticastResponseForRecord(mDNS *const m, CacheRecord *rr, const mDNSAddr *srcaddr, mDNSBool recordAccepted, - CacheRecord **McastNSEC3Records) -{ - DNSQuestion *q; - - // Accept A and AAAA if we accepted something before in the same packet as most likely related to the - // service records that we may have accepted. - if (recordAccepted && (rr->resrec.rrtype == kDNSType_A || rr->resrec.rrtype == kDNSType_AAAA)) - { - LogInfo("ExpectingMulticastResponseForRecord:A:AAAA: accepting %s, from %#a due to same packet %d", CRDisplayString(m, rr), srcaddr, m->PktNum); - return mDNStrue; - } - for (q = m->Questions; q; q=q->next) - { - if (!q->DuplicateOf && mDNSOpaque16IsZero(q->TargetQID)) - { - mDNSBool ret; - // 1. If a resource record answers question, cache it. This also will cache NSECs if it asserts - // non-existence of q->qtype. If we have any matching NSEC3 Records for the question, send - // it along with the resource record. Do it only for questions that are expecting to - // discover only its peers (q->AnonInfo not NULL) - if (q->AnonInfo && McastNSEC3Records && !rr->resrec.AnonInfo) - { - InitializeAnonInfoForCR(m, McastNSEC3Records, rr); - } - ret = ResourceRecordAnswersQuestion(&rr->resrec, q); - if (ret) - { - // The record and the question belong to the same subset. Set the - // anonymous data in the cache record. - if (q->AnonInfo && rr->resrec.AnonInfo) - { - SetAnonData(q, &rr->resrec, mDNSfalse); - } - LogInfo("ExpectingMulticastResponseForRecord: Name and Type match, accepting %s, from %#a", CRDisplayString(m, rr), srcaddr); - if (rr->resrec.rrtype == kDNSType_NSEC) - LogInfo("ExpectingMulticastResponseForRecord: record %s, question %##s (%s)", CRDisplayString(m, rr), q->qname.c, DNSTypeName(q->qtype)); - return mDNStrue; - } - if (rr->resrec.rrtype == kDNSType_SRV || rr->resrec.rrtype == kDNSType_TXT) - { - // Point to the service type in the record name - const domainname *name = SkipLeadingLabels(rr->resrec.name, 1); - - // If question is for a sub type, just compare against the primary service type - const domainname *primaryName = getPrimaryServiceName(&q->qname); - - // 2. If the SRV or TXT record matches the service name, then cache it. If the TXT or SRV record is - // before the PTR record in the packet, PTR record may not be in the cache yet and hence the logic - // in (3) below will fail to cache it. - if (q->qtype == kDNSType_PTR && name && SameDomainName(primaryName, name)) - { - LogInfo("ExpectingMulticastResponseForRecord: Accepting %s due to PTR match, question %##s from %#a, pktnum %d", - CRDisplayString(m, rr), q->qname.c, srcaddr, m->PktNum); - return mDNStrue; - } - - if (name) - { - const mDNSu32 slot = HashSlot(name); - const mDNSu32 namehash = DomainNameHashValue(name); - CacheGroup *cg = CacheGroupForName(m, slot, namehash, name); - CacheRecord *cr; - - // 3. Same as in (2), but look in the cache in case we don't have the PTR question. - - for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next) - { - if (cr->resrec.rrtype == kDNSType_PTR) - { - primaryName = getPrimaryServiceName(cr->resrec.name); - - if (SameDomainName(primaryName, name)) - { - LogInfo("ExpectingMulticastResponseForRecord: accepting %s, from %#a, pktnum %d", - CRDisplayString(m, rr), srcaddr, m->PktNum); - return mDNStrue; - } - } - } - } - } - } - } - debugf("ExpectingMulticastResponseForRecord: discarding %s, from %#a, pktnum %d", CRDisplayString(m, rr), srcaddr, m->PktNum); - return(mDNSfalse); -} - // Certain data types need more space for in-memory storage than their in-packet rdlength would imply // Currently this applies only to rdata types containing more than one domainname, // or types where the domainname is not the last item in the structure. @@ -8441,7 +8438,8 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * name = (const domainname *)(name->c + 1 + name->c[0]); hash = DomainNameHashValue(name); slot = HashSlot(name); - cg = CacheGroupForName(m, slot, hash, 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); } } } @@ -8643,7 +8641,7 @@ mDNSlocal CacheRecord* mDNSCoreReceiveCacheCheck(mDNS *const m, const DNSMessage mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end, const mDNSInterfaceID InterfaceID, CacheRecord **NSEC3Records) { - const mDNSu8 *ptr = response->data; + const mDNSu8 *ptr; CacheRecord *rr; int i; @@ -8692,24 +8690,6 @@ mDNSlocal void mDNSCoreResetRecord(mDNS *const m) } } -#define DEVICE_INFO_RECORD_LABELS 4 - -// Determine if the record is an instance of _device-info._tcp.local. -mDNSlocal mDNSBool IsDeviceInfoRecord(const domainname *d) -{ - const domainname *afterInstance; - - if (CountLabels(d) != DEVICE_INFO_RECORD_LABELS) - return mDNSfalse; - - // skip the instance name - afterInstance = SkipLeadingLabels(d, 1); - if (SameDomainName(afterInstance, &LocalDeviceInfoName)) - return mDNStrue; - - return mDNSfalse; -} - // Note: mDNSCoreReceiveResponse 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. @@ -8722,9 +8702,8 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, const mDNSInterfaceID InterfaceID) { int i; - mDNSBool myself; mDNSBool ResponseMCast = dstaddr && mDNSAddrIsDNSMulticast(dstaddr); - mDNSBool ResponseSrcLocal = !srcaddr || mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr, &myself); + mDNSBool ResponseSrcLocal = !srcaddr || mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr); DNSQuestion *llqMatch = mDNSNULL; DNSQuestion *unicastQuestion = mDNSNULL; uDNS_LLQType LLQType = uDNS_recvLLQResponse(m, response, end, srcaddr, srcport, &llqMatch); @@ -8742,12 +8721,11 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, mDNSu8 rcode = '\0'; mDNSBool rrsigsCreated = mDNSfalse; mDNSBool DNSSECQuestion = mDNSfalse; - mDNSBool recordAccepted = mDNSfalse; NetworkInterfaceInfo *llintf = FirstIPv4LLInterfaceForID(m, InterfaceID); // All records in a DNS response packet are treated as equally valid statements of truth. If we want // to guard against spoof responses, then the only credible protection against that is cryptographic - // security, e.g. DNSSEC., not worring about which section in the spoof packet contained the record + // security, e.g. DNSSEC., not worrying about which section in the spoof packet contained the record. int firstauthority = response->h.numAnswers; int firstadditional = firstauthority + response->h.numAuthorities; int totalrecords = firstadditional + response->h.numAdditionals; @@ -8983,64 +8961,69 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // Even though it is AcceptableResponse, we still need a DNSServer pointer for the resource records that // we create. - if (!mDNSOpaque16IsZero(response->h.id)) - { - DNSQuestion *q = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r, !dstaddr); - - // Initialize the DNS server on the resource record which will now filter what questions we answer with - // this record. - // - // We could potentially lookup the DNS server based on the source address, but that may not work always - // and that's why ExpectingUnicastResponseForRecord does not try to verify whether the response came - // from the DNS server that queried. We follow the same logic here. If we can find a matching quetion based - // on the "id" and "source port", then this response answers the question and assume the response - // came from the same DNS server that we sent the query to. - - if (q != mDNSNULL) - { - AcceptableResponse = mDNStrue; - if (!InterfaceID) - { - debugf("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); - m->rec.r.resrec.rDNSServer = uDNSServer = q->qDNSServer; - } - else - LogInfo("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); - } - else - { - // If we can't find a matching question, we need to see whether we have seen records earlier that matched - // the question. The code below does that. So, make this record unacceptable for now - if (!InterfaceID) - { - debugf("mDNSCoreReceiveResponse: Can't find question for record name %##s", m->rec.r.resrec.name->c); - AcceptableResponse = mDNSfalse; - } - } - } - else if (ExpectingMulticastResponseForRecord(m, &m->rec.r, srcaddr, recordAccepted, &McastNSEC3Records)) - { - recordAccepted = mDNStrue; - AcceptableResponse = mDNStrue; - LogInfo("mDNSCoreReceiveResponse: Accepting record in response to QU question %s, InterfaceID %p", CRDisplayString(m, &m->rec.r), - InterfaceID); - } - else if (IsDeviceInfoRecord(m->rec.r.resrec.name)) - { - recordAccepted = mDNStrue; - AcceptableResponse = mDNStrue; - LogInfo("mDNSCoreReceiveResponse: Accepting _device-info record %s, InterfaceID %p", - CRDisplayString(m, &m->rec.r), InterfaceID); - } + DNSQuestion *q = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r, !dstaddr); + + // Initialize the DNS server on the resource record which will now filter what questions we answer with + // this record. + // + // We could potentially lookup the DNS server based on the source address, but that may not work always + // and that's why ExpectingUnicastResponseForRecord does not try to verify whether the response came + // from the DNS server that queried. We follow the same logic here. If we can find a matching quetion based + // on the "id" and "source port", then this response answers the question and assume the response + // came from the same DNS server that we sent the query to. + + if (q != mDNSNULL) + { + AcceptableResponse = mDNStrue; + if (!InterfaceID) + { + debugf("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); + m->rec.r.resrec.rDNSServer = uDNSServer = q->qDNSServer; + } + else + LogInfo("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); + } + else + { + // If we can't find a matching question, we need to see whether we have seen records earlier that matched + // the question. The code below does that. So, make this record unacceptable for now + if (!InterfaceID) + { + debugf("mDNSCoreReceiveResponse: Can't find question for record name %##s", m->rec.r.resrec.name->c); + AcceptableResponse = mDNSfalse; + } + } } } else if (llintf && llintf->IgnoreIPv4LL && m->rec.r.resrec.rrtype == kDNSType_A) { - CacheRecord *const rr = &m->rec.r; - RDataBody2 *const rdb = (RDataBody2 *)rr->smallrdatastorage.data; + // There are some routers (rare, thankfully) that generate bogus ARP responses for + // any IPv4 address they don’t recognize, including RFC 3927 IPv4 link-local addresses. + // To work with these broken routers, client devices need to blacklist these broken + // routers and ignore their bogus ARP responses. Some devices implement a technique + // such as the one described in US Patent 7436783, which lets clients detect and + // ignore these broken routers: <https://www.google.com/patents/US7436783> + + // OS X and iOS do not implement this defensive mechanism, instead taking a simpler + // approach of just detecting these broken routers and completely disabling IPv4 + // link-local communication on interfaces where a broken router is detected. + // OS X and iOS set the IFEF_ARPLL interface flag on interfaces + // that are deemed “safe” for IPv4 link-local communication; + // the flag is cleared on interfaces where a broken router is detected. + + // OS X and iOS will not even try to communicate with an IPv4 + // link-local destination on an interface without the IFEF_ARPLL flag set. + // This can cause some badly written applications to freeze for a long time if they + // attempt to connect to an IPv4 link-local destination address and then wait for + // that connection attempt to time out before trying other candidate addresses. + + // To mask this client bug, we suppress acceptance of IPv4 link-local address + // records on interfaces where we know the OS will be unwilling even to attempt + // communication with those IPv4 link-local destination addresses. + // <rdar://problem/9400639> kSuppress IPv4LL answers on interfaces without IFEF_ARPLL - // If we are supposed to ignore link-local addresses on this interface, drop - // all "A" records that have link-local address in them. + const CacheRecord *const rr = &m->rec.r; + const RDataBody2 *const rdb = (RDataBody2 *)rr->smallrdatastorage.data; if (mDNSv4AddressIsLinkLocal(&rdb->ipv4)) { LogInfo("mDNSResponder: Dropping LinkLocal packet %s", CRDisplayString(m, &m->rec.r)); @@ -9099,7 +9082,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, if (rr->ProbeCount > DefaultProbeCountForTypeUnique) LogInfo("mDNSCoreReceiveResponse: Already reset to Probing: %s", ARDisplayString(m, rr)); else if (rr->ProbeCount == DefaultProbeCountForTypeUnique) - LogMsg("mDNSCoreReceiveResponse: Ignoring response received before we even began probing: %s", ARDisplayString(m, rr)); + LogInfo("mDNSCoreReceiveResponse: Ignoring response received before we even began probing: %s", ARDisplayString(m, rr)); else { LogMsg("mDNSCoreReceiveResponse: Received from %#a:%d %s", srcaddr, mDNSVal16(srcport), CRDisplayString(m, &m->rec.r)); @@ -9185,27 +9168,6 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, rr = mDNSCoreReceiveCacheCheck(m, response, LLQType, slot, cg, unicastQuestion, &cfp, &NSECCachePtr, InterfaceID); } - // If mDNSOppCaching is set (which affects only multicast), enable opportunistic caching in which case we cache - // everything that was received over multicast. Otherwise, we are selective about the caching. - // - // Cache everything that is from ourselves (that's how we answer any questions looking for them). Otherwise call - // ExpectingMulticastResponseForRecord which decides whether to cache this record or not. - // - if (!m->mDNSOppCaching && !rr && !myself && mDNSOpaque16IsZero(response->h.id)) - { - if (!ExpectingMulticastResponseForRecord(m, &m->rec.r, srcaddr, recordAccepted, &McastNSEC3Records)) - { - //LogMsg("mDNSCoreReceiveResponse: discarding %s", CRDisplayString(m, &m->rec.r)); - mDNSCoreResetRecord(m); - continue; - } - else - { - recordAccepted = mDNStrue; - } - } - - // If packet resource record not in our cache, add it now // (unless it is just a deletion of a record we never had, in which case we don't care) if (!rr && m->rec.r.resrec.rroriginalttl > 0) @@ -9343,15 +9305,22 @@ exit: // goodbye announcement with the cache flush bit set (or a case-change on record rdata, // which we treat as a goodbye followed by an addition) and in that case it would be // inappropriate to synchronize all the other records to a TTL of 0 (or 1). + // We suppress the message for the specific case of correcting from 240 to 60 for type TXT, // because certain early Bonjour devices are known to have this specific mismatch, and // there's no point filling syslog with messages about something we already know about. // We also don't log this for uDNS responses, since a caching name server is obliged // to give us an aged TTL to correct for how long it has held the record, // so our received TTLs are expected to vary in that case + + // We also suppress log message in the case of SRV records that are recieved + // with a TTL of 4500 that are already cached with a TTL of 120 seconds, since + // this behavior was observed for a number of discoveryd based AppleTV's in iOS 8 + // GM builds. if (r2->resrec.rroriginalttl != r1->resrec.rroriginalttl && r1->resrec.rroriginalttl > 1) { if (!(r2->resrec.rroriginalttl == 240 && r1->resrec.rroriginalttl == 60 && r2->resrec.rrtype == kDNSType_TXT) && + !(r2->resrec.rroriginalttl == 120 && r1->resrec.rroriginalttl == 4500 && r2->resrec.rrtype == kDNSType_SRV) && mDNSOpaque16IsZero(response->h.id)) LogInfo("Correcting TTL from %4d to %4d for %s", r2->resrec.rroriginalttl, r1->resrec.rroriginalttl, CRDisplayString(m, r2)); @@ -9550,6 +9519,11 @@ mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *et } else if (*ptr == ':') { + if (colons >=5 || val > 255) + { + LogMsg("GetValueForMACAddr: Address malformed colons %d val %d", colons, val); + return mDNSNULL; + } eth->b[colons] = val; colons++; val = 0; @@ -9681,6 +9655,11 @@ mDNSlocal mDNSu8 *GetValueForIPv4Addr(mDNSu8 *ptr, mDNSu8 *limit, mDNSv4Addr *v4 val = val * 10 + *ptr - '0'; else if (*ptr == '.') { + if (val > 255 || dots >= 3) + { + LogMsg("GetValueForIPv4Addr: something wrong ptr(%p) %c, limit %p, dots %d", ptr, *ptr, limit, dots); + return mDNSNULL; + } v4->b[dots++] = val; val = 0; } @@ -9723,6 +9702,37 @@ mDNSlocal mDNSu8 *GetValueForKeepalive(mDNSu8 *ptr, mDNSu8 *limit, mDNSu32 *valu return ptr; } +mDNSexport mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr) +{ + mDNSAddr laddr, raddr; + mDNSEthAddr eth; + mDNSIPPort lport, rport; + mDNSu32 timeout, seq, ack; + mDNSu16 win; + + if (!mDNS_KeepaliveRecord(&rr->resrec)) + { + return mDNSfalse; + } + + timeout = seq = ack = 0; + win = 0; + laddr = raddr = zeroAddr; + lport = rport = zeroIPPort; + + mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, &raddr, ð, &seq, &ack, &lport, &rport, &win); + + if (mDNSAddressIsZero(&laddr) || mDNSIPPortIsZero(lport) || + mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(rport) || + mDNSEthAddressIsZero(eth)) + { + return mDNSfalse; + } + + return mDNStrue; +} + + mDNSlocal void mDNS_ExtractKeepaliveInfo(AuthRecord *ar, mDNSu32 *timeout, mDNSAddr *laddr, mDNSAddr *raddr, mDNSEthAddr *eth, mDNSu32 *seq, mDNSu32 *ack, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu16 *win) { @@ -9899,16 +9909,18 @@ mDNSlocal void mDNS_SendKeepalives(mDNS *const m) mDNSlocal void mDNS_SendKeepaliveACK(mDNS *const m, AuthRecord *ar) { - if (ar != mDNSNULL) - { - LogInfo("mDNS_SendKeepalivesACK: AuthRecord is NULL"); - return; - } - mDNSu32 timeout, seq, ack; + mDNSu32 timeout, seq, ack, seqInc; mDNSu16 win; mDNSAddr laddr, raddr; mDNSEthAddr eth; mDNSIPPort lport, rport; + mDNSu8 *ptr; + + if (ar == mDNSNULL) + { + LogInfo("mDNS_SendKeepalivesACK: AuthRecord is NULL"); + return; + } timeout = seq = ack = 0; win = 0; @@ -9923,6 +9935,17 @@ mDNSlocal void mDNS_SendKeepaliveACK(mDNS *const m, AuthRecord *ar) LogInfo("mDNS_SendKeepaliveACK: not a valid record %s for keepalive", ARDisplayString(m, ar)); return; } + + // To send a keepalive ACK, we need to add one to the sequence number from the keepalive + // record, which is the TCP connection's "next" sequence number minus one. Otherwise, the + // keepalive ACK also ends up being a keepalive probe. Also, seq is in network byte order, so + // it's converted to host byte order before incrementing it by one. + ptr = (mDNSu8 *)&seq; + seqInc = (mDNSu32)((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]) + 1; + ptr[0] = (mDNSu8)((seqInc >> 24) & 0xFF); + ptr[1] = (mDNSu8)((seqInc >> 16) & 0xFF); + ptr[2] = (mDNSu8)((seqInc >> 8) & 0xFF); + ptr[3] = (mDNSu8)((seqInc ) & 0xFF); LogMsg("mDNS_SendKeepaliveACK: laddr %#a raddr %#a lport %d rport %d", &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport)); mDNSPlatformSendKeepalive(&laddr, &raddr, &lport, &rport, seq, ack, win); } @@ -10089,6 +10112,8 @@ mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg { 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); @@ -10138,8 +10163,7 @@ mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg } // Update the dynamic store with the IP Address and MAC address of the sleep proxy - char *ifname = InterfaceNameForID(m, InterfaceID); - mDNSAddr spsaddr; + ifname = InterfaceNameForID(m, InterfaceID); mDNSPlatformMemCopy(&spsaddr, srcaddr, sizeof (mDNSAddr)); mDNSPlatformStoreSPSMACAddr(&spsaddr, ifname); } @@ -10152,12 +10176,7 @@ mDNSexport void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr, const domainname *const name, const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds, mDNSInterfaceID InterfaceID, DNSServer *dnsserver) { if (cr == &m->rec.r && m->rec.r.resrec.RecordType) - { - LogMsg("MakeNegativeCacheRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r)); -#if ForceAlerts - *(long*)0 = 0; -#endif - } + LogFatalError("MakeNegativeCacheRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r)); // Create empty resource record cr->resrec.RecordType = kDNSRecordTypePacketNegative; @@ -10265,7 +10284,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co // 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, mDNSNULL) && + if (!mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr) && mDNSAddressIsAllDNSLinkGroup(dstaddr)) { m->RemoteSubnet++; @@ -10472,8 +10491,8 @@ mDNSexport McastResolver *mDNS_AddMcastResolver(mDNS *const m, const domainname { if ((*p)->interface == interface && SameDomainName(&(*p)->domain, d)) { - if (!((*p)->flags & DNSServer_FlagDelete)) LogMsg("Note: Mcast Resolver domain %##s (%p) registered more than once", d->c, interface); - (*p)->flags &= ~DNSServer_FlagDelete; + if (!((*p)->flags & McastResolver_FlagDelete)) LogMsg("Note: Mcast Resolver domain %##s (%p) registered more than once", d->c, interface); + (*p)->flags &= ~McastResolver_FlagDelete; tmp = *p; *p = tmp->next; tmp->next = mDNSNULL; @@ -10491,7 +10510,7 @@ mDNSexport McastResolver *mDNS_AddMcastResolver(mDNS *const m, const domainname else { (*p)->interface = interface; - (*p)->flags = DNSServer_FlagNew; + (*p)->flags = McastResolver_FlagNew; (*p)->timeout = timeout; AssignDomainName(&(*p)->domain, d); (*p)->next = mDNSNULL; @@ -10696,10 +10715,11 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) // match the scoped entries by mistake. // // Note: DNS configuration change will help pick the new dns servers but currently it does not affect the timeout - - if (curr->scoped && curr->interface == mDNSInterface_Any) + + // Skip DNSServers that are InterfaceID Scoped but have no valid interfaceid set OR DNSServers that are ServiceID Scoped but have no valid serviceid set + if ((curr->scoped == kScopeInterfaceID && curr->interface == mDNSInterface_Any) || (curr->scoped == kScopeServiceID && curr->serviceID <= 0)) { - debugf("SetValidDNSServers: Scoped DNS server %#a (Domain %##s) with Interface Any", &curr->addr, curr->domain.c); + LogInfo("SetValidDNSServers: ScopeType[%d] Skipping DNS server %#a (Domain %##s) Interface:[%p] Serviceid:[%d]", curr->scoped, &curr->addr, curr->domain.c, curr->interface, curr->serviceID); continue; } @@ -11350,6 +11370,9 @@ mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question) question->triedAllServersOnce = 0; question->noServerResponse = 0; question->StopTime = 0; +#if TARGET_OS_EMBEDDED + mDNSPlatformMemZero(&question->metrics, sizeof(question->metrics)); +#endif // Need not initialize the DNS Configuration for Local Only OR P2P Questions if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P) @@ -11397,6 +11420,7 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) { mDNSBool purge; int i; + mDNSBool isCellBlocked = mDNSfalse; // Note: In the case where we already have the answer to this question in our cache, that may be all the client // wanted, and they may immediately cancel their question. In this case, sending an actual query on the wire would @@ -11445,13 +11469,13 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) question->FlappingInterface1 = mDNSNULL; question->FlappingInterface2 = mDNSNULL; - // if kDNSServiceFlagsServiceIndex flag is SET by the client, then do NOT call mDNSPlatformGetServiceID() + // if kDNSServiceFlagsServiceIndex flag is SET by the client, then do NOT call mDNSPlatformGetDNSRoutePolicy() // since we would already have the question->ServiceID in that case. if (!(question->flags & kDNSServiceFlagsServiceIndex)) - question->ServiceID = mDNSPlatformGetServiceID(m, question); + mDNSPlatformGetDNSRoutePolicy(m, question, &isCellBlocked); else - LogInfo("InitCommonState: Query for %##s (%s), PID[%d], ServiceID %d is already set by client", question->qname.c, - DNSTypeName(question->qtype), question->pid, question->ServiceID); + LogInfo("InitCommonState: Query for %##s (%s), PID[%d], EUID[%d], ServiceID[%d] is already set by client", question->qname.c, + DNSTypeName(question->qtype), question->pid, question->euid, question->ServiceID); InitDNSConfig(m, question); @@ -11462,10 +11486,10 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) // If ServiceID is 0 or the policy disallows making DNS requests, // set DisallowPID - question->DisallowPID = (question->ServiceID == 0 || (mDNSPlatformAllowPID(m, question) == 0)); + question->DisallowPID = (question->ServiceID == 0 || (isCellBlocked && question->qDNSServer && question->qDNSServer->cellIntf)); if (question->DisallowPID) LogInfo("InitCommonState: Query suppressed for %##s (%s), PID %d/ServiceID %d not allowed", question->qname.c, - DNSTypeName(question->qtype), question->pid, question->ServiceID); + DNSTypeName(question->qtype), question->pid, question->ServiceID); question->NextInDQList = mDNSNULL; question->SendQNow = mDNSNULL; @@ -11584,7 +11608,7 @@ mDNSlocal void InitDNSSECProxyState(mDNS *const m, DNSQuestion *const question) { if (question->qDNSServer->cellIntf) { - LogInfo("InitDNSSECProxyState: Turning off validation for %##s (%s); going over cell", question->qname.c, DNSTypeName(question->qtype)); + debugf("InitDNSSECProxyState: Turning off validation for %##s (%s); going over cell", question->qname.c, DNSTypeName(question->qtype)); question->ValidationRequired = mDNSfalse; } if (DNSSECOptionalQuestion(question) && !(question->qDNSServer->req_DO)) @@ -11719,6 +11743,13 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu } else { +#if TARGET_OS_WATCH + m->NumAllInterfaceQuestions++; + LogInfo("mDNS_StartQuery_internal: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %##s (%s)", + m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, question->qname.c, DNSTypeName(question->qtype)); + if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1) + m->NetworkChanged = m->timenow; +#endif if (purge) { LogInfo("mDNS_StartQuery_internal: Purging for %##s", question->qname.c); @@ -11763,14 +11794,35 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que #if !ForceAlerts if (question->ThisQInterval >= 0) // Only log error message if the query was supposed to be active #endif - LogMsg("mDNS_StopQuery_internal: Question %##s (%s) not found in active list", - question->qname.c, DNSTypeName(question->qtype)); -#if ForceAlerts - *(long*)0 = 0; -#endif + LogFatalError("mDNS_StopQuery_internal: Question %##s (%s) not found in active list", question->qname.c, DNSTypeName(question->qtype)); return(mStatus_BadReferenceErr); } +#if TARGET_OS_WATCH + if (question->InterfaceID != mDNSInterface_LocalOnly && question->InterfaceID != mDNSInterface_P2P && mDNSOpaque16IsZero(question->TargetQID)) + { + if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1) + m->NetworkChanged = m->timenow; + m->NumAllInterfaceQuestions--; + LogInfo("mDNS_StopQuery_internal: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %##s (%s)", + m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, question->qname.c, DNSTypeName(question->qtype)); + } +#endif + +#if TARGET_OS_EMBEDDED + if (Question_uDNS(question) && !question->metrics.answered) + { + uDNSMetrics * metrics; + const domainname * queryName; + mDNSBool isForCellular; + + metrics = &question->metrics; + queryName = metrics->originalQName ? metrics->originalQName : &question->qname; + isForCellular = (question->qDNSServer && question->qDNSServer->cellIntf); + + MetricsUpdateUDNSStats(queryName, mDNSfalse, metrics->querySendCount, 0, isForCellular); + } +#endif // Take care to cut question from list *before* calling UpdateQuestionDuplicates UpdateQuestionDuplicates(m, question); // But don't trash ThisQInterval until afterwards. @@ -11893,6 +11945,13 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que FreeAnonInfo(question->AnonInfo); question->AnonInfo = mDNSNULL; } +#if TARGET_OS_EMBEDDED + if (question->metrics.originalQName) + { + mDNSPlatformMemFree(question->metrics.originalQName); + question->metrics.originalQName = mDNSNULL; + } +#endif return(mStatus_NoError); } @@ -12345,6 +12404,7 @@ mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, m question->qnameOrig = mDNSNULL; question->AnonInfo = mDNSNULL; question->pid = mDNSPlatformGetPID(); + question->euid = 0; question->QuestionCallback = Callback; question->QuestionContext = Context; if (DomainType > mDNS_DomainTypeMax) return(mStatus_BadParamErr); @@ -12461,26 +12521,20 @@ mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) { char buffer[MAX_REVERSE_MAPPING_NAME]; NetworkInterfaceInfo *primary; + mDNSu8 recordType; - if (!set->McastTxRx) - { - LogInfo("AdvertiseInterface: Returning, not multicast capable %s", set->ifname); - return; - } -#if TARGET_OS_EMBEDDED - if (!m->AutoTargetServices) + if (m->AutoTargetServices == 0) { LogInfo("AdvertiseInterface: Returning due to AutoTargetServices zero for %s", set->ifname); return; } -#endif primary = FindFirstAdvertisedInterface(m); if (!primary) primary = set; // If no existing advertised interface, this new NetworkInterfaceInfo becomes our new primary // 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. - mDNSu8 recordType = (set->DirectLink ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique); + recordType = (set->DirectLink ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique); if (set->DirectLink) LogInfo("AdvertiseInterface: Marking address record as kDNSRecordTypeKnownUnique for %s", set->ifname); @@ -12555,22 +12609,19 @@ mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) mDNSlocal void DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) { - NetworkInterfaceInfo *intf; - - // If we still have address records referring to this one, update them - NetworkInterfaceInfo *primary = FindFirstAdvertisedInterface(m); - AuthRecord *A = primary ? &primary->RR_A : mDNSNULL; - for (intf = m->HostInterfaces; intf; intf = intf->next) - if (intf->RR_A.RRSet == &set->RR_A) - intf->RR_A.RRSet = A; + if (m->AutoTargetServices == 0) + { + LogInfo("DeadvertiseInterface: Returning due to AutoTargetServices zero for %s", set->ifname); + return; + } // Unregister these records. // When doing the mDNS_Exit processing, we first call DeadvertiseInterface for each interface, so by the time the platform // support layer gets to call mDNS_DeregisterInterface, the address and PTR records have already been deregistered for it. // Also, in the event of a name conflict, one or more of our records will have been forcibly deregistered. // To avoid unnecessary and misleading warning messages, we check the RecordType before calling mDNS_Deregister_internal(). - if (set->RR_A.resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_A, mDNS_Dereg_normal); - if (set->RR_PTR.resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_PTR, mDNS_Dereg_normal); + if (set->RR_A .resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_A, mDNS_Dereg_normal); + if (set->RR_PTR .resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_PTR, mDNS_Dereg_normal); if (set->RR_HINFO.resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_HINFO, mDNS_Dereg_normal); #if APPLE_OSX_mDNSResponder @@ -12594,7 +12645,6 @@ mDNSlocal void AdvertiseAllInterfaceRecords(mDNS *const m) mDNSlocal void DeadvertiseAllInterfaceRecords(mDNS *const m) { -#if TARGET_OS_EMBEDDED NetworkInterfaceInfo *intf; for (intf = m->HostInterfaces; intf; intf = intf->next) { @@ -12604,15 +12654,11 @@ mDNSlocal void DeadvertiseAllInterfaceRecords(mDNS *const m) DeadvertiseInterface(m, intf); } } -#else - (void) m; //unused -#endif } mDNSexport void mDNS_SetFQDN(mDNS *const m) { domainname newmname; - NetworkInterfaceInfo *intf; AuthRecord *rr; newmname.c[0] = 0; @@ -12625,14 +12671,8 @@ mDNSexport void mDNS_SetFQDN(mDNS *const m) else { AssignDomainName(&m->MulticastHostname, &newmname); - - // 1. Stop advertising our address records on all interfaces - for (intf = m->HostInterfaces; intf; intf = intf->next) - if (intf->Advertise) DeadvertiseInterface(m, intf); - - // 2. Start advertising our address records using the new name - for (intf = m->HostInterfaces; intf; intf = intf->next) - if (intf->Advertise) AdvertiseInterface(m, intf); + DeadvertiseAllInterfaceRecords(m); + AdvertiseAllInterfaceRecords(m); } // 3. Make sure that any AutoTarget SRV records (and the like) get updated @@ -12951,6 +12991,9 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se { NetworkInterfaceInfo **p = &m->HostInterfaces; mDNSBool revalidate = mDNSfalse; + NetworkInterfaceInfo *primary; + NetworkInterfaceInfo *intf; + AuthRecord *A; mDNS_Lock(m); @@ -12967,14 +13010,13 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se if (!set->InterfaceActive) { // If this interface not the active member of its set, update the v4/v6Available flags for the active member - NetworkInterfaceInfo *intf; for (intf = m->HostInterfaces; intf; intf = intf->next) if (intf->InterfaceActive && intf->InterfaceID == set->InterfaceID) UpdateInterfaceProtocols(m, intf); } else { - NetworkInterfaceInfo *intf = FirstInterfaceForID(m, set->InterfaceID); + intf = FirstInterfaceForID(m, set->InterfaceID); if (intf) { LogInfo("mDNS_DeregisterInterface: Another representative of InterfaceID %d %s (%#a) exists;" @@ -13007,7 +13049,7 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se if (set->McastTxRx && flapping) { - LogMsg("DeregisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip); + LogMsg("mDNS_DeregisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip); m->mDNSStats.InterfaceDownFlap++; } @@ -13048,6 +13090,15 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se } } + // If we still have address records referring to this one, update them. + // This is safe, because this NetworkInterfaceInfo has already been unlinked from the list, + // so the call to FindFirstAdvertisedInterface() won’t accidentally find it. + primary = FindFirstAdvertisedInterface(m); + A = primary ? &primary->RR_A : mDNSNULL; + for (intf = m->HostInterfaces; intf; intf = intf->next) + if (intf->RR_A.RRSet == &set->RR_A) + intf->RR_A.RRSet = A; + // If we were advertising on this interface, deregister those address and reverse-lookup records now if (set->Advertise) DeadvertiseInterface(m, set); @@ -13370,8 +13421,6 @@ mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, e = &sr->Extras; while (*e) e = &(*e)->next; - if (ttl == 0) ttl = kStandardTTL; - extra->r.DependentOn = &sr->RR_SRV; debugf("mDNS_AddRecordToService adding record to %##s %s %d", @@ -14025,11 +14074,13 @@ mDNSexport void mDNSCoreReceiveRawPacket(mDNS *const m, const mDNSu8 *const p, c else if (end >= p+34 && mDNSSameOpaque16(eth->ethertype, Ethertype_IPv4) && (pkt->v4.flagsfrags.b[0] & 0x1F) == 0 && pkt->v4.flagsfrags.b[1] == 0) { const mDNSu8 *const trans = p + 14 + (pkt->v4.vlen & 0xF) * 4; + const mDNSu8 * transEnd = p + 14 + mDNSVal16(pkt->v4.totlen); + if (transEnd > end) transEnd = end; debugf("Got IPv4 %02X from %.4a to %.4a", pkt->v4.protocol, &pkt->v4.src, &pkt->v4.dst); src.type = mDNSAddrType_IPv4; src.ip.v4 = pkt->v4.src; dst.type = mDNSAddrType_IPv4; dst.ip.v4 = pkt->v4.dst; - if (end >= trans + RequiredCapLen(pkt->v4.protocol)) - mDNSCoreReceiveRawTransportPacket(m, ð->src, &src, &dst, pkt->v4.protocol, p, (TransportLayerPacket*)trans, end, InterfaceID, 0); + if (transEnd >= trans + RequiredCapLen(pkt->v4.protocol)) + mDNSCoreReceiveRawTransportPacket(m, ð->src, &src, &dst, pkt->v4.protocol, p, (TransportLayerPacket*)trans, transEnd, InterfaceID, 0); } // Is IPv6? Length must be at least 14 + 28 = 42 bytes else if (end >= p+54 && mDNSSameOpaque16(eth->ethertype, Ethertype_IPv6)) @@ -14160,6 +14211,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, if (!rrcachestorage) rrcachesize = 0; m->p = p; + m->NetworkChanged = 0; m->CanReceiveUnicastOn5353 = mDNSfalse; // Assume we can't receive unicasts on 5353, unless platform layer tells us otherwise m->AdvertiseLocalAddresses = AdvertiseLocalAddresses; m->DivertMulticastAdvertisements = mDNSfalse; @@ -14282,13 +14334,20 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->WABBrowseQueriesCount = 0; m->WABLBrowseQueriesCount = 0; m->WABRegQueriesCount = 0; -#if !TARGET_OS_EMBEDDED - m->mDNSOppCaching = mDNStrue; +#if TARGET_OS_EMBEDDED || TARGET_OS_WATCH + m->AutoTargetServices = 0; #else - m->mDNSOppCaching = mDNSfalse; + m->AutoTargetServices = 1; +#endif +#if TARGET_OS_WATCH + m->NumAllInterfaceRecords = 0; + m->NumAllInterfaceQuestions = 0; +#else + // Initialize to 1 for these targets to prevent not joining multicast group for interfaces when + // both of these values are zero. + m->NumAllInterfaceRecords = 1; + m->NumAllInterfaceQuestions = 1; #endif - m->AutoTargetServices = 0; - // NAT traversal fields m->LLQNAT.clientCallback = mDNSNULL; m->LLQNAT.clientContext = mDNSNULL; @@ -14525,6 +14584,10 @@ mDNSlocal void SetConfigState(mDNS *const m, mDNSBool delete) ptr->penaltyTime = 0; NumUnicastDNSServers--; ptr->flags |= DNSServer_FlagDelete; +#if APPLE_OSX_mDNSResponder + if (ptr->flags & DNSServer_FlagUnreachable) + NumUnreachableDNSServers--; +#endif } // We handle the mcast resolvers here itself as mDNSPlatformSetDNSConfig looks at // mcast resolvers. Today we get both mcast and ucast configuration using the same @@ -14539,6 +14602,10 @@ mDNSlocal void SetConfigState(mDNS *const m, mDNSBool delete) ptr->penaltyTime = 0; NumUnicastDNSServers++; ptr->flags &= ~DNSServer_FlagDelete; +#if APPLE_OSX_mDNSResponder + if (ptr->flags & DNSServer_FlagUnreachable) + NumUnreachableDNSServers++; +#endif } for (mr = m->McastResolvers; mr; mr = mr->next) mr->flags &= ~McastResolver_FlagDelete; @@ -14587,7 +14654,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) // affecting them as they never change. while (*mres) { - if (((*mres)->flags & DNSServer_FlagDelete) != 0) + if (((*mres)->flags & McastResolver_FlagDelete) != 0) { mr = *mres; *mres = (*mres)->next; @@ -14913,7 +14980,6 @@ mDNSlocal void DeregLoop(mDNS *const m, AuthRecord *const start) mDNSexport void mDNS_StartExit(mDNS *const m) { - NetworkInterfaceInfo *intf; AuthRecord *rr; mDNS_Lock(m); @@ -14953,9 +15019,7 @@ mDNSexport void mDNS_StartExit(mDNS *const m) } #endif - for (intf = m->HostInterfaces; intf; intf = intf->next) - if (intf->Advertise) - DeadvertiseInterface(m, intf); + DeadvertiseAllInterfaceRecords(m); // Shut down all our active NAT Traversals while (m->NATTraversals) @@ -15015,14 +15079,13 @@ mDNSexport void mDNS_StartExit(mDNS *const m) mDNSexport void mDNS_FinalExit(mDNS *const m) { mDNSu32 rrcache_active = 0; - mDNSu32 rrcache_totalused = 0; + mDNSu32 rrcache_totalused = m->rrcache_totalused; mDNSu32 slot; AuthRecord *rr; LogInfo("mDNS_FinalExit: mDNSPlatformClose"); mDNSPlatformClose(m); - rrcache_totalused = m->rrcache_totalused; for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) { while (m->rrcache_hash[slot]) @@ -15041,7 +15104,7 @@ mDNSexport void mDNS_FinalExit(mDNS *const m) } debugf("mDNS_FinalExit: RR Cache was using %ld records, %lu active", rrcache_totalused, rrcache_active); if (rrcache_active != m->rrcache_active) - LogMsg("*** ERROR *** rrcache_active %lu != m->rrcache_active %lu", rrcache_active, m->rrcache_active); + LogMsg("*** ERROR *** rrcache_totalused %lu; rrcache_active %lu != m->rrcache_active %lu", rrcache_totalused, rrcache_active, m->rrcache_active); for (rr = m->ResourceRecords; rr; rr = rr->next) LogMsg("mDNS_FinalExit failed to send goodbye for: %p %02X %s", rr, rr->resrec.RecordType, ARDisplayString(m, rr)); diff --git a/mDNSResponder/mDNSCore/mDNSDebug.h b/mDNSResponder/mDNSCore/mDNSDebug.h index 5467ae64..68a696ef 100755 --- a/mDNSResponder/mDNSCore/mDNSDebug.h +++ b/mDNSResponder/mDNSCore/mDNSDebug.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -148,12 +148,18 @@ extern void LogMsgWithLevel(mDNSLogLevel_t logLevel, const char *format, ...) IS // (or completely overhauled to use the new "log to a separate file" facility) #define LogMsgNoIdent LogMsg +#if APPLE_OSX_mDNSResponder +extern void LogFatalError(const char *format, ...); +#else +#define LogFatalError LogMsg +#endif + #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1 extern void *mallocL(char *msg, unsigned int size); extern void freeL(char *msg, void *x); -extern void LogMemCorruption(const char *format, ...); extern void uds_validatelists(void); extern void udns_validatelists(void *const v); +extern void LogMemCorruption(const char *format, ...); #else #define mallocL(X,Y) malloc(Y) #define freeL(X,Y) free(Y) diff --git a/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h b/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h index bafeb026..48f8280d 100755 --- a/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h +++ b/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -70,6 +70,7 @@ #include "mDNSDebug.h" #if APPLE_OSX_mDNSResponder #include <uuid/uuid.h> +#include <TargetConditionals.h> #endif #ifdef __cplusplus @@ -90,20 +91,14 @@ extern "C" { // In order to disable the above features pass the option to your compiler, e.g. -D UNICAST_DISABLED -// Additionally, the LIMITED_RESOURCES_TARGET compile option will eliminate caching and -// and reduce the maximum DNS message sizes. +// Additionally, the LIMITED_RESOURCES_TARGET compile option will reduce the maximum DNS message sizes. #ifdef LIMITED_RESOURCES_TARGET // Don't support jumbo frames -#define AbsoluteMaxDNSMessageData 1500 -// By the time you add IPv6 header (40 bytes) UDP header (8 bytes) and DNS message header (12 bytes) -// this makes 1560 which is 60 bytes over the standard Ethernet MTU. D'oh! - +// 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total +#define AbsoluteMaxDNSMessageData 1440 // StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes) #define MaximumRDSize 264 -// Don't cache anything -#define AUTH_HASH_SLOTS 1 -#define CACHE_HASH_SLOTS 1 #endif // *************************************************************************** @@ -556,7 +551,7 @@ typedef packedstruct { mDNSu8 vlen; mDNSu8 tos; - mDNSu16 totlen; + mDNSOpaque16 totlen; mDNSOpaque16 id; mDNSOpaque16 flagsfrags; mDNSu8 ttl; @@ -1320,8 +1315,11 @@ enum enum { - DNSServer_FlagDelete = 1, - DNSServer_FlagNew = 2 + DNSServer_FlagDelete = 0x1, + DNSServer_FlagNew = 0x2, +#if APPLE_OSX_mDNSResponder + DNSServer_FlagUnreachable = 0x4, +#endif }; enum @@ -1413,7 +1411,7 @@ struct ResourceRecord_struct // that are interface-specific (e.g. address records, especially linklocal addresses) const domainname *name; RData *rdata; // Pointer to storage for this rdata - DNSServer *rDNSServer; // Unicast DNS server authoritative for this entry;null for multicast + DNSServer *rDNSServer; // Unicast DNS server authoritative for this entry; null for multicast AnonymousInfo *AnonInfo; // Anonymous Information }; @@ -1502,7 +1500,7 @@ struct AuthRecord_struct AuthRecord *next; // Next in list; first element of structure for efficiency reasons // Field Group 1: Common ResourceRecord fields - ResourceRecord resrec; // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit + ResourceRecord resrec; // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit (now 44/64) // Field Group 2: Persistent metadata for Authoritative Records AuthRecord *Additional1; // Recommended additional record to include in response (e.g. SRV for PTR record) @@ -1634,7 +1632,7 @@ typedef struct ARListElem struct CacheRecord_struct { CacheRecord *next; // Next in list; first element of structure for efficiency reasons - ResourceRecord resrec; // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit + ResourceRecord resrec; // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit (now 44/64) // Transient state for Cache Records CacheRecord *NextInKAList; // Link to the next element in the chain of known answers to send @@ -1658,13 +1656,12 @@ struct CacheRecord_struct CacheRecord *soa; // SOA record to return for proxy questions mDNSAddr sourceAddress; // node from which we received this record - // Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit + // Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit (now 160 bytes for 64-bit) RData_small smallrdatastorage; // Storage for small records is right here (4 bytes header + 68 bytes data = 72 bytes) }; // Should match the CacheGroup_struct members, except namestorage[]. Only used to calculate -// the size of the namestorage array in CacheGroup_struct so that -// sizeof(CacheGroup) == sizeof(CacheRecord) +// the size of the namestorage array in CacheGroup_struct so that sizeof(CacheGroup) == sizeof(CacheRecord) struct CacheGroup_base { CacheGroup *next; @@ -1887,6 +1884,17 @@ typedef enum { DNSSECValNotRequired = 0, DNSSECValRequired, DNSSECValInProgress, // RFC 4122 defines it to be 16 bytes #define UUID_SIZE 16 +#if TARGET_OS_EMBEDDED +typedef struct +{ + domainname * originalQName; // Name of original A/AAAA record if this question is for a CNAME record. + mDNSu32 querySendCount; // Number of queries that have been sent to DNS servers so far. + mDNSs32 firstQueryTime; // The time when the first query was sent to a DNS server. + mDNSBool answered; // Has this question been answered? + +} uDNSMetrics; +#endif + struct DNSQuestion_struct { // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them. @@ -1997,9 +2005,13 @@ struct DNSQuestion_struct mDNSu8 ProxyDNSSECOK; // Proxy Question with EDNS0 DNSSEC OK bit set mDNSs32 pid; // Process ID of the client that is requesting the question mDNSu8 uuid[UUID_SIZE]; // Unique ID of the client that is requesting the question (valid only if pid is zero) + mDNSu32 euid; // Effective User Id of the client that is requesting the question domainname *qnameOrig; // Copy of the original question name if it is not fully qualified mDNSQuestionCallback *QuestionCallback; void *QuestionContext; +#if TARGET_OS_EMBEDDED + uDNSMetrics metrics; // Data used for collecting unicast DNS query metrics. +#endif }; typedef struct @@ -2145,6 +2157,8 @@ struct NetworkInterfaceInfo_struct mDNSu8 SendGoodbyes; // Send goodbyes on this interface while sleeping mDNSBool DirectLink; // a direct link, indicating we can skip the probe for // address records + mDNSBool SupportsUnicastMDNSResponse; // Indicates that the interface supports unicast responses + // to Bonjour queries. Generally true for an interface. }; #define SLE_DELETE 0x00000001 @@ -2259,6 +2273,7 @@ typedef struct mDNSu32 CacheRefreshed; // Number of times the cache was refreshed due to a response mDNSu32 WakeOnResolves; // Number of times we did a wake on resolve } mDNSStatistics; + extern void LogMDNSStatistics(mDNS *const m); struct mDNS_struct @@ -2269,6 +2284,7 @@ struct mDNS_struct // all required data is passed as parameters to that function. mDNS_PlatformSupport *p; // Pointer to platform-specific data of indeterminite size + mDNSs32 NetworkChanged; mDNSBool CanReceiveUnicastOn5353; mDNSBool AdvertiseLocalAddresses; mDNSBool DivertMulticastAdvertisements; // from interfaces that do not advertise local addresses to local-only @@ -2368,7 +2384,7 @@ struct mDNS_struct mDNSs32 ProbeFailTime; mDNSu32 NumFailedProbes; mDNSs32 SuppressProbes; - Platform_t mDNS_plat; + Platform_t mDNS_plat; // Why is this here in the “only required for mDNS Responder” section? -- SC // Unicast-specific data mDNSs32 NextuDNSEvent; // uDNS next event @@ -2454,9 +2470,10 @@ struct mDNS_struct TrustAnchor *TrustAnchors; int notifyToken; - int uds_listener_skt; // Listening socket for incoming UDS clients - mDNSBool mDNSOppCaching; // Opportunistic Caching + int uds_listener_skt; // Listening socket for incoming UDS clients. This should not be here -- it's private to uds_daemon.c and nothing to do with mDNSCore -- SC mDNSu32 AutoTargetServices; // # of services that have AutoTarget set + mDNSu32 NumAllInterfaceRecords; // Right now we count *all* multicast records here. Later we may want to change to count interface-specific records separately. (This count includes records on the DuplicateRecords list too.) + mDNSu32 NumAllInterfaceQuestions; // Right now we count *all* multicast questions here. Later we may want to change to count interface-specific questions separately. DNSSECStatistics DNSSECStats; mDNSStatistics mDNSStats; @@ -2468,8 +2485,8 @@ struct mDNS_struct }; #define FORALL_CACHERECORDS(SLOT,CG,CR) \ - for ((SLOT) = 0; (SLOT) < CACHE_HASH_SLOTS; (SLOT)++) \ - for ((CG)=m->rrcache_hash[(SLOT)]; (CG); (CG)=(CG)->next) \ + for ((SLOT) = 0; (SLOT) < CACHE_HASH_SLOTS; (SLOT)++) \ + for ((CG)=m->rrcache_hash[(SLOT)]; (CG); (CG)=(CG)->next) \ for ((CR) = (CG)->members; (CR); (CR)=(CR)->next) // *************************************************************************** @@ -2530,6 +2547,9 @@ extern const mDNSOpaque64 zeroOpaque64; extern mDNSBool StrictUnicastOrdering; extern mDNSu8 NumUnicastDNSServers; +#if APPLE_OSX_mDNSResponder +extern mDNSu8 NumUnreachableDNSServers; +#endif #define localdomain (*(const domainname *)"\x5" "local") #define DeviceInfoName (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp") @@ -2648,7 +2668,6 @@ extern mStatus mDNS_Init (mDNS *const m, mDNS_PlatformSupport *const p, extern void mDNS_ConfigChanged(mDNS *const m); extern void mDNS_GrowCache (mDNS *const m, CacheEntity *storage, mDNSu32 numrecords); -extern void mDNS_GrowAuth (mDNS *const m, AuthEntity *storage, mDNSu32 numrecords); extern void mDNS_StartExit (mDNS *const m); extern void mDNS_FinalExit (mDNS *const m); #define mDNS_Close(m) do { mDNS_StartExit(m); mDNS_FinalExit(m); } while(0) @@ -2784,7 +2803,7 @@ extern mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, mDNS_DomainT #define mDNS_StopAdvertiseDomains mDNS_Deregister extern mDNSOpaque16 mDNS_NewMessageID(mDNS *const m); -extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr, mDNSBool *myself); +extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr); extern DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question); extern mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question); @@ -3195,6 +3214,7 @@ extern mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, m extern void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status); extern void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason); +extern void mDNSPlatformPreventSleep(mDNS *const m, mDNSu32 timeout, const char *reason); extern void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration); extern mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID); @@ -3317,11 +3337,13 @@ extern void RemoveAutoTunnel6Record(mDNS *const m); extern mDNSBool RecordReadyForSleep(mDNS *const m, AuthRecord *rr); // For now this LocalSleepProxy stuff is specific to Mac OS X. // In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer -extern mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const intf); +extern mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const intf, mDNSBool *keepaliveOnly); extern void mDNSPlatformUpdateDNSStatus(mDNS *const m, DNSQuestion *q); extern void mDNSPlatformTriggerDNSRetry(mDNS *const m, DNSQuestion *v4q, DNSQuestion *v6q); extern void mDNSPlatformLogToFile(int log_level, const char *buffer); extern mDNSBool SupportsInNICProxy(NetworkInterfaceInfo *const intf); +extern mStatus SymptomReporterDNSServerReachable(mDNS *const m, const mDNSAddr *addr); +extern mStatus SymptomReporterDNSServerUnreachable(DNSServer *s); #endif typedef void ProxyCallback (mDNS *const m, void *socket, void *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, @@ -3336,11 +3358,11 @@ extern mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMes extern void mDNSPlatformSleepAssertion(mDNS *const m, double timeout); #endif -extern mDNSBool mDNSPlatformAllowPID(mDNS *const m, DNSQuestion *q); -extern mDNSs32 mDNSPlatformGetServiceID(mDNS *const m, DNSQuestion *q); +extern void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isBlocked); extern void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q); extern mDNSs32 mDNSPlatformGetPID(void); - +extern mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr); + // *************************************************************************** #if 0 #pragma mark - @@ -3556,21 +3578,18 @@ struct CompileTimeAssertionChecks_mDNS char sizecheck_AuthRecord [(sizeof(AuthRecord) <= 1208) ? 1 : -1]; char sizecheck_CacheRecord [(sizeof(CacheRecord) <= 232) ? 1 : -1]; char sizecheck_CacheGroup [(sizeof(CacheGroup) <= 232) ? 1 : -1]; - char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 832) ? 1 : -1]; + char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 864) ? 1 : -1]; -// Checks commented out when sizeof(DNSQuestion) change cascaded into having to change yet another -// set of hardcoded size values because these structures contain one or more DNSQuestion -// instances. -// char sizecheck_ZoneData [(sizeof(ZoneData) <= 1648) ? 1 : -1]; + char sizecheck_ZoneData [(sizeof(ZoneData) <= 1700) ? 1 : -1]; char sizecheck_NATTraversalInfo [(sizeof(NATTraversalInfo) <= 200) ? 1 : -1]; char sizecheck_HostnameInfo [(sizeof(HostnameInfo) <= 3050) ? 1 : -1]; char sizecheck_DNSServer [(sizeof(DNSServer) <= 340) ? 1 : -1]; -// char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 6988) ? 1 : -1]; + char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 7184) ? 1 : -1]; char sizecheck_ServiceRecordSet [(sizeof(ServiceRecordSet) <= 5540) ? 1 : -1]; char sizecheck_DomainAuthInfo [(sizeof(DomainAuthInfo) <= 7888) ? 1 : -1]; -// char sizecheck_ServiceInfoQuery [(sizeof(ServiceInfoQuery) <= 3302) ? 1 : -1]; + char sizecheck_ServiceInfoQuery [(sizeof(ServiceInfoQuery) <= 3488) ? 1 : -1]; #if APPLE_OSX_mDNSResponder -// char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1160) ? 1 : -1]; + char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1208) ? 1 : -1]; #endif }; diff --git a/mDNSResponder/mDNSCore/nsec.c b/mDNSResponder/mDNSCore/nsec.c index a9f16b3f..09d27356 100644 --- a/mDNSResponder/mDNSCore/nsec.c +++ b/mDNSResponder/mDNSCore/nsec.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2013 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -611,7 +611,7 @@ mDNSlocal mDNSBool NSECNoDataError(mDNS *const m, ResourceRecord *rr, domainname { const domainname *oname = rr->name; // owner name - if (wildcard) *wildcard = mDNSNULL; + *wildcard = mDNSNULL; // RFC 4035 // // section 3.1.3.1 : Name matches. Prove that the type does not exist and also CNAME is @@ -676,10 +676,10 @@ mDNSlocal mDNSBool NSECNoDataError(mDNS *const m, ResourceRecord *rr, domainname // a subdomain e.g., y.x.example or z.y.x.example and so on. if (oname->c[0] == 1 && oname->c[1] == '*') { - int r, s; + int s; const domainname *ce = SkipLeadingLabels(oname, 1); - r = DNSSECCanonicalOrder(name, ce, &s); + DNSSECCanonicalOrder(name, ce, &s); if (s) { if (RRAssertsExistence(rr, qtype) || RRAssertsExistence(rr, kDNSType_CNAME)) @@ -912,18 +912,18 @@ mDNSlocal void NoDataProof(mDNS *const m, DNSSECVerifier *dv, CacheRecord *ncr) // First verify wildcard NSEC and then when we are done, we // will verify the noname nsec dv->pendingNSEC = r; - LogDNSSEC("NoDataProof: Verifying wild and noname %s", RRDisplayString(m, nsec_wild)); + LogDNSSEC("NoDataProof: Verifying wild and noname %s", nsec_wild ? RRDisplayString(m, nsec_wild) : "NULL"); VerifyNSEC(m, nsec_wild, mDNSNULL, dv, ncr, NoDataNSECCallback); } else if ((dv->flags & WILDCARD_PROVES_NONAME_EXISTS) || (dv->flags & NSEC_PROVES_NOTYPE_EXISTS)) { - LogDNSSEC("NoDataProof: Verifying wild %s", RRDisplayString(m, nsec_wild)); + LogDNSSEC("NoDataProof: Verifying wild %s", nsec_wild ? RRDisplayString(m, nsec_wild) : "NULL"); VerifyNSEC(m, nsec_wild, mDNSNULL, dv, ncr, mDNSNULL); } else if (dv->flags & NSEC_PROVES_NONAME_EXISTS) { - LogDNSSEC("NoDataProof: Verifying noname %s", RRDisplayString(m, nsec_noname)); + LogDNSSEC("NoDataProof: Verifying noname %s", nsec_noname ? RRDisplayString(m, nsec_noname) : "NULL"); VerifyNSEC(m, nsec_noname, mDNSNULL, dv, ncr, mDNSNULL); } return; diff --git a/mDNSResponder/mDNSCore/nsec.h b/mDNSResponder/mDNSCore/nsec.h index 3dbb841f..198f57db 100644 --- a/mDNSResponder/mDNSCore/nsec.h +++ b/mDNSResponder/mDNSCore/nsec.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2012 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef __NSEC_H #define __NSEC_H diff --git a/mDNSResponder/mDNSCore/nsec3.c b/mDNSResponder/mDNSCore/nsec3.c index a039418a..c16a42d5 100644 --- a/mDNSResponder/mDNSCore/nsec3.c +++ b/mDNSResponder/mDNSCore/nsec3.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2013 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -332,7 +332,7 @@ mDNSlocal mDNSBool NSEC3Find(mDNS *const m, NSEC3FindValues val, CacheRecord *nc } } - if ((val == NSEC3Covers || val == NSEC3CEProof) && !(*closerEncloser)) + if ((val == NSEC3Covers || val == NSEC3CEProof) && (!closerEncloser || !(*closerEncloser))) { if (NSEC3CoversName(m, cr, hashName, hlen, b32Name, b32len)) { @@ -349,23 +349,22 @@ mDNSlocal mDNSBool NSEC3Find(mDNS *const m, NSEC3FindValues val, CacheRecord *nc // 2.3) If there is a matching NSEC3 RR in the response and the flag // was set, then the proof is complete, and SNAME is the closest // encloser. - if (val == NSEC3CEProof) + if (val == NSEC3CEProof && closestEncloser && *closestEncloser) { - if (*closestEncloser && *closerEncloser) + if (closerEncloser && *closerEncloser) { LogDNSSEC("NSEC3Find: Found closest and closer encloser"); return mDNStrue; } - - // 2.4) If there is a matching NSEC3 RR in the response, but the flag - // is not set, then the response is bogus. - // - // Note: We don't have to wait till we finish trying all the names. If the matchName - // happens, we found the closest encloser which means we should have found the closer - // encloser before. - - if (*closestEncloser && !(*closerEncloser)) + else { + // 2.4) If there is a matching NSEC3 RR in the response, but the flag + // is not set, then the response is bogus. + // + // Note: We don't have to wait till we finish trying all the names. If the matchName + // happens, we found the closest encloser which means we should have found the closer + // encloser before. + LogDNSSEC("NSEC3Find: Found closest, but not closer encloser"); return mDNSfalse; } @@ -388,8 +387,7 @@ mDNSlocal mDNSBool NSEC3ClosestEncloserProof(mDNS *const m, CacheRecord *ncr, do // Note: It is possible that closestEncloser and closerEncloser are the same. if (!closestEncloser || !closerEncloser || !ce) { - LogMsg("NSEC3ClosestEncloserProof: ClosestEncloser %p or CloserEncloser %p ce %p, something is NULL", *closestEncloser, - *closerEncloser, *ce); + LogMsg("NSEC3ClosestEncloserProof: ClosestEncloser %p or CloserEncloser %p ce %p, something is NULL", closestEncloser, closerEncloser, ce); return mDNSfalse; } diff --git a/mDNSResponder/mDNSCore/nsec3.h b/mDNSResponder/mDNSCore/nsec3.h index ce3b85a3..be32b809 100644 --- a/mDNSResponder/mDNSCore/nsec3.h +++ b/mDNSResponder/mDNSCore/nsec3.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2011-2012 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/mDNSResponder/mDNSCore/uDNS.c b/mDNSResponder/mDNSCore/uDNS.c index ce12d01a..3ba88b5c 100755 --- a/mDNSResponder/mDNSCore/uDNS.c +++ b/mDNSResponder/mDNSCore/uDNS.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2015 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,6 +51,9 @@ mDNSBool StrictUnicastOrdering = mDNSfalse; // arbitrary limitation of 64 DNSServers can be removed. mDNSu8 NumUnicastDNSServers = 0; #define MAX_UNICAST_DNS_SERVERS 64 +#if APPLE_OSX_mDNSResponder +mDNSu8 NumUnreachableDNSServers = 0; +#endif #define SetNextuDNSEvent(m, rr) { \ if ((m)->NextuDNSEvent - ((rr)->LastAPTime + (rr)->ThisAPInterval) >= 0) \ @@ -164,6 +167,12 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons if (tmp) { +#if APPLE_OSX_mDNSResponder + if (tmp->flags & DNSServer_FlagDelete) + { + tmp->flags &= ~DNSServer_FlagUnreachable; + } +#endif tmp->flags &= ~DNSServer_FlagDelete; *p = tmp; // move to end of list, to ensure ordering from platform layer } @@ -214,7 +223,8 @@ mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 re { DNSServer *new; DNSServer *orig = q->qDNSServer; - + mDNSu8 rcode = '\0'; + mDNS_CheckLock(m); LogInfo("PenalizeDNSServer: Penalizing DNS server %#a question for question %p %##s (%s) SuppressUnusable %d", @@ -224,10 +234,13 @@ mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 re // return the error, then return the first error. if (mDNSOpaque16IsZero(q->responseFlags)) q->responseFlags = responseFlags; + + rcode = (mDNSu8)(responseFlags.b[1] & kDNSFlag1_RC_Mask); // After we reset the qDNSServer to NULL, we could get more SERV_FAILS that might end up // peanlizing again. - if (!q->qDNSServer) goto end; + if (!q->qDNSServer) + goto end; // If strict ordering of unicast servers needs to be preserved, we just lookup // the next best match server below @@ -246,6 +259,10 @@ mDNSexport void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 re { LogInfo("PenalizeDNSServer: Not Penalizing PTR question"); } + else if ((rcode == kDNSFlag1_RC_FormErr) || (rcode == kDNSFlag1_RC_ServFail) || (rcode == kDNSFlag1_RC_NotImpl) || (rcode == kDNSFlag1_RC_Refused)) + { + LogInfo("PenalizeDNSServer: Not Penalizing DNS Server since it at least responded with rcode %d", rcode); + } else { LogInfo("PenalizeDNSServer: Penalizing question type %d", q->qtype); @@ -812,11 +829,8 @@ mDNSexport mStatus mDNS_StartNATOperation_internal(mDNS *const m, NATTraversalIn { if (traversal == *n) { - LogMsg("Error! Tried to add a NAT traversal that's already in the active list: request %p Prot %d Int %d TTL %d", + LogFatalError("Error! Tried to add a NAT traversal that's already in the active list: request %p Prot %d Int %d TTL %d", traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease); - #if ForceAlerts - *(long*)0 = 0; - #endif return(mStatus_AlreadyRegistered); } if (traversal->Protocol && traversal->Protocol == (*n)->Protocol && mDNSSameIPPort(traversal->IntPort, (*n)->IntPort) && @@ -1894,6 +1908,7 @@ mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qt zd->question.qnameOrig = mDNSNULL; zd->question.AnonInfo = mDNSNULL; zd->question.pid = mDNSPlatformGetPID(); + zd->question.euid = 0; zd->question.QuestionCallback = GetZoneData_QuestionCallback; zd->question.QuestionContext = zd; @@ -2583,6 +2598,7 @@ mDNSlocal void GetStaticHostname(mDNS *m) q->qnameOrig = mDNSNULL; q->AnonInfo = mDNSNULL; q->pid = mDNSPlatformGetPID(); + q->euid = 0; q->QuestionCallback = FoundStaticHostname; q->QuestionContext = mDNSNULL; @@ -3991,6 +4007,10 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,", msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y, " : "ies,", msg->h.numAdditionals, msg->h.numAdditionals == 1 ? "" : "s", end - msg->data); +#if APPLE_OSX_mDNSResponder + if (NumUnreachableDNSServers > 0) + SymptomReporterDNSServerReachable(m, srcaddr); +#endif if (QR_OP == StdR) { @@ -4141,7 +4161,7 @@ mDNSexport void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneI q->servAddr = zeroAddr; q->servPort = zeroIPPort; - if (!err && zoneInfo && !mDNSIPPortIsZero(zoneInfo->Port) && !mDNSAddressIsZero(&zoneInfo->Addr) && zoneInfo->Host.c[0]) + if (!err && !mDNSIPPortIsZero(zoneInfo->Port) && !mDNSAddressIsZero(&zoneInfo->Addr) && zoneInfo->Host.c[0]) { q->servAddr = zoneInfo->Addr; q->servPort = zoneInfo->Port; @@ -4238,10 +4258,14 @@ mDNSlocal void PrivateQueryGotZoneData(mDNS *const m, mStatus err, const ZoneDat // Called in normal callback context (i.e. mDNS_busy and mDNS_reentrancy are both 1) mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData) { - AuthRecord *newRR = (AuthRecord*)zoneData->ZoneDataContext; + AuthRecord *newRR; AuthRecord *ptr; int c1, c2; + if (!zoneData) { LogMsg("ERROR: RecordRegistrationGotZoneData invoked with NULL result and no error"); return; } + + newRR = (AuthRecord*)zoneData->ZoneDataContext; + if (newRR->nta != zoneData) LogMsg("RecordRegistrationGotZoneData: nta (%p) != zoneData (%p) %##s (%s)", newRR->nta, zoneData, newRR->resrec.name->c, DNSTypeName(newRR->resrec.rrtype)); @@ -4267,8 +4291,6 @@ mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const return; } - if (!zoneData) { LogMsg("ERROR: RecordRegistrationGotZoneData invoked with NULL result and no error"); return; } - if (newRR->resrec.rrclass != zoneData->ZoneClass) { LogMsg("ERROR: New resource record's class (%d) does not match zone class (%d)", newRR->resrec.rrclass, zoneData->ZoneClass); @@ -4656,7 +4678,7 @@ mDNSlocal void handle_unanswered_query(mDNS *const m) // Note: req_DO affects only DNSSEC_VALIDATION_SECURE_OPTIONAL questions; // DNSSEC_VALIDATION_SECURE questions ignores req_DO. - if (q->qDNSServer && !q->qDNSServer->DNSSECAware && q->qDNSServer->req_DO) + if (!q->qDNSServer->DNSSECAware && q->qDNSServer->req_DO) { q->qDNSServer->retransDO++; if (q->qDNSServer->retransDO == MAX_DNSSEC_RETRANSMISSIONS) @@ -4714,6 +4736,9 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) LogInfo("uDNS_CheckCurrentQuestion: Sent %d unanswered queries for %##s (%s) to %#a:%d (%##s)", q->unansweredQueries, q->qname.c, DNSTypeName(q->qtype), &orig->addr, mDNSVal16(orig->port), orig->domain.c); +#if APPLE_OSX_mDNSResponder + SymptomReporterDNSServerUnreachable(orig); +#endif PenalizeDNSServer(m, q, zeroID); q->noServerResponse = 1; } @@ -4798,7 +4823,19 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) mDNSPlatformSetuDNSSocktOpt(q->LocalSocket, &q->qDNSServer->addr, q); } if (!q->LocalSocket) err = mStatus_NoMemoryErr; // If failed to make socket (should be very rare), we'll try again next time - else err = mDNSSendDNSMessage(m, &m->omsg, end, q->qDNSServer->interface, q->LocalSocket, &q->qDNSServer->addr, q->qDNSServer->port, mDNSNULL, mDNSNULL, q->UseBackgroundTrafficClass); + else + { + err = mDNSSendDNSMessage(m, &m->omsg, end, q->qDNSServer->interface, q->LocalSocket, &q->qDNSServer->addr, q->qDNSServer->port, mDNSNULL, mDNSNULL, q->UseBackgroundTrafficClass); +#if TARGET_OS_EMBEDDED + if (!err) + { + if (q->metrics.querySendCount++ == 0) + { + q->metrics.firstQueryTime = m->timenow; + } + } +#endif + } } } @@ -4916,7 +4953,6 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) mDNSexport void CheckNATMappings(mDNS *m) { - mStatus err = mStatus_NoError; mDNSBool rfc1918 = mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4); mDNSBool HaveRoutable = !rfc1918 && !mDNSIPv4AddressIsZero(m->AdvertisedV4.ip.v4); m->NextScheduledNATOp = m->timenow + 0x3FFFFFFF; @@ -4974,7 +5010,7 @@ mDNSexport void CheckNATMappings(mDNS *m) cur->retryInterval = NATMAP_INIT_RETRY; } - err = uDNS_SendNATMsg(m, cur, mDNStrue); // Will also do UPnP discovery for us, if necessary + uDNS_SendNATMsg(m, cur, mDNStrue); // Will also do UPnP discovery for us, if necessary if (cur->ExpiryTime) // If have active mapping then set next renewal time halfway to expiry NATSetNextRenewalTime(m, cur); |