]> git.saurik.com Git - apple/mdnsresponder.git/blobdiff - mDNSCore/mDNS.c
mDNSResponder-576.30.4.tar.gz
[apple/mdnsresponder.git] / mDNSCore / mDNS.c
index ccd068075becbbff7f635949f94a41b28301150a..e0af1f1a0562c0e8f6c333f561e32b534a21bb4e 100755 (executable)
@@ -23,7 +23,7 @@
  * routines, or types (which may or may not be present on any given platform).
  */
 
-#include "DNSCommon.h"                  // Defines general DNS untility routines
+#include "DNSCommon.h"                  // Defines general DNS utility routines
 #include "uDNS.h"                       // Defines entry points into unicast-specific routines
 #include "nsec.h"
 #include "dnssec.h"
@@ -466,8 +466,10 @@ mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, Re
 {
     const mDNSBool selfref = SameDomainName(&q->qname, &rr->rdata->u.name);
     if (q->CNAMEReferrals >= 10 || selfref)
+    {
         LogMsg("AnswerQuestionByFollowingCNAME: %p %##s (%s) NOT following CNAME referral %d%s for %s",
                q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, selfref ? " (Self-Referential)" : "", RRDisplayString(m, rr));
+    }
     else
     {
         const mDNSu32 c = q->CNAMEReferrals + 1;        // Stash a copy of the new q->CNAMEReferrals value
@@ -1254,19 +1256,6 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
         }
     }
 
-    // If this resource record is referencing a specific interface, make sure it exists.
-    // Skip checks for LocalOnly and P2P as they are not valid InterfaceIDs. Also, for scoped
-    // entries in /etc/hosts skip that check as that interface may not be valid at this time.
-    if (rr->resrec.InterfaceID && rr->ARType != AuthRecordLocalOnly && rr->ARType != AuthRecordP2P)
-    {
-        NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
-        if (!intf)
-        {
-            debugf("mDNS_Register_internal: Bogus InterfaceID %p in resource record", rr->resrec.InterfaceID);
-            return(mStatus_BadReferenceErr);
-        }
-    }
-
     rr->next = mDNSNULL;
 
     // Field Group 1: The actual information pertaining to this resource record
@@ -2821,7 +2810,8 @@ mDNSlocal void SendResponses(mDNS *const m)
         if (rr->SendRNow)
         {
             if (rr->ARType != AuthRecordLocalOnly && rr->ARType != AuthRecordP2P)
-                LogMsg("SendResponses: No active interface %p to send: %p %02X %s", rr->SendRNow, rr->resrec.InterfaceID, rr->resrec.RecordType, ARDisplayString(m, rr));
+                LogInfo("SendResponses: No active interface %d to send: %d %02X %s",
+                     (uint32_t)rr->SendRNow, (uint32_t)rr->resrec.InterfaceID, rr->resrec.RecordType, ARDisplayString(m, rr));
             rr->SendRNow = mDNSNULL;
         }
 
@@ -3467,6 +3457,11 @@ mDNSlocal void SendQueries(mDNS *const m)
             {
                 if (ar->AddressProxy.type == mDNSAddrType_IPv4)
                 {
+                       // There's a problem here. If a host is waking up, and we probe to see if it responds, then
+                       // it will see those ARP probes as signalling intent to use the address, so it picks a different one.
+                       // A more benign way to find out if a host is responding to ARPs might be send a standard ARP *request*
+                       // (using our sender IP address) instead of an ARP *probe* (using all-zero sender IP address).
+                       // A similar concern may apply to the NDP Probe too. -- SC
                     LogSPS("SendQueries ARP Probe %d %s %s", ar->ProbeCount, InterfaceNameForID(m, ar->resrec.InterfaceID), ARDisplayString(m,ar));
                     SendARP(m, 1, ar, &zerov4Addr, &zeroEthAddr, &ar->AddressProxy.ip.v4, &ar->WakeUp.IMAC);
                 }
@@ -3747,7 +3742,8 @@ mDNSlocal void SendQueries(mDNS *const m)
         if (ar->SendRNow)
         {
             if (ar->ARType != AuthRecordLocalOnly && ar->ARType != AuthRecordP2P)
-                LogMsg("SendQueries: No active interface %p to send probe: %p %s", ar->SendRNow, ar->resrec.InterfaceID, ARDisplayString(m, ar));
+                LogInfo("SendQueries: No active interface %d to send probe: %d %s",
+                    (uint32_t)ar->SendRNow, (uint32_t)ar->resrec.InterfaceID, ARDisplayString(m, ar));
             ar->SendRNow = mDNSNULL;
         }
 
@@ -3778,7 +3774,8 @@ mDNSlocal void SendQueries(mDNS *const m)
         {
             DNSQuestion *x;
             for (x = m->NewQuestions; x; x=x->next) if (x == q) break;  // Check if this question is a NewQuestion
-            LogMsg("SendQueries: No active interface %p to send %s question: %p %##s (%s)", q->SendQNow, x ? "new" : "old", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
+            LogInfo("SendQueries: No active interface %d to send %s question: %d %##s (%s)",
+                (uint32_t)q->SendQNow, x ? "new" : "old", (uint32_t)q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
             q->SendQNow = mDNSNULL;
         }
         q->CachedAnswerNeedsUpdate = mDNSfalse;
@@ -5562,13 +5559,26 @@ mDNSexport void mDNS_UpdateAllowSleep(mDNS *const m)
                     }
 
                     // Disallow sleep if there is no sleep proxy server
-                    if (FindSPSInCache1(m, &intf->NetWakeBrowse, mDNSNULL, mDNSNULL) == mDNSNULL)
+                    const CacheRecord *cr = FindSPSInCache1(m, &intf->NetWakeBrowse, mDNSNULL, mDNSNULL);
+                    if ( cr == mDNSNULL)
                     {
                         allowSleep = mDNSfalse;
                         mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server on %s", intf->ifname);
                         LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server", intf->ifname);
                         break;
                     }
+                    else if (m->SPSType != 0)
+                    {
+                        mDNSu32 mymetric = LocalSPSMetric(m);
+                        mDNSu32 metric   = SPSMetric(cr->resrec.rdata->u.name.c);
+                        if (metric >= mymetric)
+                        {
+                            allowSleep = mDNSfalse;
+                            mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server with better metric on %s", intf->ifname);
+                            LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server with a better metric", intf->ifname);
+                            break;
+                        }
+                    }
                 }
             }
         }
@@ -5577,9 +5587,8 @@ mDNSexport void mDNS_UpdateAllowSleep(mDNS *const m)
     // Call the platform code to enable/disable sleep
     mDNSPlatformSetAllowSleep(m, allowSleep, reason);
 #else
-       (void) m;
+    (void) m;
 #endif /* !defined(IDLESLEEPCONTROL_DISABLED) */
-       
 }
 
 mDNSlocal mDNSBool mDNSUpdateOkToSend(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSu32 scopeid)
@@ -6237,6 +6246,10 @@ mDNSlocal void BeginSleepProcessing(mDNS *const m)
     else    // If we have at least one advertised service
     {
         NetworkInterfaceInfo *intf;
+
+        // Clear out the SCDynamic entry that stores the external SPS information
+        mDNSPlatformClearSPSMACAddr();
+
         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.
@@ -10331,6 +10344,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co
 // (b) being performed by a unicast DNS long-lived query (either full LLQ, or polling)
 // for multicast questions, we don't want to treat LongLived as anything special
 #define IsLLQ(Q) ((Q)->LongLived && !mDNSOpaque16IsZero((Q)->TargetQID))
+#define IsAWDLIncluded(Q) (((Q)->flags & kDNSServiceFlagsIncludeAWDL) != 0)
 
 mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuestion *const question)
 {
@@ -10353,6 +10367,7 @@ 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
             return(q);
     return(mDNSNULL);
@@ -11154,7 +11169,7 @@ mDNSlocal mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q
 mDNSlocal void SuppressStatusChanged(mDNS *const m, DNSQuestion *q, DNSQuestion **restart)
 {
     // NOTE: CacheRecordRmvEventsForQuestion will not generate RMV events for queries that have non-zero
-    // LOddressAnswers. Hence it is important that we call CacheRecordRmvEventsForQuestion before
+    // LOAddressAnswers. Hence it is important that we call CacheRecordRmvEventsForQuestion before
     // LocalRecordRmvEventsForQuestion (which decrements LOAddressAnswers)
     if (q->SuppressQuery)
     {
@@ -11318,8 +11333,8 @@ mDNSlocal mStatus ValidateParameters(mDNS *const m, DNSQuestion *const question)
     {
         NetworkInterfaceInfo *intf = FirstInterfaceForID(m, question->InterfaceID);
         if (!intf)
-            LogMsg("ValidateParameters: Note: InterfaceID %p for question %##s (%s) not currently found in active interface list",
-                    question->InterfaceID, question->qname.c, DNSTypeName(question->qtype));
+            LogInfo("ValidateParameters: Note: InterfaceID %d for question %##s (%s) not currently found in active interface list",
+                    (uint32_t)question->InterfaceID, question->qname.c, DNSTypeName(question->qtype));
     }
     
     return(mStatus_NoError);
@@ -11429,9 +11444,15 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question)
     question->LOAddressAnswers  = 0;
     question->FlappingInterface1 = mDNSNULL;
     question->FlappingInterface2 = mDNSNULL;
-
-    question->ServiceID = mDNSPlatformGetServiceID(m, question);
-    
+       
+       // if kDNSServiceFlagsServiceIndex flag is SET by the client, then do NOT call mDNSPlatformGetServiceID()
+       // since we would already have the question->ServiceID in that case.
+       if (!(question->flags & kDNSServiceFlagsServiceIndex))
+               question->ServiceID = mDNSPlatformGetServiceID(m, question);
+       else
+               LogInfo("InitCommonState: Query for %##s (%s), PID[%d], ServiceID %d is already set by client", question->qname.c,
+                          DNSTypeName(question->qtype), question->pid, question->ServiceID);
+       
     InitDNSConfig(m, question);
 
     question->AuthInfo          = GetAuthInfoForQuestion(m, question);
@@ -11443,10 +11464,8 @@ mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question)
     // set DisallowPID
     question->DisallowPID       = (question->ServiceID == 0 || (mDNSPlatformAllowPID(m, question) == 0));
     if (question->DisallowPID)
-    {
         LogInfo("InitCommonState: Query suppressed for %##s (%s), PID %d/ServiceID %d not allowed", question->qname.c,
-            DNSTypeName(question->qtype), question->pid, question->ServiceID);
-    }
+                                       DNSTypeName(question->qtype), question->pid, question->ServiceID);
 
     question->NextInDQList      = mDNSNULL;
     question->SendQNow          = mDNSNULL;
@@ -11967,6 +11986,8 @@ mDNSlocal mStatus mDNS_StartBrowse_internal(mDNS *const m, DNSQuestion *const qu
     question->ForceMCast       = ForceMCast;
     question->ReturnIntermed   = mDNSfalse;
     question->SuppressUnusable = mDNSfalse;
+    question->DenyOnCellInterface = mDNSfalse;
+    question->DenyOnExpInterface  = mDNSfalse;
     question->SearchListIndex  = 0;
     question->AppendSearchDomains = 0;
     question->RetryWithSearchDomains = mDNSfalse;
@@ -12163,6 +12184,8 @@ mDNSexport mStatus mDNS_StartResolveService(mDNS *const m,
     query->qSRV.ForceMCast          = mDNSfalse;
     query->qSRV.ReturnIntermed      = mDNSfalse;
     query->qSRV.SuppressUnusable    = mDNSfalse;
+    query->qSRV.DenyOnCellInterface = mDNSfalse;
+    query->qSRV.DenyOnExpInterface  = mDNSfalse;
     query->qSRV.SearchListIndex     = 0;
     query->qSRV.AppendSearchDomains = 0;
     query->qSRV.RetryWithSearchDomains = mDNSfalse;
@@ -12189,6 +12212,8 @@ mDNSexport mStatus mDNS_StartResolveService(mDNS *const m,
     query->qTXT.ForceMCast          = mDNSfalse;
     query->qTXT.ReturnIntermed      = mDNSfalse;
     query->qTXT.SuppressUnusable    = mDNSfalse;
+    query->qTXT.DenyOnCellInterface = mDNSfalse;
+    query->qTXT.DenyOnExpInterface  = mDNSfalse;
     query->qTXT.SearchListIndex     = 0;
     query->qTXT.AppendSearchDomains = 0;
     query->qTXT.RetryWithSearchDomains = mDNSfalse;
@@ -12215,6 +12240,8 @@ mDNSexport mStatus mDNS_StartResolveService(mDNS *const m,
     query->qAv4.ForceMCast          = mDNSfalse;
     query->qAv4.ReturnIntermed      = mDNSfalse;
     query->qAv4.SuppressUnusable    = mDNSfalse;
+    query->qAv4.DenyOnCellInterface = mDNSfalse;
+    query->qAv4.DenyOnExpInterface  = mDNSfalse;
     query->qAv4.SearchListIndex     = 0;
     query->qAv4.AppendSearchDomains = 0;
     query->qAv4.RetryWithSearchDomains = mDNSfalse;
@@ -12241,6 +12268,8 @@ mDNSexport mStatus mDNS_StartResolveService(mDNS *const m,
     query->qAv6.ForceMCast          = mDNSfalse;
     query->qAv6.ReturnIntermed      = mDNSfalse;
     query->qAv6.SuppressUnusable    = mDNSfalse;
+    query->qAv6.DenyOnCellInterface = mDNSfalse;
+    query->qAv6.DenyOnExpInterface  = mDNSfalse;
     query->qAv6.SearchListIndex     = 0;
     query->qAv6.AppendSearchDomains = 0;
     query->qAv6.RetryWithSearchDomains = mDNSfalse;
@@ -12302,6 +12331,8 @@ mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, m
     question->ForceMCast       = mDNSfalse;
     question->ReturnIntermed   = mDNSfalse;
     question->SuppressUnusable = mDNSfalse;
+    question->DenyOnCellInterface = mDNSfalse;
+    question->DenyOnExpInterface  = mDNSfalse;
     question->SearchListIndex  = 0;
     question->AppendSearchDomains = 0;
     question->RetryWithSearchDomains = mDNSfalse;
@@ -12447,8 +12478,15 @@ 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
 
+    // If interface is marked as a direct link, we can assume the address record is unique
+    // and does not need to go through the probe phase of the probe/announce packet sequence.
+    mDNSu8 recordType = (set->DirectLink ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique);
+
+    if (set->DirectLink)
+        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, kDNSRecordTypeUnique,      AuthRecordAny, mDNS_HostNameCallback, set);
+    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);
 
@@ -12490,13 +12528,14 @@ mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
 
     set->RR_A.RRSet = &primary->RR_A;           // May refer to self
 
+    mDNS_Register_internal(m, &set->RR_A);
+    mDNS_Register_internal(m, &set->RR_PTR);
+
 #if APPLE_OSX_mDNSResponder
+    // must be after the mDNS_Register_internal() calls so that records have complete rdata fields, etc
     D2D_start_advertising_interface(set);
 #endif // APPLE_OSX_mDNSResponder
 
-    mDNS_Register_internal(m, &set->RR_A);
-    mDNS_Register_internal(m, &set->RR_PTR);
-
     if (!NO_HINFO && m->HIHardware.c[0] > 0 && m->HISoftware.c[0] > 0 && m->HIHardware.c[0] + m->HISoftware.c[0] <= 254)
     {
         mDNSu8 *p = set->RR_HINFO.resrec.rdata->u.data;
@@ -12793,7 +12832,8 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
     if (set->Advertise)
         AdvertiseInterface(m, set);
 
-    LogInfo("mDNS_RegisterInterface: InterfaceID %p %s (%#a) %s", set->InterfaceID, set->ifname, &set->ip,
+    LogInfo("mDNS_RegisterInterface: InterfaceID %d %s (%#a) %s",
+            (uint32_t)set->InterfaceID, set->ifname, &set->ip,
             set->InterfaceActive ?
             "not represented in list; marking active and retriggering queries" :
             "already represented in list; marking inactive for now");
@@ -12937,8 +12977,8 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se
         NetworkInterfaceInfo *intf = FirstInterfaceForID(m, set->InterfaceID);
         if (intf)
         {
-            LogInfo("mDNS_DeregisterInterface: Another representative of InterfaceID %p %s (%#a) exists;"
-                    " making it active", set->InterfaceID, set->ifname, &set->ip);
+            LogInfo("mDNS_DeregisterInterface: Another representative of InterfaceID %d %s (%#a) exists;"
+                    " making it active", (uint32_t)set->InterfaceID, set->ifname, &set->ip);
             if (intf->InterfaceActive)
                 LogMsg("mDNS_DeregisterInterface: ERROR intf->InterfaceActive already set for %s (%#a)", set->ifname, &set->ip);
             intf->InterfaceActive = mDNStrue;
@@ -12960,8 +13000,8 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se
             CacheRecord *rr;
             DNSQuestion *q;
 
-            LogInfo("mDNS_DeregisterInterface: Last representative of InterfaceID %p %s (%#a) deregistered;"
-                    " marking questions etc. dormant", set->InterfaceID, set->ifname, &set->ip);
+            LogInfo("mDNS_DeregisterInterface: Last representative of InterfaceID %d %s (%#a) deregistered;"
+                    " marking questions etc. dormant", (uint32_t)set->InterfaceID, set->ifname, &set->ip);
 
             m->mDNSStats.InterfaceDown++;