]> git.saurik.com Git - apple/mdnsresponder.git/blobdiff - mDNSMacOSX/mDNSMacOSX.c
mDNSResponder-576.30.4.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / mDNSMacOSX.c
index 28d73f63f8d83d8b46e1b5e75a6f0101a3e9a9b3..f904c8b22f8cfe9d7c0c282329f33a9b8cec213c 100644 (file)
@@ -115,7 +115,6 @@ D2DStatus D2DTerminate() __attribute__((weak_import));
 #include <IOKit/platform/IOPlatformSupportPrivate.h>
 #endif // APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
 
-
 #define kInterfaceSpecificOption "interface="
 
 #define mDNS_IOREG_KEY               "mDNS_KEY"
@@ -1037,7 +1036,13 @@ mDNSexport void external_stop_resolving_service(const domainname *const fqdn, DN
 // Typically point-to-point interfaces are modems (including mobile-phone pseudo-modems), and we don't want
 // to run up the user's bill sending multicast traffic over a link where there's only a single device at the
 // other end, and that device (e.g. a modem bank) is probably not answering Multicast DNS queries anyway.
+
+// We also don't want to use multicast on *any* interface on very constrained devices.
+#if TARGET_OS_NANO
+#define MulticastInterface(i) (mDNSfalse)
+#else
 #define MulticastInterface(i) (((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT))
+#endif
 
 mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg)  // Both strings are UTF-8 text
 {
@@ -1692,35 +1697,56 @@ mDNSlocal void setTrafficClass(int socketfd, mDNSBool useBackgroundTrafficClass)
     (void) setsockopt(socketfd, SOL_SOCKET, SO_TRAFFIC_CLASS, (void *)&traffic_class, sizeof(traffic_class));
 }
 
-mDNSexport void mDNSPlatformSetDelegatePID(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q)
+mDNSexport void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q)
 {
     if (src)
     {
         int s;
 
         if (dst->type == mDNSAddrType_IPv4)
-        {
             s = src->ss.sktv4;
-        }
         else
-        {
             s = src->ss.sktv6;
-        }
 
         if (q->pid)
         {
             if (setsockopt(s, SOL_SOCKET, SO_DELEGATED, &q->pid, sizeof(q->pid)) == -1)
-            {
-                LogInfo("mDNSPlatformSetDelegatePID: Delegate PID failed %s for PID %d", strerror(errno), q->pid);
-            }
+                LogInfo("mDNSPlatformSetuDNSSocktOpt: Delegate PID failed %s for PID %d", strerror(errno), q->pid);
         }
         else
         {
             if (setsockopt(s, SOL_SOCKET, SO_DELEGATED_UUID, &q->uuid, sizeof(q->uuid)) == -1)
+                LogInfo("mDNSPlatformSetuDNSSocktOpt: Delegate UUID failed %s", strerror(errno));
+        }
+               
+#if defined(SO_NOWAKEFROMSLEEP)
+        int nowake = 1;
+        if (setsockopt(s, SOL_SOCKET, SO_NOWAKEFROMSLEEP, &nowake, sizeof(nowake)) == -1)
+            LogInfo("mDNSPlatformSetuDNSSocktOpt: SO_NOWAKEFROMSLEEP failed %s", strerror(errno));
+#endif
+       
+        if (q->DenyOnCellInterface || q->DenyOnExpInterface)
+        {
+#if defined(SO_RESTRICT_DENY_CELLULAR)
+            if (q->DenyOnCellInterface)
             {
-                LogInfo("mDNSPlatformSetDelegatePID: Delegate UUID failed %s", strerror(errno));
+                int restrictions = 0;
+                restrictions = SO_RESTRICT_DENY_CELLULAR;
+                if (setsockopt(s, SOL_SOCKET, SO_RESTRICTIONS, &restrictions, sizeof(restrictions)) == -1)
+                    LogInfo("mDNSPlatformSetuDNSSocktOpt: SO_RESTRICT_DENY_CELLULAR failed %s", strerror(errno));
             }
-        }
+#endif
+#if defined(SO_RESTRICT_DENY_EXPENSIVE)
+            if (q->DenyOnExpInterface)
+            {
+                int restrictions = 0;
+                restrictions = SO_RESTRICT_DENY_EXPENSIVE;
+                if (setsockopt(s, SOL_SOCKET, SO_RESTRICTIONS, &restrictions, sizeof(restrictions)) == -1)
+                    LogInfo("mDNSPlatformSetuDNSSocktOpt: SO_RESTRICT_DENY_EXPENSIVE failed %s", strerror(errno));
+            }
+#endif
+               }
+               
     }
 }
 
@@ -5164,6 +5190,8 @@ mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
     p->q.ForceMCast       = mDNSfalse;
     p->q.ReturnIntermed   = mDNStrue;
     p->q.SuppressUnusable = mDNSfalse;
+    p->q.DenyOnCellInterface = mDNSfalse;
+    p->q.DenyOnExpInterface  = mDNSfalse;
     p->q.SearchListIndex  = 0;
     p->q.AppendSearchDomains = 0;
     p->q.RetryWithSearchDomains = mDNSfalse;
@@ -5202,6 +5230,8 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
     if (InfoSocket < 3 && errno != EAFNOSUPPORT) 
         LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket, errno, strerror(errno));
 
+    if (m->SleepState == SleepState_Sleeping) ifa = NULL;
+
     while (ifa)
     {
 #if LIST_ALL_INTERFACES
@@ -7910,13 +7940,16 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
 }
 
 // Called with KQueueLock & mDNS lock
+// SetNetworkChanged is allowed to extend (but not reduce) the pause while we wait for configuration changes to settle
 mDNSlocal void SetNetworkChanged(mDNS *const m, mDNSs32 delay)
 {
     if (!m->p->NetworkChanged || m->p->NetworkChanged - NonZeroTime(m->timenow + delay) < 0)
     {
         m->p->NetworkChanged = NonZeroTime(m->timenow + delay);
-        LogInfo("SetNetworkChanged: scheduling in %d msec", delay);
+        LogInfo("SetNetworkChanged: Scheduling in %d msec", delay);
     }
+    else
+        LogInfo("SetNetworkChanged: *NOT* reducing delay from %d to %d", m->p->NetworkChanged - m->timenow, delay);
 }
 
 // Called with KQueueLock & mDNS lock
@@ -7948,7 +7981,7 @@ mDNSlocal CFStringRef CopyNameFromKey(CFStringRef key)
 
 // Whether a key from a network change notification corresponds to
 // an IP service that is explicitly configured for IPv4 Link Local
-mDNSlocal mDNSBool ChangedKeysHaveIPv4LL(CFArrayRef inkeys)
+mDNSlocal int ChangedKeysHaveIPv4LL(CFArrayRef inkeys)
 {
     SCDynamicStoreRef store = NULL;
     CFDictionaryRef dict = NULL;
@@ -7956,7 +7989,7 @@ mDNSlocal mDNSBool ChangedKeysHaveIPv4LL(CFArrayRef inkeys)
     const void **keys = NULL, **vals = NULL;
     CFStringRef pattern = NULL;
     int i, ic, j, jc;
-    mDNSBool found = mDNSfalse;
+    int found = 0;
 
     jc = CFArrayGetCount(inkeys);
     if (!jc) goto done;
@@ -7993,7 +8026,8 @@ mDNSlocal mDNSBool ChangedKeysHaveIPv4LL(CFArrayRef inkeys)
     keys = mDNSPlatformMemAllocate(sizeof (void *) * ic);
     CFDictionaryGetKeysAndValues(dict, keys, vals);
 
-    for (j = 0; j < jc && !found; j++)
+    // For each key we were given...
+    for (j = 0; j < jc; j++)
     {
         CFStringRef key = CFArrayGetValueAtIndex(inkeys, j);
         CFStringRef ifname = NULL;
@@ -8010,6 +8044,7 @@ mDNSlocal mDNSBool ChangedKeysHaveIPv4LL(CFArrayRef inkeys)
             LogInfo("ChangedKeysHaveIPv4LL: potential ifname %s", buf);
         }
 
+        // Loop over the interfaces to find matching the ifname, and see if that one has kSCValNetIPv4ConfigMethodLinkLocal
         for (i = 0; i < ic; i++)
         {
             CFDictionaryRef ipv4dict;
@@ -8049,7 +8084,7 @@ mDNSlocal mDNSBool ChangedKeysHaveIPv4LL(CFArrayRef inkeys)
                 LogInfo("ChangedKeysHaveIPv4LL: configmethod %s", buf);
             }
 
-            if (CFEqual(configmethod, kSCValNetIPv4ConfigMethodLinkLocal)) { found = mDNStrue; break; }
+            if (CFEqual(configmethod, kSCValNetIPv4ConfigMethodLinkLocal)) { found++; break; }
         }
 
         CFRelease(ifname);
@@ -8067,7 +8102,6 @@ done:
 mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context)
 {
     (void)store;        // Parameter not used
-    mDNSBool changeNow = mDNSfalse;
     mDNS *const m = (mDNS *const)context;
     KQueueLock(m);
     mDNS_Lock(m);
@@ -8078,10 +8112,11 @@ mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, v
     CFRange range = { 0, c };
     int c1 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_Hostnames   ) != 0);
     int c2 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_Computername) != 0);
-    int c3 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DynamicDNS  ) != 0);
-    int c4 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DNS         ) != 0);
-    if (c && c - c1 - c2 - c3 - c4 == 0)
-        delay = mDNSPlatformOneSecond/10;  // If these were the only changes, shorten delay
+    int c3 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DNS         ) != 0);
+    int c4 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DynamicDNS  ) != 0);
+    int c5 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_BackToMyMac ) != 0);
+    int c6 = ChangedKeysHaveIPv4LL(changedKeys);
+    int c7 = 0;
 
     // Do immediate network changed processing for "p2p*" interfaces and
     // for interfaces with the IFEF_DIRECTLINK flag set.
@@ -8116,8 +8151,8 @@ mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, v
                 if (CFStringGetCString(CFArrayGetValueAtIndex(labels, 3), buf, sizeof(buf), kCFStringEncodingUTF8)
                     && (strstr(buf, "p2p") || (getExtendedFlags(buf) & IFEF_DIRECTLINK)))
                 {
-                    LogInfo("NetworkChanged: interface %s, not delaying network change", buf);
-                    changeNow = mDNStrue;
+                    LogInfo("NetworkChanged: interface %s qualifies for reduced change handling delay", buf);
+                    c7++;
                     CFRelease(labels);
                     break;
                 }
@@ -8126,8 +8161,22 @@ mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, v
         }
     }
 
-    mDNSBool btmmChanged = CFArrayContainsValue(changedKeys, range, NetworkChangedKey_BackToMyMac);
-    if (btmmChanged) delay = 0;
+    if (c && c - c1 - c2 - c3 - c4 - c5 - c6 - c7 == 0)
+        delay = mDNSPlatformOneSecond/10;  // If these were the only changes, shorten delay
+
+    // Immediately force a reconfig (esp. cache flush) if any of the following is true:
+    // 1. DNS Settings changed.
+    // 2  An interface changed that is explicitly IPv4 link local
+    // 3. There are P2P/IFEF_DIRECTLINK/IsCarPlaySSID changes
+    if (c3 || ChangedKeysHaveIPv4LL(changedKeys) || c7)
+    {
+        LogInfo("NetworkChanged: %s : Handling this change immediately",
+                c3 ? "DNS Settings Changed" :
+                c7 ? "P2P/IFEF_DIRECTLINK/IsCarPlaySSID Changed" :
+                "An interface changed that is explicitly IPv4 link local");
+        m->p->NetworkChanged = NonZeroTime(m->timenow);
+        delay = 0; // for the logs below.
+    }
 
     if (mDNS_LoggingEnabled)
     {
@@ -8138,32 +8187,31 @@ mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, v
             if (!CFStringGetCString(CFArrayGetValueAtIndex(changedKeys, i), buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
             LogInfo("***   NetworkChanged SC key: %s", buf);
         }
-        LogInfo("***   NetworkChanged   *** %d change%s %s%s%s%sdelay %d",
+        LogInfo("***   NetworkChanged   *** %d change%s %s%s%s%s%s%s%sdelay %d%s",
                 c, c>1 ? "s" : "",
                 c1 ? "(Local Hostname) " : "",
                 c2 ? "(Computer Name) "  : "",
-                c3 ? "(DynamicDNS) "     : "",
-                c4 ? "(DNS) "            : "",
-                changeNow ? 0 : delay);
+                c3 ? "(DNS) "            : "",
+                c4 ? "(DynamicDNS) "     : "",
+                c5 ? "(BTMM) "           : "",
+                c6 ? "(kSCValNetIPv4ConfigMethodLinkLocal) " : "",
+                c7 ? "(P2P/IFEF_DIRECTLINK/IsCarPlaySSID) "  : "",
+                delay,
+                (c4 || c5) ? " + SetKeyChainTimer" : "");
     }
 
-    if (!changeNow)
-        SetNetworkChanged(m, delay);
+    SetNetworkChanged(m, delay);
 
     // Other software might pick up these changes to register or browse in WAB or BTMM domains,
     // so in order for secure updates to be made to the server, make sure to read the keychain and
     // setup the DomainAuthInfo before handing the network change.
     // If we don't, then we will first try to register services in the clear, then later setup the
     // DomainAuthInfo, which is incorrect.
-    if (c3 || btmmChanged)
+    if (c4 || c5)
         SetKeyChainTimer(m, delay);
 
     mDNS_Unlock(m);
 
-    // If DNS settings changed, immediately force a reconfig (esp. cache flush)
-    // Similarly, if an interface changed that is explicitly IPv4 link local, immediately force a reconfig
-    if (c4 || ChangedKeysHaveIPv4LL(changedKeys) || changeNow) mDNSMacOSXNetworkChanged(m);
-
     KQueueUnlock(m, "NetworkChanged");
 }
 
@@ -8781,9 +8829,7 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag
         // the System Configuration Framework "network changed" event that we expect
         // to receive some time shortly after the kIOMessageSystemWillPowerOn message
         mDNS_Lock(m);
-        if (!m->p->NetworkChanged ||
-            m->p->NetworkChanged - NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2) < 0)
-            m->p->NetworkChanged = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2);
+        SetNetworkChanged(m, mDNSPlatformOneSecond * 2);
         mDNS_Unlock(m);
 
         break;
@@ -8839,13 +8885,16 @@ mDNSlocal void SnowLeopardPowerChanged(void *refcon, IOPMConnection connection,
             m->SleepLimit = 0;
         }
         LogSPS("SnowLeopardPowerChanged: Waking up, Acking Wakeup, SleepLimit %d SleepState %d", m->SleepLimit, m->SleepState);
-        // If the network notifications have already come before we got the wakeup, we ignored them and
-        // in case we get no more, we need to trigger one.
-        mDNS_Lock(m);
-        SetNetworkChanged(m, 2 * mDNSPlatformOneSecond);
-        mDNS_Unlock(m);
         // CPU Waking. Note: Can get this message repeatedly, as other subsystems power up or down.
-        if (m->SleepState != SleepState_Awake) PowerOn(m);
+        if (m->SleepState != SleepState_Awake)
+        {
+                       PowerOn(m);
+                       // If the network notifications have already come before we got the wakeup, we ignored them and
+                       // in case we get no more, we need to trigger one.
+                       mDNS_Lock(m);
+                       SetNetworkChanged(m, mDNSPlatformOneSecond * 2);
+                       mDNS_Unlock(m);
+        }
         IOPMConnectionAcknowledgeEvent(connection, token);
     }
     else
@@ -10415,9 +10464,37 @@ mDNSexport void mDNSPlatformDispatchAsync(mDNS *const m, void *context, AsyncDis
 #define OSX_VER_LEN     strlen(OSX_VER) 
 #define VER_NUM_LEN     2  // 2 digits of version number added to base string
 
+#define MODEL_COLOR           "ecolor="
+#define MODEL_COLOR_LEN       strlen(MODEL_COLOR)
+#define MODEL_RGB_VALUE_LEN   strlen("255,255,255") // 'r,g,b'
+
 // Bytes available in TXT record for model name after subtracting space for other 
 // fixed size strings and their length bytes.
-#define MAX_MODEL_NAME_LEN   (256 - (DEVINFO_MODEL_LEN + 1) - (OSX_VER_LEN + VER_NUM_LEN + 1))
+#define MAX_MODEL_NAME_LEN   (256 - (DEVINFO_MODEL_LEN + 1) - (OSX_VER_LEN + VER_NUM_LEN + 1) - (MODEL_COLOR_LEN + MODEL_RGB_VALUE_LEN + 1))
+
+mDNSlocal mDNSBool getModelIconColors(char *color)
+{
+       mDNSBool hasColor = mDNSfalse;
+       mDNSPlatformMemZero(color, MODEL_RGB_VALUE_LEN + 1);
+       
+#if !TARGET_OS_EMBEDDED && defined(kIOPlatformDeviceEnclosureColorKey)
+       mDNSu8   red      = 0;
+       mDNSu8   green    = 0;
+       mDNSu8   blue     = 0;
+
+       IOReturn rGetDeviceColor = IOPlatformGetDeviceColor(kIOPlatformDeviceEnclosureColorKey,
+                                                                                                               &red, &green, &blue);
+       if (kIOReturnSuccess == rGetDeviceColor)
+       {
+               // IOKit was able to get enclosure color for the current device.
+               hasColor = true;
+               snprintf(color, MODEL_RGB_VALUE_LEN + 1, "%d,%d,%d", red, green, blue);
+       }
+#endif // !TARGET_OS_EMBEDDED && defined(kIOPlatformDeviceEnclosureColorKey)
+       
+       return hasColor;
+}
+
 
 // Initialize device-info TXT record contents and return total length of record data.
 mDNSexport mDNSu32 initializeDeviceInfoTXT(mDNS *m, mDNSu8 *ptr)
@@ -10444,7 +10521,24 @@ mDNSexport mDNSu32 initializeDeviceInfoTXT(mDNS *m, mDNSu8 *ptr)
         snprintf(ver_num, VER_NUM_LEN + 1, "%d", OSXVers);
         mDNSPlatformMemCopy(ptr, ver_num, VER_NUM_LEN);
         ptr += VER_NUM_LEN;
+               
+               char rgb[MODEL_RGB_VALUE_LEN + 1]; // RGB value + null written by snprintf
+               if (getModelIconColors(rgb))
+               {
+                       len = strlen(rgb);
+                       *ptr = MODEL_COLOR_LEN + len; // length byte
+                       ptr++;
+               
+                       mDNSPlatformMemCopy(ptr, MODEL_COLOR, MODEL_COLOR_LEN);
+                       ptr += MODEL_COLOR_LEN;
+                       
+                       mDNSPlatformMemCopy(ptr, rgb, len);
+                       ptr += len;
+               }
     }
 
     return (ptr - bufferStart);
 }
+
+
+