mDNSResponder: Update to v878.50.17

The sources can be obtained via:

https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-878.50.17.tar.gz

Update #4010.
This commit is contained in:
Sebastian Huber 2020-06-18 12:55:21 +02:00
parent a4a6523309
commit 79fabda817
9 changed files with 1379 additions and 318 deletions

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@
include $(MAKEFILEPATH)/pb_makefiles/platform.make include $(MAKEFILEPATH)/pb_makefiles/platform.make
MVERS = "mDNSResponder-878.30.4" MVERS = "mDNSResponder-878.50.17"
VER = VER =
ifneq ($(strip $(GCC_VERSION)),) ifneq ($(strip $(GCC_VERSION)),)

View File

@ -3473,9 +3473,8 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage
pktrdlength = (mDNSu16)((mDNSu16)ptr[8] << 8 | ptr[9]); pktrdlength = (mDNSu16)((mDNSu16)ptr[8] << 8 | ptr[9]);
// If mDNS record has cache-flush bit set, we mark it unique // If mDNS record has cache-flush bit set, we mark it unique
// For uDNS records, all are implicitly deemed unique (a single DNS server is always // For uDNS records, all are implicitly deemed unique (a single DNS server is always authoritative for the entire RRSet)
// authoritative for the entire RRSet), unless this is a truncated response if (ptr[2] & (kDNSClass_UniqueRRSet >> 8) || !InterfaceID)
if (ptr[2] & (kDNSClass_UniqueRRSet >> 8) || (!InterfaceID && !(msg->h.flags.b[0] & kDNSFlag0_TC)))
RecordType |= kDNSRecordTypePacketUniqueMask; RecordType |= kDNSRecordTypePacketUniqueMask;
ptr += 10; ptr += 10;
if (ptr + pktrdlength > end) { debugf("GetLargeResourceRecord: RDATA exceeds end of packet"); return(mDNSNULL); } if (ptr + pktrdlength > end) { debugf("GetLargeResourceRecord: RDATA exceeds end of packet"); return(mDNSNULL); }

View File

@ -83,7 +83,7 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m);
mDNSlocal void RetrySPSRegistrations(mDNS *const m); mDNSlocal void RetrySPSRegistrations(mDNS *const m);
mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly); mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly);
mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q); mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q);
mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q); mDNSlocal void mDNS_PurgeBeforeResolve(mDNS *const m, DNSQuestion *q);
mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q); mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q);
mDNSlocal void mDNS_SendKeepalives(mDNS *const m); mDNSlocal void mDNS_SendKeepalives(mDNS *const m);
mDNSlocal void mDNS_ExtractKeepaliveInfo(AuthRecord *ar, mDNSu32 *timeout, mDNSAddr *laddr, mDNSAddr *raddr, mDNSEthAddr *eth, mDNSlocal void mDNS_ExtractKeepaliveInfo(AuthRecord *ar, mDNSu32 *timeout, mDNSAddr *laddr, mDNSAddr *raddr, mDNSEthAddr *eth,
@ -4321,56 +4321,17 @@ mDNSlocal void CacheRecordDeferredAdd(mDNS *const m, CacheRecord *rr)
m->CurrentQuestion = mDNSNULL; m->CurrentQuestion = mDNSNULL;
} }
mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash, mDNSBool *purge) mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash)
{ {
const mDNSs32 threshhold = m->timenow + mDNSPlatformOneSecond; // See if there are any records expiring within one second const mDNSs32 threshold = m->timenow + mDNSPlatformOneSecond; // See if there are any records expiring within one second
const mDNSs32 start = m->timenow - 0x10000000; const mDNSs32 start = m->timenow - 0x10000000;
mDNSs32 delay = start; mDNSs32 delay = start;
CacheGroup *cg = CacheGroupForName(m, namehash, name); CacheGroup *cg = CacheGroupForName(m, namehash, name);
const CacheRecord *rr; const CacheRecord *rr;
if (purge)
*purge = mDNSfalse;
for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
{ {
// If there are records that will expire soon, there are cases that need delayed if (threshold - RRExpireTime(rr) >= 0) // If we have records about to expire within a second
// delivery of events:
//
// 1) A new cache entry is about to be added as a replacement. The caller needs to
// deliver a RMV (for the current old entry) followed by ADD (for the new entry).
// It needs to schedule the timer for the next cache expiry (ScheduleNextCacheCheckTime),
// so that the cache entry can be purged (purging causes the RMV followed by ADD)
//
// 2) A new question is about to be answered and the caller needs to know whether it's
// scheduling should be delayed so that the question is not answered with this record.
// Instead of delivering an ADD (old entry) followed by RMV (old entry) and another ADD
// (new entry), a single ADD can be delivered by delaying the scheduling of the question
// immediately.
//
// When the unicast cache record is created, it's TTL has been extended beyond its value
// given in the resource record (See RRAdjustTTL). If it is in the "extended" time, the
// cache is already expired and we set "purge" to indicate that. When "purge" is set, the
// return value of the function should be ignored by the callers.
//
// Note: For case (1), "purge" argument is NULL and hence the following checks are skipped.
// It is okay to skip in that case because the cache records have been set to expire almost
// immediately and the extended time does not apply.
//
// Also, if there is already an active question we don't try to optimize as purging the cache
// would end up delivering RMV for the active question and hence we avoid that.
if (purge && !rr->resrec.InterfaceID && !rr->CRActiveQuestion && rr->resrec.rroriginalttl)
{
mDNSu32 uTTL = RRUnadjustedTTL(rr->resrec.rroriginalttl);
if (m->timenow - (rr->TimeRcvd + ((mDNSs32)uTTL * mDNSPlatformOneSecond)) >= 0)
{
LogInfo("CheckForSoonToExpireRecords: %s: rroriginalttl %u, unadjustedTTL %u, currentTTL %u",
CRDisplayString(m, rr), rr->resrec.rroriginalttl, uTTL, (m->timenow - rr->TimeRcvd)/mDNSPlatformOneSecond);
*purge = mDNStrue;
continue;
}
}
if (threshhold - RRExpireTime(rr) >= 0) // If we have records about to expire within a second
{ {
if (delay - RRExpireTime(rr) < 0) // then delay until after they've been deleted if (delay - RRExpireTime(rr) < 0) // then delay until after they've been deleted
delay = RRExpireTime(rr); delay = RRExpireTime(rr);
@ -6827,7 +6788,13 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep)
#endif #endif
mDNS_ReclaimLockAfterCallback(); mDNS_ReclaimLockAfterCallback();
} }
#ifdef _LEGACY_NAT_TRAVERSAL_
if (m->SSDPSocket)
{
mDNSPlatformUDPClose(m->SSDPSocket);
m->SSDPSocket = mDNSNULL;
}
#endif
m->SleepState = SleepState_Transferring; m->SleepState = SleepState_Transferring;
if (m->SystemWakeOnLANEnabled && m->DelaySleep) if (m->SystemWakeOnLANEnabled && m->DelaySleep)
{ {
@ -8963,18 +8930,25 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
// abort our TCP connection, and not complete the operation, and end up with an incomplete RRSet in our cache. // abort our TCP connection, and not complete the operation, and end up with an incomplete RRSet in our cache.
// Next time there's a query for this RRSet we'll see answers in our cache, and assume we have the whole RRSet already, // Next time there's a query for this RRSet we'll see answers in our cache, and assume we have the whole RRSet already,
// and not even do the TCP query. // and not even do the TCP query.
// Accordingly, if we get a uDNS reply with kDNSFlag0_TC set, we bail out and wait for the TCP response containing the entire RRSet. // Accordingly, if we get a uDNS reply with kDNSFlag0_TC set, we bail out and wait for the TCP response containing the
if (!InterfaceID && (response->h.flags.b[0] & kDNSFlag0_TC)) return; // entire RRSet, with the following exception. If the response contains an answer section and one or more records in
// either the authority section or additional section, then that implies that truncation occurred beyond the answer
// section, and the answer section is therefore assumed to be complete.
//
// From section 6.2 of RFC 1035 <https://tools.ietf.org/html/rfc1035>:
// When a response is so long that truncation is required, the truncation
// should start at the end of the response and work forward in the
// datagram. Thus if there is any data for the authority section, the
// answer section is guaranteed to be unique.
if (!InterfaceID && (response->h.flags.b[0] & kDNSFlag0_TC) &&
((response->h.numAnswers == 0) || ((response->h.numAuthorities == 0) && (response->h.numAdditionals == 0)))) return;
if (LLQType == uDNS_LLQ_Ignore) return; if (LLQType == uDNS_LLQ_Ignore) return;
// 1. We ignore questions (if any) in mDNS response packets // 1. We ignore questions (if any) in mDNS response packets
// 2. If this is an LLQ response, we handle it much the same // 2. If this is an LLQ response, we handle it much the same
// 3. If we get a uDNS UDP response with the TC (truncated) bit set, then we can't treat this
// answer as being the authoritative complete RRSet, and respond by deleting all other
// matching cache records that don't appear in this packet.
// Otherwise, this is a authoritative uDNS answer, so arrange for any stale records to be purged // Otherwise, this is a authoritative uDNS answer, so arrange for any stale records to be purged
if (ResponseMCast || LLQType == uDNS_LLQ_Events || (response->h.flags.b[0] & kDNSFlag0_TC)) if (ResponseMCast || LLQType == uDNS_LLQ_Events)
ptr = LocateAnswers(response, end); ptr = LocateAnswers(response, end);
// Otherwise, for one-shot queries, any answers in our cache that are not also contained // Otherwise, for one-shot queries, any answers in our cache that are not also contained
// in this response packet are immediately deemed to be invalid. // in this response packet are immediately deemed to be invalid.
@ -9420,7 +9394,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
if (AddToCFList) if (AddToCFList)
delay = NonZeroTime(m->timenow + mDNSPlatformOneSecond); delay = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
else else
delay = CheckForSoonToExpireRecords(m, m->rec.r.resrec.name, m->rec.r.resrec.namehash, mDNSNULL); delay = CheckForSoonToExpireRecords(m, m->rec.r.resrec.name, m->rec.r.resrec.namehash);
// If unique, assume we may have to delay delivery of this 'add' event. // If unique, assume we may have to delay delivery of this 'add' event.
// Below, where we walk the CacheFlushRecords list, we either call CacheRecordDeferredAdd() // Below, where we walk the CacheFlushRecords list, we either call CacheRecordDeferredAdd()
@ -9488,6 +9462,7 @@ exit:
CacheRecord *r1 = CacheFlushRecords, *r2; CacheRecord *r1 = CacheFlushRecords, *r2;
const mDNSu32 slot = HashSlotFromNameHash(r1->resrec.namehash); const mDNSu32 slot = HashSlotFromNameHash(r1->resrec.namehash);
const CacheGroup *cg = CacheGroupForRecord(m, &r1->resrec); const CacheGroup *cg = CacheGroupForRecord(m, &r1->resrec);
mDNSBool purgedRecords = mDNSfalse;
CacheFlushRecords = CacheFlushRecords->NextInCFList; CacheFlushRecords = CacheFlushRecords->NextInCFList;
r1->NextInCFList = mDNSNULL; r1->NextInCFList = mDNSNULL;
@ -9569,8 +9544,9 @@ exit:
r2->resrec.rroriginalttl = r1->resrec.rroriginalttl; r2->resrec.rroriginalttl = r1->resrec.rroriginalttl;
} }
r2->TimeRcvd = m->timenow; r2->TimeRcvd = m->timenow;
SetNextCacheCheckTimeForRecord(m, r2);
} }
else // else, if record is old, mark it to be flushed else if (r2->resrec.InterfaceID) // else, if record is old, mark it to be flushed
{ {
verbosedebugf("Cache flush new %p age %d expire in %d %s", r1, m->timenow - r1->TimeRcvd, RRExpireTime(r1) - m->timenow, CRDisplayString(m, r1)); verbosedebugf("Cache flush new %p age %d expire in %d %s", r1, m->timenow - r1->TimeRcvd, RRExpireTime(r1) - m->timenow, CRDisplayString(m, r1));
verbosedebugf("Cache flush old %p age %d expire in %d %s", r2, m->timenow - r2->TimeRcvd, RRExpireTime(r2) - m->timenow, CRDisplayString(m, r2)); verbosedebugf("Cache flush old %p age %d expire in %d %s", r2, m->timenow - r2->TimeRcvd, RRExpireTime(r2) - m->timenow, CRDisplayString(m, r2));
@ -9608,8 +9584,14 @@ exit:
// We use (m->timenow - 1) instead of m->timenow, because we use that to identify records // We use (m->timenow - 1) instead of m->timenow, because we use that to identify records
// that we marked for deletion via an explicit DE record // that we marked for deletion via an explicit DE record
} }
SetNextCacheCheckTimeForRecord(m, r2);
}
else
{
// Old uDNS records are scheduled to be purged instead of given at most one second to live.
mDNS_PurgeCacheResourceRecord(m, r2);
purgedRecords = mDNStrue;
} }
SetNextCacheCheckTimeForRecord(m, r2);
} }
} }
@ -9637,7 +9619,16 @@ exit:
NSECRecords = mDNSNULL; NSECRecords = mDNSNULL;
NSECCachePtr = mDNSNULL; NSECCachePtr = mDNSNULL;
} }
r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash, mDNSNULL); if (r1->resrec.InterfaceID)
{
r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash);
}
else
{
// If uDNS records from an older RRset were scheduled to be purged, then delay delivery slightly to allow
// them to be deleted before any ADD events for this record.
r1->DelayDelivery = purgedRecords ? NonZeroTime(m->timenow) : 0;
}
// If no longer delaying, deliver answer now, else schedule delivery for the appropriate time // If no longer delaying, deliver answer now, else schedule delivery for the appropriate time
if (!r1->DelayDelivery) CacheRecordDeferredAdd(m, r1); if (!r1->DelayDelivery) CacheRecordDeferredAdd(m, r1);
else ScheduleNextCacheCheckTime(m, slot, r1->DelayDelivery); else ScheduleNextCacheCheckTime(m, slot, r1->DelayDelivery);
@ -11650,7 +11641,7 @@ mDNSlocal mStatus ValidateParameters(mDNS *const m, DNSQuestion *const question)
} }
// InitDNSConfig() is called by InitCommonState() to initialize the DNS configuration of the Question. // InitDNSConfig() is called by InitCommonState() to initialize the DNS configuration of the Question.
// These are a subset of the internal uDNS fields. Must be done before ShouldSuppressQuery() & mDNS_PurgeForQuestion() // These are a subset of the internal uDNS fields. Must be done before ShouldSuppressQuery() & mDNS_PurgeBeforeResolve()
mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question) mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question)
{ {
// First reset all DNS Configuration // First reset all DNS Configuration
@ -11706,9 +11697,8 @@ mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question)
// InitCommonState() is called by mDNS_StartQuery_internal() to initialize the common(uDNS/mDNS) internal // InitCommonState() is called by mDNS_StartQuery_internal() to initialize the common(uDNS/mDNS) internal
// state fields of the DNS Question. These are independent of the Client layer. // state fields of the DNS Question. These are independent of the Client layer.
mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) mDNSlocal void InitCommonState(mDNS *const m, DNSQuestion *const question)
{ {
mDNSBool purge;
int i; int i;
mDNSBool isBlocked = mDNSfalse; mDNSBool isBlocked = mDNSfalse;
@ -11727,7 +11717,7 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question)
// turned ON which can allocate memory e.g., base64 encoding, in the case of DNSSEC. // turned ON which can allocate memory e.g., base64 encoding, in the case of DNSSEC.
question->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question question->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question
question->qnamehash = DomainNameHashValue(&question->qname); question->qnamehash = DomainNameHashValue(&question->qname);
question->DelayAnswering = CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash, &purge); question->DelayAnswering = mDNSOpaque16IsZero(question->TargetQID) ? CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash) : 0;
question->LastQTime = m->timenow; question->LastQTime = m->timenow;
question->ExpectUnicastResp = 0; question->ExpectUnicastResp = 0;
question->LastAnswerPktNum = m->PktNum; question->LastAnswerPktNum = m->PktNum;
@ -11809,7 +11799,6 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question)
if (question->WakeOnResolve) if (question->WakeOnResolve)
{ {
question->WakeOnResolveCount = InitialWakeOnResolveCount; question->WakeOnResolveCount = InitialWakeOnResolveCount;
purge = mDNStrue;
} }
for (i=0; i<DupSuppressInfoSize; i++) for (i=0; i<DupSuppressInfoSize; i++)
@ -11826,8 +11815,6 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question)
if (question->DelayAnswering) if (question->DelayAnswering)
LogInfo("InitCommonState: Delaying answering for %d ticks while cache stabilizes for %##s (%s)", LogInfo("InitCommonState: Delaying answering for %d ticks while cache stabilizes for %##s (%s)",
question->DelayAnswering - m->timenow, question->qname.c, DNSTypeName(question->qtype)); question->DelayAnswering - m->timenow, question->qname.c, DNSTypeName(question->qtype));
return(purge);
} }
// Excludes the DNS Config fields which are already handled by InitDNSConfig() // Excludes the DNS Config fields which are already handled by InitDNSConfig()
@ -11909,7 +11896,7 @@ mDNSlocal void InitDNSSECProxyState(mDNS *const m, DNSQuestion *const question)
// Once the question is completely initialized including the duplicate logic, this function // Once the question is completely initialized including the duplicate logic, this function
// is called to finalize the unicast question which requires flushing the cache if needed, // is called to finalize the unicast question which requires flushing the cache if needed,
// activating the query etc. // activating the query etc.
mDNSlocal void FinalizeUnicastQuestion(mDNS *const m, DNSQuestion *question, mDNSBool purge) mDNSlocal void FinalizeUnicastQuestion(mDNS *const m, DNSQuestion *question)
{ {
// Ensure DNS related info of duplicate question is same as the orig question // Ensure DNS related info of duplicate question is same as the orig question
if (question->DuplicateOf) if (question->DuplicateOf)
@ -11934,14 +11921,7 @@ mDNSlocal void FinalizeUnicastQuestion(mDNS *const m, DNSQuestion *question, mDN
ActivateUnicastQuery(m, question, mDNSfalse); ActivateUnicastQuery(m, question, mDNSfalse);
// If purge was set above, flush the cache. Need to do this after we set the if (!question->DuplicateOf && DNSSECQuestion(question))
// DNS server on the question
if (purge)
{
question->DelayAnswering = 0;
mDNS_PurgeForQuestion(m, question);
}
else if (!question->DuplicateOf && DNSSECQuestion(question))
{ {
// For DNSSEC questions, we need to have the RRSIGs also for verification. // For DNSSEC questions, we need to have the RRSIGs also for verification.
CheckForDNSSECRecords(m, question); CheckForDNSSECRecords(m, question);
@ -11964,7 +11944,6 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
{ {
DNSQuestion **q; DNSQuestion **q;
mStatus vStatus; mStatus vStatus;
mDNSBool purge;
// First check for cache space (can't do queries if there is no cache space allocated) // First check for cache space (can't do queries if there is no cache space allocated)
if (m->rrcache_size == 0) if (m->rrcache_size == 0)
@ -12012,7 +11991,7 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
// InitCommonState -> InitDNSConfig) as DNS server selection affects DNSSEC // InitCommonState -> InitDNSConfig) as DNS server selection affects DNSSEC
// validation. // validation.
purge = InitCommonState(m, question); InitCommonState(m, question);
InitWABState(question); InitWABState(question);
InitLLQState(question); InitLLQState(question);
#ifdef DNS_PUSH_ENABLED #ifdef DNS_PUSH_ENABLED
@ -12045,7 +12024,7 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
// this routine with the question list data structures in an inconsistent state. // this routine with the question list data structures in an inconsistent state.
if (!mDNSOpaque16IsZero(question->TargetQID)) if (!mDNSOpaque16IsZero(question->TargetQID))
{ {
FinalizeUnicastQuestion(m, question, purge); FinalizeUnicastQuestion(m, question);
} }
else else
{ {
@ -12065,10 +12044,10 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
} }
} }
#endif // BONJOUR_ON_DEMAND #endif // BONJOUR_ON_DEMAND
if (purge) if (question->WakeOnResolve)
{ {
LogInfo("mDNS_StartQuery_internal: Purging for %##s", question->qname.c); LogInfo("mDNS_StartQuery_internal: Purging for %##s", question->qname.c);
mDNS_PurgeForQuestion(m, question); mDNS_PurgeBeforeResolve(m, question);
} }
} }
} }
@ -14618,7 +14597,7 @@ mDNSlocal void PurgeOrReconfirmCacheRecord(mDNS *const m, CacheRecord *cr, const
} }
} }
mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q) mDNSlocal void mDNS_PurgeBeforeResolve(mDNS *const m, DNSQuestion *q)
{ {
CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
CacheRecord *rp; CacheRecord *rp;
@ -14634,7 +14613,7 @@ mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q)
{ {
if (SameNameRecordAnswersQuestion(&rp->resrec, q)) if (SameNameRecordAnswersQuestion(&rp->resrec, q))
{ {
LogInfo("mDNS_PurgeForQuestion: Flushing %s", CRDisplayString(m, rp)); LogInfo("mDNS_PurgeBeforeResolve: Flushing %s", CRDisplayString(m, rp));
mDNS_PurgeCacheResourceRecord(m, rp); mDNS_PurgeCacheResourceRecord(m, rp);
} }
} }

View File

@ -550,7 +550,7 @@ mDNSlocal mStatus uDNS_RequestAddress(mDNS *m)
return err; return err;
} }
mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool usePCP) mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool usePCP, mDNSBool unmapping)
{ {
mStatus err = mStatus_NoError; mStatus err = mStatus_NoError;
@ -649,19 +649,25 @@ mDNSlocal mStatus uDNS_SendNATMsg(mDNS *m, NATTraversalInfo *info, mDNSBool useP
info->sentNATPMP = mDNSfalse; info->sentNATPMP = mDNSfalse;
#ifdef _LEGACY_NAT_TRAVERSAL_ #ifdef _LEGACY_NAT_TRAVERSAL_
if (mDNSIPPortIsZero(m->UPnPRouterPort) || mDNSIPPortIsZero(m->UPnPSOAPPort)) // If an unmapping is being performed, then don't send an LNT discovery message or an LNT port map request.
if (!unmapping)
{ {
LNT_SendDiscoveryMsg(m); if (mDNSIPPortIsZero(m->UPnPRouterPort) || mDNSIPPortIsZero(m->UPnPSOAPPort))
debugf("uDNS_SendNATMsg: LNT_SendDiscoveryMsg"); {
} LNT_SendDiscoveryMsg(m);
else debugf("uDNS_SendNATMsg: LNT_SendDiscoveryMsg");
{ }
mStatus lnterr = LNT_MapPort(m, info); else
if (lnterr) {
LogMsg("uDNS_SendNATMsg: LNT_MapPort returned error %d", lnterr); mStatus lnterr = LNT_MapPort(m, info);
if (lnterr)
LogMsg("uDNS_SendNATMsg: LNT_MapPort returned error %d", lnterr);
err = err ? err : lnterr; // PCP error takes precedence err = err ? err : lnterr; // PCP error takes precedence
}
} }
#else
(void)unmapping; // Unused
#endif // _LEGACY_NAT_TRAVERSAL_ #endif // _LEGACY_NAT_TRAVERSAL_
} }
} }
@ -925,6 +931,16 @@ mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *tra
} }
} }
// Even if we DIDN'T make a successful UPnP mapping yet, we might still have a partially-open TCP connection we need to clean up
// Before zeroing traversal->RequestedPort below, perform the LNT unmapping, which requires the mapping's external port,
// held by the traversal->RequestedPort variable.
#ifdef _LEGACY_NAT_TRAVERSAL_
{
mStatus err = LNT_UnmapPort(m, traversal);
if (err) LogMsg("Legacy NAT Traversal - unmap request failed with error %d", err);
}
#endif // _LEGACY_NAT_TRAVERSAL_
if (traversal->ExpiryTime && unmap) if (traversal->ExpiryTime && unmap)
{ {
traversal->NATLease = 0; traversal->NATLease = 0;
@ -946,17 +962,9 @@ mDNSexport mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *tra
traversal->RequestedPort = zeroIPPort; traversal->RequestedPort = zeroIPPort;
traversal->NewAddress = zerov4Addr; traversal->NewAddress = zerov4Addr;
uDNS_SendNATMsg(m, traversal, traversal->lastSuccessfulProtocol != NATTProtocolNATPMP); uDNS_SendNATMsg(m, traversal, traversal->lastSuccessfulProtocol != NATTProtocolNATPMP, mDNStrue);
} }
// Even if we DIDN'T make a successful UPnP mapping yet, we might still have a partially-open TCP connection we need to clean up
#ifdef _LEGACY_NAT_TRAVERSAL_
{
mStatus err = LNT_UnmapPort(m, traversal);
if (err) LogMsg("Legacy NAT Traversal - unmap request failed with error %d", err);
}
#endif // _LEGACY_NAT_TRAVERSAL_
return(mStatus_NoError); return(mStatus_NoError);
} }
@ -3660,7 +3668,7 @@ mDNSlocal void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interface
{ {
// Send a NAT-PMP request for this operation as needed // Send a NAT-PMP request for this operation as needed
// and update the state variables // and update the state variables
uDNS_SendNATMsg(m, n, mDNSfalse); uDNS_SendNATMsg(m, n, mDNSfalse, mDNSfalse);
} }
m->NextScheduledNATOp = m->timenow; m->NextScheduledNATOp = m->timenow;
@ -5003,7 +5011,7 @@ mDNSexport void CheckNATMappings(mDNS *m)
cur->retryInterval = NATMAP_INIT_RETRY; cur->retryInterval = NATMAP_INIT_RETRY;
} }
uDNS_SendNATMsg(m, cur, mDNStrue); // Will also do UPnP discovery for us, if necessary uDNS_SendNATMsg(m, cur, mDNStrue, mDNSfalse); // Will also do UPnP discovery for us, if necessary
if (cur->ExpiryTime) // If have active mapping then set next renewal time halfway to expiry if (cur->ExpiryTime) // If have active mapping then set next renewal time halfway to expiry
NATSetNextRenewalTime(m, cur); NATSetNextRenewalTime(m, cur);

View File

@ -888,9 +888,10 @@ mDNSexport void LNT_SendDiscoveryMsg(mDNS *m)
"MX:3\r\n\r\n"; "MX:3\r\n\r\n";
static const mDNSAddr multicastDest = { mDNSAddrType_IPv4, { { { 239, 255, 255, 250 } } } }; static const mDNSAddr multicastDest = { mDNSAddrType_IPv4, { { { 239, 255, 255, 250 } } } };
mDNSu8 *buf = (mDNSu8*)&m->omsg; //m->omsg is 8952 bytes, which is plenty mDNSu8 *const buf = (mDNSu8*)&m->omsg; //m->omsg is 8952 bytes, which is plenty
unsigned int bufLen; unsigned int bufLen;
if (m->SleepState != SleepState_Awake) return;
if (!mDNSIPPortIsZero(m->UPnPRouterPort)) if (!mDNSIPPortIsZero(m->UPnPRouterPort))
{ {
if (m->SSDPSocket) { debugf("LNT_SendDiscoveryMsg destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; } if (m->SSDPSocket) { debugf("LNT_SendDiscoveryMsg destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }

View File

@ -879,7 +879,11 @@ typedef unsigned long int uintptr_t;
#define false 0 #define false 0
#endif #endif
#else #else
#define COMMON_SERVICES_NEEDS_BOOL ( !defined( __cplusplus ) && !__bool_true_false_are_defined ) #if ( !defined( __cplusplus ) && !__bool_true_false_are_defined )
#define COMMON_SERVICES_NEEDS_BOOL 1
#else
#define COMMON_SERVICES_NEEDS_BOOL 0
#endif
#endif #endif
#if ( COMMON_SERVICES_NEEDS_BOOL ) #if ( COMMON_SERVICES_NEEDS_BOOL )

View File

@ -66,7 +66,7 @@
*/ */
#ifndef _DNS_SD_H #ifndef _DNS_SD_H
#define _DNS_SD_H 8783004 #define _DNS_SD_H 8785017
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -23,7 +23,7 @@
// network, you might allow anyone to perform updates. To do that, you just // network, you might allow anyone to perform updates. To do that, you just
// permit any and all updates coming from dnsextd on the same machine: // permit any and all updates coming from dnsextd on the same machine:
// //
// zone "my-dynamic-subdomain.company.com." // zone "my-dynamic-subdomain.example.com."
// { type master; file "db.xxx"; allow-update { 127.0.0.1; }; }; // { type master; file "db.xxx"; allow-update { 127.0.0.1; }; };
// //
// On a machine connected to the Internet or other large open network, // On a machine connected to the Internet or other large open network,
@ -32,11 +32,11 @@
// perform updates in your dynamic zone, like this: // perform updates in your dynamic zone, like this:
// //
// key keyname. { algorithm hmac-md5; secret "abcdefghijklmnopqrstuv=="; }; // key keyname. { algorithm hmac-md5; secret "abcdefghijklmnopqrstuv=="; };
// zone "my-dynamic-subdomain.company.com." in // zone "my-dynamic-subdomain.example.com." in
// { // {
// type master; // type master;
// file "db.my-dynamic-subdomain.company.com"; // file "db.my-dynamic-subdomain.example.com";
// update-policy { grant * wildcard *.my-dynamic-subdomain.company.com.; }; // update-policy { grant * wildcard *.my-dynamic-subdomain.example.com.; };
// }; // };
// //
// You could use a single key which you give to all authorized users, but // You could use a single key which you give to all authorized users, but
@ -55,6 +55,6 @@ options {
// llq port 5352; // llq port 5352;
}; };
zone "my-dynamic-subdomain.company.com." { zone "my-dynamic-subdomain.example.com." {
type public; type public;
}; };