X-Git-Url: https://git.saurik.com/apple/mdnsresponder.git/blobdiff_plain/95d7a4a31d5b4557b29fba1e0cdd09f1216ada8c..b8d5688b3ede9438aa8ad9679403f1d4e3faddb5:/mDNSMacOSX/mDNSMacOSX.c?ds=inline diff --git a/mDNSMacOSX/mDNSMacOSX.c b/mDNSMacOSX/mDNSMacOSX.c index 28d73f6..f904c8b 100644 --- a/mDNSMacOSX/mDNSMacOSX.c +++ b/mDNSMacOSX/mDNSMacOSX.c @@ -115,7 +115,6 @@ D2DStatus D2DTerminate() __attribute__((weak_import)); #include #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); } + + +