diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-19 08:56:09 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-20 11:23:33 +0200 |
commit | 4c086a244624bf36865edcfa4309c333d7d7200d (patch) | |
tree | e566ffc50a6b6fdb46702ac57c8e7c4088b60b42 /mDNSResponder/mDNSCore | |
parent | mDNSResponder: Update to v765.50.9 (diff) | |
download | rtems-libbsd-4c086a244624bf36865edcfa4309c333d7d7200d.tar.bz2 |
mDNSResponder: Update to v878.1.1
The sources can be obtained via:
https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-878.1.1.tar.gz
Update #3522.
Diffstat (limited to 'mDNSResponder/mDNSCore')
-rw-r--r-- | mDNSResponder/mDNSCore/DNSCommon.c | 75 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/DNSCommon.h | 5 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/anonymous.c | 12 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/dnsproxy.c | 89 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/dnsproxy.h | 8 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/dnssec.c | 37 | ||||
-rwxr-xr-x | mDNSResponder/mDNSCore/mDNS.c | 801 | ||||
-rwxr-xr-x | mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h | 179 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/nsec.c | 9 | ||||
-rw-r--r-- | mDNSResponder/mDNSCore/nsec3.c | 5 | ||||
-rwxr-xr-x | mDNSResponder/mDNSCore/uDNS.c | 146 | ||||
-rwxr-xr-x | mDNSResponder/mDNSCore/uDNS.h | 2 |
12 files changed, 704 insertions, 664 deletions
diff --git a/mDNSResponder/mDNSCore/DNSCommon.c b/mDNSResponder/mDNSCore/DNSCommon.c index 3ea9a307..be8e1065 100644 --- a/mDNSResponder/mDNSCore/DNSCommon.c +++ b/mDNSResponder/mDNSCore/DNSCommon.c @@ -21,6 +21,10 @@ #include "CryptoAlg.h" #include "anonymous.h" +#ifdef UNIT_TEST +#include "unittest.h" +#endif + // Disable certain benign warnings with Microsoft compilers #if (defined(_MSC_VER)) // Disable "conditional expression is constant" warning for debug macros. @@ -111,7 +115,8 @@ mDNSexport const mDNSOpaque16 UpdateRespFlags = { { kDNSFlag0_QR_Response | kDNS mDNSexport const mDNSOpaque16 SubscribeFlags = { { kDNSFlag0_QR_Query | kDNSFlag0_OP_Subscribe, 0 } }; mDNSexport const mDNSOpaque16 UnSubscribeFlags= { { kDNSFlag0_QR_Query | kDNSFlag0_OP_UnSubscribe, 0 } }; -mDNSexport const mDNSOpaque64 zeroOpaque64 = { { 0 } }; +mDNSexport const mDNSOpaque64 zeroOpaque64 = { { 0 } }; +mDNSexport const mDNSOpaque128 zeroOpaque128 = { { 0 } }; // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK @@ -622,6 +627,8 @@ mDNSexport mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip) #pragma mark - Domain Name Utility Functions #endif +#if !APPLE_OSX_mDNSResponder + mDNSexport mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b) { int i; @@ -642,6 +649,8 @@ mDNSexport mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b) return(mDNStrue); } +#endif // !APPLE_OSX_mDNSResponder + mDNSexport mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2) { const mDNSu8 * a = d1->c; @@ -971,10 +980,6 @@ mDNSexport void ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], do hostlabel->c[0] = (mDNSu8)(ptr - &hostlabel->c[1]); } -#define ValidTransportProtocol(X) ( (X)[0] == 4 && (X)[1] == '_' && \ - ((((X)[2] | 0x20) == 'u' && ((X)[3] | 0x20) == 'd') || (((X)[2] | 0x20) == 't' && ((X)[3] | 0x20) == 'c')) && \ - ((X)[4] | 0x20) == 'p') - mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn, const domainlabel *name, const domainname *type, const domainname *const domain) { @@ -1033,10 +1038,6 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn, { LogMsg("Bad service type in %#s.%##s%##s Application protocol name must be underscore plus 1-15 characters. " "See <http://www.dns-sd.org/ServiceTypes.html>", name->c, type->c, domain->c); -#if APPLE_OSX_mDNSResponder - ConvertDomainNameToCString(type, typeBuf); - mDNSASLLog(mDNSNULL, "serviceType.nameTooLong", "noop", typeBuf, ""); -#endif } if (len < 2 || len >= 0x40 || (len > 16 && !SameDomainName(domain, &localdomain))) return(mDNSNULL); if (src[1] != '_') { errormsg = "Application protocol name must begin with underscore"; goto fail; } @@ -1053,19 +1054,13 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn, if (src[i] == '_' && loggedUnderscore == mDNSfalse) { ConvertDomainNameToCString(type, typeBuf); - mDNSASLLog(mDNSNULL, "serviceType.nameWithUnderscore", "noop", typeBuf, ""); + LogInfo("ConstructServiceName: Service type with non-leading underscore %s", typeBuf); loggedUnderscore = mDNStrue; } #endif continue; } errormsg = "Application protocol name must contain only letters, digits, and hyphens"; -#if APPLE_OSX_mDNSResponder - { - ConvertDomainNameToCString(type, typeBuf); - mDNSASLLog(mDNSNULL, "serviceType.nameWithIllegalCharacters", "noop", typeBuf, ""); - } -#endif goto fail; } for (i=0; i<=len; i++) *dst++ = *src++; @@ -2754,12 +2749,12 @@ mDNSexport const mDNSu8 *getDomainName(const DNSMessage *const msg, const mDNSu8 while (1) // Read sequence of labels { + int i; + mDNSu16 offset; const mDNSu8 len = *ptr++; // Read length of this label if (len == 0) break; // If length is zero, that means this name is complete switch (len & 0xC0) { - int i; - mDNSu16 offset; case 0x00: if (ptr + len >= end) // Remember: expect at least one more byte for the root label { debugf("getDomainName: Malformed domain name (overruns packet end)"); return(mDNSNULL); } @@ -3457,12 +3452,6 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage rr->CRActiveQuestion = mDNSNULL; rr->UnansweredQueries = 0; rr->LastUnansweredTime= 0; -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - rr->MPUnansweredQ = 0; - rr->MPLastUnansweredQT= 0; - rr->MPUnansweredKA = 0; - rr->MPExpectingKA = mDNSfalse; -#endif rr->NextInCFList = mDNSNULL; rr->resrec.InterfaceID = InterfaceID; @@ -3617,16 +3606,27 @@ mDNSexport const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const } // Get the lease life of records in a dynamic update -// returns 0 on error or if no lease present -mDNSexport mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end) +mDNSexport mDNSBool GetPktLease(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, mDNSu32 *const lease) { - mDNSu32 result = 0; const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space); - if (ptr) ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec); - if (ptr && m->rec.r.resrec.rdlength >= DNSOpt_LeaseData_Space && m->rec.r.resrec.rdata->u.opt[0].opt == kDNSOpt_Lease) - result = m->rec.r.resrec.rdata->u.opt[0].u.updatelease; - m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it - return(result); + if (ptr) + { + ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec); + if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_OPT) + { + const rdataOPT *o; + const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength]; + for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++) + if (o->opt == kDNSOpt_Lease) + { + *lease = o->u.updatelease; + m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it + return mDNStrue; + } + } + m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it + } + return mDNSfalse; } mDNSlocal const mDNSu8 *DumpRecords(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end, int count, char *label) @@ -3725,6 +3725,10 @@ mDNSexport void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *t #pragma mark - Packet Sending Functions #endif +#ifdef UNIT_TEST +// Run the unit test of mDNSSendDNSMessage +UNITTEST_SENDDNSMESSAGE +#else // Stub definition of TCPSocket_struct so we can access flags field. (Rest of TCPSocket_struct is platform-dependent.) struct TCPSocket_struct { TCPSocketFlags flags; /* ... */ }; // Stub definition of UDPSocket_struct so we can access port field. (Rest of UDPSocket_struct is platform-dependent.) @@ -3826,6 +3830,7 @@ mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNS return(status); } +#endif // UNIT_TEST // *************************************************************************** #if COMPILER_LIKES_PRAGMA_MARK @@ -3883,7 +3888,7 @@ mDNSlocal AuthRecord *AnyLocalRecordReady(const mDNS *const m) mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m) { - mDNSs32 e = m->timenow + 0x78000000; + mDNSs32 e = m->timenow + FutureTime; if (m->mDNSPlatformStatus != mStatus_NoError) return(e); if (m->NewQuestions) { @@ -4057,7 +4062,8 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt for (c = *fmt; c != 0; c = *++fmt) { - if (c != '%') + unsigned long n; + if (c != '%') { *sbuffer++ = (char)c; if (++nwritten >= buflen) goto exit; @@ -4113,7 +4119,6 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt conv: switch (c) // perform appropriate conversion { - unsigned long n; case 'h': F.hSize = 1; c = *++fmt; goto conv; case 'l': // fall through case 'L': F.lSize = 1; c = *++fmt; goto conv; diff --git a/mDNSResponder/mDNSCore/DNSCommon.h b/mDNSResponder/mDNSCore/DNSCommon.h index 2da19700..e1ef261e 100644 --- a/mDNSResponder/mDNSCore/DNSCommon.h +++ b/mDNSResponder/mDNSCore/DNSCommon.h @@ -240,8 +240,7 @@ extern const mDNSu8 *NSEC3HashName(const domainname *name, rdataNSEC3 *nsec3, co #pragma mark - DNS Message Parsing Functions #endif -#define AuthHashSlot(X) (DomainNameHashValue(X) % AUTH_HASH_SLOTS) -#define HashSlot(X) (DomainNameHashValue(X) % CACHE_HASH_SLOTS) +#define HashSlotFromNameHash(X) ((X) % CACHE_HASH_SLOTS) extern mDNSu32 DomainNameHashValue(const domainname *const name); extern void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 rdlength); extern const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end); @@ -260,7 +259,7 @@ extern const mDNSu8 *LocateAuthorities(const DNSMessage *const msg, const mDNSu8 extern const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mDNSu8 *const end); extern const mDNSu8 *LocateOptRR(const DNSMessage *const msg, const mDNSu8 *const end, int minsize); extern const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end); -extern mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end); +extern mDNSBool GetPktLease(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, mDNSu32 *const lease); extern void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *transport, const mDNSAddr *srcaddr, mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport, const DNSMessage *const msg, const mDNSu8 *const end); diff --git a/mDNSResponder/mDNSCore/anonymous.c b/mDNSResponder/mDNSCore/anonymous.c index aaaebc27..fde3ed80 100644 --- a/mDNSResponder/mDNSCore/anonymous.c +++ b/mDNSResponder/mDNSCore/anonymous.c @@ -240,6 +240,12 @@ mDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQues debugf("SetAnonData: question %##s(%p), rr %##s(%p)", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo); if (ForQuestion) { + if (q->AnonInfo->AnonDataLen < rr->AnonInfo->AnonDataLen) + { + mDNSPlatformMemFree(q->AnonInfo->AnonData); + q->AnonInfo->AnonData = mDNSNULL; + } + if (!q->AnonInfo->AnonData) { q->AnonInfo->AnonData = mDNSPlatformMemAllocate(rr->AnonInfo->AnonDataLen); @@ -251,6 +257,12 @@ mDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQues } else { + if (rr->AnonInfo->AnonDataLen < q->AnonInfo->AnonDataLen) + { + mDNSPlatformMemFree(rr->AnonInfo->AnonData); + rr->AnonInfo->AnonData = mDNSNULL; + } + if (!rr->AnonInfo->AnonData) { rr->AnonInfo->AnonData = mDNSPlatformMemAllocate(q->AnonInfo->AnonDataLen); diff --git a/mDNSResponder/mDNSCore/dnsproxy.c b/mDNSResponder/mDNSCore/dnsproxy.c index 2afb59d1..a94c005e 100644 --- a/mDNSResponder/mDNSCore/dnsproxy.c +++ b/mDNSResponder/mDNSCore/dnsproxy.c @@ -19,6 +19,8 @@ #ifndef UNICAST_DISABLED +mDNSexport mDNS mDNSStorage; + // Implementation Notes // // DNS Proxy listens on port 53 (UDPv4v6 & TCPv4v6) for DNS queries. It handles only @@ -72,7 +74,7 @@ struct DNSProxyClient_struct { }; #define MIN_DNS_MESSAGE_SIZE 512 -DNSProxyClient *DNSProxyClients; +static DNSProxyClient *DNSProxyClients; mDNSlocal void FreeDNSProxyClient(DNSProxyClient *pc) { @@ -130,7 +132,7 @@ mDNSexport mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DN return ptr; } -mDNSlocal mDNSu8 *AddEDNS0Option(mDNS *const m, mDNSu8 *ptr, mDNSu8 *limit) +mDNSlocal mDNSu8 *AddEDNS0Option(mDNSu8 *ptr, mDNSu8 *limit) { int len = 4096; @@ -139,7 +141,7 @@ mDNSlocal mDNSu8 *AddEDNS0Option(mDNS *const m, mDNSu8 *ptr, mDNSu8 *limit) LogInfo("AddEDNS0Option: not enough space"); return mDNSNULL; } - m->omsg.h.numAdditionals++; + mDNSStorage.omsg.h.numAdditionals++; ptr[0] = 0; ptr[1] = (mDNSu8) (kDNSType_OPT >> 8); ptr[2] = (mDNSu8) (kDNSType_OPT & 0xFF); @@ -180,9 +182,9 @@ mDNSlocal mDNSOpaque16 SetResponseFlags(DNSProxyClient *pc, const mDNSOpaque16 r return rFlags; } -mDNSlocal mDNSu8 *AddResourceRecords(mDNS *const m, DNSProxyClient *pc, mDNSu8 **prevptr, mStatus *error) +mDNSlocal mDNSu8 *AddResourceRecords(DNSProxyClient *pc, mDNSu8 **prevptr, mStatus *error) { - mDNSu32 slot; + mDNS *const m = &mDNSStorage; CacheGroup *cg; CacheRecord *cr; int len = sizeof(DNSMessageHeader); @@ -229,9 +231,8 @@ mDNSlocal mDNSu8 *AddResourceRecords(mDNS *const m, DNSProxyClient *pc, mDNSu8 * again: nsec = soa = cname = mDNSNULL; - slot = HashSlot(&tempQName); - cg = CacheGroupForName(m, slot, tempQNameHash, &tempQName); + cg = CacheGroupForName(m, tempQNameHash, &tempQName); if (!cg) { LogInfo("AddResourceRecords: CacheGroup not found for %##s", tempQName.c); @@ -355,7 +356,7 @@ again: } if (pc->rcvBufSize) { - ptr = AddEDNS0Option(m, ptr, limit); + ptr = AddEDNS0Option(ptr, limit); if (!ptr) { *prevptr = orig; @@ -408,7 +409,7 @@ mDNSlocal void ProxyClientCallback(mDNS *const m, DNSQuestion *question, const R return; } } - ptr = AddResourceRecords(m, pc, &prevptr, &error); + ptr = AddResourceRecords(pc, &prevptr, &error); if (!ptr) { LogInfo("ProxyClientCallback: AddResourceRecords NULL for %##s (%s)", &pc->qname.c, DNSTypeName(pc->q.qtype)); @@ -494,9 +495,10 @@ done: FreeDNSProxyClient(pc); } -mDNSlocal void SendError(mDNS *const m, void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *dstaddr, +mDNSlocal void SendError(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, mDNSBool tcp, void *context, mDNSu8 rcode) { + mDNS *const m = &mDNSStorage; int pktlen = (int)(end - (mDNSu8 *)msg); // RFC 1035 requires that we copy the question back and RFC 2136 is okay with sending nothing @@ -509,7 +511,8 @@ mDNSlocal void SendError(mDNS *const m, void *socket, DNSMessage *const msg, con mDNSPlatformMemCopy(&m->omsg.h, &msg->h, sizeof(DNSMessageHeader)); m->omsg.h.flags.b[0] |= kDNSFlag0_QR_Response; m->omsg.h.flags.b[1] = rcode; - mDNSPlatformMemCopy(m->omsg.data, (mDNSu8 *)&msg->h.numQuestions, pktlen); + mDNSPlatformMemCopy(m->omsg.data, (mDNSu8 *)&msg->data, (pktlen - sizeof(DNSMessageHeader))); + if (!tcp) { mDNSSendDNSMessage(m, &m->omsg, (mDNSu8 *)&m->omsg + pktlen, InterfaceID, socket, dstaddr, dstport, mDNSNULL, mDNSNULL, @@ -523,14 +526,12 @@ mDNSlocal void SendError(mDNS *const m, void *socket, DNSMessage *const msg, con mDNSPlatformDisposeProxyContext(context); } -mDNSlocal DNSQuestion *IsDuplicateClient(const mDNS *const m, const mDNSAddr *const addr, const mDNSIPPort port, const mDNSOpaque16 id, +mDNSlocal DNSQuestion *IsDuplicateClient(const mDNSAddr *const addr, const mDNSIPPort port, const mDNSOpaque16 id, const DNSQuestion *const question) { DNSProxyClient *pc; - (void) m; // unused - - for (pc = DNSProxyClients; pc; pc = pc->next) + for (pc = DNSProxyClients; pc; pc = pc->next) { if (mDNSSameAddress(&pc->addr, addr) && mDNSSameIPPort(pc->port, port) && @@ -546,8 +547,9 @@ mDNSlocal DNSQuestion *IsDuplicateClient(const mDNS *const m, const mDNSAddr *co return(mDNSNULL); } -mDNSlocal mDNSBool CheckDNSProxyIpIntf(const mDNS *const m, mDNSInterfaceID InterfaceID) +mDNSlocal mDNSBool CheckDNSProxyIpIntf(mDNSInterfaceID InterfaceID) { + mDNS *const m = &mDNSStorage; int i; mDNSu32 ip_ifindex = (mDNSu32)(unsigned long)InterfaceID; @@ -570,9 +572,10 @@ mDNSlocal mDNSBool CheckDNSProxyIpIntf(const mDNS *const m, mDNSInterfaceID Inte } -mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, +mDNSlocal void ProxyCallbackCommon(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, mDNSBool tcp, void *context) { + mDNS *const m = &mDNSStorage; mDNSu8 QR_OP; const mDNSu8 *ptr; DNSQuestion q, *qptr; @@ -586,7 +589,7 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, DNSMessage *cons debugf("ProxyCallbackCommon: DNS Query coming from InterfaceID %p", InterfaceID); // Ignore if the DNS Query is not from a Valid Input InterfaceID - if (!CheckDNSProxyIpIntf(m, InterfaceID)) + if (!CheckDNSProxyIpIntf(InterfaceID)) { LogMsg("ProxyCallbackCommon: Rejecting DNS Query coming from InterfaceID %p", InterfaceID); return; @@ -598,14 +601,6 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, DNSMessage *cons return; } - QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask); - if (QR_OP != kDNSFlag0_QR_Query) - { - LogInfo("ProxyCallbackCommon: Not a query(%d) for pkt from %#a:%d", QR_OP, srcaddr, mDNSVal16(srcport)); - SendError(m, socket, msg, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_NotImpl); - return; - } - // Read the integer parts which are in IETF byte-order (MSB first, LSB second) ptr = (mDNSu8 *)&msg->h.numQuestions; msg->h.numQuestions = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]); @@ -613,11 +608,19 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, DNSMessage *cons msg->h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] << 8 | ptr[5]); msg->h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] << 8 | ptr[7]); + QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask); + if (QR_OP != kDNSFlag0_QR_Query) + { + LogInfo("ProxyCallbackCommon: Not a query(%d) for pkt from %#a:%d", QR_OP, srcaddr, mDNSVal16(srcport)); + SendError(socket, msg, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_NotImpl); + return; + } + if (msg->h.numQuestions != 1 || msg->h.numAnswers || msg->h.numAuthorities) { LogInfo("ProxyCallbackCommon: Malformed pkt from %#a:%d, Q:%d, An:%d, Au:%d", srcaddr, mDNSVal16(srcport), msg->h.numQuestions, msg->h.numAnswers, msg->h.numAuthorities); - SendError(m, socket, msg, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_FormErr); + SendError(socket, msg, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_FormErr); return; } ptr = msg->data; @@ -625,7 +628,7 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, DNSMessage *cons if (!ptr) { LogInfo("ProxyCallbackCommon: Question cannot be parsed for pkt from %#a:%d", srcaddr, mDNSVal16(srcport)); - SendError(m, socket, msg, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_FormErr); + SendError(socket, msg, end, srcaddr, srcport, InterfaceID, tcp, context, kDNSFlag1_RC_FormErr); return; } else @@ -653,7 +656,7 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, DNSMessage *cons LogInfo("ProxyCallbackCommon: EDNS0 opt not present in Question %##s (%s), ptr %p", q.qname.c, DNSTypeName(q.qtype), ptr); } - qptr = IsDuplicateClient(m, srcaddr, srcport, msg->h.id, &q); + qptr = IsDuplicateClient(srcaddr, srcport, msg->h.id, &q); if (qptr) { LogInfo("ProxyCallbackCommon: Found a duplicate for pkt from %#a:%d, ignoring this", srcaddr, mDNSVal16(srcport)); @@ -730,21 +733,21 @@ mDNSlocal void ProxyCallbackCommon(mDNS *const m, void *socket, DNSMessage *cons mDNS_StartQuery(m, &pc->q); } -mDNSexport void ProxyUDPCallback(mDNS *const m, void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, +mDNSexport void ProxyUDPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context) { LogInfo("ProxyUDPCallback: DNS Message from %#a:%d to %#a:%d length %d", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - (mDNSu8 *)msg)); - ProxyCallbackCommon(m, socket, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID, mDNSfalse, context); + ProxyCallbackCommon(socket, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID, mDNSfalse, context); } -mDNSexport void ProxyTCPCallback(mDNS *const m, void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, +mDNSexport void ProxyTCPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context) { LogInfo("ProxyTCPCallback: DNS Message from %#a:%d to %#a:%d length %d", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - (mDNSu8 *)msg)); // If the connection was closed from the other side or incoming packet does not match stored input interface list, locate the client // state and free it. - if (((end - (mDNSu8 *)msg) == 0) || (!CheckDNSProxyIpIntf(m, InterfaceID))) + if (((end - (mDNSu8 *)msg) == 0) || (!CheckDNSProxyIpIntf(InterfaceID))) { DNSProxyClient **ppc = &DNSProxyClients; DNSProxyClient **prevpc; @@ -767,11 +770,12 @@ mDNSexport void ProxyTCPCallback(mDNS *const m, void *socket, DNSMessage *const FreeDNSProxyClient(*ppc); return; } - ProxyCallbackCommon(m, socket, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID, mDNStrue, context); + ProxyCallbackCommon(socket, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID, mDNStrue, context); } -mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf) +mDNSexport void DNSProxyInit(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf) { + mDNS *const m = &mDNSStorage; int i; // Store DNSProxy Interface fields in mDNS struct @@ -783,8 +787,9 @@ mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf m->dp_ipintf[1], m->dp_ipintf[2], m->dp_ipintf[3], m->dp_ipintf[4], m->dp_opintf); } -mDNSexport void DNSProxyTerminate(mDNS *const m) +mDNSexport void DNSProxyTerminate(void) { + mDNS *const m = &mDNSStorage; int i; // Clear DNSProxy Interface fields from mDNS struct @@ -797,9 +802,8 @@ mDNSexport void DNSProxyTerminate(mDNS *const m) } #else // UNICAST_DISABLED -mDNSexport void ProxyUDPCallback(mDNS *const m, void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context) +mDNSexport void ProxyUDPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context) { - (void) m; (void) socket; (void) msg; (void) end; @@ -811,9 +815,8 @@ mDNSexport void ProxyUDPCallback(mDNS *const m, void *socket, DNSMessage *const (void) context; } -mDNSexport void ProxyTCPCallback(mDNS *const m, void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context) +mDNSexport void ProxyTCPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context) { - (void) m; (void) socket; (void) msg; (void) end; @@ -825,15 +828,13 @@ mDNSexport void ProxyTCPCallback(mDNS *const m, void *socket, DNSMessage *const (void) context; } -mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf) +mDNSexport void DNSProxyInit(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf) { - (void) m; (void) IpIfArr; (void) OpIf; } -extern void DNSProxyTerminate(mDNS *const m) +extern void DNSProxyTerminate(void) { - (void) m; } diff --git a/mDNSResponder/mDNSCore/dnsproxy.h b/mDNSResponder/mDNSCore/dnsproxy.h index a2abdfbf..6889e73a 100644 --- a/mDNSResponder/mDNSCore/dnsproxy.h +++ b/mDNSResponder/mDNSCore/dnsproxy.h @@ -21,11 +21,11 @@ #include "mDNSEmbeddedAPI.h" #include "DNSCommon.h" -extern void ProxyUDPCallback(mDNS *const m, void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, +extern void ProxyUDPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context); -extern void ProxyTCPCallback(mDNS *const m, void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, +extern void ProxyTCPCallback(void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context); -extern void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf); -extern void DNSProxyTerminate(mDNS *const m); +extern void DNSProxyInit(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf); +extern void DNSProxyTerminate(void); #endif // __DNS_PROXY_H diff --git a/mDNSResponder/mDNSCore/dnssec.c b/mDNSResponder/mDNSCore/dnssec.c index 514a488c..9525655f 100644 --- a/mDNSResponder/mDNSCore/dnssec.c +++ b/mDNSResponder/mDNSCore/dnssec.c @@ -707,7 +707,6 @@ mDNSexport void ValidateRRSIG(DNSSECVerifier *dv, RRVerifierSet type, const Reso mDNSlocal mStatus CheckRRSIGForRRSet(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr) { - mDNSu32 slot; CacheGroup *cg; CacheRecord *cr; RRVerifier *rv; @@ -722,8 +721,7 @@ mDNSlocal mStatus CheckRRSIGForRRSet(mDNS *const m, DNSSECVerifier *dv, CacheRec } rv = dv->rrset; - slot = HashSlot(&rv->name); - cg = CacheGroupForName(m, slot, rv->namehash, &rv->name); + cg = CacheGroupForName(m, rv->namehash, &rv->name); if (!cg) { debugdnssec("CheckRRSIGForRRSet: cg null"); @@ -807,7 +805,6 @@ mDNSlocal void CheckOneKeyForRRSIG(DNSSECVerifier *dv, const ResourceRecord *con mDNSlocal mStatus CheckKeyForRRSIG(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr) { - mDNSu32 slot; mDNSu32 namehash; CacheGroup *cg; CacheRecord *cr; @@ -825,9 +822,8 @@ mDNSlocal mStatus CheckKeyForRRSIG(mDNS *const m, DNSSECVerifier *dv, CacheRecor rrsig = (rdataRRSig *)dv->rrsig->rdata; name = (domainname *)&rrsig->signerName; - slot = HashSlot(name); namehash = DomainNameHashValue(name); - cg = CacheGroupForName(m, slot, namehash, name); + cg = CacheGroupForName(m, namehash, name); if (!cg) { debugdnssec("CheckKeyForRRSIG: cg null for %##s", name->c); @@ -887,7 +883,6 @@ mDNSlocal void CheckOneRRSIGForKey(DNSSECVerifier *dv, const ResourceRecord *con mDNSlocal mStatus CheckRRSIGForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr) { - mDNSu32 slot; mDNSu32 namehash; CacheGroup *cg; CacheRecord *cr; @@ -909,9 +904,8 @@ mDNSlocal mStatus CheckRRSIGForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecor rrsig = (rdataRRSig *)dv->rrsig->rdata; name = (domainname *)&rrsig->signerName; - slot = HashSlot(name); namehash = DomainNameHashValue(name); - cg = CacheGroupForName(m, slot, namehash, name); + cg = CacheGroupForName(m, namehash, name); if (!cg) { debugdnssec("CheckRRSIGForKey: cg null %##s", name->c); @@ -1010,7 +1004,6 @@ mDNSlocal void CheckOneDSForKey(DNSSECVerifier *dv, const ResourceRecord *const mDNSlocal mStatus CheckDSForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecord **negcr) { - mDNSu32 slot; mDNSu32 namehash; CacheGroup *cg; CacheRecord *cr; @@ -1030,9 +1023,8 @@ mDNSlocal mStatus CheckDSForKey(mDNS *const m, DNSSECVerifier *dv, CacheRecord * } rrsig = (rdataRRSig *)dv->rrsig->rdata; name = (domainname *)&rrsig->signerName; - slot = HashSlot(name); namehash = DomainNameHashValue(name); - cg = CacheGroupForName(m, slot, namehash, name); + cg = CacheGroupForName(m, namehash, name); if (!cg) { debugdnssec("CheckDSForKey: cg null for %s", name->c); @@ -2336,7 +2328,6 @@ mDNSlocal void SetTTLRRSet(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus statu CacheRecord *rr; RRVerifier *rrsigv; rdataRRSig *rrsig; - mDNSu32 slot; CacheGroup *cg; mDNSu32 rrTTL, rrsigTTL, rrsigOrigTTL, rrsigTimeTTL; domainname *qname; @@ -2368,8 +2359,7 @@ mDNSlocal void SetTTLRRSet(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus statu question.ThisQInterval = -1; InitializeQuestion(m, &question, dv->InterfaceID, qname, qtype, mDNSNULL, mDNSNULL); - slot = HashSlot(&question.qname); - cg = CacheGroupForName(m, slot, question.qnamehash, &question.qname); + cg = CacheGroupForName(m, question.qnamehash, &question.qname); if (!cg) { @@ -2691,7 +2681,7 @@ mDNSlocal void DNSSECNoResponse(mDNS *const m, DNSSECVerifier *dv) { CacheGroup *cg; CacheRecord *cr; - mDNSu32 slot, namehash; + mDNSu32 namehash; ResourceRecord *answer = mDNSNULL; LogDNSSEC("DNSSECNoResponse: called"); @@ -2704,10 +2694,9 @@ mDNSlocal void DNSSECNoResponse(mDNS *const m, DNSSECVerifier *dv) BumpDNSSECStats(m, kStatsActionSet, kStatsTypeStatus, DNSSEC_NoResponse); - slot = HashSlot(&dv->origName); namehash = DomainNameHashValue(&dv->origName); - cg = CacheGroupForName(m, (const mDNSu32)slot, namehash, &dv->origName); + cg = CacheGroupForName(m, namehash, &dv->origName); if (!cg) { LogDNSSEC("DNSSECNoResponse: cg NULL for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType)); @@ -3033,7 +3022,7 @@ done: mDNSlocal void DNSSECValidationCB(mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status) { - mDNSu32 slot, namehash; + mDNSu32 namehash; CacheGroup *cg; CacheRecord *cr; @@ -3053,10 +3042,9 @@ mDNSlocal void DNSSECValidationCB(mDNS *const m, DNSSECVerifier *dv, DNSSECStatu ProveInsecure(m, dv, mDNSNULL, mDNSNULL); return; } - slot = HashSlot(&dv->origName); namehash = DomainNameHashValue(&dv->origName); - cg = CacheGroupForName(m, (const mDNSu32)slot, namehash, &dv->origName); + cg = CacheGroupForName(m, namehash, &dv->origName); if (!cg) { LogDNSSEC("DNSSECValidationCB: cg NULL for %##s (%s)", dv->origName.c, DNSTypeName(dv->origType)); @@ -3082,8 +3070,7 @@ mDNSlocal void DNSSECValidationCB(mDNS *const m, DNSSECVerifier *dv, DNSSECStatu mDNSexport void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *q) { - mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); CacheRecord *rr; mDNSBool first = mDNSfalse; static mDNSBool TrustAnchorsUpdated = mDNSfalse; @@ -3319,14 +3306,12 @@ mDNSlocal mStatus TrustedKey(mDNS *const m, DNSSECVerifier *dv) mDNSlocal CacheRecord* NegativeCacheRecordForRR(mDNS *const m, const ResourceRecord *const rr) { - mDNSu32 slot; mDNSu32 namehash; CacheGroup *cg; CacheRecord *cr; - slot = HashSlot(rr->name); namehash = DomainNameHashValue(rr->name); - cg = CacheGroupForName(m, slot, namehash, rr->name); + cg = CacheGroupForName(m, namehash, rr->name); if (!cg) { LogMsg("NegativeCacheRecordForRR: cg null %##s", rr->name->c); diff --git a/mDNSResponder/mDNSCore/mDNS.c b/mDNSResponder/mDNSCore/mDNS.c index a58a6c1a..0d4d8ae4 100755 --- a/mDNSResponder/mDNSCore/mDNS.c +++ b/mDNSResponder/mDNSCore/mDNS.c @@ -45,6 +45,7 @@ #endif #include "dns_sd.h" // for kDNSServiceFlags* definitions +#include "dns_sd_internal.h" #if APPLE_OSX_mDNSResponder #include <WebFilterDNS/WebFilterDNS.h> @@ -65,15 +66,22 @@ void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import)); #define NO_WCF 1 #endif // APPLE_OSX_mDNSResponder -#if TARGET_OS_EMBEDDED +#if AWD_METRICS #include "Metrics.h" #endif +#if USE_DNS64 +#include "DNS64.h" +#endif + +#ifdef UNIT_TEST +#include "unittest.h" +#endif + // Forward declarations mDNSlocal void BeginSleepProcessing(mDNS *const m); mDNSlocal void RetrySPSRegistrations(mDNS *const m); mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly); -mDNSlocal mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q); mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q); mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q); mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q); @@ -109,6 +117,10 @@ mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *et #define NR_AnswerMulticast (mDNSu8*)~0 #define NR_AnswerUnicast (mDNSu8*)~1 +// Question default timeout values +#define DEFAULT_MCAST_TIMEOUT 5 +#define DEFAULT_LO_OR_P2P_TIMEOUT 5 + // The code (see SendQueries() and BuildQuestion()) needs to have the // RequestUnicast value set to a value one greater than the number of times you want the query // sent with the "request unicast response" (QU) bit set. @@ -274,24 +286,27 @@ mDNSlocal AuthEntity *GetAuthEntity(AuthHash *r, const AuthGroup *const Preserve return(e); } -mDNSexport AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name) +mDNSexport AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 namehash, const domainname *const name) { AuthGroup *ag; + const mDNSu32 slot = namehash % AUTH_HASH_SLOTS; + for (ag = r->rrauth_hash[slot]; ag; ag=ag->next) if (ag->namehash == namehash && SameDomainName(ag->name, name)) break; return(ag); } -mDNSexport AuthGroup *AuthGroupForRecord(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr) +mDNSexport AuthGroup *AuthGroupForRecord(AuthHash *r, const ResourceRecord *const rr) { - return(AuthGroupForName(r, slot, rr->namehash, rr->name)); + return(AuthGroupForName(r, rr->namehash, rr->name)); } -mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr) +mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const ResourceRecord *const rr) { mDNSu16 namelen = DomainNameLength(rr->name); AuthGroup *ag = (AuthGroup*)GetAuthEntity(r, mDNSNULL); + const mDNSu32 slot = rr->namehash % AUTH_HASH_SLOTS; if (!ag) { LogMsg("GetAuthGroup: Failed to allocate memory for %##s", rr->name->c); return(mDNSNULL); } ag->next = r->rrauth_hash[slot]; ag->namehash = rr->namehash; @@ -310,9 +325,9 @@ mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const mDNSu32 slot, const Resourc } AssignDomainName(ag->name, rr->name); - if (AuthGroupForRecord(r, slot, rr)) LogMsg("GetAuthGroup: Already have AuthGroup for %##s", rr->name->c); + if (AuthGroupForRecord(r, rr)) LogMsg("GetAuthGroup: Already have AuthGroup for %##s", rr->name->c); r->rrauth_hash[slot] = ag; - if (AuthGroupForRecord(r, slot, rr) != ag) LogMsg("GetAuthGroup: Not finding AuthGroup for %##s", rr->name->c); + if (AuthGroupForRecord(r, rr) != ag) LogMsg("GetAuthGroup: Not finding AuthGroup for %##s", rr->name->c); return(ag); } @@ -320,11 +335,11 @@ mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const mDNSu32 slot, const Resourc // Returns the AuthGroup in which the AuthRecord was inserted mDNSexport AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr) { - (void)m; AuthGroup *ag; - const mDNSu32 slot = AuthHashSlot(rr->resrec.name); - ag = AuthGroupForRecord(r, slot, &rr->resrec); - if (!ag) ag = GetAuthGroup(r, slot, &rr->resrec); // If we don't have a AuthGroup for this name, make one now + + (void)m; + ag = AuthGroupForRecord(r, &rr->resrec); + if (!ag) ag = GetAuthGroup(r, &rr->resrec); // If we don't have a AuthGroup for this name, make one now if (ag) { *(ag->rrauth_tail) = rr; // Append this record to tail of cache slot list @@ -337,9 +352,8 @@ mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *r { AuthGroup *a; AuthRecord **rp; - const mDNSu32 slot = AuthHashSlot(rr->resrec.name); - a = AuthGroupForRecord(r, slot, &rr->resrec); + a = AuthGroupForRecord(r, &rr->resrec); if (!a) { LogMsg("RemoveAuthRecord: ERROR!! AuthGroup not found for %s", ARDisplayString(m, rr)); return mDNSNULL; } rp = &a->members; while (*rp) @@ -359,18 +373,19 @@ mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *r return a; } -mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name) +mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 namehash, const domainname *const name) { CacheGroup *cg; + mDNSu32 slot = HashSlotFromNameHash(namehash); for (cg = m->rrcache_hash[slot]; cg; cg=cg->next) if (cg->namehash == namehash && SameDomainName(cg->name, name)) break; return(cg); } -mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const mDNSu32 slot, const ResourceRecord *const rr) +mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const ResourceRecord *const rr) { - return(CacheGroupForName(m, slot, rr->namehash, rr->name)); + return(CacheGroupForName(m, rr->namehash, rr->name)); } mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr) @@ -472,7 +487,7 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re const mDNSu32 c = q->CNAMEReferrals + 1; // Stash a copy of the new q->CNAMEReferrals value UDPSocket *sock = q->LocalSocket; mDNSOpaque16 id = q->TargetQID; -#if TARGET_OS_EMBEDDED +#if AWD_METRICS uDNSMetrics metrics; #endif @@ -496,7 +511,7 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re LogInfo("AnswerQuestionByFollowingCNAME: %p %##s (%s) following CNAME referral %d for %s", q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, RRDisplayString(m, rr)); -#if TARGET_OS_EMBEDDED +#if AWD_METRICS if ((q->CNAMEReferrals == 0) && !q->metrics.originalQName) { domainname * qName; @@ -532,7 +547,7 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re // Record how many times we've done this. We need to do this *after* mDNS_StartQuery_internal, // because mDNS_StartQuery_internal re-initializes CNAMEReferrals to zero q->CNAMEReferrals = c; -#if TARGET_OS_EMBEDDED +#if AWD_METRICS q->metrics = metrics; #endif if (sock) @@ -787,7 +802,6 @@ mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRec (X) &kDNSRecordTypeActiveUniqueMask ? DefaultAnnounceIntervalForTypeUnique : 0) #define TimeToAnnounceThisRecord(RR,time) ((RR)->AnnounceCount && (time) - ((RR)->LastAPTime + (RR)->ThisAPInterval) >= 0) -#define TimeToSendThisRecord(RR,time) ((TimeToAnnounceThisRecord(RR,time) || (RR)->ImmedAnswer) && ResourceRecordIsValidAnswer(RR)) #define TicksTTL(RR) ((mDNSs32)(RR)->resrec.rroriginalttl * mDNSPlatformOneSecond) #define RRExpireTime(RR) ((RR)->TimeRcvd + TicksTTL(RR)) @@ -962,9 +976,9 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr) } rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval; } - // Skip kDNSRecordTypeKnownUnique records here and set their LastAPTime in the "else" block below so that they get announced immediately, - // otherwise, their announcement would be delayed until all other record probes complete. - else if ((rr->resrec.RecordType != kDNSRecordTypeKnownUnique) && m->SuppressProbes && m->SuppressProbes - m->timenow >= 0) + // Skip kDNSRecordTypeKnownUnique and kDNSRecordTypeShared records here and set their LastAPTime in the "else" block below so + // that they get announced immediately, otherwise, their announcement would be delayed until the based on the SuppressProbes value. + else if ((rr->resrec.RecordType != kDNSRecordTypeKnownUnique) && (rr->resrec.RecordType != kDNSRecordTypeShared) && m->SuppressProbes && (m->SuppressProbes - m->timenow >= 0)) rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval + DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2; else rr->LastAPTime = m->timenow - rr->ThisAPInterval; @@ -1155,9 +1169,8 @@ mDNSlocal AuthRecord *CheckAuthIdenticalRecord(AuthHash *r, AuthRecord *rr) { const AuthGroup *a; AuthRecord *rp; - const mDNSu32 slot = AuthHashSlot(rr->resrec.name); - a = AuthGroupForRecord(r, slot, &rr->resrec); + a = AuthGroupForRecord(r, &rr->resrec); if (!a) return mDNSNULL; rp = a->members; while (rp) @@ -1181,9 +1194,8 @@ mDNSlocal mDNSBool CheckAuthRecordConflict(AuthHash *r, AuthRecord *rr) { const AuthGroup *a; const AuthRecord *rp; - const mDNSu32 slot = AuthHashSlot(rr->resrec.name); - a = AuthGroupForRecord(r, slot, &rr->resrec); + a = AuthGroupForRecord(r, &rr->resrec); if (!a) return mDNSfalse; rp = a->members; while (rp) @@ -1203,9 +1215,8 @@ mDNSlocal AuthRecord *CheckAuthSameRecord(AuthHash *r, AuthRecord *rr) { const AuthGroup *a; AuthRecord *rp; - const mDNSu32 slot = AuthHashSlot(rr->resrec.name); - a = AuthGroupForRecord(r, slot, &rr->resrec); + a = AuthGroupForRecord(r, &rr->resrec); if (!a) return mDNSNULL; rp = a->members; while (rp) @@ -1386,9 +1397,9 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) { if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified; - else + else if (rr->resrec.RecordType != kDNSRecordTypeKnownUnique) { - LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique", + LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique or kDNSRecordTypeKnownUnique", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); return(mStatus_Invalid); } @@ -1630,7 +1641,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) getKeepaliveRaddr(m, rr, &raddr); // This is an asynchronous call. Once the remote MAC address is available, helper will schedule an // asynchronous task to update the resource record - mDNSPlatformGetRemoteMacAddr(m, &raddr); + mDNSPlatformGetRemoteMacAddr(&raddr); } return(mStatus_NoError); @@ -1679,9 +1690,8 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, { AuthGroup *a; AuthRecord **rp; - const mDNSu32 slot = AuthHashSlot(rr->resrec.name); - a = AuthGroupForRecord(&m->rrauth, slot, &rr->resrec); + a = AuthGroupForRecord(&m->rrauth, &rr->resrec); if (!a) return mDNSfalse; rp = &a->members; while (*rp && *rp != rr) rp=&(*rp)->next; @@ -1954,6 +1964,27 @@ mDNSlocal void AddRecordToResponseList(AuthRecord ***nrpp, AuthRecord *rr, AuthR debugf("AddRecordToResponseList: %##s (%s) already in list", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); } +mDNSlocal void AddRRSetAdditionalsToResponseList(mDNS *const m, AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *additional, const mDNSInterfaceID InterfaceID) +{ + AuthRecord *rr2; + if (additional->resrec.RecordType & kDNSRecordTypeUniqueMask) + { + for (rr2 = m->ResourceRecords; rr2; rr2 = rr2->next) + { + if ((rr2->resrec.namehash == additional->resrec.namehash) && + (rr2->resrec.rrtype == additional->resrec.rrtype) && + (rr2 != additional) && + (rr2->resrec.RecordType & kDNSRecordTypeUniqueMask) && + (rr2->resrec.rrclass == additional->resrec.rrclass) && + ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) && + SameDomainName(rr2->resrec.name, additional->resrec.name)) + { + AddRecordToResponseList(nrpp, rr2, rr); + } + } + } +} + mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseRecords, AuthRecord ***nrpp, const mDNSInterfaceID InterfaceID) { AuthRecord *rr, *rr2; @@ -1962,10 +1993,16 @@ mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseR // (Note: This is an "if", not a "while". If we add a record, we'll find it again // later in the "for" loop, and we will follow further "additional" links then.) if (rr->Additional1 && ResourceRecordIsValidInterfaceAnswer(rr->Additional1, InterfaceID)) + { AddRecordToResponseList(nrpp, rr->Additional1, rr); + AddRRSetAdditionalsToResponseList(m, nrpp, rr, rr->Additional1, InterfaceID); + } if (rr->Additional2 && ResourceRecordIsValidInterfaceAnswer(rr->Additional2, InterfaceID)) + { AddRecordToResponseList(nrpp, rr->Additional2, rr); + AddRRSetAdditionalsToResponseList(m, nrpp, rr, rr->Additional2, InterfaceID); + } // For SRV records, automatically add the Address record(s) for the target host if (rr->resrec.rrtype == kDNSType_SRV) @@ -2485,7 +2522,7 @@ mDNSlocal void SendResponses(mDNS *const m) mDNSs32 maxExistingAnnounceInterval = 0; const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces); - m->NextScheduledResponse = m->timenow + 0x78000000; + m->NextScheduledResponse = m->timenow + FutureTime; if (m->SleepState == SleepState_Transferring) RetrySPSRegistrations(m); @@ -3059,13 +3096,18 @@ mDNSexport void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const verbosedebugf("SetNextCacheCheckTimeForRecord: NextRequiredQuery in %ld sec CacheCheckGracePeriod %d ticks for %s", (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr), CRDisplayString(m,rr)); } - ScheduleNextCacheCheckTime(m, HashSlot(rr->resrec.name), NextCacheCheckEvent(rr)); + ScheduleNextCacheCheckTime(m, HashSlotFromNameHash(rr->resrec.namehash), NextCacheCheckEvent(rr)); } #define kMinimumReconfirmTime ((mDNSu32)mDNSPlatformOneSecond * 5) #define kDefaultReconfirmTimeForWake ((mDNSu32)mDNSPlatformOneSecond * 5) #define kDefaultReconfirmTimeForNoAnswer ((mDNSu32)mDNSPlatformOneSecond * 5) -#define kDefaultReconfirmTimeForFlappingInterface ((mDNSu32)mDNSPlatformOneSecond * 5) + +// Delay before restarting questions on a flapping interface. +#define kDefaultQueryDelayTimeForFlappingInterface ((mDNSu32)mDNSPlatformOneSecond * 3) +// After kDefaultQueryDelayTimeForFlappingInterface seconds, allow enough time for up to three queries (0, 1, and 4 seconds) +// plus three seconds for "response delay" before removing the reconfirmed records from the cache. +#define kDefaultReconfirmTimeForFlappingInterface (kDefaultQueryDelayTimeForFlappingInterface + ((mDNSu32)mDNSPlatformOneSecond * 7)) mDNSexport mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval) { @@ -3080,7 +3122,7 @@ mDNSexport mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, // Add a 33% random amount to the interval, to avoid synchronization between multiple hosts // For all the reconfirmations in a given batch, we want to use the same random value // so that the reconfirmation questions can be grouped into a single query packet - if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(0x3FFFFFFF); + if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(FutureTime); interval += m->RandomReconfirmDelay % ((interval/3) + 1); rr->TimeRcvd = m->timenow - (mDNSs32)interval * 3; rr->resrec.rroriginalttl = (interval * 4 + mDNSPlatformOneSecond - 1) / mDNSPlatformOneSecond; @@ -3110,8 +3152,7 @@ mDNSlocal mDNSBool BuildQuestion(mDNS *const m, const NetworkInterfaceInfo *intf else { mDNSu32 forecast = *answerforecast + anoninfo_space; - const mDNSu32 slot = HashSlot(&q->qname); - const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + const CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); CacheRecord *rr; CacheRecord **ka = *kalistptrptr; // Make a working copy of the pointer we're going to update @@ -3204,7 +3245,7 @@ mDNSlocal void ReconfirmAntecedents(mDNS *const m, const domainname *const name, // to get a AAAA response is not grounds to doubt the PTR/SRV chain that lead us to that name. mDNSlocal const CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const domainname *const name, const mDNSu32 namehash) { - CacheGroup *const cg = CacheGroupForName(m, HashSlot(name), namehash, name); + CacheGroup *const cg = CacheGroupForName(m, namehash, name); const CacheRecord *cr = cg ? cg->members : mDNSNULL; while (cr && !RRTypeIsAddressType(cr->resrec.rrtype)) cr=cr->next; return(cr); @@ -3214,7 +3255,7 @@ mDNSlocal const CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const dom mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *const q, const CacheRecord *const c0, const CacheRecord *const c1) { #ifndef SPC_DISABLED - CacheGroup *const cg = CacheGroupForName(m, HashSlot(&q->qname), q->qnamehash, &q->qname); + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); const CacheRecord *cr, *bestcr = mDNSNULL; mDNSu32 bestmetric = 1000000; for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next) @@ -3365,7 +3406,7 @@ mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q) mDNSPlatformMemCopy(IPAddr, &d->c[i + 1], len - i); IPAddr[len - i] = 0; m->mDNSStats.WakeOnResolves++; - mDNSPlatformSendWakeupPacket(m, InterfaceID, EthAddr, IPAddr, InitialWakeOnResolveCount - q->WakeOnResolveCount); + mDNSPlatformSendWakeupPacket(InterfaceID, EthAddr, IPAddr, InitialWakeOnResolveCount - q->WakeOnResolveCount); return; } else if (d->c[i] == ':') @@ -3386,8 +3427,7 @@ mDNSlocal mDNSBool AccelerateThisQuery(mDNS *const m, DNSQuestion *q) { // We forecast: qname (n) type (2) class (2) mDNSu32 forecast = (mDNSu32)DomainNameLength(&q->qname) + 4; - const mDNSu32 slot = HashSlot(&q->qname); - const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + const CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); const CacheRecord *rr; for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) // If we have a resource record in our cache, if (rr->resrec.rdlength <= SmallRecordLimit && // which is small enough to sensibly fit in the packet @@ -3490,7 +3530,7 @@ mDNSlocal void SendQueries(mDNS *const m) const mDNSu8 *const limit = m->omsg.data + sizeof(m->omsg.data); // If we fail to get a new on-demand socket (should only happen cases of the most extreme resource exhaustion), we'll try again next time - if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort); + if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(zeroIPPort); if (q->LocalSocket) { InitializeDNSMessage(&m->omsg.h, q->TargetQID, QueryFlags); @@ -3531,7 +3571,7 @@ mDNSlocal void SendQueries(mDNS *const m) // Note: Don't set NextScheduledQuery until here, because uDNS_CheckCurrentQuestion in the loop above can add new questions to the list, // which causes NextScheduledQuery to get (incorrectly) set to m->timenow. Setting it here is the right place, because the very // next thing we do is scan the list and call SetNextQueryTime() for every question we find, so we know we end up with the right value. - m->NextScheduledQuery = m->timenow + 0x78000000; + m->NextScheduledQuery = m->timenow + FutureTime; for (q = m->Questions; q && q != m->NewQuestions; q=q->next) { if (mDNSOpaque16IsZero(q->TargetQID) @@ -3610,7 +3650,7 @@ mDNSlocal void SendQueries(mDNS *const m) // 2. Scan our authoritative RR list to see what probes we might need to send - m->NextScheduledProbe = m->timenow + 0x78000000; + m->NextScheduledProbe = m->timenow + FutureTime; if (m->CurrentRecord) LogMsg("SendQueries ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); @@ -4110,7 +4150,7 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco return; } -#if TARGET_OS_EMBEDDED +#if AWD_METRICS if ((AddRecord == QC_add) && Question_uDNS(q) && !followcname) { const domainname * queryName; @@ -4169,6 +4209,11 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco if (rr->DelayDelivery) return; // We'll come back later when CacheRecordDeferredAdd() calls us +#if USE_DNS64 + // If DNS64StateMachine() returns true, then the question was restarted as a different question, so return. + if (!mDNSOpaque16IsZero(q->TargetQID) && DNS64StateMachine(m, q, &rr->resrec, AddRecord)) return; +#endif + #ifdef USE_LIBIDN if (rr->resrec.RecordType == kDNSRecordTypePacketNegative) // If negative answer, check if we need to try Punycode conversion { @@ -4209,7 +4254,18 @@ mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheReco q->QuestionCallback(m, q, &neg.resrec, AddRecord); } else - q->QuestionCallback(m, q, &rr->resrec, AddRecord); + { +#if USE_DNS64 + if (DNS64ShouldAnswerQuestion(q, &rr->resrec)) + { + DNS64AnswerQuestion(m, q, &rr->resrec, AddRecord); + } + else +#endif + { + q->QuestionCallback(m, q, &rr->resrec, AddRecord); + } + } mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again } // If this is an "Add" operation and this question needs validation, validate the response. @@ -4265,12 +4321,12 @@ mDNSlocal void CacheRecordDeferredAdd(mDNS *const m, CacheRecord *rr) m->CurrentQuestion = mDNSNULL; } -mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const mDNSu32 slot, mDNSBool *purge) +mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash, mDNSBool *purge) { const mDNSs32 threshhold = m->timenow + mDNSPlatformOneSecond; // See if there are any records expiring within one second const mDNSs32 start = m->timenow - 0x10000000; mDNSs32 delay = start; - CacheGroup *cg = CacheGroupForName(m, slot, namehash, name); + CacheGroup *cg = CacheGroupForName(m, namehash, name); const CacheRecord *rr; if (purge) @@ -4559,13 +4615,12 @@ mDNSlocal void ReleaseAdditionalCacheRecords(mDNS *const m, CacheRecord **rp) mDNSexport void ReleaseCacheRecord(mDNS *const m, CacheRecord *r) { CacheGroup *cg; - const mDNSu32 slot = HashSlot(r->resrec.name); //LogMsg("ReleaseCacheRecord: Releasing %s", CRDisplayString(m, r)); if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->smallrdatastorage) mDNSPlatformMemFree(r->resrec.rdata); r->resrec.rdata = mDNSNULL; - cg = CacheGroupForRecord(m, slot, &r->resrec); + cg = CacheGroupForRecord(m, &r->resrec); if (!cg) { @@ -4662,7 +4717,7 @@ mDNSlocal void CheckCacheExpiration(mDNS *const m, const mDNSu32 slot, CacheGrou m->NextScheduledQuery = m->timenow; // After sending the query we'll increment UnansweredQueries and call SetNextCacheCheckTimeForRecord(), // which will correctly update m->NextCacheCheck for us. - event = m->timenow + 0x3FFFFFFF; + event = m->timenow + FutureTime; } } } @@ -4687,15 +4742,13 @@ mDNSlocal void CheckCacheExpiration(mDNS *const m, const mDNSu32 slot, CacheGrou // returns true to indicate the same. mDNSlocal mDNSBool AnswerQuestionWithLORecord(mDNS *const m, DNSQuestion *q, mDNSBool checkOnly) { - mDNSu32 slot; AuthRecord *lr; AuthGroup *ag; if (m->CurrentRecord) LogMsg("AnswerQuestionWithLORecord ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); - slot = AuthHashSlot(&q->qname); - ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname); + ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname); if (ag) { m->CurrentRecord = ag->members; @@ -4772,8 +4825,19 @@ mDNSlocal mDNSBool AnswerQuestionWithLORecord(mDNS *const m, DNSQuestion *q, mDN // reasons for suppressing the query, this function should be updated. mDNSlocal void AnswerSuppressedQuestion(mDNS *const m, DNSQuestion *q) { - mDNSBool SuppressQuery = q->SuppressQuery; - mDNSBool DisallowPID = q->DisallowPID; + mDNSBool SuppressQuery; + mDNSBool DisallowPID; + + // If the client did not set the kDNSServiceFlagsReturnIntermediates flag, then don't generate a negative response, just + // deactivate the DNSQuestion. + if (!q->ReturnIntermed) + { + q->ThisQInterval = 0; + return; + } + + SuppressQuery = q->SuppressQuery; + DisallowPID = q->DisallowPID; // make sure that QuerySuppressed() returns false q->SuppressQuery = mDNSfalse; @@ -4789,13 +4853,15 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m) { mDNSBool ShouldQueryImmediately = mDNStrue; DNSQuestion *const q = m->NewQuestions; // Grab the question we're going to answer - mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); +#if USE_DNS64 + if (!mDNSOpaque16IsZero(q->TargetQID)) DNS64HandleNewQuestion(m, q); +#endif + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); mDNSBool AnsweredFromCache = mDNSfalse; verbosedebugf("AnswerNewQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); - if (cg) CheckCacheExpiration(m, slot, cg); + if (cg) CheckCacheExpiration(m, HashSlotFromNameHash(q->qnamehash), cg); if (m->NewQuestions != q) { LogInfo("AnswerNewQuestion: Question deleted while doing CheckCacheExpiration"); goto exit; } m->NewQuestions = q->next; // Advance NewQuestions to the next *after* calling CheckCacheExpiration, because if we advance it first @@ -4935,11 +5001,10 @@ exit: // appropriate answers, stopping if it reaches a NewLocalOnlyRecord -- these will be handled by AnswerAllLocalQuestionsWithLocalAuthRecord mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m) { - mDNSu32 slot; AuthGroup *ag; DNSQuestion *q = m->NewLocalOnlyQuestions; // Grab the question we're going to answer - m->NewLocalOnlyQuestions = q->next; // Advance NewLocalOnlyQuestions to the next (if any) mDNSBool retEv = mDNSfalse; + m->NewLocalOnlyQuestions = q->next; // Advance NewLocalOnlyQuestions to the next (if any) debugf("AnswerNewLocalOnlyQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); @@ -4954,8 +5019,7 @@ mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m) // 1. First walk the LocalOnly records answering the LocalOnly question // 2. As LocalOnly questions should also be answered by any other Auth records local to the machine, // walk the ResourceRecords list delivering the answers - slot = AuthHashSlot(&q->qname); - ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname); + ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname); if (ag) { m->CurrentRecord = ag->members; @@ -5120,9 +5184,9 @@ mDNSlocal CacheGroup *GetCacheGroup(mDNS *const m, const mDNSu32 slot, const Res } AssignDomainName(cg->name, rr->name); - if (CacheGroupForRecord(m, slot, rr)) LogMsg("GetCacheGroup: Already have CacheGroup for %##s", rr->name->c); + if (CacheGroupForRecord(m, rr)) LogMsg("GetCacheGroup: Already have CacheGroup for %##s", rr->name->c); m->rrcache_hash[slot] = cg; - if (CacheGroupForRecord(m, slot, rr) != cg) LogMsg("GetCacheGroup: Not finding CacheGroup for %##s", rr->name->c); + if (CacheGroupForRecord(m, rr) != cg) LogMsg("GetCacheGroup: Not finding CacheGroup for %##s", rr->name->c); return(cg); } @@ -5162,7 +5226,7 @@ mDNSexport mDNSs32 mDNS_TimeNow(const mDNS *const m) // had its Sleep Proxy client list change, and defer to actual BPF reconfiguration to mDNS_Execute(). // (GetNextScheduledEvent() returns "now" when m->SPSProxyListChanged is set) #define SetSPSProxyListChanged(X) do { \ - if (m->SPSProxyListChanged && m->SPSProxyListChanged != (X)) mDNSPlatformUpdateProxyList(m, m->SPSProxyListChanged); \ + if (m->SPSProxyListChanged && m->SPSProxyListChanged != (X)) mDNSPlatformUpdateProxyList(m->SPSProxyListChanged); \ m->SPSProxyListChanged = (X); } while(0) // Called from mDNS_Execute() to expire stale proxy records @@ -5221,13 +5285,12 @@ mDNSlocal void CheckRmvEventsForLocalRecords(mDNS *const m) } } -mDNSlocal void TimeoutQuestions(mDNS *const m) +mDNSlocal void TimeoutQuestions_internal(mDNS *const m, DNSQuestion* questions, mDNSInterfaceID InterfaceID) { - m->NextScheduledStopTime = m->timenow + 0x3FFFFFFF; if (m->CurrentQuestion) LogMsg("TimeoutQuestions ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); - m->CurrentQuestion = m->Questions; + m->CurrentQuestion = questions; while (m->CurrentQuestion) { DNSQuestion *const q = m->CurrentQuestion; @@ -5239,7 +5302,8 @@ mDNSlocal void TimeoutQuestions(mDNS *const m) if (m->timenow - q->StopTime >= 0) { LogInfo("TimeoutQuestions: question %p %##s timed out, time %d", q, q->qname.c, m->timenow - q->StopTime); - GenerateNegativeResponse(m, mDNSInterface_Any, QC_forceresponse); + q->LOAddressAnswers = 0; // unset since timing out the question + GenerateNegativeResponse(m, InterfaceID, QC_forceresponse); if (m->CurrentQuestion == q) q->StopTime = 0; } else @@ -5257,6 +5321,13 @@ mDNSlocal void TimeoutQuestions(mDNS *const m) m->CurrentQuestion = mDNSNULL; } +mDNSlocal void TimeoutQuestions(mDNS *const m) +{ + m->NextScheduledStopTime = m->timenow + FutureTime; // push reschedule of TimeoutQuestions to way off into the future + TimeoutQuestions_internal(m, m->Questions, mDNSInterface_Any); + TimeoutQuestions_internal(m, m->LocalOnlyQuestions, mDNSInterface_LocalOnly); +} + mDNSlocal void mDNSCoreFreeProxyRR(mDNS *const m) { AuthRecord *rrPtr = m->SPSRRSet, *rrNext = mDNSNULL; @@ -5274,10 +5345,6 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) { mDNS_Lock(m); // Must grab lock before trying to read m->timenow -#if APPLE_OSX_mDNSResponder - mDNSLogStatistics(m); -#endif // APPLE_OSX_mDNSResponder - if (m->timenow - m->NextScheduledEvent >= 0) { int i; @@ -5304,13 +5371,13 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) if (m->rrcache_size && m->timenow - m->NextCacheCheck >= 0) { mDNSu32 numchecked = 0; - m->NextCacheCheck = m->timenow + 0x3FFFFFFF; + m->NextCacheCheck = m->timenow + FutureTime; for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) { if (m->timenow - m->rrcache_nextcheck[slot] >= 0) { CacheGroup **cp = &m->rrcache_hash[slot]; - m->rrcache_nextcheck[slot] = m->timenow + 0x3FFFFFFF; + m->rrcache_nextcheck[slot] = m->timenow + FutureTime; while (*cp) { debugf("m->NextCacheCheck %4d Slot %3d %##s", numchecked, slot, *cp ? (*cp)->name : (domainname*)"\x04NULL"); @@ -5330,7 +5397,7 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) if (m->timenow - m->NextScheduledSPS >= 0) { - m->NextScheduledSPS = m->timenow + 0x3FFFFFFF; + m->NextScheduledSPS = m->timenow + FutureTime; CheckProxyRecords(m, m->DuplicateRecords); // Clear m->DuplicateRecords first, then m->ResourceRecords CheckProxyRecords(m, m->ResourceRecords); } @@ -5341,7 +5408,7 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) // as records could have expired during that check if (m->timenow - m->NextScheduledKA >= 0) { - m->NextScheduledKA = m->timenow + 0x3FFFFFFF; + m->NextScheduledKA = m->timenow + FutureTime; mDNS_SendKeepalives(m); } @@ -5525,16 +5592,17 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) m->RandomQueryDelay = 0; m->RandomReconfirmDelay = 0; + // See if any questions (or local-only questions) have timed out if (m->NextScheduledStopTime && m->timenow - m->NextScheduledStopTime >= 0) TimeoutQuestions(m); #ifndef UNICAST_DISABLED if (m->NextSRVUpdate && m->timenow - m->NextSRVUpdate >= 0) UpdateAllSRVRecords(m); if (m->timenow - m->NextScheduledNATOp >= 0) CheckNATMappings(m); if (m->timenow - m->NextuDNSEvent >= 0) uDNS_Tasks(m); #endif -#if APPLE_OSX_mDNSResponder +#if APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR extern void serviceBLE(); if (m->NextBLEServiceTime && (m->timenow - m->NextBLEServiceTime >= 0)) serviceBLE(); -#endif // APPLE_OSX_mDNSResponder +#endif // APPLE_OSX_mDNSResponder && ENABLE_BLE_TRIGGERED_BONJOUR } // Note about multi-threaded systems: @@ -5574,11 +5642,9 @@ mDNSlocal void SuspendLLQs(mDNS *m) mDNSlocal mDNSBool QuestionHasLocalAnswers(mDNS *const m, DNSQuestion *q) { AuthRecord *rr; - mDNSu32 slot; AuthGroup *ag; - slot = AuthHashSlot(&q->qname); - ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname); + ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname); if (ag) { for (rr = ag->members; rr; rr=rr->next) @@ -5614,7 +5680,7 @@ mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question, !SameDomainLabel(question->qname.c, (const mDNSu8 *)"\x0c_autotunnel6")&& question->QuestionCallback != AutoTunnelCallback) { question->NoAnswer = NoAnswer_Suspended; - AddNewClientTunnel(m, question); + AddNewClientTunnel(question); return; } #endif // APPLE_OSX_mDNSResponder @@ -5890,7 +5956,7 @@ mDNSexport void mDNS_UpdateAllowSleep(mDNS *const m) } // Call the platform code to enable/disable sleep - mDNSPlatformSetAllowSleep(m, allowSleep, reason); + mDNSPlatformSetAllowSleep(allowSleep, reason); #else (void) m; #endif /* !defined(IDLESLEEPCONTROL_DISABLED) */ @@ -6001,7 +6067,7 @@ mDNSexport mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkIn // now, then we don't update the DNS NULL record. But we do not prevent it from registering with the SPS. When SPS sees // this DNS NULL record, it does not send any keepalives as it does not have all the information mDNSPlatformMemZero(&mti, sizeof (mDNSTCPInfo)); - ret = mDNSPlatformRetrieveTCPInfo(m, &laddr, &lport, &raddr, &rport, &mti); + ret = mDNSPlatformRetrieveTCPInfo(&laddr, &lport, &raddr, &rport, &mti); if (ret != mStatus_NoError) { LogMsg("mDNSPlatformRetrieveTCPInfo: mDNSPlatformRetrieveTCPInfo failed %d", ret); @@ -6568,15 +6634,14 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m) m->NextScheduledSPRetry = m->timenow; + // Clear out the SCDynamic entry that stores the external SPS information + mDNSPlatformClearSPSData(); + if (!m->SystemWakeOnLANEnabled) LogSPS("BeginSleepProcessing: m->SystemWakeOnLANEnabled is false"); else if (!mDNSCoreHaveAdvertisedMulticastServices(m)) LogSPS("BeginSleepProcessing: No advertised services"); else // If we have at least one advertised service { NetworkInterfaceInfo *intf; - - // Clear out the SCDynamic entry that stores the external SPS information - mDNSPlatformClearSPSData(); - for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) { // Intialize it to false. These values make sense only when SleepState is set to Sleeping. @@ -6616,7 +6681,7 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m) else if (SupportsInNICProxy(intf)) { mDNSBool keepaliveOnly = mDNSfalse; - if (ActivateLocalProxy(m, intf, &keepaliveOnly) == mStatus_NoError) + if (ActivateLocalProxy(intf, &keepaliveOnly) == mStatus_NoError) { SendGoodbyesForWakeOnlyService(m, &WakeOnlyService); @@ -6833,11 +6898,6 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep) // 2. Re-validate our cache records currtime = mDNSPlatformUTC(); -#if APPLE_OSX_mDNSResponder - // start time of this statistics gathering interval - m->StatStartTime = currtime; -#endif // APPLE_OSX_mDNSResponder - diff = currtime - m->TimeSlept; FORALL_CACHERECORDS(slot, cg, cr) { @@ -6984,7 +7044,7 @@ mDNSexport mDNSBool mDNSCoreReadyForSleep(mDNS *m, mDNSs32 now) if (rr->state == regState_Refresh && rr->tcp) { LogSPS("mDNSCoreReadyForSleep: waiting for Record updateIntID 0x%x 0x%x (updateid %d) %s", rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto notready; } #if APPLE_OSX_mDNSResponder - if (!RecordReadyForSleep(m, rr)) { LogSPS("mDNSCoreReadyForSleep: waiting for %s", ARDisplayString(m, rr)); goto notready; } + if (!RecordReadyForSleep(rr)) { LogSPS("mDNSCoreReadyForSleep: waiting for %s", ARDisplayString(m, rr)); goto notready; } #endif } @@ -7315,8 +7375,7 @@ exit: mDNSlocal CacheRecord *FindIdenticalRecordInCache(const mDNS *const m, const ResourceRecord *const pktrr) { - mDNSu32 slot = HashSlot(pktrr->name); - CacheGroup *cg = CacheGroupForRecord(m, slot, pktrr); + CacheGroup *cg = CacheGroupForRecord(m, pktrr); CacheRecord *rr; mDNSBool match; for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) @@ -7563,7 +7622,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con // We only mark this question for sending if it is at least one second since the last time we multicast it // on this interface. If it is more than a second, or LastMCInterface is different, then we may multicast it. // This is to guard against the case where someone blasts us with queries as fast as they can. - if (m->timenow - (rr->LastMCTime + mDNSPlatformOneSecond) >= 0 || + if ((mDNSu32)(m->timenow - rr->LastMCTime) >= (mDNSu32)mDNSPlatformOneSecond || (rr->LastMCInterface != mDNSInterfaceMark && rr->LastMCInterface != InterfaceID)) rr->NR_AnswerTo = NR_AnswerMulticast; } @@ -7592,44 +7651,25 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con if (query->h.flags.b[0] & kDNSFlag0_TC) m->mDNSStats.KnownAnswerMultiplePkts++; -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - if (QuestionNeedsMulticastResponse) -#else // We only do the following accelerated cache expiration and duplicate question suppression processing // for non-truncated multicast queries with multicast responses. // For any query generating a unicast response we don't do this because we can't assume we will see the response. // For truncated queries we don't do this because a response we're expecting might be suppressed by a subsequent // known-answer packet, and when there's packet loss we can't safely assume we'll receive *all* known-answer packets. if (QuestionNeedsMulticastResponse && !(query->h.flags.b[0] & kDNSFlag0_TC)) -#endif { #if POOF_ENABLED - const mDNSu32 slot = HashSlot(&pktq.qname); - CacheGroup *cg = CacheGroupForName(m, slot, pktq.qnamehash, &pktq.qname); + CacheGroup *cg = CacheGroupForName(m, pktq.qnamehash, &pktq.qname); CacheRecord *cr; // Make a list indicating which of our own cache records we expect to see updated as a result of this query // Note: Records larger than 1K are not habitually multicast, so don't expect those to be updated -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - if (!(query->h.flags.b[0] & kDNSFlag0_TC)) -#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next) if (SameNameRecordAnswersQuestion(&cr->resrec, &pktq) && cr->resrec.rdlength <= SmallRecordLimit) if (!cr->NextInKAList && eap != &cr->NextInKAList) { *eap = cr; eap = &cr->NextInKAList; -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - if (cr->MPUnansweredQ == 0 || m->timenow - cr->MPLastUnansweredQT >= mDNSPlatformOneSecond) - { - // Although MPUnansweredQ is only really used for multi-packet query processing, - // we increment it for both single-packet and multi-packet queries, so that it stays in sync - // with the MPUnansweredKA value, which by necessity is incremented for both query types. - cr->MPUnansweredQ++; - cr->MPLastUnansweredQT = m->timenow; - cr->MPExpectingKA = mDNStrue; - } -#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING } #endif // POOF_ENABLED @@ -7637,9 +7677,6 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con // We only do this for non-truncated queries. Right now it would be too complicated to try // to keep track of duplicate suppression state between multiple packets, especially when we // can't guarantee to receive all of the Known Answer packets that go with a particular query. -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - if (!(query->h.flags.b[0] & kDNSFlag0_TC)) -#endif // For anonymous question, the duplicate suppressesion should happen if the // question belongs in the same group. As the group is expected to be // small, we don't do the optimization for now. @@ -7723,16 +7760,6 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con ourcacherr = FindIdenticalRecordInCache(m, &m->rec.r.resrec); - #if ENABLE_MULTI_PACKET_QUERY_SNOOPING - // See if this Known-Answer suppresses any answers we were expecting for our cache records. We do this always, - // even if the TC bit is not set (the TC bit will *not* be set in the *last* packet of a multi-packet KA list). - if (ourcacherr && ourcacherr->MPExpectingKA && m->timenow - ourcacherr->MPLastUnansweredQT < mDNSPlatformOneSecond) - { - ourcacherr->MPUnansweredKA++; - ourcacherr->MPExpectingKA = mDNSfalse; - } - #endif - #if POOF_ENABLED // Having built our ExpectedAnswers list from the questions in this packet, we then remove // any records that are suppressed by the Known Answer list in this packet. @@ -7779,13 +7806,9 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con mDNSBool SendMulticastResponse = mDNSfalse; // Send modern multicast response mDNSBool SendUnicastResponse = mDNSfalse; // Send modern unicast response (not legacy unicast response) -#if !TARGET_OS_EMBEDDED - // always honor kDNSQClass_UnicastResponse in embedded environment to increase reliability - // in high multicast packet loss environments. - // If it's been one TTL/4 since we multicast this, then send a multicast response // for conflict detection, etc. - if (m->timenow - (rr->LastMCTime + TicksTTL(rr)/4) >= 0) + if ((mDNSu32)(m->timenow - rr->LastMCTime) >= (mDNSu32)TicksTTL(rr)/4) { SendMulticastResponse = mDNStrue; // If this record was marked for modern (delayed) unicast response, then mark it as promoted to @@ -7797,7 +7820,6 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con rr->NR_AnswerTo = NR_AnswerMulticast; } } -#endif // !TARGET_OS_EMBEDDED // If the client insists on a multicast response, then we'd better send one if (rr->NR_AnswerTo == NR_AnswerMulticast) @@ -7925,12 +7947,7 @@ exit: cr->UnansweredQueries++; cr->LastUnansweredTime = m->timenow; if (cr->UnansweredQueries > 1) - #if ENABLE_MULTI_PACKET_QUERY_SNOOPING - debugf("ProcessQuery: (!TC) UAQ %lu MPQ %lu MPKA %lu %s", - cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr)); - #else debugf("ProcessQuery: UnansweredQueries %lu %s", cr->UnansweredQueries, CRDisplayString(m, cr)); - #endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING SetNextCacheCheckTimeForRecord(m, cr); } @@ -7940,49 +7957,12 @@ exit: { // Only show debugging message if this record was not about to expire anyway if (RRExpireTime(cr) - m->timenow > (mDNSs32) kDefaultReconfirmTimeForNoAnswer * 4 / 3 + mDNSPlatformOneSecond) - #if ENABLE_MULTI_PACKET_QUERY_SNOOPING - debugf("ProcessQuery: (Max) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s", - cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr)); - #else - LogInfo("ProcessQuery: UnansweredQueries %lu TTL %lu mDNS_Reconfirm() for %s", - cr->UnansweredQueries, (RRExpireTime(cr) - m->timenow + mDNSPlatformOneSecond-1) / mDNSPlatformOneSecond, CRDisplayString(m, cr)); - #endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING + LogInfo("ProcessQuery: UnansweredQueries %lu interface %lu TTL %lu mDNS_Reconfirm() for %s", + cr->UnansweredQueries, InterfaceID, (RRExpireTime(cr) - m->timenow + mDNSPlatformOneSecond-1) / mDNSPlatformOneSecond, CRDisplayString(m, cr)); m->mDNSStats.PoofCacheDeletions++; mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer); } -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - // Make a guess, based on the multi-packet query / known answer counts, whether we think we - // should have seen an answer for this. (We multiply MPQ by 4 and MPKA by 5, to allow for - // possible packet loss of up to 20% of the additional KA packets.) - else if (cr->MPUnansweredQ * 4 > cr->MPUnansweredKA * 5 + 8) - { - // We want to do this conservatively. - // If there are so many machines on the network that they have to use multi-packet known-answer lists, - // then we don't want them to all hit the network simultaneously with their final expiration queries. - // By setting the record to expire in four minutes, we achieve two things: - // (a) the 90-95% final expiration queries will be less bunched together - // (b) we allow some time for us to witness enough other failed queries that we don't have to do our own - mDNSu32 remain = (mDNSu32)(RRExpireTime(cr) - m->timenow) / 4; - if (remain > 240 * (mDNSu32)mDNSPlatformOneSecond) - remain = 240 * (mDNSu32)mDNSPlatformOneSecond; - - // Only show debugging message if this record was not about to expire anyway - if (RRExpireTime(cr) - m->timenow > 4 * mDNSPlatformOneSecond) - debugf("ProcessQuery: (MPQ) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s", - cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr)); - - if (remain <= 60 * (mDNSu32)mDNSPlatformOneSecond) - cr->UnansweredQueries++; // Treat this as equivalent to one definite unanswered query - cr->MPUnansweredQ = 0; // Clear MPQ/MPKA statistics - cr->MPUnansweredKA = 0; - cr->MPExpectingKA = mDNSfalse; - - if (remain < kDefaultReconfirmTimeForNoAnswer) - remain = kDefaultReconfirmTimeForNoAnswer; - mDNS_Reconfirm_internal(m, cr, remain); - } -#endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING } #endif // POOF_ENABLED @@ -8229,19 +8209,13 @@ mDNSlocal void RefreshCacheRecord(mDNS *const m, CacheRecord *rr, mDNSu32 ttl) rr->TimeRcvd = m->timenow; rr->resrec.rroriginalttl = ttl; rr->UnansweredQueries = 0; -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - rr->MPUnansweredQ = 0; - rr->MPUnansweredKA = 0; - rr->MPExpectingKA = mDNSfalse; -#endif SetNextCacheCheckTimeForRecord(m, rr); } mDNSexport void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease) { CacheRecord *rr; - const mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + CacheGroup *cg = CacheGroupForName(m, q->qnamehash, &q->qname); for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) if (rr->CRActiveQuestion == q) { @@ -8454,8 +8428,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr))) { CacheRecord *rr, *neg = mDNSNULL; - mDNSu32 slot = HashSlot(&q.qname); - CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname); + CacheGroup *cg = CacheGroupForName(m, q.qnamehash, &q.qname); for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) if (SameNameRecordAnswersQuestion(&rr->resrec, qptr)) { @@ -8524,8 +8497,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec); if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_SOA) { - const mDNSu32 s = HashSlot(m->rec.r.resrec.name); - CacheGroup *cgSOA = CacheGroupForRecord(m, s, &m->rec.r.resrec); + CacheGroup *cgSOA = CacheGroupForRecord(m, &m->rec.r.resrec); const rdataSOA *const soa = (const rdataSOA *)m->rec.r.resrec.rdata->u.data; mDNSu32 ttl_s = soa->min; // We use the lesser of the SOA.MIN field and the SOA record's TTL, *except* @@ -8537,7 +8509,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * // Create the SOA record as we may have to return this to the questions // that we are acting as a proxy for currently or in the future. - SOARecord = CreateNewCacheEntry(m, s, cgSOA, 1, mDNSfalse, mDNSNULL); + SOARecord = CreateNewCacheEntry(m, HashSlotFromNameHash(m->rec.r.resrec.namehash), cgSOA, 1, mDNSfalse, mDNSNULL); // Special check for SOA queries: If we queried for a.b.c.d.com, and got no answer, // with an Authority Section SOA record for d.com, then this is a hint that the authority @@ -8620,12 +8592,12 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * // been NULL. If we pass NULL cg to new cache entries that we create below, // it will create additional cache groups for the same name. To avoid that, // look up the cache group again to re-initialize cg again. - cg = CacheGroupForName(m, slot, hash, name); + cg = CacheGroupForName(m, hash, name); if (NSECRecords && DNSSECQuestion(qptr)) { // Create the cache entry with delay and then add the NSEC records // to it and add it immediately. - negcr = CreateNewCacheEntry(m, slot, cg, 1, mDNStrue, mDNSNULL); + negcr = CreateNewCacheEntry(m, HashSlotFromNameHash(hash), cg, 1, mDNStrue, mDNSNULL); if (negcr) { negcr->CRDNSSECQuestion = 0; @@ -8650,7 +8622,7 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * else { // Need to add with a delay so that we can tag the SOA record - negcr = CreateNewCacheEntry(m, slot, cg, 1, mDNStrue, mDNSNULL); + negcr = CreateNewCacheEntry(m, HashSlotFromNameHash(hash), cg, 1, mDNStrue, mDNSNULL); if (negcr) { negcr->CRDNSSECQuestion = 0; @@ -8674,9 +8646,6 @@ mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage * repeat--; name = (const domainname *)(name->c + 1 + name->c[0]); hash = DomainNameHashValue(name); - slot = HashSlot(name); - // For now, we don't need to update cg here, because we'll do it again immediately, back up at the start of this loop - //cg = CacheGroupForName(m, slot, hash, name); } } } @@ -8891,7 +8860,6 @@ mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const resp } for (i = 0; i < response->h.numAuthorities && ptr && ptr < end; i++) { - mDNSu32 slot; CacheGroup *cg; ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec); @@ -8901,11 +8869,10 @@ mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const resp m->rec.r.resrec.RecordType = 0; continue; } - slot = HashSlot(m->rec.r.resrec.name); - cg = CacheGroupForRecord(m, slot, &m->rec.r.resrec); + cg = CacheGroupForRecord(m, &m->rec.r.resrec); // Create the cache entry but don't add it to the cache it. We need // to cache this along with the main cache record. - rr = CreateNewCacheEntry(m, slot, cg, 0, mDNSfalse, mDNSNULL); + rr = CreateNewCacheEntry(m, HashSlotFromNameHash(m->rec.r.resrec.namehash), cg, 0, mDNSfalse, mDNSNULL); if (rr) { debugf("mDNSParseNSEC3Records: %s", CRDisplayString(m, rr)); @@ -9027,8 +8994,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, CacheRecord *rr; // Remember the unicast question that we found, which we use to make caching // decisions later on in this function - const mDNSu32 slot = HashSlot(&q.qname); - CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname); + CacheGroup *cg = CacheGroupForName(m, q.qnamehash, &q.qname); if (!mDNSOpaque16IsZero(response->h.id)) { unicastQuestion = qptr; @@ -9401,7 +9367,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, // have any record(s) of the same type that we should re-assert to rescue them // (see note about "multi-homing and bridged networks" at the end of this function). else if (m->rec.r.resrec.rrtype == rr->resrec.rrtype) - if ((m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) && m->timenow - rr->LastMCTime > mDNSPlatformOneSecond/2) + if ((m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) && (mDNSu32)(m->timenow - rr->LastMCTime) > (mDNSu32)mDNSPlatformOneSecond/2) { rr->ImmedAnswer = mDNSInterfaceMark; m->NextScheduledResponse = m->timenow; } } } @@ -9420,8 +9386,8 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, if (!AcceptableResponse) LogInfo("mDNSCoreReceiveResponse ignoring %s", CRDisplayString(m, &m->rec.r)); if (m->rrcache_size && AcceptableResponse) { - const mDNSu32 slot = HashSlot(m->rec.r.resrec.name); - CacheGroup *cg = CacheGroupForRecord(m, slot, &m->rec.r.resrec); + const mDNSu32 slot = HashSlotFromNameHash(m->rec.r.resrec.namehash); + CacheGroup *cg = CacheGroupForRecord(m, &m->rec.r.resrec); CacheRecord *rr = mDNSNULL; if (McastNSEC3Records) @@ -9447,7 +9413,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, if (AddToCFList) delay = NonZeroTime(m->timenow + mDNSPlatformOneSecond); else - delay = CheckForSoonToExpireRecords(m, m->rec.r.resrec.name, m->rec.r.resrec.namehash, slot, mDNSNULL); + delay = CheckForSoonToExpireRecords(m, m->rec.r.resrec.name, m->rec.r.resrec.namehash, mDNSNULL); // If unique, assume we may have to delay delivery of this 'add' event. // Below, where we walk the CacheFlushRecords list, we either call CacheRecordDeferredAdd() @@ -9513,8 +9479,8 @@ exit: while (CacheFlushRecords != (CacheRecord*)1) { CacheRecord *r1 = CacheFlushRecords, *r2; - const mDNSu32 slot = HashSlot(r1->resrec.name); - const CacheGroup *cg = CacheGroupForRecord(m, slot, &r1->resrec); + const mDNSu32 slot = HashSlotFromNameHash(r1->resrec.namehash); + const CacheGroup *cg = CacheGroupForRecord(m, &r1->resrec); CacheFlushRecords = CacheFlushRecords->NextInCFList; r1->NextInCFList = mDNSNULL; @@ -9664,7 +9630,7 @@ exit: NSECRecords = mDNSNULL; NSECCachePtr = mDNSNULL; } - r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash, slot, mDNSNULL); + r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash, mDNSNULL); // If no longer delaying, deliver answer now, else schedule delivery for the appropriate time if (!r1->DelayDelivery) CacheRecordDeferredAdd(m, r1); else ScheduleNextCacheCheckTime(m, slot, r1->DelayDelivery); @@ -10382,13 +10348,14 @@ mDNSlocal mDNSu32 mDNSGenerateOwnerOptForInterface(mDNS *const m, const mDNSInte mDNSu8 *end = mDNSNULL; mDNSu32 length = 0; AuthRecord opt; + NetworkInterfaceInfo *intf; mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); opt.resrec.rrclass = NormalMaxDNSMessageData; opt.resrec.rdlength = sizeof(rdataOPT); opt.resrec.rdestimate = sizeof(rdataOPT); - NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID); + intf = FirstInterfaceForID(m, InterfaceID); SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]); LogSPS("Generated OPT record : %s", ARDisplayString(m, &opt)); @@ -10405,30 +10372,18 @@ mDNSlocal mDNSu32 mDNSGenerateOwnerOptForInterface(mDNS *const m, const mDNSInte return length; } +// Note that this routine is called both for Sleep Proxy Registrations, and for Standard Dynamic +// DNS registrations, but (currently) only has to handle the Sleep Proxy Registration reply case, +// and should ignore Standard Dynamic DNS registration replies, because those are handled elsewhere. +// Really, both should be unified and handled in one place. mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *end, const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID) { if (InterfaceID) { - mDNSu32 updatelease = 60 * 60; // If SPS fails to indicate lease time, assume one hour - const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space); - mDNSAddr spsaddr; - char *ifname; - if (ptr) - { - ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec); - if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_OPT) - { - const rdataOPT *o; - const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength]; - for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++) - if (o->opt == kDNSOpt_Lease) - { - updatelease = o->u.updatelease; - LogSPS("Sleep Proxy granted lease time %4d seconds, updateid %d, InterfaceID %p", updatelease, mDNSVal16(msg->h.id), InterfaceID); - } - } - m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it - } + mDNSu32 pktlease = 0, spsupdates = 0; + const mDNSBool gotlease = GetPktLease(m, msg, end, &pktlease); + const mDNSu32 updatelease = gotlease ? pktlease : 60 * 60; // If SPS fails to indicate lease time, assume one hour + if (gotlease) LogSPS("DNS Update response contains lease option granting %4d seconds, updateid %d, InterfaceID %p", updatelease, mDNSVal16(msg->h.id), InterfaceID); if (m->CurrentRecord) LogMsg("mDNSCoreReceiveUpdateR ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); @@ -10447,7 +10402,8 @@ mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg if (mDNSOpaque64IsZero(&rr->updateIntID)) rr->updateid = zeroID; rr->expire = NonZeroTime(m->timenow + updatelease * mDNSPlatformOneSecond); - LogSPS("Sleep Proxy %s record %5d 0x%x 0x%x (%d) %s", rr->WakeUp.HMAC.l[0] ? "transferred" : "registered", updatelease, rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr)); + spsupdates++; + LogSPS("Sleep Proxy %s record %2d %5d 0x%x 0x%x (%d) %s", rr->WakeUp.HMAC.l[0] ? "transferred" : "registered", spsupdates, updatelease, rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr)); if (rr->WakeUp.HMAC.l[0]) { rr->WakeUp.HMAC = zeroEthAddr; // Clear HMAC so that mDNS_Deregister_internal doesn't waste packets trying to wake this host @@ -10460,22 +10416,26 @@ mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now m->CurrentRecord = rr->next; } - - // Update the dynamic store with the IP Address and MAC address of the sleep proxy - ifname = InterfaceNameForID(m, InterfaceID); - mDNSPlatformMemCopy(&spsaddr, srcaddr, sizeof (mDNSAddr)); - mDNSPlatformStoreSPSMACAddr(&spsaddr, ifname); - - // Store the Owner OPT record for this interface. - // Configd may use the OPT record if it detects a conflict with the BSP when the system wakes up - DNSMessage optMsg; - int length = 0; - InitializeDNSMessage(&optMsg.h, zeroID, ResponseFlags); - length = mDNSGenerateOwnerOptForInterface(m, InterfaceID, &optMsg); - if (length != 0) + if (spsupdates) // Only do this dynamic store stuff if this was, in fact, a Sleep Proxy Update response { - length += sizeof(DNSMessageHeader); - mDNSPlatformStoreOwnerOptRecord(ifname, &optMsg, length); + char *ifname; + mDNSAddr spsaddr; + DNSMessage optMsg; + int length; + // Update the dynamic store with the IP Address and MAC address of the sleep proxy + ifname = InterfaceNameForID(m, InterfaceID); + mDNSPlatformMemCopy(&spsaddr, srcaddr, sizeof (mDNSAddr)); + mDNSPlatformStoreSPSMACAddr(&spsaddr, ifname); + + // Store the Owner OPT record for this interface. + // Configd may use the OPT record if it detects a conflict with the BSP when the system wakes up + InitializeDNSMessage(&optMsg.h, zeroID, ResponseFlags); + length = mDNSGenerateOwnerOptForInterface(m, InterfaceID, &optMsg); + if (length != 0) + { + length += sizeof(DNSMessageHeader); + mDNSPlatformStoreOwnerOptRecord(ifname, &optMsg, length); + } } } // If we were waiting to go to sleep, then this SPS registration or wide-area record deletion @@ -10512,12 +10472,6 @@ mDNSexport void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr, cr->CRActiveQuestion = mDNSNULL; cr->UnansweredQueries = 0; cr->LastUnansweredTime = 0; -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - cr->MPUnansweredQ = 0; - cr->MPLastUnansweredQT = 0; - cr->MPUnansweredKA = 0; - cr->MPExpectingKA = mDNSfalse; -#endif cr->NextInCFList = mDNSNULL; cr->nsec = mDNSNULL; cr->soa = mDNSNULL; @@ -10595,7 +10549,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNS // Track the number of multicast packets received from a source outside our subnet. // Check the destination address to avoid accounting for spurious packets that // comes in with message id zero. - if (!mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr) && + if (!mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr) && dstaddr && mDNSAddressIsAllDNSLinkGroup(dstaddr)) { m->RemoteSubnet++; @@ -10624,8 +10578,8 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNS { static int msgCount = 0; if (msgCount < 1000) { - msgCount++; int i = 0; + msgCount++; LogInfo("Unknown DNS packet type %02X%02X from %#-15a:%-5d to %#-15a:%-5d length %d on %p (ignored)", msg->h.flags.b[0], msg->h.flags.b[1], srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), (int)(end - pkt), InterfaceID); while (i < (int)(end - pkt)) @@ -10658,6 +10612,11 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNS #define SameQTarget(A,B) (((A)->Target.type == mDNSAddrType_None && (B)->Target.type == mDNSAddrType_None) || \ (mDNSSameAddress(& (A)->Target, & (B)->Target) && mDNSSameIPPort((A)->TargetPort, (B)->TargetPort))) +// SameQuestionKind is true if *both* questions are either multicast or unicast +// TargetQID is used for this determination. +#define SameQuestionKind(A,B) ((mDNSOpaque16IsZero(A) && mDNSOpaque16IsZero(B)) || \ + ((!mDNSOpaque16IsZero(A)) && (!mDNSOpaque16IsZero(B)))) + // Note: We explicitly disallow making a public query be a duplicate of a private one. This is to avoid the // circular deadlock where a client does a query for something like "dns-sd -Q _dns-query-tls._tcp.company.com SRV" // and we have a key for company.com, so we try to locate the private query server for company.com, which necessarily entails @@ -10701,8 +10660,9 @@ mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuest (q->DisallowPID == question->DisallowPID) && // Disallowing a PID should not affect a PID that is allowed (q->BrowseThreshold == question->BrowseThreshold) && // browse thresholds must match q->qnamehash == question->qnamehash && - (IsAWDLIncluded(q) == IsAWDLIncluded(question)) && // Inclusion of AWDL interface must match - SameDomainName(&q->qname, &question->qname)) // and name + (IsAWDLIncluded(q) == IsAWDLIncluded(question)) && // Inclusion of AWDL interface must match + SameQuestionKind(q->TargetQID, question->TargetQID) && // mDNS or uDNS must match + SameDomainName(&q->qname, &question->qname)) // and name return(q); return(mDNSNULL); } @@ -11007,7 +10967,7 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) mDNSu32 timeout = 0; mDNSBool DEQuery; - question->validDNSServers = zeroOpaque64; + question->validDNSServers = zeroOpaque128; DEQuery = DomainEnumQuery(&question->qname); for (curr = m->DNSServers; curr; curr = curr->next) { @@ -11036,6 +10996,7 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) currcount = CountLabels(&curr->domain); if ((!curr->cellIntf || (!DEQuery && !(question->flags & kDNSServiceFlagsDenyCellular))) && + (!curr->isExpensive || !(question->flags & kDNSServiceFlagsDenyExpensive)) && DNSServerMatch(curr, question->InterfaceID, question->ServiceID)) { bettermatch = BetterMatchForName(&question->qname, namecount, &curr->domain, currcount, bestmatchlen); @@ -11050,7 +11011,7 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) if (bettermatch) { debugf("SetValidDNSServers: Resetting all the bits"); - question->validDNSServers = zeroOpaque64; + question->validDNSServers = zeroOpaque128; timeout = 0; } debugf("SetValidDNSServers: question %##s Setting the bit for DNS server Address %#a (Domain %##s), Scoped:%d index %d," @@ -11059,15 +11020,15 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) timeout += curr->timeout; if (DEQuery) debugf("DomainEnumQuery: Question %##s, DNSServer %#a, cell %d", question->qname.c, &curr->addr, curr->cellIntf); - bit_set_opaque64(question->validDNSServers, index); + bit_set_opaque128(question->validDNSServers, index); } } index++; } question->noServerResponse = 0; - debugf("SetValidDNSServers: ValidDNSServer bits 0x%x%x for question %p %##s (%s)", - question->validDNSServers.l[1], question->validDNSServers.l[0], question, question->qname.c, DNSTypeName(question->qtype)); + debugf("SetValidDNSServers: ValidDNSServer bits 0x%x%x%x%x for question %p %##s (%s)", + question->validDNSServers.l[3], question->validDNSServers.l[2], question->validDNSServers.l[1], question->validDNSServers.l[0], question, question->qname.c, DNSTypeName(question->qtype)); // If there are no matching resolvers, then use the default timeout value. // For ProxyQuestion, shorten the timeout so that dig does not timeout on us in case of no response. return ((question->ProxyQuestion || question->ValidatingResponse) ? DEFAULT_UDNSSEC_TIMEOUT : timeout ? timeout : DEFAULT_UDNS_TIMEOUT); @@ -11075,7 +11036,7 @@ mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) // Get the Best server that matches a name. If you find penalized servers, look for the one // that will come out of the penalty box soon -mDNSlocal DNSServer *GetBestServer(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID, mDNSs32 ServiceID, mDNSOpaque64 validBits, +mDNSlocal DNSServer *GetBestServer(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID, mDNSs32 ServiceID, mDNSOpaque128 validBits, int *selected, mDNSBool nameMatch) { DNSServer *curmatch = mDNSNULL; @@ -11154,7 +11115,7 @@ mDNSlocal DNSServer *GetServerForName(mDNS *m, const domainname *name, mDNSInter { DNSServer *curmatch = mDNSNULL; char *ifname = mDNSNULL; // for logging purposes only - mDNSOpaque64 allValid; + mDNSOpaque128 allValid; if ((InterfaceID == mDNSInterface_Unicast) || (InterfaceID == mDNSInterface_LocalOnly)) InterfaceID = mDNSNULL; @@ -11162,7 +11123,7 @@ mDNSlocal DNSServer *GetServerForName(mDNS *m, const domainname *name, mDNSInter if (InterfaceID) ifname = InterfaceNameForID(m, InterfaceID); // By passing in all ones, we make sure that every DNS server is considered - allValid.l[0] = allValid.l[1] = 0xFFFFFFFF; + allValid.l[0] = allValid.l[1] = allValid.l[2] = allValid.l[3] = 0xFFFFFFFF; curmatch = GetBestServer(m, name, InterfaceID, ServiceID, allValid, mDNSNULL, mDNStrue); @@ -11191,11 +11152,11 @@ mDNSexport DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question) if (InterfaceID) ifname = InterfaceNameForID(m, InterfaceID); - if (!mDNSOpaque64IsZero(&question->validDNSServers)) + if (!mDNSOpaque128IsZero(&question->validDNSServers)) { curmatch = GetBestServer(m, name, InterfaceID, question->ServiceID, question->validDNSServers, &currindex, mDNSfalse); if (currindex != -1) - bit_clr_opaque64(question->validDNSServers, currindex); + bit_clr_opaque128(question->validDNSServers, currindex); } if (curmatch != mDNSNULL) @@ -11289,6 +11250,13 @@ mDNSlocal mDNSBool ShouldSuppressUnicastQuery(mDNS *const m, DNSQuestion *q, DNS DNSTypeName(q->qtype), d->domain.c, &d->addr, mDNSVal16(d->port)); return mDNSfalse; } +#if USE_DNS64 + if (DNS64IsQueryingARecord(q->dns64.state)) + { + LogInfo("ShouldSuppressUnicastQuery: DNS64 query not suppressed for %##s, qtype %s", q->qname.c, DNSTypeName(q->qtype)); + return mDNSfalse; + } +#endif LogInfo("ShouldSuppressUnicastQuery: Query suppressed for %##s, qtype %s, since DNS Configuration does not allow (req_A is %s and req_AAAA is %s)", q->qname.c, DNSTypeName(q->qtype), d->req_A ? "true" : "false", d->req_AAAA ? "true" : "false"); @@ -11384,11 +11352,9 @@ mDNSlocal mDNSBool ShouldSuppressQuery(mDNS *const m, DNSQuestion *q) mDNSlocal void CacheRecordRmvEventsForCurrentQuestion(mDNS *const m, DNSQuestion *q) { CacheRecord *rr; - mDNSu32 slot; CacheGroup *cg; - slot = HashSlot(&q->qname); - cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + cg = CacheGroupForName(m, q->qnamehash, &q->qname); for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) { // Don't deliver RMV events for negative records @@ -11445,7 +11411,6 @@ mDNSlocal mDNSBool IsQuestionNew(mDNS *const m, DNSQuestion *question) mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q) { AuthRecord *rr; - mDNSu32 slot; AuthGroup *ag; if (m->CurrentQuestion) @@ -11458,8 +11423,7 @@ mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q return mDNStrue; } m->CurrentQuestion = q; - slot = AuthHashSlot(&q->qname); - ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname); + ag = AuthGroupForName(&m->rrauth, q->qnamehash, &q->qname); if (ag) { for (rr = ag->members; rr; rr=rr->next) @@ -11485,7 +11449,7 @@ mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q // Returns false if the question got deleted while delivering the RMV events // The caller should handle the case -mDNSlocal mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q) +mDNSexport mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q) { if (m->CurrentQuestion) LogMsg("CacheRecordRmvEventsForQuestion: ERROR m->CurrentQuestion already set: %##s (%s)", @@ -11684,33 +11648,29 @@ mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question) { // First reset all DNS Configuration question->qDNSServer = mDNSNULL; - question->validDNSServers = zeroOpaque64; + question->validDNSServers = zeroOpaque128; question->triedAllServersOnce = 0; question->noServerResponse = 0; - question->StopTime = 0; -#if TARGET_OS_EMBEDDED + question->StopTime = (question->TimeoutQuestion) ? question->StopTime : 0; +#if AWD_METRICS mDNSPlatformMemZero(&question->metrics, sizeof(question->metrics)); #endif - // Need not initialize the DNS Configuration for Local Only OR P2P Questions - if (LocalOnlyOrP2PInterface(question->InterfaceID)) + // Need not initialize the DNS Configuration for Local Only OR P2P Questions when timeout not specified + if (LocalOnlyOrP2PInterface(question->InterfaceID) && !question->TimeoutQuestion) return; // Proceed to initialize DNS Configuration (some are set in SetValidDNSServers()) if (!mDNSOpaque16IsZero(question->TargetQID)) { mDNSu32 timeout = SetValidDNSServers(m, question); - // We set the timeout whenever mDNS_StartQuery_internal is called. This means if we have - // a networking change/search domain change that calls this function again we keep - // reinitializing the timeout value which means it may never timeout. If this becomes - // a common case in the future, we can easily fix this by adding extra state that - // indicates that we have already set the StopTime. - // - // Note that we set the timeout for all questions. If this turns out to be a duplicate, + // We set the timeout value the first time mDNS_StartQuery_internal is called for a question. + // So if a question is restarted when a network change occurs, the StopTime is not reset. + // Note that we set the timeout for all questions. If this turns out to be a duplicate, // it gets a full timeout value even if the original question times out earlier. - if (question->TimeoutQuestion) + if (question->TimeoutQuestion && !question->StopTime) { question->StopTime = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond); - LogInfo("InitDNSConfig: Setting StopTime on question %p %##s (%s)", question, question->qname.c, DNSTypeName(question->qtype)); + LogInfo("InitDNSConfig: Setting StopTime on the uDNS question %p %##s (%s)", question, question->qname.c, DNSTypeName(question->qtype)); } question->qDNSServer = GetServerForQuestion(m, question); @@ -11719,17 +11679,22 @@ mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question) question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL, mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort)); } - else + else if (question->TimeoutQuestion && !question->StopTime) { - if (question->TimeoutQuestion) - question->StopTime = NonZeroTime(m->timenow + GetTimeoutForMcastQuestion(m, question) * mDNSPlatformOneSecond); + // If the question is to be timed out and its a multicast, local-only or P2P case, + // then set it's stop time. + mDNSu32 timeout = LocalOnlyOrP2PInterface(question->InterfaceID) ? + DEFAULT_LO_OR_P2P_TIMEOUT : GetTimeoutForMcastQuestion(m, question); + question->StopTime = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond); + LogInfo("InitDNSConfig: Setting StopTime on question %p %##s (%s)", question, question->qname.c, DNSTypeName(question->qtype)); } // Set StopTime here since it is a part of DNS Configuration if (question->StopTime) SetNextQueryStopTime(m, question); - // SetNextQueryTime() need not be initialized for LocalOnly OR P2P Questions since those questions - // will never be transmitted on the wire. Hence we call SetNextQueryTime() here. - SetNextQueryTime(m,question); + // Don't call SetNextQueryTime() if a LocalOnly OR P2P Question since those questions + // will never be transmitted on the wire. + if (!(LocalOnlyOrP2PInterface(question->InterfaceID))) + SetNextQueryTime(m,question); } // InitCommonState() is called by mDNS_StartQuery_internal() to initialize the common(uDNS/mDNS) internal @@ -11755,7 +11720,7 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) // turned ON which can allocate memory e.g., base64 encoding, in the case of DNSSEC. question->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question question->qnamehash = DomainNameHashValue(&question->qname); - question->DelayAnswering = CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash, HashSlot(&question->qname), &purge); + question->DelayAnswering = CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash, &purge); question->LastQTime = m->timenow; question->ExpectUnicastResp = 0; question->LastAnswerPktNum = m->PktNum; @@ -11792,7 +11757,7 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) if (!(question->flags & kDNSServiceFlagsServiceIndex)) { #if APPLE_OSX_mDNSResponder - mDNSPlatformGetDNSRoutePolicy(m, question, &isBlocked); + mDNSPlatformGetDNSRoutePolicy(question, &isBlocked); #else question->ServiceID = -1; #endif @@ -11897,10 +11862,12 @@ mDNSlocal void InitLLQState(DNSQuestion *const question) question->id = zeroOpaque64; } +#ifdef DNS_PUSH_ENABLED mDNSlocal void InitDNSPNState(DNSQuestion *const question) { question->dnsPushState = DNSPUSH_INIT; } +#endif // DNS_PUSH_ENABLED // InitDNSSECProxyState() is called by mDNS_StartQuery_internal() to initialize // DNSSEC & DNS Proxy fields of the DNS Question. @@ -11941,6 +11908,16 @@ mDNSlocal void FinalizeUnicastQuestion(mDNS *const m, DNSQuestion *question, mDN if (question->DuplicateOf) { question->validDNSServers = question->DuplicateOf->validDNSServers; + // If current(dup) question has DNS Server assigned but the original question has no DNS Server assigned to it, + // then we log a line as it could indicate an issue + if (question->DuplicateOf->qDNSServer == mDNSNULL) + { + if (question->qDNSServer) + LogInfo("FinalizeUnicastQuestion: Current(dup) question %p has DNSServer(%#a:%d) but original question(%p) has no DNS Server! %##s (%s)", + question, question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL, + mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zeroIPPort), + question->DuplicateOf, question->qname.c, DNSTypeName(question->qtype)); + } question->qDNSServer = question->DuplicateOf->qDNSServer; LogInfo("FinalizeUnicastQuestion: Duplicate question %p (%p) %##s (%s), DNS Server %#a:%d", question, question->DuplicateOf, question->qname.c, DNSTypeName(question->qtype), @@ -12031,7 +12008,9 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu purge = InitCommonState(m, question); InitWABState(question); InitLLQState(question); +#ifdef DNS_PUSH_ENABLED InitDNSPNState(question); +#endif // DNS_PUSH_ENABLED InitDNSSECProxyState(m, question); // FindDuplicateQuestion should be called last after all the intialization @@ -12108,8 +12087,7 @@ mDNSexport void CancelGetZoneData(mDNS *const m, ZoneData *nta) mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question) { - const mDNSu32 slot = HashSlot(&question->qname); - CacheGroup *cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname); + CacheGroup *cg = CacheGroupForName(m, question->qnamehash, &question->qname); CacheRecord *rr; DNSQuestion **qp = &m->Questions; @@ -12139,24 +12117,16 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que } #endif // BONJOUR_ON_DEMAND -#if TARGET_OS_EMBEDDED +#if AWD_METRICS if (Question_uDNS(question) && !question->metrics.answered && (question->metrics.querySendCount > 0)) { const domainname * queryName; mDNSBool isForCell; mDNSu32 durationMs; - queryName = question->metrics.originalQName ? question->metrics.originalQName : &question->qname; - isForCell = (question->qDNSServer && question->qDNSServer->cellIntf); - - if (question->metrics.querySendCount > 0) - { - durationMs = ((m->timenow - question->metrics.firstQueryTime) * 1000) / mDNSPlatformOneSecond; - } - else - { - durationMs = 0; - } + queryName = question->metrics.originalQName ? question->metrics.originalQName : &question->qname; + isForCell = (question->qDNSServer && question->qDNSServer->cellIntf); + durationMs = ((m->timenow - question->metrics.firstQueryTime) * 1000) / mDNSPlatformOneSecond; MetricsUpdateUDNSQueryStats(queryName, question->qtype, mDNSNULL, question->metrics.querySendCount, durationMs, isForCell); } #endif @@ -12279,6 +12249,7 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que question->tcp = mDNSNULL; } } +#ifdef DNS_PUSH_ENABLED else if (question->dnsPushState == DNSPUSH_ESTABLISHED) { if (question->tcp) @@ -12288,6 +12259,7 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que question->tcp = mDNSNULL; } } +#endif // DNS_PUSH_ENABLED #if APPLE_OSX_mDNSResponder UpdateAutoTunnelDomainStatuses(m); #endif @@ -12306,7 +12278,7 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que FreeAnonInfo(question->AnonInfo); question->AnonInfo = mDNSNULL; } -#if TARGET_OS_EMBEDDED +#if AWD_METRICS if (question->metrics.originalQName) { mDNSPlatformMemFree(question->metrics.originalQName); @@ -12314,6 +12286,10 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que } #endif +#if USE_DNS64 + DNS64ResetState(question); +#endif + return(mStatus_NoError); } @@ -12352,8 +12328,7 @@ mDNSexport mStatus mDNS_StopQueryWithRemoves(mDNS *const m, DNSQuestion *const q if (status == mStatus_NoError && !qq) { const CacheRecord *rr; - const mDNSu32 slot = HashSlot(&question->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname); + CacheGroup *const cg = CacheGroupForName(m, question->qnamehash, &question->qname); LogInfo("Generating terminal removes for %##s (%s)", question->qname.c, DNSTypeName(question->qtype)); for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) if (rr->resrec.RecordType != kDNSRecordTypePacketNegative && SameNameRecordAnswersQuestion(&rr->resrec, question)) @@ -12585,6 +12560,8 @@ mDNSlocal NetworkInterfaceInfo *FindFirstAdvertisedInterface(mDNS *const m) return(intf); } +// The parameter "set" here refers to the set of AuthRecords used to advertise this interface. +// (It's a set of records, not a set of interfaces.) mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) { char buffer[MAX_REVERSE_MAPPING_NAME]; @@ -12599,6 +12576,8 @@ mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) primary = FindFirstAdvertisedInterface(m); if (!primary) primary = set; // If no existing advertised interface, this new NetworkInterfaceInfo becomes our new primary + // We should never have primary be NULL, because even if there is + // no other interface yet, we should always find ourself in the list. // If interface is marked as a direct link, we can assume the address record is unique // and does not need to go through the probe phase of the probe/announce packet sequence. @@ -12608,9 +12587,9 @@ mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) LogInfo("AdvertiseInterface: Marking address record as kDNSRecordTypeKnownUnique for %s", set->ifname); // Send dynamic update for non-linklocal IPv4 Addresses - mDNS_SetupResourceRecord(&set->RR_A, mDNSNULL, set->InterfaceID, kDNSType_A, kHostNameTTL, recordType, AuthRecordAny, mDNS_HostNameCallback, set); - mDNS_SetupResourceRecord(&set->RR_PTR, mDNSNULL, set->InterfaceID, kDNSType_PTR, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); - mDNS_SetupResourceRecord(&set->RR_HINFO, mDNSNULL, set->InterfaceID, kDNSType_HINFO, kHostNameTTL, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL); + mDNS_SetupResourceRecord(&set->RR_A, mDNSNULL, set->InterfaceID, kDNSType_A, kHostNameTTL, recordType, AuthRecordAny, mDNS_HostNameCallback, set); + mDNS_SetupResourceRecord(&set->RR_PTR, mDNSNULL, set->InterfaceID, kDNSType_PTR, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); + mDNS_SetupResourceRecord(&set->RR_HINFO, mDNSNULL, set->InterfaceID, kDNSType_HINFO, kHostNameTTL, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL); #if ANSWER_REMOTE_HOSTNAME_QUERIES set->RR_A.AllowRemoteQuery = mDNStrue; @@ -12907,7 +12886,7 @@ mDNSexport void mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceI } } -mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping) +mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed activationSpeed) { AuthRecord *rr; mDNSBool FirstOfType = mDNStrue; @@ -12978,32 +12957,56 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s // We don't want to do a probe, and then see a stale echo of an announcement we ourselves sent, // and think it's a conflicting answer to our probe. // In the case of a flapping interface, we pause for five seconds, and reduce the announcement count to one packet. - const mDNSs32 probedelay = flapping ? mDNSPlatformOneSecond * 5 : mDNSPlatformOneSecond / 2; - const mDNSu8 numannounce = flapping ? (mDNSu8)1 : InitialAnnounceCount; + mDNSs32 probedelay; + mDNSu8 numannounce; + switch (activationSpeed) + { + case FastActivation: + probedelay = (mDNSs32)0; + numannounce = InitialAnnounceCount; + LogMsg("mDNS_RegisterInterface: Using fast activation for DirectLink interface %s (%#a)", set->ifname, &set->ip); + break; - // Use a small amount of randomness: - // In the case of a network administrator turning on an Ethernet hub so that all the - // connected machines establish link at exactly the same time, we don't want them all - // to go and hit the network with identical queries at exactly the same moment. - // We set a random delay of up to InitialQuestionInterval (1/3 second). - // We must *never* set m->SuppressSending to more than that (or set it repeatedly in a way - // that causes mDNSResponder to remain in a prolonged state of SuppressSending, because - // suppressing packet sending for more than about 1/3 second can cause protocol correctness - // to start to break down (e.g. we don't answer probes fast enough, and get name conflicts). - // See <rdar://problem/4073853> mDNS: m->SuppressSending set too enthusiastically - if (!m->SuppressSending) m->SuppressSending = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval); + case SlowActivation: + probedelay = mDNSPlatformOneSecond * 5; + numannounce = (mDNSu8)1; + LogMsg("mDNS_RegisterInterface: Frequent transitions for interface %s (%#a), doing slow activation", set->ifname, &set->ip); + m->mDNSStats.InterfaceUpFlap++; + break; - if (flapping) - { - LogMsg("mDNS_RegisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip); - m->mDNSStats.InterfaceUpFlap++; + case NormalActivation: + default: + probedelay = mDNSPlatformOneSecond / 2; + numannounce = InitialAnnounceCount; + break; } LogInfo("mDNS_RegisterInterface: %s (%#a) probedelay %d", set->ifname, &set->ip, probedelay); - if (m->SuppressProbes == 0 || - m->SuppressProbes - NonZeroTime(m->timenow + probedelay) < 0) - m->SuppressProbes = NonZeroTime(m->timenow + probedelay); + // No probe or sending suppression on DirectLink type interfaces. + if (activationSpeed == FastActivation) + { + m->SuppressSending = 0; + m->SuppressProbes = 0; + } + else + { + // Use a small amount of randomness: + // In the case of a network administrator turning on an Ethernet hub so that all the + // connected machines establish link at exactly the same time, we don't want them all + // to go and hit the network with identical queries at exactly the same moment. + // We set a random delay of up to InitialQuestionInterval (1/3 second). + // We must *never* set m->SuppressSending to more than that (or set it repeatedly in a way + // that causes mDNSResponder to remain in a prolonged state of SuppressSending, because + // suppressing packet sending for more than about 1/3 second can cause protocol correctness + // to start to break down (e.g. we don't answer probes fast enough, and get name conflicts). + // See <rdar://problem/4073853> mDNS: m->SuppressSending set too enthusiastically + if (!m->SuppressSending) m->SuppressSending = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval); + + if (m->SuppressProbes == 0 || + m->SuppressProbes - NonZeroTime(m->timenow + probedelay) < 0) + m->SuppressProbes = NonZeroTime(m->timenow + probedelay); + } // Include OWNER option in packets for 60 seconds after connecting to the network. Setting // it here also handles the wake up case as the network link comes UP after waking causing @@ -13020,10 +13023,10 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s if (!q->InterfaceID || q->InterfaceID == set->InterfaceID) // If non-specific Q, or Q on this specific interface, { // then reactivate this question // If flapping, delay between first and second queries is nine seconds instead of one second - mDNSBool dodelay = flapping && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID); + mDNSBool dodelay = (activationSpeed == SlowActivation) && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID); mDNSs32 initial = dodelay ? InitialQuestionInterval * QuestionIntervalStep2 : InitialQuestionInterval; - mDNSs32 qdelay = dodelay ? mDNSPlatformOneSecond * 5 : 0; - if (dodelay) LogInfo("No cache records expired for %##s (%s); okay to delay questions a little", q->qname.c, DNSTypeName(q->qtype)); + mDNSs32 qdelay = dodelay ? kDefaultQueryDelayTimeForFlappingInterface : 0; + if (dodelay) LogInfo("No cache records expired for %##s (%s); delaying questions by %d seconds", q->qname.c, DNSTypeName(q->qtype), qdelay); if (!q->ThisQInterval || q->ThisQInterval > initial) { @@ -13066,7 +13069,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s // Note: mDNS_DeregisterInterface calls mDNS_Deregister_internal which can call a user callback, which may change // the record list and/or question list. // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. -mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping) +mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed activationSpeed) { NetworkInterfaceInfo **p = &m->HostInterfaces; mDNSBool revalidate = mDNSfalse; @@ -13126,7 +13129,7 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se m->mDNSStats.InterfaceDown++; - if (set->McastTxRx && flapping) + if (set->McastTxRx && (activationSpeed == SlowActivation)) { LogMsg("mDNS_DeregisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip); m->mDNSStats.InterfaceDownFlap++; @@ -13152,9 +13155,10 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se { // If this interface is deemed flapping, // postpone deleting the cache records in case the interface comes back again - if (set->McastTxRx && flapping) + if (set->McastTxRx && (activationSpeed == SlowActivation)) { - // For a flapping interface we want these record to go away after 30 seconds + // For a flapping interface we want these records to go away after + // kDefaultReconfirmTimeForFlappingInterface seconds if they are not reconfirmed. mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface); // We set UnansweredQueries = MaxUnansweredQueries so we don't waste time doing any queries for them -- // if the interface does come back, any relevant questions will be reactivated anyway @@ -13314,10 +13318,7 @@ mDNSlocal void NSSCallback(mDNS *const m, AuthRecord *const rr, mStatus result) } -// Derive AuthRecType from the coreFlag* values. -// Note, this is not using the external flags values, kDNSServiceFlags*, defined in dns_sd.h. -// It should be changed to do so once the use of coreFlag* is completely replaced with -// the use the kDNSServiceFlags* definitions within mDNSResponder. +// Derive AuthRecType from the kDNSServiceFlags* values. mDNSlocal AuthRecType setAuthRecType(mDNSInterfaceID InterfaceID, mDNSu32 flags) { AuthRecType artype; @@ -13326,12 +13327,12 @@ mDNSlocal AuthRecType setAuthRecType(mDNSInterfaceID InterfaceID, mDNSu32 flags) artype = AuthRecordLocalOnly; else if (InterfaceID == mDNSInterface_P2P || InterfaceID == mDNSInterface_BLE) artype = AuthRecordP2P; - else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeP2P) - && (flags & coreFlagIncludeAWDL)) + else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P) + && (flags & kDNSServiceFlagsIncludeAWDL)) artype = AuthRecordAnyIncludeAWDLandP2P; - else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeP2P)) + else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeP2P)) artype = AuthRecordAnyIncludeP2P; - else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeAWDL)) + else if ((InterfaceID == mDNSInterface_Any) && (flags & kDNSServiceFlagsIncludeAWDL)) artype = AuthRecordAnyIncludeAWDL; else artype = AuthRecordAny; @@ -13370,7 +13371,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr, mDNSu32 i; mDNSu32 hostTTL; AuthRecType artype; - mDNSu8 recordType = (flags & coreFlagKnownUnique) ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique; + mDNSu8 recordType = (flags & kDNSServiceFlagsKnownUnique) ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique; sr->ServiceCallback = Callback; sr->ServiceContext = Context; @@ -13388,7 +13389,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr, mDNS_SetupResourceRecord(&sr->RR_ADV, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeAdvisory, artype, ServiceCallback, sr); mDNS_SetupResourceRecord(&sr->RR_PTR, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared, artype, ServiceCallback, sr); - if (flags & coreFlagWakeOnly) + if (flags & kDNSServiceFlagsWakeOnlyService) { sr->RR_PTR.AuthFlags = AuthFlagsWakeOnly; } @@ -13399,7 +13400,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr, hostTTL = kHostNameTTL; mDNS_SetupResourceRecord(&sr->RR_SRV, mDNSNULL, InterfaceID, kDNSType_SRV, hostTTL, recordType, artype, ServiceCallback, sr); - mDNS_SetupResourceRecord(&sr->RR_TXT, mDNSNULL, InterfaceID, kDNSType_TXT, kStandardTTL, kDNSRecordTypeUnique, artype, ServiceCallback, sr); + mDNS_SetupResourceRecord(&sr->RR_TXT, mDNSNULL, InterfaceID, kDNSType_TXT, kStandardTTL, recordType, artype, ServiceCallback, sr); // If port number is zero, that means the client is really trying to do a RegisterNoSuchService if (mDNSIPPortIsZero(port)) @@ -13841,7 +13842,7 @@ mDNSlocal void mDNSCoreReceiveRawARP(mDNS *const m, const ARP_EthIP *const arp, } else if (msg == msg3) { - mDNSPlatformSetLocalAddressCacheEntry(m, &rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID); + mDNSPlatformSetLocalAddressCacheEntry(&rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID); } else if (msg == msg4) { @@ -13947,7 +13948,7 @@ mDNSlocal void mDNSCoreReceiveRawND(mDNS *const m, const mDNSEthAddr *const sha, LogSPS("Reached maximum number of restarts for probing - %s", ARDisplayString(m,rr)); } else if (msg == msg3) - mDNSPlatformSetLocalAddressCacheEntry(m, &rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID); + mDNSPlatformSetLocalAddressCacheEntry(&rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID); else if (msg == msg4) SendNDP(m, NDP_Adv, NDP_Solicited, rr, &ndp->target, mDNSNULL, spa, sha); else if (msg == msg5) @@ -14286,7 +14287,7 @@ mDNSexport void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, m { if (!m->SPSSocket) { - m->SPSSocket = mDNSPlatformUDPSocket(m, zeroIPPort); + m->SPSSocket = mDNSPlatformUDPSocket(zeroIPPort); if (!m->SPSSocket) { LogMsg("mDNSCoreBeSleepProxyServer: Failed to allocate SPSSocket"); goto fail; } } #ifndef SPC_DISABLED @@ -14328,9 +14329,9 @@ mDNSexport void mDNS_GrowCache(mDNS *const m, CacheEntity *storage, mDNSu32 numr mDNS_Unlock(m); } -mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, - CacheEntity *rrcachestorage, mDNSu32 rrcachesize, - mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context) +mDNSlocal mStatus mDNS_InitStorage(mDNS *const m, mDNS_PlatformSupport *const p, + CacheEntity *rrcachestorage, mDNSu32 rrcachesize, + mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context) { mDNSu32 slot; mDNSs32 timenow; @@ -14370,14 +14371,14 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->timenow_last = timenow; m->NextScheduledEvent = timenow; m->SuppressSending = timenow; - m->NextCacheCheck = timenow + 0x78000000; - m->NextScheduledQuery = timenow + 0x78000000; - m->NextScheduledProbe = timenow + 0x78000000; - m->NextScheduledResponse = timenow + 0x78000000; - m->NextScheduledNATOp = timenow + 0x78000000; - m->NextScheduledSPS = timenow + 0x78000000; - m->NextScheduledKA = timenow + 0x78000000; - m->NextScheduledStopTime = timenow + 0x78000000; + m->NextCacheCheck = timenow + FutureTime; + m->NextScheduledQuery = timenow + FutureTime; + m->NextScheduledProbe = timenow + FutureTime; + m->NextScheduledResponse = timenow + FutureTime; + m->NextScheduledNATOp = timenow + FutureTime; + m->NextScheduledSPS = timenow + FutureTime; + m->NextScheduledKA = timenow + FutureTime; + m->NextScheduledStopTime = timenow + FutureTime; m->NextBLEServiceTime = 0; // zero indicates inactive #if BONJOUR_ON_DEMAND @@ -14399,9 +14400,6 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->SleepLimit = 0; #if APPLE_OSX_mDNSResponder - m->StatStartTime = mDNSPlatformUTC(); - m->NextStatLogTime = m->StatStartTime + kDefaultNextStatsticsLogTime; - m->ActiveStatTime = 0; m->UnicastPacketsSent = 0; m->MulticastPacketsSent = 0; m->RemoteSubnet = 0; @@ -14424,7 +14422,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) { m->rrcache_hash[slot] = mDNSNULL; - m->rrcache_nextcheck[slot] = timenow + 0x78000000;; + m->rrcache_nextcheck[slot] = timenow + FutureTime;; } mDNS_GrowCache_internal(m, rrcachestorage, rrcachesize); @@ -14450,8 +14448,8 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->SuppressProbes = 0; #ifndef UNICAST_DISABLED - m->NextuDNSEvent = timenow + 0x78000000; - m->NextSRVUpdate = timenow + 0x78000000; + m->NextuDNSEvent = timenow + FutureTime; + m->NextSRVUpdate = timenow + FutureTime; m->DNSServers = mDNSNULL; @@ -14482,7 +14480,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, m->NATTraversals = mDNSNULL; m->CurrentNATTraversal = mDNSNULL; m->retryIntervalGetAddr = 0; // delta between time sent and retry - m->retryGetAddr = timenow + 0x78000000; // absolute time when we retry + m->retryGetAddr = timenow + FutureTime; // absolute time when we retry m->ExtAddress = zerov4Addr; m->PCPNonce[0] = mDNSRandom(-1); m->PCPNonce[1] = mDNSRandom(-1); @@ -14531,6 +14529,17 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, #endif + return(result); +} + +mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, + CacheEntity *rrcachestorage, mDNSu32 rrcachesize, + mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context) +{ + mStatus result = mDNS_InitStorage(m, p, rrcachestorage, rrcachesize, AdvertiseLocalAddresses, Callback, Context); + if (result != mStatus_NoError) + return(result); + result = mDNSPlatformInit(m); #ifndef UNICAST_DISABLED @@ -14604,8 +14613,7 @@ mDNSlocal void PurgeOrReconfirmCacheRecord(mDNS *const m, CacheRecord *cr, const mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q) { - const mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); CacheRecord *rp; mDNSu8 validatingResponse = 0; @@ -14640,8 +14648,7 @@ mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q) // them. mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q) { - const mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); CacheRecord *rp; for (rp = cg ? cg->members : mDNSNULL; rp; rp = rp->next) @@ -14664,8 +14671,7 @@ mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q) mDNSexport mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16 qtype) { DNSQuestion question; - const mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); CacheRecord *rp; // Create an identical question but with qtype @@ -14788,7 +14794,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) // hence we are ready to ack the configuration as this is the last call to mDNSPlatformSetConfig // for the dns configuration change notification. SetConfigState(m, mDNStrue); - if (!mDNSPlatformSetDNSConfig(m, mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL, mDNStrue)) + if (!mDNSPlatformSetDNSConfig(mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL, mDNStrue)) { SetDynDNSHostNameIfChanged(m, &fqdn); SetConfigState(m, mDNSfalse); @@ -14844,6 +14850,9 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) // cache records and as the resGroupID is different, you can't use the cache record from the scoped DNSServer to answer the // non-scoped question and vice versa. // +#if USE_DNS64 + DNS64RestartQuestions(m); +#endif for (q = m->Questions; q; q=q->next) { if (!mDNSOpaque16IsZero(q->TargetQID)) @@ -15007,7 +15016,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) { LogMsg("uDNS_SetupDNSConfig: ERROR!! Cache Record %s Active question %##s (%s) (scope:%p) pointing to DNSServer Address %#a" " to be freed", CRDisplayString(m, cr), qptr->qname.c, DNSTypeName(qptr->qtype), qptr->InterfaceID, &ptr->addr); - qptr->validDNSServers = zeroOpaque64; + qptr->validDNSServers = zeroOpaque128; qptr->qDNSServer = mDNSNULL; cr->resrec.rDNSServer = mDNSNULL; } @@ -15070,7 +15079,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) v4 = v6 = r = zeroAddr; v4.type = r.type = mDNSAddrType_IPv4; - if (mDNSPlatformGetPrimaryInterface(m, &v4, &v6, &r) == mStatus_NoError && !mDNSv4AddressIsLinkLocal(&v4.ip.v4)) + if (mDNSPlatformGetPrimaryInterface(&v4, &v6, &r) == mStatus_NoError && !mDNSv4AddressIsLinkLocal(&v4.ip.v4)) { mDNS_SetPrimaryInterfaceInfo(m, !mDNSIPv4AddressIsZero(v4.ip.v4) ? &v4 : mDNSNULL, @@ -15256,3 +15265,7 @@ mDNSexport void mDNS_FinalExit(mDNS *const m) LogInfo("mDNS_FinalExit: done"); } + +#ifdef UNIT_TEST +#include "../unittests/mdns_ut.c" +#endif diff --git a/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h b/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h index 81ade5c5..0e96058d 100755 --- a/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h +++ b/mDNSResponder/mDNSCore/mDNSEmbeddedAPI.h @@ -296,6 +296,11 @@ typedef mDNSOpaque48 mDNSEthAddr; // An Ethernet address is a six-byte opa #define bit_set_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY)))) #define bit_clr_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY)))) #define bit_get_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY)))) + +// Bit operations for opaque 128 bit quantity. Uses the 32 bit quantity(l[4]) to set and clear bits +#define bit_set_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY)))) +#define bit_clr_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY)))) +#define bit_get_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY)))) typedef enum { @@ -722,7 +727,7 @@ typedef packedstruct // Bit 6 (value 0x40) is set for answer records; clear for authority/additional records // Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet -enum +typedef enum { kDNSRecordTypeUnregistered = 0x00, // Not currently in any list kDNSRecordTypeDeregistering = 0x01, // Shared record about to announce its departure and leave the list @@ -750,7 +755,7 @@ enum kDNSRecordTypePacketNegative = 0xF0, // Pseudo-RR generated to cache non-existence results like NXDomain kDNSRecordTypePacketUniqueMask = 0x10 // True for PacketAddUnique, PacketAnsUnique, PacketAuthUnique, kDNSRecordTypePacketNegative -}; +} kDNSRecordTypes; typedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target; } rdataSRV; typedef packedstruct { mDNSu16 preference; domainname exchange; } rdataMX; @@ -1359,14 +1364,14 @@ typedef struct DNSServer mDNSs32 penaltyTime; // amount of time this server is penalized mDNSu32 scoped; // See the scoped enum above mDNSu32 timeout; // timeout value for questions - mDNSBool cellIntf; // Resolver from Cellular Interface ? mDNSu16 resGroupID; // ID of the resolver group that contains this DNSServer + mDNSu8 retransDO; // Total Retransmissions for queries sent with DO option + mDNSBool cellIntf; // Resolver from Cellular Interface? mDNSBool req_A; // If set, send v4 query (DNSConfig allows A queries) mDNSBool req_AAAA; // If set, send v6 query (DNSConfig allows AAAA queries) mDNSBool req_DO; // If set, okay to send DNSSEC queries (EDNS DO bit is supported) - mDNSBool retransDO; // Total Retransmissions for queries sent with DO option - mDNSBool DNSSECAware; // set if we are able to receive a response to a request - // sent with DO option. + mDNSBool DNSSECAware; // Set if we are able to receive a response to a request sent with DO option. + mDNSBool isExpensive; // True if the interface to this server is expensive. } DNSServer; typedef struct @@ -1380,9 +1385,9 @@ typedef struct struct ResourceRecord_struct { - mDNSu8 RecordType; // See enum above - mDNSu16 rrtype; - mDNSu16 rrclass; + mDNSu8 RecordType; // See kDNSRecordTypes enum. + mDNSu16 rrtype; // See DNS_TypeValues enum. + mDNSu16 rrclass; // See DNS_ClassValues enum. mDNSu32 rroriginalttl; // In seconds mDNSu16 rdlength; // Size of the raw rdata, in bytes, in the on-the-wire format // (In-memory storage may be larger, for structures containing 'holes', like SOA) @@ -1595,7 +1600,7 @@ struct AuthRecord_struct // Everywhere else in the code, the determination of whether a question is unicast is made by checking to see if TargetQID is nonzero. #define AuthRecord_uDNS(R) ((R)->resrec.InterfaceID == mDNSInterface_Any && !(R)->ForceMCast && !IsLocalDomain((R)->resrec.name)) #define Question_uDNS(Q) ((Q)->InterfaceID == mDNSInterface_Unicast || (Q)->ProxyQuestion || \ - ((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname))) + ((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && (Q)->InterfaceID != mDNSInterface_BLE && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname))) // AuthRecordLocalOnly records are registered using mDNSInterface_LocalOnly and // AuthRecordP2P records are created by D2DServiceFound events. Both record types are kept on the same list. @@ -1639,12 +1644,6 @@ struct CacheRecord_struct mDNSu8 UnansweredQueries; // Number of times we've issued a query for this record without getting an answer mDNSu8 CRDNSSECQuestion; // Set to 1 if this was created in response to a DNSSEC question mDNSOpaque16 responseFlags; // Second 16 bit in the DNS response -#if ENABLE_MULTI_PACKET_QUERY_SNOOPING - mDNSu32 MPUnansweredQ; // Multi-packet query handling: Number of times we've seen a query for this record - mDNSs32 MPLastUnansweredQT; // Multi-packet query handling: Last time we incremented MPUnansweredQ - mDNSu32 MPUnansweredKA; // Multi-packet query handling: Number of times we've seen this record in a KA list - mDNSBool MPExpectingKA; // Multi-packet query handling: Set when we increment MPUnansweredQ; allows one KA -#endif CacheRecord *NextInCFList; // Set if this is in the list of records we just received with the cache flush bit set CacheRecord *nsec; // NSEC records needed for non-existence proofs CacheRecord *soa; // SOA record to return for proxy questions @@ -1897,7 +1896,9 @@ typedef enum { DNSSECValNotRequired = 0, DNSSECValRequired, DNSSECValInProgress, // RFC 4122 defines it to be 16 bytes #define UUID_SIZE 16 -#if TARGET_OS_EMBEDDED +#define AWD_METRICS (USE_AWD && TARGET_OS_EMBEDDED) + +#if AWD_METRICS typedef struct { domainname * originalQName; // Name of original A/AAAA record if this question is for a CNAME record. @@ -1906,10 +1907,18 @@ typedef struct mDNSBool answered; // Has this question been answered? } uDNSMetrics; - +#endif + +// DNS64 code is only for iOS, which is currently the only Apple OS that supports DNS proxy network extensions. +#define USE_DNS64 (HAVE_DNS64 && TARGET_OS_IOS) + +#if USE_DNS64 +#include "DNS64State.h" +#endif + +#if TARGET_OS_EMBEDDED extern mDNSu32 curr_num_regservices; // tracks the current number of services registered extern mDNSu32 max_num_regservices; // tracks the max number of simultaneous services registered by the device - #endif struct DNSQuestion_struct @@ -1964,7 +1973,7 @@ struct DNSQuestion_struct // |-> DNS Configuration related fields used in uDNS (Subset of Wide Area/Unicast fields) DNSServer *qDNSServer; // Caching server for this query (in the absence of an SRV saying otherwise) - mDNSOpaque64 validDNSServers; // Valid DNSServers for this question + mDNSOpaque128 validDNSServers; // Valid DNSServers for this question mDNSu16 noServerResponse; // At least one server did not respond. mDNSu16 triedAllServersOnce; // Tried all DNS servers once mDNSu8 unansweredQueries; // The number of unanswered queries to this server @@ -2033,6 +2042,9 @@ struct DNSQuestion_struct #if TARGET_OS_EMBEDDED uDNSMetrics metrics; // Data used for collecting unicast DNS query metrics. #endif +#if USE_DNS64 + DNS64 dns64; // DNS64 state for performing IPv6 address synthesis on networks with NAT64. +#endif }; typedef enum { ZoneServiceUpdate, ZoneServiceQuery, ZoneServiceLLQ, ZoneServiceDNSPush } ZoneService; @@ -2281,6 +2293,10 @@ struct mDNS_DNSPushNotificationZone } ; +// Time constant (~= 260 hours ~= 10 days and 21 hours) used to set +// various time values to a point well into the future. +#define FutureTime 0x38000000 + struct mDNS_struct { // Internal state fields. These hold the main internal state of mDNSCore; @@ -2346,9 +2362,6 @@ struct mDNS_struct // during which underying platform layer should inhibit system sleep mDNSs32 TimeSlept; // Time we went to sleep. - mDNSs32 StatStartTime; // Time we started gathering statistics during this interval. - mDNSs32 NextStatLogTime; // Next time to log statistics. - mDNSs32 ActiveStatTime; // Total time awake/gathering statistics for this log period. mDNSs32 UnicastPacketsSent; // Number of unicast packets sent. mDNSs32 MulticastPacketsSent; // Number of multicast packets sent. mDNSs32 RemoteSubnet; // Multicast packets received from outside our subnet. @@ -2445,11 +2458,11 @@ struct mDNS_struct mDNSBool SSDPWANPPPConnection; // whether we should send the SSDP query for WANIPConnection or WANPPPConnection mDNSIPPort UPnPRouterPort; // port we send discovery messages to mDNSIPPort UPnPSOAPPort; // port we send SOAP messages to - mDNSu8 *UPnPRouterURL; // router's URL string + char *UPnPRouterURL; // router's URL string mDNSBool UPnPWANPPPConnection; // whether we're using WANIPConnection or WANPPPConnection - mDNSu8 *UPnPSOAPURL; // router's SOAP control URL string - mDNSu8 *UPnPRouterAddressString; // holds both the router's address and port - mDNSu8 *UPnPSOAPAddressString; // holds both address and port for SOAP messages + char *UPnPSOAPURL; // router's SOAP control URL string + char *UPnPRouterAddressString; // holds both the router's address and port + char *UPnPSOAPAddressString; // holds both address and port for SOAP messages // DNS Push Notification fields DNSPushNotificationServer *DNSPushServers; // DNS Push Notification Servers @@ -2476,7 +2489,6 @@ struct mDNS_struct #if APPLE_OSX_mDNSResponder ClientTunnel *TunnelClients; - uuid_t asl_uuid; // uuid for ASL logging void *WCF; #endif // DNS Proxy fields @@ -2569,7 +2581,8 @@ extern const mDNSOpaque16 SubscribeFlags; extern const mDNSOpaque16 UnSubscribeFlags; extern const mDNSOpaque64 zeroOpaque64; - +extern const mDNSOpaque128 zeroOpaque128; + extern mDNSBool StrictUnicastOrdering; extern mDNSu8 NumUnicastDNSServers; #if APPLE_OSX_mDNSResponder @@ -2762,17 +2775,6 @@ typedef enum { mDNS_Dereg_normal, mDNS_Dereg_rapid, mDNS_Dereg_conflict, mDNS_De extern void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID, mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, AuthRecType artype, mDNSRecordCallback Callback, void *Context); -// mDNS_RegisterService() flags parameter bit definitions. -// Note these are only defined to transfer the corresponding DNSServiceFlags settings into mDNSCore routines, -// since code in mDNSCore does not include the DNSServiceFlags definitions in dns_sd.h. -enum -{ - coreFlagIncludeP2P = 0x1, // include P2P interfaces when using mDNSInterface_Any - coreFlagIncludeAWDL = 0x2, // include AWDL interface when using mDNSInterface_Any - coreFlagKnownUnique = 0x4, // client guarantees that SRV and TXT record names are unique - coreFlagWakeOnly = 0x8 // Service won't be registered with sleep proxy -}; - extern mDNSu32 deriveD2DFlagsFromAuthRecType(AuthRecType authRecType); extern mStatus mDNS_RegisterService (mDNS *const m, ServiceRecordSet *sr, const domainlabel *const name, const domainname *const type, const domainname *const domain, @@ -2900,6 +2902,10 @@ extern char *ConvertDomainNameToCString_withescape(const domainname *const na extern void ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], domainlabel *const hostlabel); +#define ValidTransportProtocol(X) ( (X)[0] == 4 && (X)[1] == '_' && \ + ((((X)[2] | 0x20) == 'u' && ((X)[3] | 0x20) == 'd') || (((X)[2] | 0x20) == 't' && ((X)[3] | 0x20) == 'c')) && \ + ((X)[4] | 0x20) == 'p') + extern mDNSu8 *ConstructServiceName(domainname *const fqdn, const domainlabel *name, const domainname *type, const domainname *const domain); extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel *const name, domainname *const type, domainname *const domain); @@ -2955,6 +2961,7 @@ extern mDNSBool mDNSAddrIPv4FromMappedIPv6(mDNSv6Addr *in, mDNSv4Addr *out); #define mDNSIPPortIsZero(A) ((A).NotAnInteger == 0) #define mDNSOpaque16IsZero(A) ((A).NotAnInteger == 0) #define mDNSOpaque64IsZero(A) (((A)->l[0] | (A)->l[1] ) == 0) +#define mDNSOpaque128IsZero(A) (((A)->l[0] | (A)->l[1] | (A)->l[2] | (A)->l[3]) == 0) #define mDNSIPv4AddressIsZero(A) ((A).NotAnInteger == 0) #define mDNSIPv6AddressIsZero(A) (((A).l[0] | (A).l[1] | (A).l[2] | (A).l[3]) == 0) #define mDNSEthAddressIsZero(A) (((A).w[0] | (A).w[1] | (A).w[2] ) == 0) @@ -2989,12 +2996,6 @@ extern mDNSBool mDNSAddrIPv4FromMappedIPv6(mDNSv6Addr *in, mDNSv4Addr *out); ((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLinkLocal(&(X)->ip.v4) : \ ((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLinkLocal(&(X)->ip.v6) : mDNSfalse) -#define mDNSv4AddressIsLoopback(X) ((X)->b[0] == 127 && (X)->b[1] == 0 && (X)->b[2] == 0 && (X)->b[3] == 1) -#define mDNSv6AddressIsLoopback(X) ((((X)->l[0] | (X)->l[1] | (X)->l[2]) == 0) && ((X)->b[12] == 0 && (X)->b[13] == 0 && (X)->b[14] == 0 && (X)->b[15] == 1)) - -#define mDNSAddressIsLoopback(X) ( \ - ((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLoopback(&(X)->ip.v4) : \ - ((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLoopback(&(X)->ip.v6) : mDNSfalse) // *************************************************************************** #if 0 @@ -3038,8 +3039,8 @@ extern void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCa extern void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn); extern void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, const mDNSAddr *v6addr, const mDNSAddr *router); extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSs32 serviceID, const mDNSAddr *addr, - const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSu16 resGroupID, mDNSBool reqA, - mDNSBool reqAAAA, mDNSBool reqDO); + const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSBool isExpensive, mDNSu16 resGroupID, + mDNSBool reqA, mDNSBool reqAAAA, mDNSBool reqDO); extern void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 responseFlags); extern void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID); @@ -3157,17 +3158,6 @@ extern void mDNSPlatformWriteDebugMsg(const char *msg); #endif extern void mDNSPlatformWriteLogMsg(const char *ident, const char *msg, mDNSLogLevel_t loglevel); -#if APPLE_OSX_mDNSResponder -// Utility function for ASL logging -mDNSexport void mDNSASLLog(uuid_t *uuid, const char *subdomain, const char *result, const char *signature, const char *fmt, ...); - -// Log unicast and multicast traffic statistics once a day. Also used for DNSSEC statistics. -#define kDefaultNextStatsticsLogTime (24 * 60 * 60) - -extern void mDNSLogStatistics(mDNS *const m); - -#endif // APPLE_OSX_mDNSResponder - // Platform support modules should provide the following functions to map between opaque interface IDs // and interface indexes in order to support the DNS-SD API. If your target platform does not support // multiple interfaces and/or does not support the DNS-SD API, these functions can be empty. @@ -3198,7 +3188,7 @@ typedef enum } TCPSocketFlags; typedef void (*TCPConnectionCallback)(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err); -extern TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags, mDNSIPPort *port, mDNSBool useBackgroundTrafficClass); // creates a TCP socket +extern TCPSocket *mDNSPlatformTCPSocket(TCPSocketFlags flags, mDNSIPPort *port, mDNSBool useBackgroundTrafficClass); // creates a TCP socket extern TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd); extern int mDNSPlatformTCPGetFD(TCPSocket *sock); extern mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname, @@ -3206,17 +3196,18 @@ extern mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, m extern void mDNSPlatformTCPCloseConnection(TCPSocket *sock); extern long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed); extern long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len); -extern UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport); +extern UDPSocket *mDNSPlatformUDPSocket(const mDNSIPPort requestedport); extern mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock); extern void mDNSPlatformUDPClose(UDPSocket *sock); -extern void mDNSPlatformReceiveBPF_fd(mDNS *const m, int fd); -extern void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID); +extern mDNSBool mDNSPlatformUDPSocketEncounteredEOF(const UDPSocket *sock); +extern void mDNSPlatformReceiveBPF_fd(int fd); +extern void mDNSPlatformUpdateProxyList(const mDNSInterfaceID InterfaceID); extern void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID); -extern void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID); +extern void mDNSPlatformSetLocalAddressCacheEntry(const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID); extern void mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst); extern void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win); -extern mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti); -extern mStatus mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr); +extern mStatus mDNSPlatformRetrieveTCPInfo(mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti); +extern mStatus mDNSPlatformGetRemoteMacAddr(mDNSAddr *raddr); extern mStatus mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname); extern mStatus mDNSPlatformClearSPSData(void); extern mStatus mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage *msg, int length); @@ -3228,14 +3219,14 @@ extern void mDNSPlatformTLSTearDownCerts(void); // Platforms that support unicast browsing and dynamic update registration for clients who do not specify a domain // in browse/registration calls must implement these routines to get the "default" browse/registration list. -extern mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains, +extern mDNSBool mDNSPlatformSetDNSConfig(mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains, DNameListElem **BrowseDomains, mDNSBool ackConfig); -extern mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router); +extern mStatus mDNSPlatformGetPrimaryInterface(mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router); 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 void mDNSPlatformSetAllowSleep(mDNSBool allowSleep, const char *reason); +extern void mDNSPlatformPreventSleep(mDNSu32 timeout, const char *reason); +extern void mDNSPlatformSendWakeupPacket(mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration); extern mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID); extern mDNSBool mDNSPlatformInterfaceIsAWDL(const NetworkInterfaceInfo *intf); @@ -3293,8 +3284,17 @@ extern void LNT_ClearState(mDNS *const m); extern void mDNS_SetFQDN(mDNS *const m); extern void mDNS_ActivateNetWake_internal (mDNS *const m, NetworkInterfaceInfo *set); extern void mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set); -extern mStatus mDNS_RegisterInterface (mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping); -extern void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping); + +// Attributes that controls the Bonjour operation initiation and response speed for an interface. +typedef enum +{ + FastActivation, // For p2p* and DirectLink type interfaces + NormalActivation, // For standard interface timing + SlowActivation // For flapping interfaces +} InterfaceActivationSpeed; + +extern mStatus mDNS_RegisterInterface (mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed probeDelay); +extern void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed probeDelay); extern void mDNSCoreInitComplete(mDNS *const m, mStatus result); extern void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, @@ -3316,7 +3316,7 @@ extern void mDNSCoreReceiveRawPacket (mDNS *const m, const mDNSu8 *const p, extern mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip); extern CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, mDNSs32 delay, mDNSBool Add, const mDNSAddr *sourceAddress); -extern CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name); +extern CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 namehash, const domainname *const name); extern void ReleaseCacheRecord(mDNS *const m, CacheRecord *r); extern void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event); extern void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const rr); @@ -3340,8 +3340,8 @@ extern void UpdateRMAC(mDNS *const m, void *context); // Used only in logging to restrict the number of /etc/hosts entries printed extern void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result); // exported for using the hash for /etc/hosts AuthRecords -extern AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name); -extern AuthGroup *AuthGroupForRecord(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr); +extern AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 namehash, const domainname *const name); +extern AuthGroup *AuthGroupForRecord(AuthHash *r, const ResourceRecord *const rr); extern AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr); extern AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr); extern mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16 qtype); @@ -3350,35 +3350,36 @@ extern mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16 // In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer #if APPLE_OSX_mDNSResponder extern void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord); -extern void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q); -extern void StartServerTunnel(mDNS *const m, DomainAuthInfo *const info); +extern void AddNewClientTunnel(DNSQuestion *const q); +extern void StartServerTunnel(DomainAuthInfo *const info); extern void UpdateAutoTunnelDomainStatuses(const mDNS *const m); extern void RemoveAutoTunnel6Record(mDNS *const m); -extern mDNSBool RecordReadyForSleep(mDNS *const m, AuthRecord *rr); +extern mDNSBool RecordReadyForSleep(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, mDNSBool *keepaliveOnly); -extern void mDNSPlatformUpdateDNSStatus(mDNS *const m, DNSQuestion *q); -extern void mDNSPlatformTriggerDNSRetry(mDNS *const m, DNSQuestion *v4q, DNSQuestion *v6q); +extern mStatus ActivateLocalProxy(NetworkInterfaceInfo *const intf, mDNSBool *keepaliveOnly); +extern void mDNSPlatformUpdateDNSStatus(DNSQuestion *q); +extern void mDNSPlatformTriggerDNSRetry(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, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, +typedef void ProxyCallback (void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context); -extern void mDNSPlatformInitDNSProxySkts(mDNS *const m, ProxyCallback *UDPCallback, ProxyCallback *TCPCallback); +extern void mDNSPlatformInitDNSProxySkts(ProxyCallback *UDPCallback, ProxyCallback *TCPCallback); extern void mDNSPlatformCloseDNSProxySkts(mDNS *const m); extern void mDNSPlatformDisposeProxyContext(void *context); extern mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *start, mDNSu8 *limit); #if APPLE_OSX_mDNSResponder -extern void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isBlocked); +extern void mDNSPlatformGetDNSRoutePolicy(DNSQuestion *q, mDNSBool *isBlocked); #endif extern void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, const DNSQuestion *q); extern mDNSs32 mDNSPlatformGetPID(void); extern mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr); +extern mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q); // *************************************************************************** #if 0 @@ -3600,17 +3601,17 @@ 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) <= 894) ? 1 : -1]; + char sizecheck_DNSQuestion [(sizeof(DNSQuestion) <= 912) ? 1 : -1]; - char sizecheck_ZoneData [(sizeof(ZoneData) <= 1730) ? 1 : -1]; + char sizecheck_ZoneData [(sizeof(ZoneData) <= 1744) ? 1 : -1]; char sizecheck_NATTraversalInfo [(sizeof(NATTraversalInfo) <= 200) ? 1 : -1]; char sizecheck_HostnameInfo [(sizeof(HostnameInfo) <= 3050) ? 1 : -1]; char sizecheck_DNSServer [(sizeof(DNSServer) <= 330) ? 1 : -1]; - char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 7272) ? 1 : -1]; + char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <= 7376) ? 1 : -1]; char sizecheck_ServiceRecordSet [(sizeof(ServiceRecordSet) <= 5540) ? 1 : -1]; char sizecheck_DomainAuthInfo [(sizeof(DomainAuthInfo) <= 7888) ? 1 : -1]; #if APPLE_OSX_mDNSResponder - char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1230) ? 1 : -1]; + char sizecheck_ClientTunnel [(sizeof(ClientTunnel) <= 1256) ? 1 : -1]; #endif }; diff --git a/mDNSResponder/mDNSCore/nsec.c b/mDNSResponder/mDNSCore/nsec.c index 09d27356..31cf1e95 100644 --- a/mDNSResponder/mDNSCore/nsec.c +++ b/mDNSResponder/mDNSCore/nsec.c @@ -56,12 +56,10 @@ mDNSlocal CacheRecord *NSECParentForQuestion(mDNS *const m, DNSQuestion *q) { CacheGroup *cg; CacheRecord *cr; - mDNSu32 slot; mDNSu32 namehash; - slot = HashSlot(&q->qname); namehash = DomainNameHashValue(&q->qname); - cg = CacheGroupForName(m, slot, namehash, &q->qname); + cg = CacheGroupForName(m, namehash, &q->qname); if (!cg) { LogDNSSEC("NSECParentForQuestion: Cannot find cg for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); @@ -1050,12 +1048,11 @@ mDNSexport CacheRecord *NSECRecordIsDelegation(mDNS *const m, domainname *name, { CacheGroup *cg; CacheRecord *cr; - mDNSu32 slot, namehash; + mDNSu32 namehash; - slot = HashSlot(name); namehash = DomainNameHashValue(name); - cg = CacheGroupForName(m, (const mDNSu32)slot, namehash, name); + cg = CacheGroupForName(m, namehash, name); if (!cg) { LogDNSSEC("NSECRecordForName: cg NULL for %##s", name); diff --git a/mDNSResponder/mDNSCore/nsec3.c b/mDNSResponder/mDNSCore/nsec3.c index 4e9e8c82..43cd37a8 100644 --- a/mDNSResponder/mDNSCore/nsec3.c +++ b/mDNSResponder/mDNSCore/nsec3.c @@ -675,12 +675,11 @@ mDNSexport CacheRecord *NSEC3RecordIsDelegation(mDNS *const m, domainname *name, CacheGroup *cg; CacheRecord *cr; CacheRecord *ncr; - mDNSu32 slot, namehash; + mDNSu32 namehash; - slot = HashSlot(name); namehash = DomainNameHashValue(name); - cg = CacheGroupForName(m, (const mDNSu32)slot, namehash, name); + cg = CacheGroupForName(m, namehash, name); if (!cg) { LogDNSSEC("NSEC3RecordForName: cg NULL for %##s", name); diff --git a/mDNSResponder/mDNSCore/uDNS.c b/mDNSResponder/mDNSCore/uDNS.c index 3677b9f7..dc87724c 100755 --- a/mDNSResponder/mDNSCore/uDNS.c +++ b/mDNSResponder/mDNSCore/uDNS.c @@ -45,12 +45,12 @@ mDNSexport SearchListElem *SearchList = mDNSNULL; mDNSBool StrictUnicastOrdering = mDNSfalse; // We keep track of the number of unicast DNS servers and log a message when we exceed 64. -// Currently the unicast queries maintain a 64 bit map to track the valid DNS servers for that +// Currently the unicast queries maintain a 128 bit map to track the valid DNS servers for that // question. Bit position is the index into the DNS server list. This is done so to try all // the servers exactly once before giving up. If we could allocate memory in the core, then -// arbitrary limitation of 64 DNSServers can be removed. +// arbitrary limitation of 128 DNSServers can be removed. mDNSu8 NumUnicastDNSServers = 0; -#define MAX_UNICAST_DNS_SERVERS 64 +#define MAX_UNICAST_DNS_SERVERS 128 #if APPLE_OSX_mDNSResponder mDNSu8 NumUnreachableDNSServers = 0; #endif @@ -112,8 +112,8 @@ mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mDNSu32 random) #endif mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSs32 serviceID, const mDNSAddr *addr, - const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSu16 resGroupID, mDNSBool reqA, - mDNSBool reqAAAA, mDNSBool reqDO) + const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSBool isExpensive, mDNSu16 resGroupID, + mDNSBool reqA, mDNSBool reqAAAA, mDNSBool reqDO) { DNSServer **p = &m->DNSServers; DNSServer *tmp = mDNSNULL; @@ -127,9 +127,9 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons if (!d) d = (const domainname *)""; - LogInfo("mDNS_AddDNSServer(%d): Adding %#a for %##s, InterfaceID %p, serviceID %u, scoped %d, resGroupID %d req_A is %s req_AAAA is %s cell %s req_DO is %s", + LogInfo("mDNS_AddDNSServer(%d): Adding %#a for %##s, InterfaceID %p, serviceID %u, scoped %d, resGroupID %d req_A is %s req_AAAA is %s cell %s isExpensive %s req_DO is %s", NumUnicastDNSServers, addr, d->c, interface, serviceID, scoped, resGroupID, reqA ? "True" : "False", reqAAAA ? "True" : "False", - cellIntf ? "True" : "False", reqDO ? "True" : "False"); + cellIntf ? "True" : "False", isExpensive ? "True" : "False", reqDO ? "True" : "False"); mDNS_CheckLock(m); @@ -186,17 +186,18 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons } else { - (*p)->scoped = scoped; - (*p)->interface = interface; - (*p)->serviceID = serviceID; - (*p)->addr = *addr; - (*p)->port = port; - (*p)->flags = DNSServer_FlagNew; - (*p)->timeout = timeout; - (*p)->cellIntf = cellIntf; - (*p)->req_A = reqA; - (*p)->req_AAAA = reqAAAA; - (*p)->req_DO = reqDO; + (*p)->scoped = scoped; + (*p)->interface = interface; + (*p)->serviceID = serviceID; + (*p)->addr = *addr; + (*p)->port = port; + (*p)->flags = DNSServer_FlagNew; + (*p)->timeout = timeout; + (*p)->cellIntf = cellIntf; + (*p)->isExpensive = isExpensive; + (*p)->req_A = reqA; + (*p)->req_AAAA = reqAAAA; + (*p)->req_DO = reqDO; // We start off assuming that the DNS server is not DNSSEC aware and // when we receive the first response to a DNSSEC question, we set // it to true. @@ -485,7 +486,7 @@ mDNSlocal mStatus uDNS_RequestAddress(mDNS *m) if (!m->NATTraversals) { - m->retryGetAddr = NonZeroTime(m->timenow + 0x78000000); + m->retryGetAddr = NonZeroTime(m->timenow + FutureTime); LogInfo("uDNS_RequestAddress: Setting retryGetAddr to future"); } else if (m->timenow - m->retryGetAddr >= 0) @@ -1554,7 +1555,7 @@ mDNSlocal tcpInfo_t *MakeTCPConn(mDNS *const m, const DNSMessage *const msg, con mDNSPlatformMemZero(info, sizeof(tcpInfo_t)); info->m = m; - info->sock = mDNSPlatformTCPSocket(m, flags, &srcport, useBackgroundTrafficClass); + info->sock = mDNSPlatformTCPSocket(flags, &srcport, useBackgroundTrafficClass); info->requestLen = 0; info->question = question; info->rr = rr; @@ -1720,7 +1721,7 @@ mDNSexport const domainname *GetServiceTarget(mDNS *m, AuthRecord *const rr) DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, rr->resrec.name); if (AuthInfo && AuthInfo->AutoTunnel) { - StartServerTunnel(m, AuthInfo); + StartServerTunnel(AuthInfo); if (AuthInfo->AutoTunnelHostRecord.namestorage.c[0] == 0) return(mDNSNULL); debugf("GetServiceTarget: Returning %##s", AuthInfo->AutoTunnelHostRecord.namestorage.c); return(&AuthInfo->AutoTunnelHostRecord.namestorage); @@ -2759,7 +2760,6 @@ mDNSexport void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr, co m->NextSRVUpdate = NonZeroTime(m->timenow); #if APPLE_OSX_mDNSResponder - if (RouterChanged) uuid_generate(m->asl_uuid); UpdateAutoTunnelDomainStatuses(m); #endif } @@ -3034,7 +3034,6 @@ exit: mDNSlocal mDNSBool IsRecordMergeable(mDNS *const m, AuthRecord *rr, mDNSs32 time) { DomainAuthInfo *info; - (void) m; //unused // A record is eligible for merge, if the following properties are met. // // 1. uDNS Resource Record @@ -3697,9 +3696,7 @@ mDNSlocal void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interface if (AddrReply->opcode == NATOp_AddrResponse) { #if APPLE_OSX_mDNSResponder - static char msgbuf[16]; - mDNS_snprintf(msgbuf, sizeof(msgbuf), "%d", AddrReply->err); - mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.natpmp.AddressRequest", AddrReply->err ? "failure" : "success", msgbuf, ""); + LogInfo("uDNS_ReceiveNATPMPPacket: AddressRequest %s error %d", AddrReply->err ? "failure" : "success", AddrReply->err); #endif if (!AddrReply->err && len < sizeof(NATAddrReply)) { LogMsg("NAT-PMP AddrResponse message too short (%d bytes)", len); return; } natTraversalHandleAddressReply(m, AddrReply->err, AddrReply->ExtAddr); @@ -3708,9 +3705,8 @@ mDNSlocal void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interface { mDNSu8 Protocol = AddrReply->opcode & 0x7F; #if APPLE_OSX_mDNSResponder - static char msgbuf[16]; - mDNS_snprintf(msgbuf, sizeof(msgbuf), "%s - %d", AddrReply->opcode == NATOp_MapUDPResponse ? "UDP" : "TCP", PortMapReply->err); - mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.natpmp.PortMapRequest", PortMapReply->err ? "failure" : "success", msgbuf, ""); + LogInfo("uDNS_ReceiveNATPMPPacket: PortMapRequest %s %s - error %d", + PortMapReply->err ? "failure" : "success", (AddrReply->opcode == NATOp_MapUDPResponse) ? "UDP" : "TCP", PortMapReply->err); #endif if (!PortMapReply->err) { @@ -3921,7 +3917,9 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS if (QR_OP == UpdateR) { - mDNSu32 lease = GetPktLease(m, msg, end); + mDNSu32 pktlease = 0; + mDNSBool gotlease = GetPktLease(m, msg, end, &pktlease); + mDNSu32 lease = gotlease ? pktlease : 60 * 60; // If lease option missing, assume one hour mDNSs32 expire = m->timenow + (mDNSs32)lease * mDNSPlatformOneSecond; mDNSu32 random = mDNSRandom((mDNSs32)lease * mDNSPlatformOneSecond/10); @@ -4088,6 +4086,7 @@ mDNSexport void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneI mDNS_Unlock(m); } +#ifdef DNS_PUSH_ENABLED mDNSexport void DNSPushNotificationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo) { DNSQuestion *q = (DNSQuestion *)zoneInfo->ZoneDataContext; @@ -4120,7 +4119,7 @@ mDNSexport void DNSPushNotificationGotZoneData(mDNS *const m, mStatus err, const } mDNS_Unlock(m); } - +#endif // DNS_PUSH_ENABLED // Called in normal callback context (i.e. mDNS_busy and mDNS_reentrancy are both 1) mDNSlocal void PrivateQueryGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo) @@ -4625,9 +4624,11 @@ mDNSlocal void handle_unanswered_query(mDNS *const m) mDNSlocal void uDNS_HandleLLQState(mDNS *const m, DNSQuestion *q) { +#ifdef DNS_PUSH_ENABLED // First attempt to use DNS Push Notification. if (q->dnsPushState == DNSPUSH_INIT) DiscoverDNSPushNotificationServer(m, q); +#endif // DNS_PUSH_ENABLED switch (q->state) { case LLQ_InitialRequest: startLLQHandshake(m, q); break; @@ -4733,9 +4734,20 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) debugf("uDNS_CheckCurrentQuestion sending %p %##s (%s) %#a:%d UnansweredQueries %d", q, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL, mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zeroIPPort), q->unansweredQueries); +#if APPLE_OSX_mDNSResponder + // When a DNS proxy network extension initiates the close of a UDP flow (this usually happens when a DNS + // proxy gets disabled or crashes), mDNSResponder's corresponding UDP socket will be marked with the + // SS_CANTRCVMORE state flag. Reading from such a socket is no longer possible, so close the current + // socket pair so that we can create a new pair. + if (q->LocalSocket && mDNSPlatformUDPSocketEncounteredEOF(q->LocalSocket)) + { + mDNSPlatformUDPClose(q->LocalSocket); + q->LocalSocket = mDNSNULL; + } +#endif if (!q->LocalSocket) { - q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort); + q->LocalSocket = mDNSPlatformUDPSocket(zeroIPPort); if (q->LocalSocket) { mDNSPlatformSetSocktOpt(q->LocalSocket, mDNSTransport_UDP, mDNSAddrType_IPv4, q); @@ -4777,8 +4789,18 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) } newServer = GetServerForQuestion(m, q); - DNSServerChangeForQuestion(m, q, newServer); - + if (!newServer) + { + q->triedAllServersOnce = 1; + SetValidDNSServers(m, q); + newServer = GetServerForQuestion(m, q); + } + if (newServer) + { + LogInfo("uDNS_checkCurrentQuestion: Retrying question %p %##s (%s) DNS Server %#a:%u ThisQInterval %d", + q, q->qname.c, DNSTypeName(q->qtype), newServer ? &newServer->addr : mDNSNULL, mDNSVal16(newServer ? newServer->port : zeroIPPort), q->ThisQInterval); + DNSServerChangeForQuestion(m, q, newServer); + } if (q->triedAllServersOnce) { q->LastQTime = m->timenow; @@ -4789,7 +4811,6 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) q->LastQTime = m->timenow - q->ThisQInterval; } q->unansweredQueries = 0; - q->noServerResponse = 1; } else { @@ -4839,20 +4860,20 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m) // passed to uDNS_CheckCurrentQuestion -- we only want one set of query packets hitting the wire -- // but we want *all* of the questions to get answer callbacks.) CacheRecord *rr; - const mDNSu32 slot = HashSlot(&q->qname); - CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); + const mDNSu32 slot = HashSlotFromNameHash(q->qnamehash); + CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname); if (!q->qDNSServer) { - if (!mDNSOpaque64IsZero(&q->validDNSServers)) - LogMsg("uDNS_CheckCurrentQuestion: ERROR!!: valid DNSServer bits not zero 0x%x, 0x%x for question %##s (%s)", - q->validDNSServers.l[1], q->validDNSServers.l[0], q->qname.c, DNSTypeName(q->qtype)); + if (!mDNSOpaque128IsZero(&q->validDNSServers)) + LogMsg("uDNS_CheckCurrentQuestion: ERROR!!: valid DNSServer bits not zero 0x%x, 0x%x 0x%x 0x%x for question %##s (%s)", + q->validDNSServers.l[3], q->validDNSServers.l[2], q->validDNSServers.l[1], q->validDNSServers.l[0], q->qname.c, DNSTypeName(q->qtype)); // If we reached the end of list while picking DNS servers, then we don't want to deactivate the // question. Try after 60 seconds. We find this by looking for valid DNSServers for this question, // if we find any, then we must have tried them before we came here. This avoids maintaining // another state variable to see if we had valid DNS servers for this question. SetValidDNSServers(m, q); - if (mDNSOpaque64IsZero(&q->validDNSServers)) + if (mDNSOpaque128IsZero(&q->validDNSServers)) { LogInfo("uDNS_CheckCurrentQuestion: no DNS server for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); q->ThisQInterval = 0; @@ -4916,7 +4937,7 @@ mDNSexport void CheckNATMappings(mDNS *m) { mDNSBool rfc1918 = mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4); mDNSBool HaveRoutable = !rfc1918 && !mDNSIPv4AddressIsZero(m->AdvertisedV4.ip.v4); - m->NextScheduledNATOp = m->timenow + 0x3FFFFFFF; + m->NextScheduledNATOp = m->timenow + FutureTime; if (HaveRoutable) m->ExtAddress = m->AdvertisedV4.ip.v4; @@ -4926,7 +4947,7 @@ mDNSexport void CheckNATMappings(mDNS *m) { // we need to log a message if we can't get our socket, but only the first time (after success) static mDNSBool needLog = mDNStrue; - m->NATMcastRecvskt = mDNSPlatformUDPSocket(m, NATPMPAnnouncementPort); + m->NATMcastRecvskt = mDNSPlatformUDPSocket(NATPMPAnnouncementPort); if (!m->NATMcastRecvskt) { if (needLog) @@ -5047,7 +5068,7 @@ mDNSexport void CheckNATMappings(mDNS *m) mDNSlocal mDNSs32 CheckRecordUpdates(mDNS *m) { AuthRecord *rr; - mDNSs32 nextevent = m->timenow + 0x3FFFFFFF; + mDNSs32 nextevent = m->timenow + FutureTime; CheckGroupRecordUpdates(m); @@ -5105,7 +5126,7 @@ mDNSexport void uDNS_Tasks(mDNS *const m) mDNSs32 nexte; DNSServer *d; - m->NextuDNSEvent = m->timenow + 0x3FFFFFFF; + m->NextuDNSEvent = m->timenow + FutureTime; nexte = CheckRecordUpdates(m); if (m->NextuDNSEvent - nexte > 0) @@ -5400,7 +5421,7 @@ mDNSexport void uDNS_SetupWABQueries(mDNS *const m) // Make sure we have the search domains from the platform layer so that if we start the WAB // queries below, we have the latest information. mDNS_Lock(m); - if (!mDNSPlatformSetDNSConfig(m, mDNSfalse, mDNStrue, mDNSNULL, mDNSNULL, mDNSNULL, mDNSfalse)) + if (!mDNSPlatformSetDNSConfig(mDNSfalse, mDNStrue, mDNSNULL, mDNSNULL, mDNSNULL, mDNSfalse)) { // If the configuration did not change, clear the flag so that we don't free the searchlist. // We still have to start the domain enumeration queries as we may not have started them @@ -5648,11 +5669,10 @@ mDNSexport void uDNS_StopWABQueries(mDNS *const m, int queryType) uDNS_SetupWABQueries(m); } -mDNSexport domainname *uDNS_GetNextSearchDomain(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal) +mDNSexport domainname *uDNS_GetNextSearchDomain(mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal) { SearchListElem *p = SearchList; int count = *searchIndex; - (void) m; // unused if (count < 0) { LogMsg("uDNS_GetNextSearchDomain: count %d less than zero", count); return mDNSNULL; } @@ -5775,10 +5795,15 @@ struct CompileTimeAssertionChecks_uDNS #pragma mark - DNS Push Notification functions #endif +#ifdef DNS_PUSH_ENABLED mDNSlocal tcpInfo_t * GetTCPConnectionToPushServer(mDNS *m, DNSQuestion *q) { + DNSPushNotificationZone *zone; + DNSPushNotificationServer *server; + DNSPushNotificationZone *newZone; + DNSPushNotificationServer *newServer; + // If we already have a question for this zone and if the server is the same, reuse it - DNSPushNotificationZone *zone = mDNSNULL; for (zone = m->DNSPushZones; zone != mDNSNULL; zone = zone->next) { if (SameDomainName(&q->nta->ChildName, &zone->zoneName)) @@ -5797,12 +5822,11 @@ mDNSlocal tcpInfo_t * GetTCPConnectionToPushServer(mDNS *m, DNSQuestion *q) } // If we have a connection to this server but it is for a differnt zone, create a new zone entry and reuse the connection - DNSPushNotificationServer *server = mDNSNULL; for (server = m->DNSPushServers; server != mDNSNULL; server = server->next) { if (mDNSSameAddress(&q->dnsPushServerAddr, &server->serverAddr)) { - DNSPushNotificationZone *newZone = mDNSPlatformMemAllocate(sizeof(DNSPushNotificationZone)); + newZone = mDNSPlatformMemAllocate(sizeof(DNSPushNotificationZone)); newZone->numberOfQuestions = 1; newZone->zoneName = q->nta->ChildName; newZone->servers = server; @@ -5817,8 +5841,8 @@ mDNSlocal tcpInfo_t * GetTCPConnectionToPushServer(mDNS *m, DNSQuestion *q) } // If we do not have any existing connections, create a new connection - DNSPushNotificationServer *newServer = mDNSPlatformMemAllocate(sizeof(DNSPushNotificationServer)); - DNSPushNotificationZone *newZone = mDNSPlatformMemAllocate(sizeof(DNSPushNotificationZone)); + newServer = mDNSPlatformMemAllocate(sizeof(DNSPushNotificationServer)); + newZone = mDNSPlatformMemAllocate(sizeof(DNSPushNotificationZone)); newServer->numberOfQuestions = 1; newServer->serverAddr = q->dnsPushServerAddr; @@ -5930,6 +5954,9 @@ mDNSlocal void reconcileDNSPushConnection(mDNS *m, DNSQuestion *q) { DNSPushNotificationZone *zone; DNSPushNotificationServer *server; + DNSPushNotificationServer *nextServer; + DNSPushNotificationZone *nextZone; + // Update the counts for (zone = m->DNSPushZones; zone != mDNSNULL; zone = zone->next) { @@ -5946,7 +5973,7 @@ mDNSlocal void reconcileDNSPushConnection(mDNS *m, DNSQuestion *q) // Now prune the lists server = m->DNSPushServers; - DNSPushNotificationServer *nextServer = mDNSNULL; + nextServer = mDNSNULL; while(server != mDNSNULL) { nextServer = server->next; @@ -5962,7 +5989,7 @@ mDNSlocal void reconcileDNSPushConnection(mDNS *m, DNSQuestion *q) } zone = m->DNSPushZones; - DNSPushNotificationZone *nextZone = mDNSNULL; + nextZone = mDNSNULL; while(zone != mDNSNULL) { nextZone = zone->next; @@ -5994,6 +6021,7 @@ mDNSexport void UnSubscribeToDNSPushNotificationServer(mDNS *m, DNSQuestion *q) reconcileDNSPushConnection(m, q); } +#endif // DNS_PUSH_ENABLED #if COMPILER_LIKES_PRAGMA_MARK #pragma mark - #endif @@ -6119,9 +6147,8 @@ mDNSexport mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info, const return mStatus_UnsupportedErr; } -mDNSexport domainname *uDNS_GetNextSearchDomain(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal) +mDNSexport domainname *uDNS_GetNextSearchDomain(mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal) { - (void) m; (void) InterfaceID; (void) searchIndex; (void) ignoreDotLocal; @@ -6154,8 +6181,8 @@ mDNSexport mStatus mDNS_StopNATOperation(mDNS *const m, NATTraversalInfo *traver } mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSs32 serviceID, const mDNSAddr *addr, - const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSu16 resGroupID, mDNSBool reqA, - mDNSBool reqAAAA, mDNSBool reqDO) + const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSBool isExpensive, mDNSu16 resGroupID, + mDNSBool reqA, mDNSBool reqAAAA, mDNSBool reqDO) { (void) m; (void) d; @@ -6166,6 +6193,7 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons (void) scoped; (void) timeout; (void) cellIntf; + (void) isExpensive; (void) resGroupID; (void) reqA; (void) reqAAAA; diff --git a/mDNSResponder/mDNSCore/uDNS.h b/mDNSResponder/mDNSCore/uDNS.h index 910449f1..27b7acee 100755 --- a/mDNSResponder/mDNSCore/uDNS.h +++ b/mDNSResponder/mDNSCore/uDNS.h @@ -128,7 +128,7 @@ extern mStatus uDNS_SetupDNSConfig(mDNS *const m); extern void uDNS_SetupWABQueries(mDNS *const m); extern void uDNS_StartWABQueries(mDNS *const m, int queryType); extern void uDNS_StopWABQueries(mDNS *const m, int queryType); -extern domainname *uDNS_GetNextSearchDomain(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal); +extern domainname *uDNS_GetNextSearchDomain(mDNSInterfaceID InterfaceID, mDNSs8 *searchIndex, mDNSBool ignoreDotLocal); typedef enum { |