include $(MAKEFILEPATH)/pb_makefiles/platform.make
-MVERS = "mDNSResponder-522.92.1"
+MVERS = "mDNSResponder-541"
DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig"
VER =
}
// 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;
+ }
+ }
}
}
}
// 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)
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.
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);
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;
mDNSu8 Loopback; // Set if this is the loopback interface
mDNSu8 IgnoreIPv4LL; // Set if IPv4 Link-Local addresses have to be ignored.
mDNSu8 SendGoodbyes; // Send goodbyes on this interface while sleeping
+ mDNSBool DirectLink; // a direct link, indicating we can skip the probe for
+ // address records
};
#define SLE_DELETE 0x00000001
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 mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname);
+extern mStatus mDNSPlatformClearSPSMACAddr(void);
// mDNSPlatformTLSSetupCerts/mDNSPlatformTLSTearDownCerts used by dnsextd
extern mStatus mDNSPlatformTLSSetupCerts(void);
#define ValidSPSName(X) ((X)[0] >= 5 && mDNSIsDigit((X)[1]) && mDNSIsDigit((X)[2]) && mDNSIsDigit((X)[4]) && mDNSIsDigit((X)[5]))
#define SPSMetric(X) (!ValidSPSName(X) || PrototypeSPSName(X) ? 1000000 : \
((X)[1]-'0') * 100000 + ((X)[2]-'0') * 10000 + ((X)[4]-'0') * 1000 + ((X)[5]-'0') * 100 + ((X)[7]-'0') * 10 + ((X)[8]-'0'))
-
+#define LocalSPSMetric(X) ( (X)->SPSType * 10000 + (X)->SPSPortability * 100 + (X)->SPSMarginalPower)
#define SPSFeatures(X) ((X)[0] >= 13 && (X)[12] =='.' ? ((X)[13]-'0') : 0 )
#define MD5_DIGEST_LENGTH 16 /* digest length in bytes */
}
CFStringRef cfServiceName = CFStringCreateWithCString(NULL, serviceName, kCFStringEncodingUTF8);
- if (cfServiceName == NULL)
- {
- static int msg_count = 0;
- if (msg_count < 1000)
- {
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s Can not create CFString for serviceName %s", sPluginIdentifier, __FUNCTION__, serviceName);
- msg_count++;
- }
- return;
- }
if (flags & kDNSServiceFlagsAdd)
{
{
ethaddr_t eth;
char spsip[INET6_ADDRSTRLEN];
- int ret = 0;
- CFStringRef sckey = NULL;
- SCDynamicStoreRef store = NULL;
- CFMutableDictionaryRef dict = NULL;
+ int ret = 0;
+ CFStringRef sckey = NULL;
+ SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:StoreSPSMACAddress"), NULL, NULL);
+ SCDynamicStoreRef ipstore = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetIPv6Addresses"), NULL, NULL);
+ CFMutableDictionaryRef dict = NULL;
+ CFStringRef entityname = NULL;
+ CFDictionaryRef ipdict = NULL;
+ CFArrayRef addrs = NULL;
if (!authorized(&token))
{
return kmDNSHelperNotAuthorized;
}
+ if ((store == NULL) || (ipstore == NULL))
+ {
+ helplog(ASL_LEVEL_ERR, "Unable to access SC Dynamic Store");
+ return KERN_FAILURE;
+ }
+
// Get the MAC address of the Sleep Proxy Server
memset(eth, 0, sizeof(eth));
ret = do_mDNSGetRemoteMAC(port, family, spsaddr, eth, token);
CFStringRef macaddr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
CFDictionarySetValue(dict, CFSTR("MACAddress"), macaddr);
- CFRelease(macaddr);
+ if (NULL != macaddr) CFRelease(macaddr);
if( NULL == inet_ntop(family, (void *)spsaddr, spsip, sizeof(spsip)))
{
CFStringRef ipaddr = CFStringCreateWithCString(NULL, spsip, kCFStringEncodingUTF8);
CFDictionarySetValue(dict, CFSTR("IPAddress"), ipaddr);
- CFRelease(ipaddr);
+ if (NULL != ipaddr) CFRelease(ipaddr);
+ // Get the current IPv6 addresses on this interface and store them so NAs can be sent on wakeup
+ if ((entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/IPv6"), ifname)) != NULL)
+ {
+ if ((ipdict = SCDynamicStoreCopyValue(ipstore, entityname)) != NULL)
+ {
+ if((addrs = CFDictionaryGetValue(ipdict, CFSTR("Addresses"))) != NULL)
+ {
+ addrs = CFRetain(addrs);
+ CFDictionarySetValue(dict, CFSTR("RegisteredAddresses"), addrs);
+ }
+ }
+ }
SCDynamicStoreSetValue(store, sckey, dict);
fin:
- if (NULL != store)
- CFRelease(store);
- if (NULL != sckey)
- CFRelease(sckey);
- if (NULL != dict)
- CFRelease(dict);
+ if (store) CFRelease(store);
+ if (ipstore) CFRelease(ipstore);
+ if (sckey) CFRelease(sckey);
+ if (dict) CFRelease(dict);
+ if (ipdict) CFRelease(ipdict);
+ if (entityname) CFRelease(entityname);
+ if (addrs) CFRelease(addrs);
update_idle_timer();
return ret;
// via the D2D interface layer.
if (interface->InterfaceID == AWDLInterfaceID)
{
- LogInfo("D2D_start_advertising_interface: %s", interface->ifname);
- external_start_advertising_service(&interface->RR_A.resrec, NULL);
- external_start_advertising_service(&interface->RR_PTR.resrec, NULL);
+ // only log if we have a valid record to start advertising
+ if (interface->RR_A.resrec.RecordType || interface->RR_PTR.resrec.RecordType)
+ LogInfo("D2D_start_advertising_interface: %s", interface->ifname);
+
+ if (interface->RR_A.resrec.RecordType)
+ external_start_advertising_service(&interface->RR_A.resrec, NULL);
+ if (interface->RR_PTR.resrec.RecordType)
+ external_start_advertising_service(&interface->RR_PTR.resrec, NULL);
}
}
{
if (interface->InterfaceID == AWDLInterfaceID)
{
- LogInfo("D2D_stop_advertising_interface: %s", interface->ifname);
+ // only log if we have a valid record to stop advertising
+ if (interface->RR_A.resrec.RecordType || interface->RR_PTR.resrec.RecordType)
+ LogInfo("D2D_stop_advertising_interface: %s", interface->ifname);
+
if (interface->RR_A.resrec.RecordType)
external_stop_advertising_service(&interface->RR_A.resrec, NULL);
if (interface->RR_PTR.resrec.RecordType)
typedef struct D2DRecordListElem
{
struct D2DRecordListElem *next;
+ AuthRecord ar;
D2DServiceInstance instanceHandle;
D2DTransportType transportType;
- AuthRecord ar; // must be last in the structure to accomodate extra space
- // allocated for large records.
} D2DRecordListElem;
static D2DRecordListElem *D2DRecords = NULL; // List of records returned with D2DServiceFound events
if (resourceRecord->rrtype == kDNSType_SRV)
mDNSUpdatePacketFilter(NULL);
- if (resourceRecord->rrtype == kDNSServiceType_A || resourceRecord->rrtype == kDNSServiceType_AAAA)
- {
- LogInfo("external_start_advertising_service: ignoring address record");
- return;
- }
rhs = DNSNameCompressionBuildLHS(&lower, resourceRecord->rrtype);
end = DNSNameCompressionBuildRHS(rhs, resourceRecord);
PrintHelper(__func__, compression_lhs, rhs - compression_lhs, rhs, end - rhs);
if (resourceRecord->rrtype == kDNSType_SRV)
mDNSUpdatePacketFilter(resourceRecord);
- if (resourceRecord->rrtype == kDNSServiceType_A || resourceRecord->rrtype == kDNSServiceType_AAAA)
- {
- LogInfo("external_stop_advertising_service: ignoring address record");
- return;
- }
rhs = DNSNameCompressionBuildLHS(&lower, resourceRecord->rrtype);
end = DNSNameCompressionBuildRHS(rhs, resourceRecord);
PrintHelper(__func__, compression_lhs, rhs - compression_lhs, rhs, end - rhs);
// Note: When handling multiple packets in a batch, MUST reset InterfaceID before handling each packet
mDNSInterfaceID InterfaceID = mDNSNULL;
- //NetworkInterfaceInfo *intf = m->HostInterfaces;
- //while (intf && strcmp(intf->ifname, packetifname)) intf = intf->next;
-
NetworkInterfaceInfoOSX *intf = m->p->InterfaceList;
- while (intf && strcmp(intf->ifinfo.ifname, packetifname)) intf = intf->next;
+ while (intf)
+ {
+ if (intf->Exists && !strcmp(intf->ifinfo.ifname, packetifname))
+ break;
+ intf = intf->next;
+ }
// When going to sleep we deregister all our interfaces, but if the machine
// takes a few seconds to sleep we may continue to receive multicasts
mDNSSendKeepalive(sadd->ip.v6.b, dadd->ip.v6.b, lport->NotAnInteger, rport->NotAnInteger, seq, ack, win);
}
+mDNSexport mStatus mDNSPlatformClearSPSMACAddr(void)
+{
+ SCDynamicStoreRef store = NULL;
+ CFStringRef entityname = NULL;
+
+ if ((store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:ClearSPSMACAddress"), NULL, NULL)))
+ {
+ if ((entityname = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", "[^/]", "/BonjourSleepProxyAddress")))
+ {
+ if (SCDynamicStoreRemoveValue(store, entityname) == false)
+ LogMsg("mDNSPlatformClearSPSMACAddr: Unable to remove key");
+ }
+ }
+
+ if (entityname) CFRelease(entityname);
+ if (store) CFRelease(store);
+ return KERN_SUCCESS;
+}
+
mDNSexport mStatus mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname)
{
int family = (spsaddr->type == mDNSAddrType_IPv4) ? AF_INET : AF_INET6;
i->ifinfo.McastTxRx = mDNSfalse; // For now; will be set up later at the end of UpdateInterfaceList
i->ifinfo.Loopback = ((ifa->ifa_flags & IFF_LOOPBACK) != 0) ? mDNStrue : mDNSfalse;
i->ifinfo.IgnoreIPv4LL = ((eflags & IFEF_ARPLL) != 0) ? mDNSfalse : mDNStrue;
+ i->ifinfo.DirectLink = (eflags & IFEF_DIRECTLINK) ? mDNStrue: mDNSfalse;
i->next = mDNSNULL;
i->m = m;
i->Flashing = mDNSfalse;
i->Occulting = mDNSfalse;
i->D2DInterface = (eflags & IFEF_LOCALNET_PRIVATE) ? mDNStrue: mDNSfalse;
- i->DirectLink = (eflags & IFEF_DIRECTLINK) ? mDNStrue: mDNSfalse;
if (eflags & IFEF_AWDL)
{
AWDLInterfaceID = i->ifinfo.InterfaceID;
// mDNS_RegisterInterface() changes the probe delay from 1/2 second to 5 seconds and
// logs a warning message to system.log noting frequent interface transitions.
// Same logic applies when IFEF_DIRECTLINK flag is set on the interface.
- if ((strncmp(i->ifinfo.ifname, "p2p", 3) == 0) || i->DirectLink)
+ if ((strncmp(i->ifinfo.ifname, "p2p", 3) == 0) || i->ifinfo.DirectLink)
{
LogInfo("SetupActiveInterfaces: %s interface registering %s %s", i->ifinfo.ifname,
i->Flashing ? " (Flashing)" : "",
// stale data returned to the application even after the interface is removed. The application
// then starts to send data but the new interface is not yet created.
// Same logic applies when IFEF_DIRECTLINK flag is set on the interface.
- if ((strncmp(i->ifinfo.ifname, "p2p", 3) == 0) || i->DirectLink)
+ if ((strncmp(i->ifinfo.ifname, "p2p", 3) == 0) || i->ifinfo.DirectLink)
{
LogInfo("ClearInactiveInterfaces: %s interface deregistering %s %s", i->ifinfo.ifname,
i->Flashing ? " (Flashing)" : "",
// computed value (currently 40 "Primary Network Infrastructure Software" or 80 "Incidentally Available Software")
if (sps && OfferSleepProxyService && OfferSleepProxyService < 100) sps = OfferSleepProxyService;
+#ifdef NO_APPLETV_SLEEP_PROXY_ON_WIFI
+ // AppleTVs are not reliable sleep proxy servers on WiFi. Do not offer to be a BSP if the WiFi interface is active.
+ if (IsAppleTV())
+ {
+ NetworkInterfaceInfo *intf = mDNSNULL;
+ mDNSEthAddr bssid = zeroEthAddr;
+ for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
+ {
+ bssid = GetBSSID(intf->ifname);
+ if (!mDNSSameEthAddress(&bssid, &zeroEthAddr))
+ {
+ LogMsg("SetSPS: AppleTV on WiFi - not advertising BSP services");
+ sps = 0;
+ break;
+ }
+ }
+ }
+#endif // NO_APPLETV_SLEEP_PROXY_ON_WIFI
+
mDNSCoreBeSleepProxyServer(m, sps, SPMetricPortability, SPMetricMarginalPower, SPMetricTotalPower, SPMetricFeatures);
}
<true/>
<key>com.apple.private.snhelper</key>
<true/>
+ <key>com.apple.telephony.cupolicy-monitor-access</key>
+ <true/>
</dict>
</plist>
(global-name "com.apple.wifi.manager")
(global-name "com.apple.commcenter.cupolicy.xpc")
(global-name "com.apple.blued")
+ (global-name "com.apple.mobilegestalt.xpc")
(global-name "com.apple.snhelper"))
(allow mach-register
);
GCC_STRICT_ALIASING = YES;
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
"_BUILDING_XCODE_PROJECT_=1",
);
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
MVERS = "\"(Engineering Build)\"";
OTHER_CFLAGS = (
"-DUSE_SYSTEMCONFIGURATION_PRIVATE_HEADERS",
#endif
}
+ // If interface is a direct link, address record will be marked as kDNSRecordTypeKnownUnique
+ // and skip the probe phase of the probe/announce packet sequence.
+ intf->coreIntf.DirectLink = mDNSfalse;
+
// The interface is all ready to go, let's register it with the mDNS core.
if (err == 0)
err = mDNS_RegisterInterface(m, &intf->coreIntf, mDNSfalse);
return mStatus_NoError;
}
+mDNSexport mStatus mDNSPlatformClearSPSMACAddr(void)
+{
+ return mStatus_NoError;
+}
+
mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
{
(void) sock; // unused
*/
#ifndef _DNS_SD_H
-#define _DNS_SD_H 5229201
+#define _DNS_SD_H 5410000
#ifdef __cplusplus
extern "C" {
(void) ifname; // Unused
}
+mDNSexport mStatus mDNSPlatformClearSPSMACAddr(void)
+ {
+ }
+
mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti)
{
(void) m; // Unused
require_noerr( err, exit );
}
+ // If interface is a direct link, address record will be marked as kDNSRecordTypeKnownUnique
+ // and skip the probe phase of the probe/announce packet sequence.
+ ifd->interfaceInfo.DirectLink = mDNSfalse;
+
err = mDNS_RegisterInterface( inMDNS, &ifd->interfaceInfo, mDNSfalse );
require_noerr( err, exit );
ifd->hostRegistered = mDNStrue;