summaryrefslogtreecommitdiffstats
path: root/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c
diff options
context:
space:
mode:
Diffstat (limited to 'mDNSResponder/mDNSMacOSX/mDNSMacOSX.c')
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSMacOSX.c2900
1 files changed, 1117 insertions, 1783 deletions
diff --git a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c
index 84e9de8c..ced72a69 100644
--- a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c
+++ b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.c
@@ -29,7 +29,7 @@
#include "uDNS.h"
#include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform
#include "dns_sd.h" // For mDNSInterface_LocalOnly etc.
-#include "dns_sd_private.h"
+#include "dns_sd_internal.h"
#include "PlatformCommon.h"
#include "uds_daemon.h"
#include "CryptoSupport.h"
@@ -83,7 +83,6 @@
#include "helper.h"
#include "P2PPacketFilter.h"
-#include <asl.h>
#include <SystemConfiguration/SCPrivate.h>
#if TARGET_OS_IPHONE
@@ -95,32 +94,12 @@
// Include definition of opaque_presence_indication for KEV_DL_NODE_PRESENCE handling logic.
#include <Kernel/IOKit/apple80211/apple80211_var.h>
+#include <network_information.h> // for nwi_state
#if APPLE_OSX_mDNSResponder
-#include <DeviceToDeviceManager/DeviceToDeviceManager.h>
#include <AWACS.h>
#include <ne_session.h> // for ne_session_set_socket_attributes()
-#if !NO_D2D
-#include "BLE.h"
-
-D2DStatus D2DInitialize(CFRunLoopRef runLoop, D2DServiceCallback serviceCallback, void* userData) __attribute__((weak_import));
-D2DStatus D2DRetain(D2DServiceInstance instanceHandle, D2DTransportType transportType) __attribute__((weak_import));
-D2DStatus D2DStopAdvertisingPairOnTransport(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize, D2DTransportType transport) __attribute__((weak_import));
-D2DStatus D2DRelease(D2DServiceInstance instanceHandle, D2DTransportType transportType) __attribute__((weak_import));
-D2DStatus D2DStartAdvertisingPairOnTransport(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize, D2DTransportType transport) __attribute__((weak_import));
-D2DStatus D2DStartBrowsingForKeyOnTransport(const Byte *key, const size_t keySize, D2DTransportType transport) __attribute__((weak_import));
-D2DStatus D2DStopBrowsingForKeyOnTransport(const Byte *key, const size_t keySize, D2DTransportType transport) __attribute__((weak_import));
-void D2DStartResolvingPairOnTransport(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize, D2DTransportType transport) __attribute__((weak_import));
-void D2DStopResolvingPairOnTransport(const Byte *key, const size_t keySize, const Byte *value, const size_t valueSize, D2DTransportType transport) __attribute__((weak_import));
-D2DStatus D2DTerminate() __attribute__((weak_import));
-
-void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize);
-void xD2DRemoveFromCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize);
-
-#endif // ! NO_D2D
-
#else
-#define NO_D2D 1
#define NO_AWACS 1
#endif // APPLE_OSX_mDNSResponder
@@ -128,6 +107,10 @@ void xD2DRemoveFromCache(mDNS *const m, D2DStatus result, D2DServiceInstance ins
#include <IOKit/platform/IOPlatformSupportPrivate.h>
#endif // APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
+#ifdef UNIT_TEST
+#include "unittest.h"
+#endif
+
#define kInterfaceSpecificOption "interface="
#define mDNS_IOREG_KEY "mDNS_KEY"
@@ -207,952 +190,6 @@ const char dnsprefix[] = "dns:";
static CFArrayRef privateDnsArray = NULL;
// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - D2D Support
-#endif
-
-#if !NO_D2D
-
-mDNSexport void D2D_start_advertising_interface(NetworkInterfaceInfo *interface)
-{
- // AWDL wants the address and reverse address PTR record communicated
- // via the D2D interface layer.
- if (interface->InterfaceID == AWDLInterfaceID)
- {
- // 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, 0);
- if (interface->RR_PTR.resrec.RecordType)
- external_start_advertising_service(&interface->RR_PTR.resrec, 0);
- }
-}
-
-mDNSexport void D2D_stop_advertising_interface(NetworkInterfaceInfo *interface)
-{
- if (interface->InterfaceID == AWDLInterfaceID)
- {
- // 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, 0);
- if (interface->RR_PTR.resrec.RecordType)
- external_stop_advertising_service(&interface->RR_PTR.resrec, 0);
- }
-}
-
-// If record would have been advertised to the D2D plugin layer, stop that advertisement.
-mDNSexport void D2D_stop_advertising_record(AuthRecord *ar)
-{
- DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(ar->ARType);
- if (callExternalHelpers(ar->resrec.InterfaceID, ar->resrec.name, flags))
- {
- external_stop_advertising_service(&ar->resrec, flags);
- }
-}
-
-// If record should be advertised to the D2D plugin layer, start that advertisement.
-mDNSexport void D2D_start_advertising_record(AuthRecord *ar)
-{
- DNSServiceFlags flags = deriveD2DFlagsFromAuthRecType(ar->ARType);
- if (callExternalHelpers(ar->resrec.InterfaceID, ar->resrec.name, flags))
- {
- external_start_advertising_service(&ar->resrec, flags);
- }
-}
-
-// Name compression items for fake packet version number 1
-static const mDNSu8 compression_packet_v1 = 0x01;
-
-static DNSMessage compression_base_msg = { { {{0}}, {{0}}, 2, 0, 0, 0 }, "\x04_tcp\x05local\x00\x00\x0C\x00\x01\x04_udp\xC0\x11\x00\x0C\x00\x01" };
-static mDNSu8 *const compression_limit = (mDNSu8 *) &compression_base_msg + sizeof(DNSMessage);
-static mDNSu8 *const compression_lhs = (mDNSu8 *const) compression_base_msg.data + 27;
-
-mDNSlocal void FreeD2DARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
-mDNSlocal void PrintHex(mDNSu8 *data, mDNSu16 len);
-
-typedef struct D2DRecordListElem
-{
- struct D2DRecordListElem *next;
- 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
-
-typedef struct D2DBrowseListElem
-{
- struct D2DBrowseListElem *next;
- domainname name;
- mDNSu16 type;
- unsigned int refCount;
-} D2DBrowseListElem;
-
-D2DBrowseListElem* D2DBrowseList = NULL;
-
-mDNSlocal mDNSu8 *putVal16(mDNSu8 *ptr, mDNSu16 val)
-{
- ptr[0] = (mDNSu8)((val >> 8 ) & 0xFF);
- ptr[1] = (mDNSu8)((val ) & 0xFF);
- return ptr + sizeof(mDNSu16);
-}
-
-mDNSlocal mDNSu8 *putVal32(mDNSu8 *ptr, mDNSu32 val)
-{
- ptr[0] = (mDNSu8)((val >> 24) & 0xFF);
- ptr[1] = (mDNSu8)((val >> 16) & 0xFF);
- ptr[2] = (mDNSu8)((val >> 8) & 0xFF);
- ptr[3] = (mDNSu8)((val ) & 0xFF);
- return ptr + sizeof(mDNSu32);
-}
-
-mDNSlocal void DomainnameToLower(const domainname * const in, domainname * const out)
-{
- const mDNSu8 * const start = (const mDNSu8 * const)in;
- mDNSu8 *ptr = (mDNSu8*)start;
- while(*ptr)
- {
- mDNSu8 c = *ptr;
- out->c[ptr-start] = *ptr;
- ptr++;
- for (; c; c--,ptr++) out->c[ptr-start] = mDNSIsUpperCase(*ptr) ? (*ptr - 'A' + 'a') : *ptr;
- }
- out->c[ptr-start] = *ptr;
-}
-
-mDNSlocal mDNSu8 * DNSNameCompressionBuildLHS(const domainname* typeDomain, DNS_TypeValues qtype)
-{
- mDNSu8 *ptr = putDomainNameAsLabels(&compression_base_msg, compression_lhs, compression_limit, typeDomain);
- if (!ptr) return ptr;
- *ptr = (qtype >> 8) & 0xff;
- ptr += 1;
- *ptr = qtype & 0xff;
- ptr += 1;
- *ptr = compression_packet_v1;
- return ptr + 1;
-}
-
-mDNSlocal mDNSu8 * DNSNameCompressionBuildRHS(mDNSu8 *start, const ResourceRecord *const resourceRecord)
-{
- return putRData(&compression_base_msg, start, compression_limit, resourceRecord);
-}
-
-#define PRINT_DEBUG_BYTES_LIMIT 64 // set limit on number of record bytes printed for debugging
-
-mDNSlocal void PrintHex(mDNSu8 *data, mDNSu16 len)
-{
- mDNSu8 *end;
- char buffer[49] = {0};
- char *bufend = buffer + sizeof(buffer);
-
- if (len > PRINT_DEBUG_BYTES_LIMIT)
- {
- LogInfo(" (limiting debug output to %d bytes)", PRINT_DEBUG_BYTES_LIMIT);
- len = PRINT_DEBUG_BYTES_LIMIT;
- }
- end = data + len;
-
- while(data < end)
- {
- char *ptr = buffer;
- for(; data < end && ptr < bufend-1; ptr+=3,data++)
- mDNS_snprintf(ptr, bufend - ptr, "%02X ", *data);
- LogInfo(" %s", buffer);
- }
-}
-
-mDNSlocal void PrintHelper(const char *const tag, mDNSu8 *lhs, mDNSu16 lhs_len, mDNSu8 *rhs, mDNSu16 rhs_len)
-{
- if (!mDNS_LoggingEnabled) return;
-
- LogInfo("%s:", tag);
- LogInfo(" LHS: (%d bytes)", lhs_len);
- PrintHex(lhs, lhs_len);
-
- if (!rhs) return;
-
- LogInfo(" RHS: (%d bytes)", rhs_len);
- PrintHex(rhs, rhs_len);
-}
-
-mDNSlocal void FreeD2DARElemCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
- (void)m; // unused
- if (result == mStatus_MemFree)
- {
- D2DRecordListElem **ptr = &D2DRecords;
- D2DRecordListElem *tmp;
- while (*ptr && &(*ptr)->ar != rr) ptr = &(*ptr)->next;
- if (!*ptr) { LogMsg("FreeD2DARElemCallback: Could not find in D2DRecords: %s", ARDisplayString(m, rr)); return; }
- LogInfo("FreeD2DARElemCallback: Found in D2DRecords: %s", ARDisplayString(m, rr));
- tmp = *ptr;
- *ptr = (*ptr)->next;
- // Just because we stoppped browsing, doesn't mean we should tear down the PAN connection.
- mDNSPlatformMemFree(tmp);
- }
-}
-
-mDNSexport void external_connection_release(const domainname *instance)
-{
- (void) instance;
- D2DRecordListElem *ptr = D2DRecords;
-
- for ( ; ptr ; ptr = ptr->next)
- {
- if ((ptr->ar.resrec.rrtype == kDNSServiceType_PTR) &&
- SameDomainName(&ptr->ar.rdatastorage.u.name, instance))
- {
- LogInfo("external_connection_release: Calling D2DRelease(instanceHandle = %p, transportType = %d",
- ptr->instanceHandle, ptr->transportType);
- if (D2DRelease) D2DRelease(ptr->instanceHandle, ptr->transportType);
- }
- }
-}
-
-mDNSlocal void xD2DClearCache(const domainname *regType, DNS_TypeValues qtype)
-{
- D2DRecordListElem *ptr = D2DRecords;
- for ( ; ptr ; ptr = ptr->next)
- {
- if ((ptr->ar.resrec.rrtype == qtype) && SameDomainName(&ptr->ar.namestorage, regType))
- {
- LogInfo("xD2DClearCache: Clearing cache record and deregistering %s", ARDisplayString(&mDNSStorage, &ptr->ar));
- mDNS_Deregister(&mDNSStorage, &ptr->ar);
- }
- }
-}
-
-mDNSlocal D2DBrowseListElem ** D2DFindInBrowseList(const domainname *const name, mDNSu16 type)
-{
- D2DBrowseListElem **ptr = &D2DBrowseList;
-
- for ( ; *ptr; ptr = &(*ptr)->next)
- if ((*ptr)->type == type && SameDomainName(&(*ptr)->name, name))
- break;
-
- return ptr;
-}
-
-mDNSlocal unsigned int D2DBrowseListRefCount(const domainname *const name, mDNSu16 type)
-{
- D2DBrowseListElem **ptr = D2DFindInBrowseList(name, type);
- return *ptr ? (*ptr)->refCount : 0;
-}
-
-mDNSlocal void D2DBrowseListRetain(const domainname *const name, mDNSu16 type)
-{
- D2DBrowseListElem **ptr = D2DFindInBrowseList(name, type);
-
- if (!*ptr)
- {
- *ptr = mDNSPlatformMemAllocate(sizeof(**ptr));
- mDNSPlatformMemZero(*ptr, sizeof(**ptr));
- (*ptr)->type = type;
- AssignDomainName(&(*ptr)->name, name);
- }
- (*ptr)->refCount += 1;
-
- LogInfo("D2DBrowseListRetain: %##s %s refcount now %u", (*ptr)->name.c, DNSTypeName((*ptr)->type), (*ptr)->refCount);
-}
-
-// Returns true if found in list, false otherwise
-mDNSlocal bool D2DBrowseListRelease(const domainname *const name, mDNSu16 type)
-{
- D2DBrowseListElem **ptr = D2DFindInBrowseList(name, type);
-
- if (!*ptr) { LogMsg("D2DBrowseListRelease: Didn't find %##s %s in list", name->c, DNSTypeName(type)); return false; }
-
- (*ptr)->refCount -= 1;
-
- LogInfo("D2DBrowseListRelease: %##s %s refcount now %u", (*ptr)->name.c, DNSTypeName((*ptr)->type), (*ptr)->refCount);
-
- if (!(*ptr)->refCount)
- {
- D2DBrowseListElem *tmp = *ptr;
- *ptr = (*ptr)->next;
- mDNSPlatformMemFree(tmp);
- }
- return true;
-}
-
-mDNSlocal mStatus xD2DParse(mDNS *const m, const mDNSu8 * const lhs, const mDNSu16 lhs_len, const mDNSu8 * const rhs, const mDNSu16 rhs_len, D2DRecordListElem **D2DListp)
-{
- // Sanity check that key array (lhs) has one domain name, followed by the record type and single byte D2D
- // plugin protocol version number.
- // Note, we don't have a DNSMessage pointer at this point, so just pass in the lhs value as the lower bound
- // of the input bytes we are processing. skipDomainName() does not try to follow name compression pointers,
- // so it is safe to pass it the key byte array since it will stop parsing the DNS name and return a pointer
- // to the byte after the first name compression pointer it encounters.
- const mDNSu8 *keyp = skipDomainName((const DNSMessage *const) lhs, lhs, lhs + lhs_len);
-
- // There should be 3 bytes remaining in a valid key,
- // two for the DNS record type, and one for the D2D protocol version number.
- if (keyp == NULL || (keyp + 3 != (lhs + lhs_len)))
- {
- LogInfo("xD2DParse: Could not parse DNS name in key");
- return mStatus_Incompatible;
- }
- keyp += 2; // point to D2D compression packet format version byte
- if (*keyp != compression_packet_v1)
- {
- LogInfo("xD2DParse: Invalid D2D packet version: %d", *keyp);
- return mStatus_Incompatible;
- }
-
- if (mDNS_LoggingEnabled)
- {
- LogInfo("%s", __func__);
- LogInfo(" Static Bytes: (%d bytes)", compression_lhs - (mDNSu8*)&compression_base_msg);
- PrintHex((mDNSu8*)&compression_base_msg, compression_lhs - (mDNSu8*)&compression_base_msg);
- }
-
- mDNSu8 *ptr = compression_lhs; // pointer to the end of our fake packet
-
- // Check to make sure we're not going to go past the end of the DNSMessage data
- // 7 = 2 for CLASS (-1 for our version) + 4 for TTL + 2 for RDLENGTH
- if (ptr + lhs_len - 7 + rhs_len >= compression_limit) return mStatus_NoMemoryErr;
-
- // Copy the LHS onto our fake wire packet
- mDNSPlatformMemCopy(ptr, lhs, lhs_len);
- ptr += lhs_len - 1;
-
- // Check the 'fake packet' version number, to ensure that we know how to decompress this data
- if (*ptr != compression_packet_v1) return mStatus_Incompatible;
-
- // two bytes of CLASS
- ptr = putVal16(ptr, kDNSClass_IN | kDNSClass_UniqueRRSet);
-
- // four bytes of TTL
- ptr = putVal32(ptr, 120);
-
- // Copy the RHS length into the RDLENGTH of our fake wire packet
- ptr = putVal16(ptr, rhs_len);
-
- // Copy the RHS onto our fake wire packet
- mDNSPlatformMemCopy(ptr, rhs, rhs_len);
- ptr += rhs_len;
-
- if (mDNS_LoggingEnabled)
- {
- LogInfo(" Our Bytes (%d bytes): ", ptr - compression_lhs);
- PrintHex(compression_lhs, ptr - compression_lhs);
- }
-
- ptr = (mDNSu8 *) GetLargeResourceRecord(m, &compression_base_msg, compression_lhs, ptr, mDNSInterface_Any, kDNSRecordTypePacketAns, &m->rec);
- if (!ptr || m->rec.r.resrec.RecordType == kDNSRecordTypePacketNegative)
- {
- LogMsg("xD2DParse: failed to get large RR");
- m->rec.r.resrec.RecordType = 0;
- return mStatus_UnknownErr;
- }
- else
- {
- LogInfo("xD2DParse: got rr: %s", CRDisplayString(m, &m->rec.r));
- }
-
- *D2DListp = mDNSPlatformMemAllocate(sizeof(D2DRecordListElem) + (m->rec.r.resrec.rdlength <= sizeof(RDataBody) ? 0 : m->rec.r.resrec.rdlength - sizeof(RDataBody)));
- if (!*D2DListp) return mStatus_NoMemoryErr;
-
- AuthRecord *rr = &(*D2DListp)->ar;
- mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSInterface_P2P, m->rec.r.resrec.rrtype, 7200, kDNSRecordTypeShared, AuthRecordP2P, FreeD2DARElemCallback, NULL);
- AssignDomainName(&rr->namestorage, &m->rec.namestorage);
- rr->resrec.rdlength = m->rec.r.resrec.rdlength;
- rr->resrec.rdata->MaxRDLength = m->rec.r.resrec.rdlength;
- mDNSPlatformMemCopy(rr->resrec.rdata->u.data, m->rec.r.resrec.rdata->u.data, m->rec.r.resrec.rdlength);
- rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
- SetNewRData(&rr->resrec, mDNSNULL, 0); // Sets rr->rdatahash for us
-
- m->rec.r.resrec.RecordType = 0; // Mark m->rec as no longer in use
-
- return mStatus_NoError;
-}
-
-mDNSexport void xD2DAddToCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
-{
- if (result == kD2DSuccess)
- {
- if ( key == NULL || value == NULL || keySize == 0 || valueSize == 0) { LogMsg("xD2DAddToCache: NULL Byte * passed in or length == 0"); return; }
-
- mStatus err;
- D2DRecordListElem *ptr = NULL;
-
- err = xD2DParse(m, (const mDNSu8 * const)key, (const mDNSu16)keySize, (const mDNSu8 * const)value, (const mDNSu16)valueSize, &ptr);
- if (err)
- {
- LogMsg("xD2DAddToCache: xD2DParse returned error: %d", err);
- PrintHelper(__func__, (mDNSu8 *)key, (mDNSu16)keySize, (mDNSu8 *)value, (mDNSu16)valueSize);
- if (ptr)
- mDNSPlatformMemFree(ptr);
- return;
- }
-
- // If the record was created based on a BLE beacon, update the interface index to indicate
- // this and thus match BLE specific queries.
- if (transportType == D2DBLETransport)
- ptr->ar.resrec.InterfaceID = mDNSInterface_BLE;
-
- err = mDNS_Register(m, &ptr->ar);
- if (err)
- {
- LogMsg("xD2DAddToCache: mDNS_Register returned error %d for %s", err, ARDisplayString(m, &ptr->ar));
- mDNSPlatformMemFree(ptr);
- return;
- }
-
- LogInfo("xD2DAddToCache: mDNS_Register succeeded for %s", ARDisplayString(m, &ptr->ar));
- ptr->instanceHandle = instanceHandle;
- ptr->transportType = transportType;
- ptr->next = D2DRecords;
- D2DRecords = ptr;
- }
- else
- LogMsg("xD2DAddToCache: Unexpected result %d", result);
-}
-
-mDNSlocal D2DRecordListElem * xD2DFindInList(mDNS *const m, const Byte *const key, const size_t keySize, const Byte *const value, const size_t valueSize)
-{
- D2DRecordListElem *ptr = D2DRecords;
- D2DRecordListElem *arptr = NULL;
-
- if ( key == NULL || value == NULL || keySize == 0 || valueSize == 0) { LogMsg("xD2DFindInList: NULL Byte * passed in or length == 0"); return NULL; }
-
- mStatus err = xD2DParse(m, (const mDNSu8 *const)key, (const mDNSu16)keySize, (const mDNSu8 *const)value, (const mDNSu16)valueSize, &arptr);
- if (err)
- {
- LogMsg("xD2DFindInList: xD2DParse returned error: %d", err);
- PrintHelper(__func__, (mDNSu8 *)key, (mDNSu16)keySize, (mDNSu8 *)value, (mDNSu16)valueSize);
- if (arptr)
- mDNSPlatformMemFree(arptr);
- return NULL;
- }
-
- while (ptr)
- {
- if (IdenticalResourceRecord(&arptr->ar.resrec, &ptr->ar.resrec)) break;
- ptr = ptr->next;
- }
-
- if (!ptr) LogMsg("xD2DFindInList: Could not find in D2DRecords: %s", ARDisplayString(m, &arptr->ar));
- mDNSPlatformMemFree(arptr);
- return ptr;
-}
-
-mDNSexport void xD2DRemoveFromCache(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
-{
- (void)transportType; // We don't care about this, yet.
- (void)instanceHandle; // We don't care about this, yet.
-
- if (result == kD2DSuccess)
- {
- D2DRecordListElem *ptr = xD2DFindInList(m, key, keySize, value, valueSize);
- if (ptr)
- {
- LogInfo("xD2DRemoveFromCache: Remove from cache: %s", ARDisplayString(m, &ptr->ar));
- mDNS_Deregister(m, &ptr->ar);
- }
- }
- else
- LogMsg("xD2DRemoveFromCache: Unexpected result %d", result);
-}
-
-mDNSlocal void xD2DServiceResolved(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
-{
- (void)m;
- (void)key;
- (void)keySize;
- (void)value;
- (void)valueSize;
-
- if (result == kD2DSuccess)
- {
- LogInfo("xD2DServiceResolved: Starting up PAN connection for %p", instanceHandle);
- if (D2DRetain) D2DRetain(instanceHandle, transportType);
- }
- else LogMsg("xD2DServiceResolved: Unexpected result %d", result);
-}
-
-mDNSlocal void xD2DRetainHappened(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
-{
- (void)m;
- (void)instanceHandle;
- (void)transportType;
- (void)key;
- (void)keySize;
- (void)value;
- (void)valueSize;
-
- if (result == kD2DSuccess) LogInfo("xD2DRetainHappened: Opening up PAN connection for %p", instanceHandle);
- else LogMsg("xD2DRetainHappened: Unexpected result %d", result);
-}
-
-mDNSlocal void xD2DReleaseHappened(mDNS *const m, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
-{
- (void)m;
- (void)instanceHandle;
- (void)transportType;
- (void)key;
- (void)keySize;
- (void)value;
- (void)valueSize;
-
- if (result == kD2DSuccess) LogInfo("xD2DReleaseHappened: Closing PAN connection for %p", instanceHandle);
- else LogMsg("xD2DReleaseHappened: Unexpected result %d", result);
-}
-
-mDNSlocal void xD2DServiceCallback(D2DServiceEvent event, D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize, void *userData)
-{
- mDNS *m = (mDNS *) userData;
- const char *eventString = "unknown";
-
- KQueueLock(m);
-
- if (keySize > 0xFFFF) LogMsg("xD2DServiceCallback: keySize too large: %u", keySize);
- if (valueSize > 0xFFFF) LogMsg("xD2DServiceCallback: valueSize too large: %u", valueSize);
-
- switch (event)
- {
- case D2DServiceFound:
- eventString = "D2DServiceFound";
- break;
- case D2DServiceLost:
- eventString = "D2DServiceLost";
- break;
- case D2DServiceResolved:
- eventString = "D2DServiceResolved";
- break;
- case D2DServiceRetained:
- eventString = "D2DServiceRetained";
- break;
- case D2DServiceReleased:
- eventString = "D2DServiceReleased";
- break;
- default:
- break;
- }
-
- LogInfo("xD2DServiceCallback: event=%s result=%d instanceHandle=%p transportType=%d LHS=%p (%u) RHS=%p (%u) userData=%p", eventString, result, instanceHandle, transportType, key, keySize, value, valueSize, userData);
- PrintHelper(__func__, (mDNSu8 *)key, (mDNSu16)keySize, (mDNSu8 *)value, (mDNSu16)valueSize);
-
- switch (event)
- {
- case D2DServiceFound:
- xD2DAddToCache(m, result, instanceHandle, transportType, key, keySize, value, valueSize);
- break;
- case D2DServiceLost:
- xD2DRemoveFromCache(m, result, instanceHandle, transportType, key, keySize, value, valueSize);
- break;
- case D2DServiceResolved:
- xD2DServiceResolved(m, result, instanceHandle, transportType, key, keySize, value, valueSize);
- break;
- case D2DServiceRetained:
- xD2DRetainHappened(m, result, instanceHandle, transportType, key, keySize, value, valueSize);
- break;
- case D2DServiceReleased:
- xD2DReleaseHappened(m, result, instanceHandle, transportType, key, keySize, value, valueSize);
- break;
- default:
- break;
- }
-
- // Need to tickle the main kqueue loop to potentially handle records we removed or added.
- KQueueUnlock(m, "xD2DServiceCallback");
-}
-
-// Map interface index and flags to a specific D2D transport type or D2DTransportMax if all plugins
-// should be called.
-// When D2DTransportMax is returned, if a specific transport should not be called, *excludedTransportType
-// will be set to the excluded transport value, otherwise, it will be set to D2DTransportMax.
-// If the return value is not D2DTransportMax, excludedTransportType is undefined.
-
-mDNSlocal D2DTransportType xD2DInterfaceToTransportType(mDNSInterfaceID InterfaceID, DNSServiceFlags flags, D2DTransportType * excludedTransportType)
-{
- NetworkInterfaceInfoOSX *info;
-
- // Default exludes the D2DAWDLTransport when D2DTransportMax is returned.
- *excludedTransportType = D2DAWDLTransport;
-
- // Call all D2D plugins when both kDNSServiceFlagsIncludeP2P and kDNSServiceFlagsIncludeAWDL are set.
- if ((flags & kDNSServiceFlagsIncludeP2P) && (flags & kDNSServiceFlagsIncludeAWDL))
- {
- LogInfo("xD2DInterfaceToTransportType: returning D2DTransportMax (including AWDL) since both kDNSServiceFlagsIncludeP2P and kDNSServiceFlagsIncludeAWDL are set");
- *excludedTransportType = D2DTransportMax;
- return D2DTransportMax;
- }
- // Call all D2D plugins (exlcluding AWDL) when only kDNSServiceFlagsIncludeP2P is set.
- else if (flags & kDNSServiceFlagsIncludeP2P)
- {
- LogInfo("xD2DInterfaceToTransportType: returning D2DTransportMax (excluding AWDL) since only kDNSServiceFlagsIncludeP2P is set");
- return D2DTransportMax;
- }
- // Call AWDL D2D plugin when only kDNSServiceFlagsIncludeAWDL is set.
- else if (flags & kDNSServiceFlagsIncludeAWDL)
- {
- LogInfo("xD2DInterfaceToTransportType: returning D2DAWDLTransport since only kDNSServiceFlagsIncludeAWDL is set");
- return D2DAWDLTransport;
- }
-
- if (InterfaceID == mDNSInterface_P2P)
- {
- LogInfo("xD2DInterfaceToTransportType: returning D2DTransportMax (excluding AWDL) for interface index mDNSInterface_P2P");
- return D2DTransportMax;
- }
-
- // Compare to cached AWDL interface ID.
- if (AWDLInterfaceID && (InterfaceID == AWDLInterfaceID))
- {
- LogInfo("xD2DInterfaceToTransportType: returning D2DAWDLTransport for interface index %d", InterfaceID);
- return D2DAWDLTransport;
- }
-
- info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
- if (info == NULL)
- {
- LogInfo("xD2DInterfaceToTransportType: Invalid interface index %d", InterfaceID);
- return D2DTransportMax;
- }
-
- // Recognize AirDrop specific p2p* interface based on interface name.
- if (strncmp(info->ifinfo.ifname, "p2p", 3) == 0)
- {
- LogInfo("xD2DInterfaceToTransportType: returning D2DWifiPeerToPeerTransport for interface index %d", InterfaceID);
- return D2DWifiPeerToPeerTransport;
- }
-
- // Currently there is no way to identify Bluetooth interface by name,
- // since they use "en*" based name strings.
-
- LogInfo("xD2DInterfaceToTransportType: returning default D2DTransportMax for interface index %d", InterfaceID);
- return D2DTransportMax;
-}
-
-// Similar to callExternalHelpers(), but without the checks for the BLE specific interface or flags.
-// It's assumed that the domain was already verified to be .local once we are at this level.
-mDNSlocal mDNSBool callInternalHelpers(mDNSInterfaceID InterfaceID, DNSServiceFlags flags)
-{
- if ( ((InterfaceID == mDNSInterface_Any) && (flags & (kDNSServiceFlagsIncludeP2P | kDNSServiceFlagsIncludeAWDL)))
- || mDNSPlatformInterfaceIsD2D(InterfaceID))
- return mDNStrue;
- else
- return mDNSfalse;
-}
-
-mDNSexport void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags, DNSQuestion * q)
-{
- // BLE support currently not handled by a D2D plugin
- if (applyToBLE(InterfaceID, flags))
- {
- domainname lower;
-
- DomainnameToLower(typeDomain, &lower);
- // pass in the key and keySize
- mDNSu8 *end = DNSNameCompressionBuildLHS(&lower, qtype);
- start_BLE_browse(q, &lower, qtype, flags, compression_lhs, end - compression_lhs);
- }
-
- if (callInternalHelpers(InterfaceID, flags))
- internal_start_browsing_for_service(InterfaceID, typeDomain, qtype, flags);
-}
-
-mDNSexport void internal_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags)
-{
- domainname lower;
-
- DomainnameToLower(typeDomain, &lower);
-
- if (!D2DBrowseListRefCount(&lower, qtype))
- {
- D2DTransportType transportType, excludedTransport;
-
- LogInfo("%s: Starting browse for: %##s %s", __func__, lower.c, DNSTypeName(qtype));
- mDNSu8 *end = DNSNameCompressionBuildLHS(&lower, qtype);
- PrintHelper(__func__, compression_lhs, end - compression_lhs, mDNSNULL, 0);
-
- transportType = xD2DInterfaceToTransportType(InterfaceID, flags, & excludedTransport);
- if (transportType == D2DTransportMax)
- {
- D2DTransportType i;
- for (i = 0; i < D2DTransportMax; i++)
- {
- if (i == excludedTransport) continue;
- if (D2DStartBrowsingForKeyOnTransport) D2DStartBrowsingForKeyOnTransport(compression_lhs, end - compression_lhs, i);
- }
- }
- else
- {
- if (D2DStartBrowsingForKeyOnTransport) D2DStartBrowsingForKeyOnTransport(compression_lhs, end - compression_lhs, transportType);
- }
- }
- D2DBrowseListRetain(&lower, qtype);
-}
-
-mDNSexport void external_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags)
-{
- // BLE support currently not handled by a D2D plugin
- if (applyToBLE(InterfaceID, flags))
- {
- domainname lower;
-
- // If this is the last instance of this browse, clear any cached records recieved for it.
- // We are not guaranteed to get a D2DServiceLost event for all key, value pairs cached over BLE.
- DomainnameToLower(typeDomain, &lower);
- if (stop_BLE_browse(&lower, qtype, flags))
- xD2DClearCache(&lower, qtype);
- }
-
- if (callInternalHelpers(InterfaceID, flags))
- internal_stop_browsing_for_service(InterfaceID, typeDomain, qtype, flags);
-}
-
-mDNSexport void internal_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags)
-{
- domainname lower;
-
- DomainnameToLower(typeDomain, &lower);
-
- // If found in list and this is the last reference to this browse, remove the key from the D2D plugins.
- if (D2DBrowseListRelease(&lower, qtype) && !D2DBrowseListRefCount(&lower, qtype))
- {
- D2DTransportType transportType, excludedTransport;
-
- LogInfo("%s: Stopping browse for: %##s %s", __func__, lower.c, DNSTypeName(qtype));
- mDNSu8 *end = DNSNameCompressionBuildLHS(&lower, qtype);
- PrintHelper(__func__, compression_lhs, end - compression_lhs, mDNSNULL, 0);
-
- transportType = xD2DInterfaceToTransportType(InterfaceID, flags, & excludedTransport);
- if (transportType == D2DTransportMax)
- {
- D2DTransportType i;
- for (i = 0; i < D2DTransportMax; i++)
- {
- if (i == excludedTransport) continue;
- if (D2DStopBrowsingForKeyOnTransport) D2DStopBrowsingForKeyOnTransport(compression_lhs, end - compression_lhs, i);
- }
- }
- else
- {
- if (D2DStopBrowsingForKeyOnTransport) D2DStopBrowsingForKeyOnTransport(compression_lhs, end - compression_lhs, transportType);
- }
-
- // The D2D driver may not generate the D2DServiceLost event for this key after
- // the D2DStopBrowsingForKey*() call above. So, we flush the key from the D2D
- // record cache now.
- xD2DClearCache(&lower, qtype);
- }
-}
-
-mDNSexport void external_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags)
-{
- // Note, start_BLE_advertise() is currently called directly from external_start_advertising_helper() since
- // it needs to pass the ServiceRecordSet so that we can promote the record advertisements to AWDL
- // when we see the corresponding browse indication over BLE.
-
- if (callInternalHelpers(resourceRecord->InterfaceID, flags))
- internal_start_advertising_service(resourceRecord, flags);
-}
-
-mDNSexport void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags)
-{
- domainname lower;
- mDNSu8 *rhs = NULL;
- mDNSu8 *end = NULL;
- D2DTransportType transportType, excludedTransport;
- DomainnameToLower(resourceRecord->name, &lower);
-
- LogInfo("%s: %s", __func__, RRDisplayString(&mDNSStorage, resourceRecord));
-
- // For SRV records, update packet filter if p2p interface already exists, otherwise,
- // if will be updated when we get the KEV_DL_IF_ATTACHED event for the interface.
- if (resourceRecord->rrtype == kDNSType_SRV)
- mDNSUpdatePacketFilter(NULL);
-
- rhs = DNSNameCompressionBuildLHS(&lower, resourceRecord->rrtype);
- end = DNSNameCompressionBuildRHS(rhs, resourceRecord);
- PrintHelper(__func__, compression_lhs, rhs - compression_lhs, rhs, end - rhs);
-
- transportType = xD2DInterfaceToTransportType(resourceRecord->InterfaceID, flags, & excludedTransport);
- if (transportType == D2DTransportMax)
- {
- D2DTransportType i;
- for (i = 0; i < D2DTransportMax; i++)
- {
- if (i == excludedTransport) continue;
- if (D2DStartAdvertisingPairOnTransport) D2DStartAdvertisingPairOnTransport(compression_lhs, rhs - compression_lhs, rhs, end - rhs, i);
- }
- }
- else
- {
- if (D2DStartAdvertisingPairOnTransport) D2DStartAdvertisingPairOnTransport(compression_lhs, rhs - compression_lhs, rhs, end - rhs, transportType);
- }
-}
-
-mDNSexport void external_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags)
-{
- // BLE support currently not handled by a D2D plugin
- if (applyToBLE(resourceRecord->InterfaceID, flags))
- {
- domainname lower;
-
- DomainnameToLower(resourceRecord->name, &lower);
- stop_BLE_advertise(&lower, resourceRecord->rrtype, flags);
- }
-
- if (callInternalHelpers(resourceRecord->InterfaceID, flags))
- internal_stop_advertising_service(resourceRecord, flags);
-}
-
-mDNSexport void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags)
-{
- domainname lower;
- mDNSu8 *rhs = NULL;
- mDNSu8 *end = NULL;
- D2DTransportType transportType, excludedTransport;
- DomainnameToLower(resourceRecord->name, &lower);
-
- LogInfo("%s: %s", __func__, RRDisplayString(&mDNSStorage, resourceRecord));
-
- // For SRV records, update packet filter if p2p interface already exists, otherwise,
- // For SRV records, update packet filter to to remove this port from list
- if (resourceRecord->rrtype == kDNSType_SRV)
- mDNSUpdatePacketFilter(resourceRecord);
-
- rhs = DNSNameCompressionBuildLHS(&lower, resourceRecord->rrtype);
- end = DNSNameCompressionBuildRHS(rhs, resourceRecord);
- PrintHelper(__func__, compression_lhs, rhs - compression_lhs, rhs, end - rhs);
-
- transportType = xD2DInterfaceToTransportType(resourceRecord->InterfaceID, flags, & excludedTransport);
- if (transportType == D2DTransportMax)
- {
- D2DTransportType i;
- for (i = 0; i < D2DTransportMax; i++)
- {
- if (i == excludedTransport) continue;
- if (D2DStopAdvertisingPairOnTransport) D2DStopAdvertisingPairOnTransport(compression_lhs, rhs - compression_lhs, rhs, end - rhs, i);
- }
- }
- else
- {
- if (D2DStopAdvertisingPairOnTransport) D2DStopAdvertisingPairOnTransport(compression_lhs, rhs - compression_lhs, rhs, end - rhs, transportType);
- }
-}
-
-mDNSexport void external_start_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags)
-{
- domainname lower;
- mDNSu8 *rhs = NULL;
- mDNSu8 *end = NULL;
- mDNSBool AWDL_used = false; // whether AWDL was used for this resolve
- D2DTransportType transportType, excludedTransport;
- DomainnameToLower(SkipLeadingLabels(fqdn, 1), &lower);
-
- LogInfo("external_start_resolving_service: %##s", fqdn->c);
- rhs = DNSNameCompressionBuildLHS(&lower, kDNSType_PTR);
- end = putDomainNameAsLabels(&compression_base_msg, rhs, compression_limit, fqdn);
- PrintHelper(__func__, compression_lhs, rhs - compression_lhs, rhs, end - rhs);
-
- transportType = xD2DInterfaceToTransportType(InterfaceID, flags, & excludedTransport);
- if (transportType == D2DTransportMax)
- {
- // Resolving over all the transports, except for excludedTransport if set.
- D2DTransportType i;
- for (i = 0; i < D2DTransportMax; i++)
- {
- if (i == excludedTransport) continue;
- if (D2DStartResolvingPairOnTransport) D2DStartResolvingPairOnTransport(compression_lhs, rhs - compression_lhs, rhs, end - rhs, i);
-
- if (i == D2DAWDLTransport)
- AWDL_used = true;
- }
- }
- else
- {
- // Resolving over one specific transport.
- if (D2DStartResolvingPairOnTransport) D2DStartResolvingPairOnTransport(compression_lhs, rhs - compression_lhs, rhs, end - rhs, transportType);
-
- if (transportType == D2DAWDLTransport)
- AWDL_used = true;
- }
-
- // AWDL wants the SRV and TXT record queries communicated over the D2D interface.
- // We only want these records going to AWDL, so use AWDLInterfaceID as the
- // interface and don't set any other flags.
- if (AWDL_used && AWDLInterfaceID)
- {
- LogInfo("external_start_resolving_service: browse for TXT and SRV over AWDL");
- external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_TXT, 0, 0);
- external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_SRV, 0, 0);
- }
-}
-
-mDNSexport void external_stop_resolving_service(mDNSInterfaceID InterfaceID, const domainname *const fqdn, DNSServiceFlags flags)
-{
- domainname lower;
- mDNSu8 *rhs = NULL;
- mDNSu8 *end = NULL;
- mDNSBool AWDL_used = false; // whether AWDL was used for this resolve
- D2DTransportType transportType, excludedTransport;
- DomainnameToLower(SkipLeadingLabels(fqdn, 1), &lower);
-
- LogInfo("external_stop_resolving_service: %##s", fqdn->c);
- rhs = DNSNameCompressionBuildLHS(&lower, kDNSType_PTR);
- end = putDomainNameAsLabels(&compression_base_msg, rhs, compression_limit, fqdn);
- PrintHelper(__func__, compression_lhs, rhs - compression_lhs, rhs, end - rhs);
-
- transportType = xD2DInterfaceToTransportType(InterfaceID, flags, & excludedTransport);
- if (transportType == D2DTransportMax)
- {
- D2DTransportType i;
- for (i = 0; i < D2DTransportMax; i++)
- {
- if (i == excludedTransport) continue;
- if (D2DStopResolvingPairOnTransport) D2DStopResolvingPairOnTransport(compression_lhs, rhs - compression_lhs, rhs, end - rhs, i);
-
- if (i == D2DAWDLTransport)
- AWDL_used = true;
- }
- }
- else
- {
- if (D2DStopResolvingPairOnTransport) D2DStopResolvingPairOnTransport(compression_lhs, rhs - compression_lhs, rhs, end - rhs, transportType);
-
- if (transportType == D2DAWDLTransport)
- AWDL_used = true;
- }
-
- // AWDL wants the SRV and TXT record queries communicated over the D2D interface.
- // We only want these records going to AWDL, so use AWDLInterfaceID as the
- // interface and don't set any other flags.
- if (AWDL_used && AWDLInterfaceID)
- {
- LogInfo("external_stop_resolving_service: stop browse for TXT and SRV on AWDL");
- external_stop_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_TXT, 0);
- external_stop_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_SRV, 0);
- }
-}
-
-#elif APPLE_OSX_mDNSResponder
-
-mDNSexport void internal_start_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags }
-mDNSexport void internal_stop_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags;}
-mDNSexport void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { (void)resourceRecord; (void)flags;}
-mDNSexport void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { (void)resourceRecord; (void)flags;}
-
-mDNSexport void external_start_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags; (void)q }
-mDNSexport void external_stop_browsing_for_service(mDNS *const m, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags) { (void)m; (void)type; (void)qtype; (void)flags;}
-mDNSexport void external_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { (void)resourceRecord; (void)flags;}
-mDNSexport void external_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags) { (void)resourceRecord; (void)flags;}
-mDNSexport void external_start_resolving_service(const domainname *const fqdn, DNSServiceFlags flags) { (void)fqdn; (void)flags;}
-mDNSexport void external_stop_resolving_service(const domainname *const fqdn, DNSServiceFlags flags) { (void)fqdn; (void)flags;}
-
-#endif // ! NO_D2D
-
-// ***************************************************************************
// Functions
#if COMPILER_LIKES_PRAGMA_MARK
@@ -1381,7 +418,7 @@ mDNSexport void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropert
CFWriteStreamRef stream = NULL;
CFDataRef bytes = NULL;
CFIndex ret;
- KQueueLock(&mDNSStorage);
+ KQueueLock();
if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(NULL, NULL)))
{
@@ -1417,15 +454,15 @@ mDNSexport void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropert
if (subkeyCopy)
mDNSPlatformMemFree(subkeyCopy);
- KQueueUnlock(&mDNSStorage, "mDNSDynamicStoreSetConfig");
+ KQueueUnlock("mDNSDynamicStoreSetConfig");
});
}
// To match *either* a v4 or v6 instance of this interface name, pass AF_UNSPEC for type
-mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(mDNS *const m, const char *ifname, int type)
+mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(const char *ifname, int type)
{
NetworkInterfaceInfoOSX *i;
- for (i = m->p->InterfaceList; i; i = i->next)
+ for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
if (i->Exists && !strcmp(i->ifinfo.ifname, ifname) &&
((type == AF_UNSPEC ) ||
(type == AF_INET && i->ifinfo.ip.type == mDNSAddrType_IPv4) ||
@@ -1437,14 +474,15 @@ mDNSlocal int myIfIndexToName(u_short ifindex, char *name)
{
struct ifaddrs *ifa;
for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
- if (ifa->ifa_addr->sa_family == AF_LINK)
+ if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK)
if (((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index == ifindex)
{ strlcpy(name, ifa->ifa_name, IF_NAMESIZE); return 0; }
return -1;
}
-mDNSexport NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(const mDNS *const m, mDNSInterfaceID ifindex)
+mDNSexport NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(mDNSInterfaceID ifindex)
{
+ mDNS *const m = &mDNSStorage;
mDNSu32 scope_id = (mDNSu32)(uintptr_t)ifindex;
NetworkInterfaceInfoOSX *i;
@@ -1457,18 +495,19 @@ mDNSexport NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(const mDNS *const
mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex)
{
+ (void) m;
if (ifindex == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
if (ifindex == kDNSServiceInterfaceIndexP2P ) return(mDNSInterface_P2P);
if (ifindex == kDNSServiceInterfaceIndexBLE ) return(mDNSInterface_BLE);
if (ifindex == kDNSServiceInterfaceIndexAny ) return(mDNSNULL);
- NetworkInterfaceInfoOSX* ifi = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)ifindex);
+ NetworkInterfaceInfoOSX* ifi = IfindexToInterfaceInfoOSX((mDNSInterfaceID)(uintptr_t)ifindex);
if (!ifi)
{
// Not found. Make sure our interface list is up to date, then try again.
LogInfo("mDNSPlatformInterfaceIDfromInterfaceIndex: InterfaceID for interface index %d not found; Updating interface list", ifindex);
- mDNSMacOSXNetworkChanged(m);
- ifi = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)ifindex);
+ mDNSMacOSXNetworkChanged();
+ ifi = IfindexToInterfaceInfoOSX((mDNSInterfaceID)(uintptr_t)ifindex);
}
if (!ifi) return(mDNSNULL);
@@ -1497,273 +536,13 @@ mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNS
// Not found. Make sure our interface list is up to date, then try again.
LogInfo("Interface index for InterfaceID %p not found; Updating interface list", id);
- mDNSMacOSXNetworkChanged(m);
+ mDNSMacOSXNetworkChanged();
for (i = m->p->InterfaceList; i; i = i->next)
if (i->scope_id == scope_id) return(i->scope_id);
return(0);
}
-#if APPLE_OSX_mDNSResponder
-mDNSexport void mDNSASLLog(uuid_t *uuid, const char *subdomain, const char *result, const char *signature, const char *fmt, ...)
-{
- if (iOSVers)
- return; // No ASL on iOS
-
- static char buffer[512];
- aslmsg asl_msg = asl_new(ASL_TYPE_MSG);
-
- if (!asl_msg) { LogMsg("mDNSASLLog: asl_new failed"); return; }
- if (uuid)
- {
- char uuidStr[37];
- uuid_unparse(*uuid, uuidStr);
- asl_set (asl_msg, "com.apple.message.uuid", uuidStr);
- }
-
- static char domainBase[] = "com.apple.mDNSResponder.%s";
- mDNS_snprintf (buffer, sizeof(buffer), domainBase, subdomain);
- asl_set (asl_msg, "com.apple.message.domain", buffer);
-
- if (result) asl_set(asl_msg, "com.apple.message.result", result);
- if (signature) asl_set(asl_msg, "com.apple.message.signature", signature);
-
- va_list ptr;
- va_start(ptr,fmt);
- mDNS_vsnprintf(buffer, sizeof(buffer), fmt, ptr);
- va_end(ptr);
-
- int old_filter = asl_set_filter(NULL,ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
- asl_log(NULL, asl_msg, ASL_LEVEL_DEBUG, "%s", buffer);
- asl_set_filter(NULL, old_filter);
- asl_free(asl_msg);
-}
-
-
-mDNSlocal void mDNSLogDNSSECStatistics(mDNS *const m)
-{
- char buffer[16];
-
- aslmsg aslmsg = asl_new(ASL_TYPE_MSG);
-
- // If we failed to allocate an aslmsg structure, keep accumulating
- // the statistics and try again at the next log interval.
- if (!aslmsg)
- {
- LogMsg("mDNSLogDNSSECStatistics: asl_new() failed!");
- return;
- }
-
- asl_set(aslmsg,"com.apple.message.domain", "com.apple.mDNSResponder.DNSSECstatistics");
-
- if (m->rrcache_totalused_unicast)
- {
- mDNS_snprintf(buffer, sizeof(buffer), "%u", (mDNSu32) ((unsigned long)(m->DNSSECStats.TotalMemUsed * 100))/m->rrcache_totalused_unicast);
- }
- else
- {
- LogMsg("mDNSLogDNSSECStatistics: unicast is zero");
- buffer[0] = 0;
- }
- asl_set(aslmsg,"com.apple.message.MemUsage", buffer);
-
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.Latency0);
- asl_set(aslmsg,"com.apple.message.Latency0", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.Latency10);
- asl_set(aslmsg,"com.apple.message.Latency10", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.Latency20);
- asl_set(aslmsg,"com.apple.message.Latency20", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.Latency50);
- asl_set(aslmsg,"com.apple.message.Latency50", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.Latency100);
- asl_set(aslmsg,"com.apple.message.Latency100", buffer);
-
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.ExtraPackets0);
- asl_set(aslmsg,"com.apple.message.ExtraPackets0", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.ExtraPackets3);
- asl_set(aslmsg,"com.apple.message.ExtraPackets3", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.ExtraPackets7);
- asl_set(aslmsg,"com.apple.message.ExtraPackets7", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.ExtraPackets10);
- asl_set(aslmsg,"com.apple.message.ExtraPackets10", buffer);
-
- // Ignore IndeterminateStatus as we don't log them
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.SecureStatus);
- asl_set(aslmsg,"com.apple.message.SecureStatus", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.InsecureStatus);
- asl_set(aslmsg,"com.apple.message.InsecureStatus", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.BogusStatus);
- asl_set(aslmsg,"com.apple.message.BogusStatus", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.NoResponseStatus);
- asl_set(aslmsg,"com.apple.message.NoResponseStatus", buffer);
-
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.NumProbesSent);
- asl_set(aslmsg,"com.apple.message.NumProbesSent", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.MsgSize0);
- asl_set(aslmsg,"com.apple.message.MsgSize0", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.MsgSize1);
- asl_set(aslmsg,"com.apple.message.MsgSize1", buffer);
- mDNS_snprintf(buffer, sizeof(buffer), "%u", m->DNSSECStats.MsgSize2);
- asl_set(aslmsg,"com.apple.message.MsgSize2", buffer);
-
- asl_log(NULL, aslmsg, ASL_LEVEL_NOTICE, "");
- asl_free(aslmsg);
-}
-
-// Calculate packets per hour given total packet count and interval in seconds.
-// Cast one term of multiplication to (long) to use 64-bit arithmetic
-// and avoid a potential 32-bit overflow prior to the division.
-#define ONE_HOUR 3600
-#define PACKET_RATE(PACKETS, INTERVAL) (int)(((long) (PACKETS) * ONE_HOUR)/(INTERVAL))
-
-// Put packet rate data in discrete buckets.
-mDNSlocal int mDNSBucketData(int inputData, int interval)
-{
- if (!interval)
- {
- LogMsg("mDNSBucketData: interval is zero!");
- return 0;
- }
-
- int ratePerHour = PACKET_RATE(inputData, interval);
- int bucket;
-
- if (ratePerHour == 0)
- bucket = 0;
- else if (ratePerHour <= 10)
- bucket = 10;
- else if (ratePerHour <= 100)
- bucket = 100;
- else if (ratePerHour <= 1000)
- bucket = 1000;
- else if (ratePerHour <= 5000)
- bucket = 5000;
- else if (ratePerHour <= 10000)
- bucket = 10000;
- else if (ratePerHour <= 50000)
- bucket = 50000;
- else if (ratePerHour <= 100000)
- bucket = 100000;
- else if (ratePerHour <= 250000)
- bucket = 250000;
- else if (ratePerHour <= 500000)
- bucket = 500000;
- else
- bucket = 1000000;
-
- return bucket;
-}
-
-mDNSlocal void mDNSLogBonjourStatistics(mDNS *const m)
-{
- static mDNSs32 last_PktNum, last_MPktNum;
- static mDNSs32 last_UnicastPacketsSent, last_MulticastPacketsSent;
- static mDNSs32 last_RemoteSubnet;
-
- mDNSs32 interval;
- char buffer[16];
- mDNSs32 inMulticast = m->MPktNum - last_MPktNum;
- mDNSs32 inUnicast = m->PktNum - last_PktNum - inMulticast;
- mDNSs32 outUnicast = m->UnicastPacketsSent - last_UnicastPacketsSent;
- mDNSs32 outMulticast = m->MulticastPacketsSent - last_MulticastPacketsSent;
- mDNSs32 remoteSubnet = m->RemoteSubnet - last_RemoteSubnet;
-
-
- // save starting values for new interval
- last_PktNum = m->PktNum;
- last_MPktNum = m->MPktNum;
- last_UnicastPacketsSent = m->UnicastPacketsSent;
- last_MulticastPacketsSent = m->MulticastPacketsSent;
- last_RemoteSubnet = m->RemoteSubnet;
-
- // Need a non-zero active time interval.
- if (!m->ActiveStatTime)
- return;
-
- // Round interval time to nearest hour boundary. Less then 30 minutes rounds to zero.
- interval = (m->ActiveStatTime + ONE_HOUR/2)/ONE_HOUR;
-
- // Use a minimum of 30 minutes of awake time to calculate average packet rates.
- // The rounded awake interval should not be greater than the rounded reporting
- // interval.
- if ((interval == 0) || (interval > (kDefaultNextStatsticsLogTime + ONE_HOUR/2)/ONE_HOUR))
- return;
-
- aslmsg aslmsg = asl_new(ASL_TYPE_MSG);
-
- if (!aslmsg)
- {
- LogMsg("mDNSLogBonjourStatistics: asl_new() failed!");
- return;
- }
- // log in MessageTracer format
- asl_set(aslmsg,"com.apple.message.domain", "com.apple.mDNSResponder.statistics");
-
- snprintf(buffer, sizeof(buffer), "%d", interval);
- asl_set(aslmsg,"com.apple.message.interval", buffer);
-
- // log the packet rates as packets per hour
- snprintf(buffer, sizeof(buffer), "%d",
- mDNSBucketData(inUnicast, m->ActiveStatTime));
- asl_set(aslmsg,"com.apple.message.UnicastIn", buffer);
-
- snprintf(buffer, sizeof(buffer), "%d",
- mDNSBucketData(inMulticast, m->ActiveStatTime));
- asl_set(aslmsg,"com.apple.message.MulticastIn", buffer);
-
- snprintf(buffer, sizeof(buffer), "%d",
- mDNSBucketData(outUnicast, m->ActiveStatTime));
- asl_set(aslmsg,"com.apple.message.UnicastOut", buffer);
-
- snprintf(buffer, sizeof(buffer), "%d",
- mDNSBucketData(outMulticast, m->ActiveStatTime));
- asl_set(aslmsg,"com.apple.message.MulticastOut", buffer);
-
- snprintf(buffer, sizeof(buffer), "%d",
- mDNSBucketData(remoteSubnet, m->ActiveStatTime));
- asl_set(aslmsg,"com.apple.message.RemoteSubnet", buffer);
-
- asl_log(NULL, aslmsg, ASL_LEVEL_NOTICE, "");
-
- asl_free(aslmsg);
-}
-
-// Log multicast and unicast traffic statistics to MessageTracer on OSX
-mDNSexport void mDNSLogStatistics(mDNS *const m)
-{
- // MessageTracer only available on OSX
- if (iOSVers)
- return;
-
- mDNSs32 currentUTC = mDNSPlatformUTC();
-
- // log runtime statistics
- if ((currentUTC - m->NextStatLogTime) >= 0)
- {
- m->NextStatLogTime = currentUTC + kDefaultNextStatsticsLogTime;
- // If StatStartTime is zero, it hasn't been reinitialized yet
- // in the wakeup code path.
- if (m->StatStartTime)
- {
- m->ActiveStatTime += currentUTC - m->StatStartTime;
- }
-
- // Only log statistics if we have recorded some active time during
- // this statistics interval.
- if (m->ActiveStatTime)
- {
- mDNSLogBonjourStatistics(m);
- mDNSLogDNSSECStatistics(m);
- }
-
- // Start a new statistics gathering interval.
- m->StatStartTime = currentUTC;
- m->ActiveStatTime = 0;
- }
-}
-
-#endif // APPLE_OSX_mDNSResponder
-
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark -
#pragma mark - UDP & TCP send & receive
@@ -1816,6 +595,10 @@ mDNSlocal void setTrafficClass(int socketfd, mDNSBool useBackgroundTrafficClass)
(void) setsockopt(socketfd, SOL_SOCKET, SO_TRAFFIC_CLASS, (void *)&traffic_class, sizeof(traffic_class));
}
+#ifdef UNIT_TEST
+// Run the unit test main
+UNITTEST_SETSOCKOPT
+#else
mDNSlocal int mDNSPlatformGetSocktFd(void *sockCxt, mDNSTransport_Type transType, mDNSAddr_Type addrType)
{
if (transType == mDNSTransport_UDP)
@@ -1863,29 +646,8 @@ mDNSexport void mDNSPlatformSetSocktOpt(void *sockCxt, mDNSTransport_Type transT
int nowake = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_NOWAKEFROMSLEEP, &nowake, sizeof(nowake)) == -1)
LogInfo("mDNSPlatformSetSocktOpt: SO_NOWAKEFROMSLEEP failed %s", strerror(errno));
-
- if ((q->flags & kDNSServiceFlagsDenyCellular) || (q->flags & kDNSServiceFlagsDenyExpensive))
- {
-#if defined(SO_RESTRICT_DENY_CELLULAR)
- if (q->flags & kDNSServiceFlagsDenyCellular)
- {
- int restrictions = 0;
- restrictions = SO_RESTRICT_DENY_CELLULAR;
- if (setsockopt(sockfd, SOL_SOCKET, SO_RESTRICTIONS, &restrictions, sizeof(restrictions)) == -1)
- LogMsg("mDNSPlatformSetSocktOpt: SO_RESTRICT_DENY_CELLULAR failed %s", strerror(errno));
- }
-#endif
-#if defined(SO_RESTRICT_DENY_EXPENSIVE)
- if (q->flags & kDNSServiceFlagsDenyExpensive)
- {
- int restrictions = 0;
- restrictions = SO_RESTRICT_DENY_EXPENSIVE;
- if (setsockopt(sockfd, SOL_SOCKET, SO_RESTRICTIONS, &restrictions, sizeof(restrictions)) == -1)
- LogMsg("mDNSPlatformSetSocktOpt: SO_RESTRICT_DENY_EXPENSIVE failed %s", strerror(errno));
- }
-#endif
- }
}
+#endif // UNIT_TEST
// Note: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket"
// Note: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface"
@@ -1902,7 +664,7 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
if (InterfaceID)
{
- info = IfindexToInterfaceInfoOSX(m, InterfaceID);
+ info = IfindexToInterfaceInfoOSX(InterfaceID);
if (info == NULL)
{
// We may not have registered interfaces with the "core" as we may not have
@@ -2137,13 +899,13 @@ mDNSexport ssize_t myrecvfrom(const int s, void *const buffer, const size_t max,
}
// What is this for, and why does it use xor instead of a simple quality check? -- SC
-mDNSlocal mDNSInterfaceID FindMyInterface(mDNS *const m, const mDNSAddr *addr)
+mDNSlocal mDNSInterfaceID FindMyInterface(const mDNSAddr *addr)
{
NetworkInterfaceInfo *intf;
if (addr->type == mDNSAddrType_IPv4)
{
- for (intf = m->HostInterfaces; intf; intf = intf->next)
+ for (intf = mDNSStorage.HostInterfaces; intf; intf = intf->next)
{
if (intf->ip.type == addr->type && intf->McastTxRx)
{
@@ -2157,7 +919,7 @@ mDNSlocal mDNSInterfaceID FindMyInterface(mDNS *const m, const mDNSAddr *addr)
if (addr->type == mDNSAddrType_IPv6)
{
- for (intf = m->HostInterfaces; intf; intf = intf->next)
+ for (intf = mDNSStorage.HostInterfaces; intf; intf = intf->next)
{
if (intf->ip.type == addr->type && intf->McastTxRx)
{
@@ -2174,7 +936,7 @@ mDNSlocal mDNSInterfaceID FindMyInterface(mDNS *const m, const mDNSAddr *addr)
return(mDNSInterface_Any);
}
-mDNSexport void myKQSocketCallBack(int s1, short filter, void *context)
+mDNSexport void myKQSocketCallBack(int s1, short filter, void *context, mDNSBool encounteredEOF)
{
KQSocketSet *const ss = (KQSocketSet *)context;
mDNS *const m = ss->m;
@@ -2189,6 +951,22 @@ mDNSexport void myKQSocketCallBack(int s1, short filter, void *context)
LogMsg("myKQSocketCallBack: sktv4 %d sktv6 %d", ss->sktv4, ss->sktv6);
}
+ if (encounteredEOF)
+ {
+ LogMsg("myKQSocketCallBack: socket %d is no longer readable (EOF)", s1);
+ if (s1 == ss->sktv4)
+ {
+ ss->sktv4EOF = mDNStrue;
+ KQueueSet(ss->sktv4, EV_DELETE, EVFILT_READ, &ss->kqsv4);
+ }
+ else if (s1 == ss->sktv6)
+ {
+ ss->sktv6EOF = mDNStrue;
+ KQueueSet(ss->sktv6, EV_DELETE, EVFILT_READ, &ss->kqsv6);
+ }
+ return;
+ }
+
while (!closed)
{
mDNSAddr senderAddr, destAddr = zeroAddr;
@@ -2248,7 +1026,7 @@ mDNSexport void myKQSocketCallBack(int s1, short filter, void *context)
if (!InterfaceID)
{
- InterfaceID = FindMyInterface(m, &destAddr);
+ InterfaceID = FindMyInterface(&destAddr);
}
// LogMsg("myKQSocketCallBack got packet from %#a to %#a on interface %#a/%s",
@@ -2262,7 +1040,7 @@ mDNSexport void myKQSocketCallBack(int s1, short filter, void *context)
if (ss->proxy)
{
- m->p->UDPProxyCallback(m, &m->p->UDPProxy, &m->imsg.m, (unsigned char*)&m->imsg + err, &senderAddr,
+ m->p->UDPProxyCallback(&m->p->UDPProxy, &m->imsg.m, (unsigned char*)&m->imsg + err, &senderAddr,
senderPort, &destAddr, ss->port, InterfaceID, NULL);
}
else
@@ -2275,8 +1053,9 @@ mDNSexport void myKQSocketCallBack(int s1, short filter, void *context)
if (!closed) ss->closeFlag = mDNSNULL;
}
- // If a client application is put in the background, it's socket to us can go defunct and
- // we'll get an ENOTCONN error on that connection. Just close the socket in that case.
+ // If a client application's sockets are marked as defunct
+ // sockets we have delegated to it with SO_DELEGATED will also go defunct.
+ // We get an ENOTCONN error for defunct sockets and should just close the socket in that case.
if (err < 0 && errno == ENOTCONN)
{
LogInfo("myKQSocketCallBack: ENOTCONN, closing socket");
@@ -2317,8 +1096,7 @@ mDNSexport void myKQSocketCallBack(int s1, short filter, void *context)
if (numLogMessages > 5)
NotifyOfElusiveBug("Flaw in Kernel (select/recvfrom mismatch)",
"Congratulations, you've reproduced an elusive bug.\r"
- "Please contact the current assignee of <rdar://problem/3375328>.\r"
- "Alternatively, you can send email to radar-3387020@group.apple.com. (Note number is different.)\r"
+ "Please send email to radar-3387020@group.apple.com.)\r"
"If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
sleep(1); // After logging this error, rate limit so we don't flood syslog
@@ -2386,13 +1164,12 @@ mDNSlocal OSStatus tlsSetupSock(TCPSocket *sock, SSLProtocolSide pside, SSLConne
goto fail;
}
- // Instead of listing all the acceptable ciphers, we just disable the bad ciphers. It does not disable
- // all the bad ciphers like RC4_MD5, but it assumes that the servers don't offer them.
- err = SSLSetAllowAnonymousCiphers(sock->tlsContext, 0);
+ // Set the default ciphersuite configuration
+ err = SSLSetSessionConfig(sock->tlsContext, CFSTR("default"));
if (err)
- {
- LogMsg("ERROR: tlsSetupSock: SSLSetAllowAnonymousCiphers failed with error code: %d", err);
- goto fail;
+ {
+ LogMsg("ERROR: tlsSetupSock: SSLSetSessionConfig failed with error code: %d", err);
+ goto fail;
}
// We already checked for NULL in hostname and this should never happen. Hence, returning -1
@@ -2479,10 +1256,9 @@ mDNSlocal void *doSSLHandshake(TCPSocket *sock)
{
// Warning: Touching sock without the kqueue lock!
// We're protected because sock->handshake == handshake_in_progress
- mDNS * const m = sock->m; // Get m now, as we may free sock if marked to be closed while we're waiting on SSLHandshake
mStatus err = SSLHandshake(sock->tlsContext);
- KQueueLock(m);
+ KQueueLock();
debugf("doSSLHandshake %p: got lock", sock); // Log *after* we get the lock
if (sock->handshake == handshake_to_be_closed)
@@ -2515,7 +1291,7 @@ mDNSlocal void *doSSLHandshake(TCPSocket *sock)
}
debugf("SSLHandshake %p: dropping lock for fd %d", sock, sock->fd);
- KQueueUnlock(m, "doSSLHandshake");
+ KQueueUnlock("doSSLHandshake");
return NULL;
}
#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
@@ -2537,7 +1313,7 @@ mDNSlocal void spawnSSLHandshake(TCPSocket* sock)
#endif /* NO_SECURITYFRAMEWORK */
-mDNSlocal void tcpKQSocketCallback(__unused int fd, short filter, void *context)
+mDNSlocal void tcpKQSocketCallback(__unused int fd, short filter, void *context, __unused mDNSBool encounteredEOF)
{
TCPSocket *sock = context;
sock->err = mStatus_NoError;
@@ -2655,13 +1431,11 @@ mDNSexport int KQueueSet(int fd, u_short flags, short filter, KQueueEntry *const
return 0;
}
-mDNSexport void KQueueLock(mDNS *const m)
+mDNSexport void KQueueLock()
{
- (void)m; //unused
}
-mDNSexport void KQueueUnlock(mDNS *const m, const char const *task)
+mDNSexport void KQueueUnlock(const char const *task)
{
- (void)m; //unused
(void)task; //unused
}
#else
@@ -2672,14 +1446,16 @@ mDNSexport int KQueueSet(int fd, u_short flags, short filter, const KQueueEntry
return (kevent(KQueueFD, &new_event, 1, NULL, 0, NULL) < 0) ? errno : 0;
}
-mDNSexport void KQueueLock(mDNS *const m)
+mDNSexport void KQueueLock()
{
+ mDNS *const m = &mDNSStorage;
pthread_mutex_lock(&m->p->BigMutex);
m->p->BigMutexStartTime = mDNSPlatformRawTime();
}
-mDNSexport void KQueueUnlock(mDNS *const m, const char* task)
+mDNSexport void KQueueUnlock(const char* task)
{
+ mDNS *const m = &mDNSStorage;
mDNSs32 end = mDNSPlatformRawTime();
(void)task;
if (end - m->p->BigMutexStartTime >= WatchDogReportingThreshold)
@@ -2785,17 +1561,16 @@ mDNSlocal mStatus SetupTCPSocket(TCPSocket *sock, u_short sa_family, mDNSIPPort
return mStatus_NoError;
}
-mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags, mDNSIPPort *port, mDNSBool useBackgroundTrafficClass)
+mDNSexport TCPSocket *mDNSPlatformTCPSocket(TCPSocketFlags flags, mDNSIPPort *port, mDNSBool useBackgroundTrafficClass)
{
mStatus err;
- (void) m;
TCPSocket *sock = mallocL("TCPSocket/mDNSPlatformTCPSocket", sizeof(TCPSocket));
if (!sock) { LogMsg("mDNSPlatformTCPSocket: memory allocation failure"); return(mDNSNULL); }
mDNSPlatformMemZero(sock, sizeof(TCPSocket));
- sock->ss.m = m;
+ sock->ss.m = &mDNSStorage;
sock->ss.sktv4 = -1;
sock->ss.sktv6 = -1;
err = SetupTCPSocket(sock, AF_INET, port, useBackgroundTrafficClass);
@@ -2819,7 +1594,7 @@ mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags,
sock->setup = mDNSfalse;
sock->connected = mDNSfalse;
sock->handshake = handshake_required;
- sock->m = m;
+ sock->m = &mDNSStorage;
sock->err = mStatus_NoError;
return sock;
@@ -2889,7 +1664,7 @@ mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst,
// UDP). mDNSInterface_Unicast indicates this case and not a valid interface.
if (InterfaceID && InterfaceID != mDNSInterface_Unicast)
{
- NetworkInterfaceInfoOSX *info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
+ NetworkInterfaceInfoOSX *info = IfindexToInterfaceInfoOSX(InterfaceID);
if (dst->type == mDNSAddrType_IPv4)
{
#ifdef IP_BOUND_IF
@@ -3289,7 +2064,7 @@ fail:
return(err);
}
-mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
+mDNSexport UDPSocket *mDNSPlatformUDPSocket(const mDNSIPPort requestedport)
{
mStatus err;
mDNSIPPort port = requestedport;
@@ -3299,7 +2074,7 @@ mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requ
if (!p) { LogMsg("mDNSPlatformUDPSocket: memory exhausted"); return(mDNSNULL); }
mDNSPlatformMemZero(p, sizeof(UDPSocket));
p->ss.port = zeroIPPort;
- p->ss.m = m;
+ p->ss.m = &mDNSStorage;
p->ss.sktv4 = -1;
p->ss.sktv6 = -1;
p->ss.proxy = mDNSfalse;
@@ -3332,11 +2107,20 @@ mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requ
return(p);
}
+#ifdef UNIT_TEST
+UNITTEST_UDPCLOSE
+#else
mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock)
{
CloseSocketSet(&sock->ss);
freeL("UDPSocket", sock);
}
+#endif
+
+mDNSexport mDNSBool mDNSPlatformUDPSocketEncounteredEOF(const UDPSocket *sock)
+{
+ return (sock->ss.sktv4EOF || sock->ss.sktv6EOF);
+}
#if COMPILER_LIKES_PRAGMA_MARK
#pragma mark -
@@ -3350,10 +2134,10 @@ mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *c
if (!InterfaceID) { LogMsg("mDNSPlatformSendRawPacket: No InterfaceID specified"); return; }
NetworkInterfaceInfoOSX *info;
- info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
+ info = IfindexToInterfaceInfoOSX(InterfaceID);
if (info == NULL)
{
- LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
+ LogMsg("mDNSPlatformSendRawPacket: Invalid interface index %p", InterfaceID);
return;
}
if (info->BPF_fd < 0)
@@ -3366,15 +2150,15 @@ mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *c
}
}
-mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
+mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
{
if (!InterfaceID) { LogMsg("mDNSPlatformSetLocalAddressCacheEntry: No InterfaceID specified"); return; }
NetworkInterfaceInfoOSX *info;
- info = IfindexToInterfaceInfoOSX(m, InterfaceID);
+ info = IfindexToInterfaceInfoOSX(InterfaceID);
if (info == NULL) { LogMsg("mDNSPlatformSetLocalAddressCacheEntry: Invalid interface index %p", InterfaceID); return; }
// Manually inject an entry into our local ARP cache.
// (We can't do this by sending an ARP broadcast, because the kernel only pays attention to incoming ARP packets, not outgoing.)
- if (!mDNS_AddressIsLocalSubnet(m, InterfaceID, tpa))
+ if (!mDNS_AddressIsLocalSubnet(&mDNSStorage, InterfaceID, tpa))
LogSPS("Don't need address cache entry for %s %#a %.6a", info->ifinfo.ifname, tpa, tha);
else
{
@@ -3406,7 +2190,7 @@ mDNSlocal void CloseBPF(NetworkInterfaceInfoOSX *const i)
mDNSlocal void bpf_callback_common(NetworkInterfaceInfoOSX *info)
{
- KQueueLock(info->m);
+ KQueueLock();
// Now we've got the lock, make sure the kqueue thread didn't close the fd out from under us (will not be a problem once the OS X
// kernel has a mechanism for dispatching all events to a single thread, but for now we have to guard against this race condition).
@@ -3449,7 +2233,7 @@ mDNSlocal void bpf_callback_common(NetworkInterfaceInfoOSX *info)
ptr += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen);
}
exit:
- KQueueUnlock(info->m, "bpf_callback");
+ KQueueUnlock("bpf_callback");
}
#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
mDNSlocal void bpf_callback_dispatch(NetworkInterfaceInfoOSX *const info)
@@ -3475,23 +2259,38 @@ mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIP
mDNSexport mStatus mDNSPlatformClearSPSData(void)
{
- CFStringRef spsAddress = NULL;
- CFStringRef ownerOPTRec = NULL;
+ CFStringRef spsAddressKey = NULL;
+ CFStringRef ownerOPTRecKey = NULL;
+ SCDynamicStoreRef addrStore = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:SPSAddresses"), NULL, NULL);
+ SCDynamicStoreRef optStore = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:SPSOPTRecord"), NULL, NULL);
- if ((spsAddress = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", "[^/]", "/BonjourSleepProxyAddress")))
+ spsAddressKey = SCDynamicStoreKeyCreateNetworkInterfaceEntity (kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCCompAnyRegex, CFSTR("BonjourSleepProxyAddress"));
+ if (spsAddressKey != NULL)
{
- if (SCDynamicStoreRemoveValue(NULL, spsAddress) == false)
- LogSPS("mDNSPlatformClearSPSData: Unable to remove sleep proxy address key");
+ CFArrayRef keyList = SCDynamicStoreCopyKeyList(addrStore, spsAddressKey);
+ if (keyList != NULL)
+ {
+ if (SCDynamicStoreSetMultiple(addrStore, NULL, keyList, NULL) == false)
+ LogSPS("mDNSPlatformClearSPSData: Unable to remove %s : error %s", CFStringGetCStringPtr( spsAddressKey, kCFStringEncodingASCII), SCErrorString(SCError()));
+ }
+ if (keyList) CFRelease(keyList);
}
-
- if((ownerOPTRec = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", "[^/]", "/BonjourSleepProxyOPTRecord")))
+ ownerOPTRecKey= SCDynamicStoreKeyCreateNetworkInterfaceEntity (kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCCompAnyRegex, CFSTR("BonjourSleepProxyOPTRecord"));
+ if(ownerOPTRecKey != NULL)
{
- if (SCDynamicStoreRemoveValue(NULL, ownerOPTRec) == false)
- LogSPS("mDNSPlatformClearSPSData: Unable to remove sleep proxy owner option record key");
+ CFArrayRef keyList = SCDynamicStoreCopyKeyList(addrStore, ownerOPTRecKey);
+ if (keyList != NULL)
+ {
+ if (SCDynamicStoreSetMultiple(optStore, NULL, keyList, NULL) == false)
+ LogSPS("mDNSPlatformClearSPSData: Unable to remove %s : error %s", CFStringGetCStringPtr(ownerOPTRecKey, kCFStringEncodingASCII), SCErrorString(SCError()));
+ }
+ if (keyList) CFRelease(keyList);
}
- if (spsAddress) CFRelease(spsAddress);
- if (ownerOPTRec) CFRelease(ownerOPTRec);
+ if (addrStore) CFRelease(addrStore);
+ if (optStore) CFRelease(optStore);
+ if (spsAddressKey) CFRelease(spsAddressKey);
+ if (ownerOPTRecKey) CFRelease(ownerOPTRecKey);
return KERN_SUCCESS;
}
@@ -3799,7 +2598,7 @@ fin:
return ret;
}
-mDNSlocal void mDNSGet_RemoteMAC(mDNS *const m, int family, v6addr_t raddr)
+mDNSlocal void mDNSGet_RemoteMAC(int family, v6addr_t raddr)
{
ethaddr_t eth;
IPAddressMACMapping *addrMapping;
@@ -3808,9 +2607,10 @@ mDNSlocal void mDNSGet_RemoteMAC(mDNS *const m, int family, v6addr_t raddr)
{
v6addr_t addr;
} dst;
-
+
+ bzero(eth, sizeof(ethaddr_t));
mDNSPlatformMemCopy(dst.addr, raddr, sizeof(v6addr_t));
-
+
kr = GetRemoteMacinternal(family, (uint8_t *)dst.addr, eth);
// If the call to get the remote MAC address succeeds, allocate and copy
@@ -3830,21 +2630,21 @@ mDNSlocal void mDNSGet_RemoteMAC(mDNS *const m, int family, v6addr_t raddr)
addrMapping->ipaddr.type = mDNSAddrType_IPv6;
mDNSPlatformMemCopy(addrMapping->ipaddr.ip.v6.b, raddr, sizeof(v6addr_t));
}
- UpdateRMAC(m, addrMapping);
+ UpdateRMAC(&mDNSStorage, addrMapping);
}
}
-mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr)
+mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNSAddr *raddr)
{
int family = (raddr->type == mDNSAddrType_IPv4) ? AF_INET : AF_INET6;
LogInfo("mDNSPlatformGetRemoteMacAddr calling mDNSGet_RemoteMAC");
- mDNSGet_RemoteMAC(m, family, raddr->ip.v6.b);
+ mDNSGet_RemoteMAC(family, raddr->ip.v6.b);
return KERN_SUCCESS;
}
-mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti)
+mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti)
{
mDNSs32 intfid;
mDNSs32 error = 0;
@@ -3856,25 +2656,25 @@ mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, m
LogMsg("%s: mDNSRetrieveTCPInfo returned : %d", __func__, error);
return error;
}
- mti->IntfId = mDNSPlatformInterfaceIDfromInterfaceIndex(m, intfid);
+ mti->IntfId = mDNSPlatformInterfaceIDfromInterfaceIndex(&mDNSStorage, intfid);
return error;
}
#define BPF_SetOffset(from, cond, to) (from)->cond = (to) - 1 - (from)
-mDNSlocal int CountProxyTargets(mDNS *const m, NetworkInterfaceInfoOSX *x, int *p4, int *p6)
+mDNSlocal int CountProxyTargets(NetworkInterfaceInfoOSX *x, int *p4, int *p6)
{
int numv4 = 0, numv6 = 0;
AuthRecord *rr;
- for (rr = m->ResourceRecords; rr; rr=rr->next)
+ for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next)
if (rr->resrec.InterfaceID == x->ifinfo.InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4)
{
if (p4) LogSPS("CountProxyTargets: fd %d %-7s IP%2d %.4a", x->BPF_fd, x->ifinfo.ifname, numv4, &rr->AddressProxy.ip.v4);
numv4++;
}
- for (rr = m->ResourceRecords; rr; rr=rr->next)
+ for (rr = mDNSStorage.ResourceRecords; rr; rr=rr->next)
if (rr->resrec.InterfaceID == x->ifinfo.InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv6)
{
if (p6) LogSPS("CountProxyTargets: fd %d %-7s IP%2d %.16a", x->BPF_fd, x->ifinfo.ifname, numv6, &rr->AddressProxy.ip.v6);
@@ -3886,8 +2686,9 @@ mDNSlocal int CountProxyTargets(mDNS *const m, NetworkInterfaceInfoOSX *x, int *
return(numv4 + numv6);
}
-mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
+mDNSexport void mDNSPlatformUpdateProxyList(const mDNSInterfaceID InterfaceID)
{
+ mDNS *const m = &mDNSStorage;
NetworkInterfaceInfoOSX *x;
// Note: We can't use IfIndexToInterfaceInfoOSX because that looks for Registered also.
@@ -3898,7 +2699,7 @@ mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID
#define MAX_BPF_ADDRS 250
int numv4 = 0, numv6 = 0;
- if (CountProxyTargets(m, x, &numv4, &numv6) > MAX_BPF_ADDRS)
+ if (CountProxyTargets(x, &numv4, &numv6) > MAX_BPF_ADDRS)
{
LogMsg("mDNSPlatformUpdateProxyList: ERROR Too many address proxy records v4 %d v6 %d", numv4, numv6);
if (numv4 > MAX_BPF_ADDRS) numv4 = MAX_BPF_ADDRS;
@@ -3927,131 +2728,149 @@ mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 30), // 8 Read IPv4 Dst (bytes 30,31,32,33)
};
- struct bpf_insn *pc = &filter[9];
- struct bpf_insn *chk6 = pc + numv4 + 1; // numv4 address checks, plus a "return 0"
- struct bpf_insn *fail = chk6 + 1 + numv6; // Get v6 Dst LSW, plus numv6 address checks
- struct bpf_insn *ret4 = fail + 1;
- struct bpf_insn *ret6 = ret4 + 4;
-
- static const struct bpf_insn rf = BPF_STMT(BPF_RET + BPF_K, 0); // No match: Return nothing
-
- static const struct bpf_insn g6 = BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 50); // Read IPv6 Dst LSW (bytes 50,51,52,53)
-
- static const struct bpf_insn r4a = BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14); // Get IP Header length (normally 20)
- static const struct bpf_insn r4b = BPF_STMT(BPF_LD + BPF_IMM, 54); // A = 54 (14-byte Ethernet plus 20-byte TCP + 20 bytes spare)
- static const struct bpf_insn r4c = BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0); // A += IP Header length
- static const struct bpf_insn r4d = BPF_STMT(BPF_RET + BPF_A, 0); // Success: Return Ethernet + IP + TCP + 20 bytes spare (normally 74)
-
- static const struct bpf_insn r6a = BPF_STMT(BPF_RET + BPF_K, 94); // Success: Return Eth + IPv6 + TCP + 20 bytes spare
-
- BPF_SetOffset(&filter[4], jf, fail); // If Ethertype not ARP, IPv4, or IPv6, fail
- BPF_SetOffset(&filter[6], jf, chk6); // If IPv6 but not ICMPv6, go to IPv6 address list check
-
- // BPF Byte-Order Note
- // The BPF API designers apparently thought that programmers would not be smart enough to use htons
- // and htonl correctly to convert numeric values to network byte order on little-endian machines,
- // so instead they chose to make the API implicitly byte-swap *ALL* values, even literal byte strings
- // that shouldn't be byte-swapped, like ASCII text, Ethernet addresses, IP addresses, etc.
- // As a result, if we put Ethernet addresses and IP addresses in the right byte order, the BPF API
- // will byte-swap and make them backwards, and then our filter won't work. So, we have to arrange
- // that on little-endian machines we deliberately put addresses in memory with the bytes backwards,
- // so that when the BPF API goes through and swaps them all, they end up back as they should be.
- // In summary, if we byte-swap all the non-numeric fields that shouldn't be swapped, and we *don't*
- // swap any of the numeric values that *should* be byte-swapped, then the filter will work correctly.
-
- // IPSEC capture size notes:
- // 8 bytes UDP header
- // 4 bytes Non-ESP Marker
- // 28 bytes IKE Header
- // --
- // 40 Total. Capturing TCP Header + 20 gets us enough bytes to receive the IKE Header in a UDP-encapsulated IKE packet.
-
- AuthRecord *rr;
- for (rr = m->ResourceRecords; rr; rr=rr->next)
- if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4)
- {
- mDNSv4Addr a = rr->AddressProxy.ip.v4;
- pc->code = BPF_JMP + BPF_JEQ + BPF_K;
- BPF_SetOffset(pc, jt, ret4);
- pc->jf = 0;
- pc->k = (bpf_u_int32)a.b[0] << 24 | (bpf_u_int32)a.b[1] << 16 | (bpf_u_int32)a.b[2] << 8 | (bpf_u_int32)a.b[3];
- pc++;
- }
- *pc++ = rf;
-
- if (pc != chk6) LogMsg("mDNSPlatformUpdateProxyList: pc %p != chk6 %p", pc, chk6);
- *pc++ = g6; // chk6 points here
+ // Special filter program to use when there are no address proxy records
+ static struct bpf_insn nullfilter[] =
+ {
+ BPF_STMT(BPF_RET | BPF_K, 0) // 0 Match no packets and return size 0
+ };
- // First cancel any previous ND group memberships we had, then create a fresh socket
- if (x->BPF_mcfd >= 0) close(x->BPF_mcfd);
- x->BPF_mcfd = socket(AF_INET6, SOCK_DGRAM, 0);
+ struct bpf_program prog;
+ if (!numv4 && !numv6)
+ {
+ LogSPS("mDNSPlatformUpdateProxyList: No need for filter");
+ if (m->timenow == 0) LogMsg("mDNSPlatformUpdateProxyList: m->timenow == 0");
- for (rr = m->ResourceRecords; rr; rr=rr->next)
- if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv6)
+ // Cancel any previous ND group memberships we had
+ if (x->BPF_mcfd >= 0)
{
- const mDNSv6Addr *const a = &rr->AddressProxy.ip.v6;
- pc->code = BPF_JMP + BPF_JEQ + BPF_K;
- BPF_SetOffset(pc, jt, ret6);
- pc->jf = 0;
- pc->k = (bpf_u_int32)a->b[0x0C] << 24 | (bpf_u_int32)a->b[0x0D] << 16 | (bpf_u_int32)a->b[0x0E] << 8 | (bpf_u_int32)a->b[0x0F];
- pc++;
-
- struct ipv6_mreq i6mr;
- i6mr.ipv6mr_interface = x->scope_id;
- i6mr.ipv6mr_multiaddr = *(const struct in6_addr*)&NDP_prefix;
- i6mr.ipv6mr_multiaddr.s6_addr[0xD] = a->b[0xD];
- i6mr.ipv6mr_multiaddr.s6_addr[0xE] = a->b[0xE];
- i6mr.ipv6mr_multiaddr.s6_addr[0xF] = a->b[0xF];
-
- // Do precautionary IPV6_LEAVE_GROUP first, necessary to clear stale kernel state
- mStatus err = setsockopt(x->BPF_mcfd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &i6mr, sizeof(i6mr));
- if (err < 0 && (errno != EADDRNOTAVAIL))
- LogMsg("mDNSPlatformUpdateProxyList: IPV6_LEAVE_GROUP error %d errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+ close(x->BPF_mcfd);
+ x->BPF_mcfd = -1;
+ }
- err = setsockopt(x->BPF_mcfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr));
- if (err < 0 && (errno != EADDRINUSE)) // Joining same group twice can give "Address already in use" error -- no need to report that
- LogMsg("mDNSPlatformUpdateProxyList: IPV6_JOIN_GROUP error %d errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+ // Schedule check to see if we can close this BPF_fd now
+ if (!m->NetworkChanged) m->NetworkChanged = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2);
+ if (x->BPF_fd < 0) return; // If we've already closed our BPF_fd, no need to generate an error message below
+ prog.bf_len = 1;
+ prog.bf_insns = nullfilter;
+ }
+ else
+ {
+ struct bpf_insn *pc = &filter[9];
+ struct bpf_insn *chk6 = pc + numv4 + 1; // numv4 address checks, plus a "return 0"
+ struct bpf_insn *fail = chk6 + 1 + numv6; // Get v6 Dst LSW, plus numv6 address checks
+ struct bpf_insn *ret4 = fail + 1;
+ struct bpf_insn *ret6 = ret4 + 4;
+
+ static const struct bpf_insn rf = BPF_STMT(BPF_RET + BPF_K, 0); // No match: Return nothing
+
+ static const struct bpf_insn g6 = BPF_STMT(BPF_LD + BPF_W + BPF_ABS, 50); // Read IPv6 Dst LSW (bytes 50,51,52,53)
+
+ static const struct bpf_insn r4a = BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14); // Get IP Header length (normally 20)
+ static const struct bpf_insn r4b = BPF_STMT(BPF_LD + BPF_IMM, 54); // A = 54 (14-byte Ethernet plus 20-byte TCP + 20 bytes spare)
+ static const struct bpf_insn r4c = BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0); // A += IP Header length
+ static const struct bpf_insn r4d = BPF_STMT(BPF_RET + BPF_A, 0); // Success: Return Ethernet + IP + TCP + 20 bytes spare (normally 74)
+
+ static const struct bpf_insn r6a = BPF_STMT(BPF_RET + BPF_K, 94); // Success: Return Eth + IPv6 + TCP + 20 bytes spare
+
+ BPF_SetOffset(&filter[4], jf, fail); // If Ethertype not ARP, IPv4, or IPv6, fail
+ BPF_SetOffset(&filter[6], jf, chk6); // If IPv6 but not ICMPv6, go to IPv6 address list check
+
+ // BPF Byte-Order Note
+ // The BPF API designers apparently thought that programmers would not be smart enough to use htons
+ // and htonl correctly to convert numeric values to network byte order on little-endian machines,
+ // so instead they chose to make the API implicitly byte-swap *ALL* values, even literal byte strings
+ // that shouldn't be byte-swapped, like ASCII text, Ethernet addresses, IP addresses, etc.
+ // As a result, if we put Ethernet addresses and IP addresses in the right byte order, the BPF API
+ // will byte-swap and make them backwards, and then our filter won't work. So, we have to arrange
+ // that on little-endian machines we deliberately put addresses in memory with the bytes backwards,
+ // so that when the BPF API goes through and swaps them all, they end up back as they should be.
+ // In summary, if we byte-swap all the non-numeric fields that shouldn't be swapped, and we *don't*
+ // swap any of the numeric values that *should* be byte-swapped, then the filter will work correctly.
+
+ // IPSEC capture size notes:
+ // 8 bytes UDP header
+ // 4 bytes Non-ESP Marker
+ // 28 bytes IKE Header
+ // --
+ // 40 Total. Capturing TCP Header + 20 gets us enough bytes to receive the IKE Header in a UDP-encapsulated IKE packet.
+
+ AuthRecord *rr;
+ for (rr = m->ResourceRecords; rr; rr=rr->next)
+ if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv4)
+ {
+ mDNSv4Addr a = rr->AddressProxy.ip.v4;
+ pc->code = BPF_JMP + BPF_JEQ + BPF_K;
+ BPF_SetOffset(pc, jt, ret4);
+ pc->jf = 0;
+ pc->k = (bpf_u_int32)a.b[0] << 24 | (bpf_u_int32)a.b[1] << 16 | (bpf_u_int32)a.b[2] << 8 | (bpf_u_int32)a.b[3];
+ pc++;
+ }
+ *pc++ = rf;
- LogSPS("Joined IPv6 ND multicast group %.16a for %.16a", &i6mr.ipv6mr_multiaddr, a);
- }
+ if (pc != chk6) LogMsg("mDNSPlatformUpdateProxyList: pc %p != chk6 %p", pc, chk6);
+ *pc++ = g6; // chk6 points here
- if (pc != fail) LogMsg("mDNSPlatformUpdateProxyList: pc %p != fail %p", pc, fail);
- *pc++ = rf; // fail points here
+ // First cancel any previous ND group memberships we had, then create a fresh socket
+ if (x->BPF_mcfd >= 0) close(x->BPF_mcfd);
+ x->BPF_mcfd = socket(AF_INET6, SOCK_DGRAM, 0);
- if (pc != ret4) LogMsg("mDNSPlatformUpdateProxyList: pc %p != ret4 %p", pc, ret4);
- *pc++ = r4a; // ret4 points here
- *pc++ = r4b;
- *pc++ = r4c;
- *pc++ = r4d;
+ for (rr = m->ResourceRecords; rr; rr=rr->next)
+ if (rr->resrec.InterfaceID == InterfaceID && rr->AddressProxy.type == mDNSAddrType_IPv6)
+ {
+ const mDNSv6Addr *const a = &rr->AddressProxy.ip.v6;
+ pc->code = BPF_JMP + BPF_JEQ + BPF_K;
+ BPF_SetOffset(pc, jt, ret6);
+ pc->jf = 0;
+ pc->k = (bpf_u_int32)a->b[0x0C] << 24 | (bpf_u_int32)a->b[0x0D] << 16 | (bpf_u_int32)a->b[0x0E] << 8 | (bpf_u_int32)a->b[0x0F];
+ pc++;
+
+ struct ipv6_mreq i6mr;
+ i6mr.ipv6mr_interface = x->scope_id;
+ i6mr.ipv6mr_multiaddr = *(const struct in6_addr*)&NDP_prefix;
+ i6mr.ipv6mr_multiaddr.s6_addr[0xD] = a->b[0xD];
+ i6mr.ipv6mr_multiaddr.s6_addr[0xE] = a->b[0xE];
+ i6mr.ipv6mr_multiaddr.s6_addr[0xF] = a->b[0xF];
+
+ // Do precautionary IPV6_LEAVE_GROUP first, necessary to clear stale kernel state
+ mStatus err = setsockopt(x->BPF_mcfd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &i6mr, sizeof(i6mr));
+ if (err < 0 && (errno != EADDRNOTAVAIL))
+ LogMsg("mDNSPlatformUpdateProxyList: IPV6_LEAVE_GROUP error %d errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+
+ err = setsockopt(x->BPF_mcfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr));
+ if (err < 0 && (errno != EADDRINUSE)) // Joining same group twice can give "Address already in use" error -- no need to report that
+ LogMsg("mDNSPlatformUpdateProxyList: IPV6_JOIN_GROUP error %d errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+
+ LogSPS("Joined IPv6 ND multicast group %.16a for %.16a", &i6mr.ipv6mr_multiaddr, a);
+ }
- if (pc != ret6) LogMsg("mDNSPlatformUpdateProxyList: pc %p != ret6 %p", pc, ret6);
- *pc++ = r6a; // ret6 points here
+ if (pc != fail) LogMsg("mDNSPlatformUpdateProxyList: pc %p != fail %p", pc, fail);
+ *pc++ = rf; // fail points here
- struct bpf_program prog = { pc - filter, filter };
+ if (pc != ret4) LogMsg("mDNSPlatformUpdateProxyList: pc %p != ret4 %p", pc, ret4);
+ *pc++ = r4a; // ret4 points here
+ *pc++ = r4b;
+ *pc++ = r4c;
+ *pc++ = r4d;
+ if (pc != ret6) LogMsg("mDNSPlatformUpdateProxyList: pc %p != ret6 %p", pc, ret6);
+ *pc++ = r6a; // ret6 points here
#if 0
- // For debugging BPF filter program
- unsigned int q;
- for (q=0; q<prog.bf_len; q++)
- LogSPS("mDNSPlatformUpdateProxyList: %2d { 0x%02x, %d, %d, 0x%08x },", q, prog.bf_insns[q].code, prog.bf_insns[q].jt, prog.bf_insns[q].jf, prog.bf_insns[q].k);
+ // For debugging BPF filter program
+ unsigned int q;
+ for (q=0; q<prog.bf_len; q++)
+ LogSPS("mDNSPlatformUpdateProxyList: %2d { 0x%02x, %d, %d, 0x%08x },", q, prog.bf_insns[q].code, prog.bf_insns[q].jt, prog.bf_insns[q].jf, prog.bf_insns[q].k);
#endif
-
- if (!numv4 && !numv6)
- {
- LogSPS("mDNSPlatformUpdateProxyList: No need for filter");
- if (m->timenow == 0) LogMsg("mDNSPlatformUpdateProxyList: m->timenow == 0");
- // Schedule check to see if we can close this BPF_fd now
- if (!m->NetworkChanged) m->NetworkChanged = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2);
- // prog.bf_len = 0; This seems to panic the kernel
- if (x->BPF_fd < 0) return; // If we've already closed our BPF_fd, no need to generate an error message below
+ prog.bf_len = (u_int)(pc - filter);
+ prog.bf_insns = filter;
}
-
+
if (ioctl(x->BPF_fd, BIOCSETFNR, &prog) < 0) LogMsg("mDNSPlatformUpdateProxyList: BIOCSETFNR(%d) failed %d (%s)", prog.bf_len, errno, strerror(errno));
else LogSPS("mDNSPlatformUpdateProxyList: BIOCSETFNR(%d) successful", prog.bf_len);
}
-mDNSexport void mDNSPlatformReceiveBPF_fd(mDNS *const m, int fd)
+mDNSexport void mDNSPlatformReceiveBPF_fd(int fd)
{
+ mDNS *const m = &mDNSStorage;
mDNS_Lock(m);
NetworkInterfaceInfoOSX *i;
@@ -4119,7 +2938,7 @@ mDNSexport void mDNSPlatformReceiveBPF_fd(mDNS *const m, int fd)
i->BPF_rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, i->BPF_cfs, 0);
CFRunLoopAddSource(CFRunLoopGetMain(), i->BPF_rls, kCFRunLoopDefaultMode);
#endif
- mDNSPlatformUpdateProxyList(m, i->ifinfo.InterfaceID);
+ mDNSPlatformUpdateProxyList(i->ifinfo.InterfaceID);
}
}
@@ -4333,7 +3152,7 @@ mDNSlocal int GetMAC(mDNSEthAddr *eth, u_short ifindex)
{
struct ifaddrs *ifa;
for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
- if (ifa->ifa_addr->sa_family == AF_LINK)
+ if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK)
{
const struct sockaddr_dl *const sdl = (const struct sockaddr_dl *)ifa->ifa_addr;
if (sdl->sdl_index == ifindex)
@@ -4366,18 +3185,27 @@ mDNSlocal mDNSBool CheckInterfaceSupport(NetworkInterfaceInfo *const intf, cons
io_name_t n1, n2;
IOObjectGetClass(service, n1);
- io_object_t parent;
- mDNSBool ret = mDNSfalse;
+ io_object_t parent = IO_OBJECT_NULL;
+ mDNSBool ret = mDNSfalse;
+
kern_return_t kr = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent);
if (kr == KERN_SUCCESS)
{
CFStringRef keystr = CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8);
IOObjectGetClass(parent, n2);
LogSPS("CheckInterfaceSupport: Interface %s service %s parent %s", intf->ifname, n1, n2);
- const CFTypeRef ref = IORegistryEntryCreateCFProperty(parent, keystr, kCFAllocatorDefault, mDNSNULL);
+ CFTypeRef ref = mDNSNULL;
+
+ // Currently, the key can be in a different part of the IOKit hierarchy on the AppleTV.
+ // TODO: revist if it is ok to have the same call for all platforms.
+ if (IsAppleTV())
+ ref = IORegistryEntrySearchCFProperty(parent, kIOServicePlane, keystr, kCFAllocatorDefault, kIORegistryIterateParents | kIORegistryIterateRecursively);
+ else
+ ref = IORegistryEntryCreateCFProperty(parent, keystr, kCFAllocatorDefault, mDNSNULL);
+
if (!ref)
{
- LogSPS("CheckInterfaceSupport: No mDNS_IOREG_KEY for interface %s/%s/%s", intf->ifname, n1, n2);
+ LogSPS("CheckInterfaceSupport: No %s for interface %s/%s/%s", key, intf->ifname, n1, n2);
ret = mDNSfalse;
}
else
@@ -4393,6 +3221,7 @@ mDNSlocal mDNSBool CheckInterfaceSupport(NetworkInterfaceInfo *const intf, cons
LogSPS("CheckInterfaceSupport: IORegistryEntryGetParentEntry for %s/%s failed %d", intf->ifname, n1, kr);
ret = mDNSfalse;
}
+
IOObjectRelease(service);
return ret;
}
@@ -4439,7 +3268,7 @@ mDNSlocal mDNSBool NetWakeInterface(NetworkInterfaceInfoOSX *i)
// ifr.ifr_wake_flags = IF_WAKE_ON_MAGIC_PACKET; // For testing with MacBook Air, using a USB dongle that doesn't actually support Wake-On-LAN
- LogSPS("%-6s %#-14a %s WOMP", i->ifinfo.ifname, &i->ifinfo.ip, (ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) ? "supports" : "no");
+ LogSPS("NetWakeInterface: %-6s %#-14a %s WOMP", i->ifinfo.ifname, &i->ifinfo.ip, (ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) ? "supports" : "no");
return((ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) != 0);
}
@@ -4464,7 +3293,6 @@ mDNSlocal u_int64_t getExtendedFlags(char * ifa_name)
LogMsg("getExtendedFlags: SIOCGIFEFLAGS failed, errno = %d (%s)", errno, strerror(errno));
ifr.ifr_eflags = 0;
}
- LogInfo("getExtendedFlags: %s ifr_eflags = 0x%x", ifa_name, ifr.ifr_eflags);
close(sockFD);
return ifr.ifr_eflags;
@@ -4543,50 +3371,78 @@ exit:
return isInitialized;
}
+#define CARPLAY_DEBUG 0
+
// Return true if the interface is associate to a CarPlay hosted SSID.
+// If we have associated with a CarPlay hosted SSID, then use the same
+// optimizations that are used when an interface has the IFEF_DIRECTLINK flag set.
mDNSlocal mDNSBool IsCarPlaySSID(char *ifa_name)
{
static WiFiManagerClientRef manager = NULL;
- mDNSBool rvalue = mDNSfalse;
+ CFArrayRef devices;
+ WiFiDeviceClientRef device;
+ WiFiNetworkRef network;
+ mDNSBool rvalue = mDNSfalse;
if (!MobileWiFiLibLoad())
+ {
+ LogInfo("IsCarPlaySSID: MobileWiFiLibLoad() failed!");
return mDNSfalse;
+ }
- // If we have associated with a CarPlay hosted SSID, then use the same
- // optimizations that are used if an interface has the IFEF_DIRECTLINK flag set.
-
- // Get one WiFiManagerClientRef to use for all calls.
+ // Cache the WiFiManagerClientRef.
if (manager == NULL)
manager = WiFiManagerClientCreate_p(NULL, kWiFiClientTypeNormal);
if (manager == NULL)
{
LogInfo("IsCarPlaySSID: WiFiManagerClientCreate() failed!");
+ return mDNSfalse;
}
- else
+
+ devices = WiFiManagerClientCopyDevices_p(manager);
+
+ // If the first call fails, update the cached WiFiManagerClientRef pointer and try again.
+ if (devices == NULL)
{
- CFArrayRef devices;
+ LogInfo("IsCarPlaySSID: First call to WiFiManagerClientCopyDevices() returned NULL for %s", ifa_name);
+ // Release the previously cached WiFiManagerClientRef which is apparently now stale.
+ CFRelease(manager);
+ manager = WiFiManagerClientCreate_p(NULL, kWiFiClientTypeNormal);
+ if (manager == NULL)
+ {
+ LogInfo("IsCarPlaySSID: WiFiManagerClientCreate() failed!");
+ return mDNSfalse;
+ }
devices = WiFiManagerClientCopyDevices_p(manager);
- if (devices != NULL)
+ if (devices == NULL)
{
- WiFiDeviceClientRef device;
- WiFiNetworkRef network;
+ LogInfo("IsCarPlaySSID: Second call to WiFiManagerClientCopyDevices() returned NULL for %s", ifa_name);
+ return mDNSfalse;
+ }
+ }
- device = (WiFiDeviceClientRef)CFArrayGetValueAtIndex(devices, 0);
- network = WiFiDeviceClientCopyCurrentNetwork_p(device);
- if (network != NULL)
- {
- if (WiFiNetworkIsCarPlay_p(network))
- {
- LogInfo("%s is CarPlay hosted", ifa_name);
- rvalue = mDNStrue;
- }
- CFRelease(network);
- }
- CFRelease(devices);
+ device = (WiFiDeviceClientRef)CFArrayGetValueAtIndex(devices, 0);
+ network = WiFiDeviceClientCopyCurrentNetwork_p(device);
+ if (network != NULL)
+ {
+ if (WiFiNetworkIsCarPlay_p(network))
+ {
+ LogInfo("IsCarPlaySSID: %s is CarPlay hosted", ifa_name);
+ rvalue = mDNStrue;
}
+#if CARPLAY_DEBUG
+ else
+ LogInfo("IsCarPlaySSID: %s is NOT CarPlay hosted", ifa_name);
+#endif // CARPLAY_DEBUG
+
+ CFRelease(network);
}
+ else
+ LogInfo("IsCarPlaySSID: WiFiDeviceClientCopyCurrentNetwork() returned NULL for %s", ifa_name);
+
+ CFRelease(devices);
return rvalue;
}
@@ -4607,8 +3463,9 @@ mDNSlocal mDNSBool IsCarPlaySSID(char *ifa_name)
// pointer to already-existing NetworkInterfaceInfoOSX object found in list, or
// may return NULL if out of memory (unlikely) or parameters are invalid for some reason
// (e.g. sa_family not AF_INET or AF_INET6)
-mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifaddrs *ifa, mDNSs32 utc)
+mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(struct ifaddrs *ifa, mDNSs32 utc)
{
+ mDNS *const m = &mDNSStorage;
mDNSu32 scope_id = if_nametoindex(ifa->ifa_name);
mDNSEthAddr bssid = GetBSSID(ifa->ifa_name);
u_int64_t eflags = getExtendedFlags(ifa->ifa_name);
@@ -4676,17 +3533,27 @@ mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifad
// Setting DirectLink indicates we can do the optimization of skipping the probe phase
// for the interface address records since they should be unique.
- if (eflags & IFEF_DIRECTLINK)
+ // Unfortunately, the legacy p2p* interfaces do not set the IFEF_LOCALNET_PRIVATE
+ // or IFEF_DIRECTLINK flags, so we have to match against the name.
+ if ((eflags & (IFEF_DIRECTLINK | IFEF_AWDL)) || (strncmp(i->ifinfo.ifname, "p2p", 3) == 0))
i->ifinfo.DirectLink = mDNStrue;
else
i->ifinfo.DirectLink = IsCarPlaySSID(ifa->ifa_name);
+ if (i->ifinfo.DirectLink)
+ LogInfo("AddInterfaceToList: DirectLink set for %s", ifa->ifa_name);
+
i->next = mDNSNULL;
i->m = m;
i->Exists = mDNStrue;
i->Flashing = mDNSfalse;
i->Occulting = mDNSfalse;
- i->D2DInterface = (eflags & IFEF_LOCALNET_PRIVATE) ? mDNStrue: mDNSfalse;
+
+ i->D2DInterface = ((eflags & IFEF_LOCALNET_PRIVATE) || (strncmp(i->ifinfo.ifname, "p2p", 3) == 0)) ? mDNStrue: mDNSfalse;
+ if (i->D2DInterface)
+ LogInfo("AddInterfaceToList: D2DInterface set for %s", ifa->ifa_name);
+
+ i->isExpensive = (eflags & IFEF_EXPENSIVE) ? mDNStrue: mDNSfalse;
if (eflags & IFEF_AWDL)
{
// Set SupportsUnicastMDNSResponse false for the AWDL interface since unicast reserves
@@ -4694,7 +3561,6 @@ mDNSlocal NetworkInterfaceInfoOSX *AddInterfaceToList(mDNS *const m, struct ifad
// Bonjour requests over the AWDL interface.
i->ifinfo.SupportsUnicastMDNSResponse = mDNSfalse;
AWDLInterfaceID = i->ifinfo.InterfaceID;
- i->ifinfo.DirectLink = mDNStrue;
LogInfo("AddInterfaceToList: AWDLInterfaceID = %d", (int) AWDLInterfaceID);
}
else
@@ -4752,11 +3618,11 @@ mDNSlocal mStatus CheckQuestionForStatus(const DNSQuestion *const q)
return mStatus_NoError;
}
-mDNSlocal mStatus UpdateLLQStatus(const mDNS *const m, char *buffer, int bufsz, const DomainAuthInfo *const info)
+mDNSlocal mStatus UpdateLLQStatus(char *buffer, int bufsz, const DomainAuthInfo *const info)
{
mStatus status = mStatus_NoError;
DNSQuestion* q, *worst_q = mDNSNULL;
- for (q = m->Questions; q; q=q->next)
+ for (q = mDNSStorage.Questions; q; q=q->next)
if (q->AuthInfo == info)
{
mStatus newStatus = CheckQuestionForStatus(q);
@@ -4772,12 +3638,12 @@ mDNSlocal mStatus UpdateLLQStatus(const mDNS *const m, char *buffer, int bufsz,
return status;
}
-mDNSlocal mStatus UpdateRRStatus(const mDNS *const m, char *buffer, int bufsz, const DomainAuthInfo *const info)
+mDNSlocal mStatus UpdateRRStatus(char *buffer, int bufsz, const DomainAuthInfo *const info)
{
AuthRecord *r;
if (info->deltime) return mStatus_NoError;
- for (r = m->ResourceRecords; r; r = r->next)
+ for (r = mDNSStorage.ResourceRecords; r; r = r->next)
{
// This function is called from UpdateAutoTunnelDomainStatus which in turn may be called from
// a callback e.g., CheckNATMappings. GetAuthInfoFor_internal does not like that (reentrancy being 1),
@@ -4787,7 +3653,7 @@ mDNSlocal mStatus UpdateRRStatus(const mDNS *const m, char *buffer, int bufsz, c
while (n->c[0])
{
DomainAuthInfo *ptr;
- for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
+ for (ptr = mDNSStorage.AuthInfoList; ptr; ptr = ptr->next)
if (SameDomainName(&ptr->domain, n))
{
if (ptr == info && (r->updateError == mStatus_BadSig || r->updateError == mStatus_BadKey || r->updateError == mStatus_BadTime))
@@ -4805,14 +3671,14 @@ mDNSlocal mStatus UpdateRRStatus(const mDNS *const m, char *buffer, int bufsz, c
#endif // ndef NO_SECURITYFRAMEWORK
// MUST be called with lock held
-mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAuthInfo *const info)
+mDNSlocal void UpdateAutoTunnelDomainStatus(const DomainAuthInfo *const info)
{
#ifdef NO_SECURITYFRAMEWORK
- (void) m;
(void)info;
#else
// Note that in the LLQNAT, the clientCallback being non-zero means it's in use,
// whereas in the AutoTunnelNAT, the clientContext being non-zero means it's in use
+ mDNS *const m = &mDNSStorage;
const NATTraversalInfo *const llq = m->LLQNAT.clientCallback ? &m->LLQNAT : mDNSNULL;
const NATTraversalInfo *const tun = m->AutoTunnelNAT.clientContext ? &m->AutoTunnelNAT : mDNSNULL;
char buffer[1024];
@@ -4937,8 +3803,8 @@ mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAut
}
mDNS_snprintf(buffer, sizeof(buffer), "Success");
- llqStatus = UpdateLLQStatus(m, llqBuffer, sizeof(llqBuffer), info);
- status = UpdateRRStatus(m, buffer, sizeof(buffer), info);
+ llqStatus = UpdateLLQStatus(llqBuffer, sizeof(llqBuffer), info);
+ status = UpdateRRStatus(buffer, sizeof(buffer), info);
// If we have a bad signature error updating a RR, it overrides any error as it needs to be
// reported so that it can be fixed automatically (or the user needs to be notified)
@@ -5024,9 +3890,7 @@ mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, const DomainAut
CFDictionarySetValue(domainStatusDict, domain, dict);
if (!m->ShutdownTime)
{
- static char statusBuf[16];
- mDNS_snprintf(statusBuf, sizeof(statusBuf), "%d", (int)status);
- mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.domainstatus", status ? "failure" : "success", statusBuf, "");
+ LogInfo("UpdateAutoTunnelDomainStatus: %s status %d", status ? "failure" : "success", status);
mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, mDNSNULL, domainStatusDict);
}
}
@@ -5048,7 +3912,7 @@ mDNSexport void UpdateAutoTunnelDomainStatuses(const mDNS *const m)
DomainAuthInfo* info;
for (info = m->AuthInfoList; info; info = info->next)
if (info->AutoTunnel && !info->deltime)
- UpdateAutoTunnelDomainStatus(m, info);
+ UpdateAutoTunnelDomainStatus(info);
#endif // def NO_SECURITYFRAMEWORK
}
@@ -5243,7 +4107,7 @@ mDNSlocal void DeregisterAutoTunnel6Record(mDNS *m, DomainAuthInfo *info)
DeregisterAutoTunnelRecord(m, info, &info->AutoTunnel6Record);
UpdateAutoTunnelHostRecord(m, info);
- UpdateAutoTunnelDomainStatus(m, info);
+ UpdateAutoTunnelDomainStatus(info);
}
// Caller must hold the lock
@@ -5364,8 +4228,9 @@ mDNSlocal void AutoTunnelHostNameChanged(mDNS *m, DomainAuthInfo *info)
}
// Must be called with the lock held
-mDNSexport void StartServerTunnel(mDNS *const m, DomainAuthInfo *const info)
+mDNSexport void StartServerTunnel(DomainAuthInfo *const info)
{
+ mDNS *const m = &mDNSStorage;
if (info->deltime) return;
if (info->AutoTunnelServiceStarted)
@@ -5435,8 +4300,9 @@ mDNSlocal mStatus AutoTunnelSetKeys(ClientTunnel *tun, mDNSBool AddNew)
// If the EUI-64 part of the IPv6 ULA matches, then that means the two addresses point to the same machine
#define mDNSSameClientTunnel(A,B) ((A)->l[2] == (B)->l[2] && (A)->l[3] == (B)->l[3])
-mDNSlocal void ReissueBlockedQuestionWithType(mDNS *const m, domainname *d, mDNSBool success, mDNSu16 qtype)
+mDNSlocal void ReissueBlockedQuestionWithType(domainname *d, mDNSBool success, mDNSu16 qtype)
{
+ mDNS *const m = &mDNSStorage;
DNSQuestion *q = m->Questions;
while (q)
{
@@ -5462,29 +4328,31 @@ mDNSlocal void ReissueBlockedQuestionWithType(mDNS *const m, domainname *d, mDNS
}
}
-mDNSlocal void ReissueBlockedQuestions(mDNS *const m, domainname *d, mDNSBool success)
+mDNSlocal void ReissueBlockedQuestions(domainname *d, mDNSBool success)
{
// 1. We deliberately restart AAAA queries before A queries, because in the common case where a BTTM host has
// a v6 address but no v4 address, we prefer the caller to get the positive AAAA response before the A NXDOMAIN.
// 2. In the case of AAAA queries, if our tunnel setup failed, then we return a deliberate failure indication to the caller --
// even if the name does have a valid AAAA record, we don't want clients trying to connect to it without a properly encrypted tunnel.
// 3. For A queries we never fabricate failures -- if a BTTM service is really using raw IPv4, then it doesn't need the IPv6 tunnel.
- ReissueBlockedQuestionWithType(m, d, success, kDNSType_AAAA);
- ReissueBlockedQuestionWithType(m, d, mDNStrue, kDNSType_A);
+ ReissueBlockedQuestionWithType(d, success, kDNSType_AAAA);
+ ReissueBlockedQuestionWithType(d, mDNStrue, kDNSType_A);
}
-mDNSlocal void UnlinkAndReissueBlockedQuestions(mDNS *const m, ClientTunnel *tun, mDNSBool success)
+mDNSlocal void UnlinkAndReissueBlockedQuestions(ClientTunnel *tun, mDNSBool success)
{
+ mDNS *const m = &mDNSStorage;
ClientTunnel **p = &m->TunnelClients;
while (*p != tun && *p) p = &(*p)->next;
if (*p) *p = tun->next;
- ReissueBlockedQuestions(m, &tun->dstname, success);
+ ReissueBlockedQuestions(&tun->dstname, success);
LogInfo("UnlinkAndReissueBlockedQuestions: Disposing ClientTunnel %p", tun);
freeL("ClientTunnel", tun);
}
-mDNSlocal mDNSBool TunnelClientDeleteMatching(mDNS *const m, ClientTunnel *tun, mDNSBool v6Tunnel)
+mDNSlocal mDNSBool TunnelClientDeleteMatching(ClientTunnel *tun, mDNSBool v6Tunnel)
{
+ mDNS *const m = &mDNSStorage;
ClientTunnel **p;
mDNSBool needSetKeys = mDNStrue;
@@ -5564,7 +4432,7 @@ mDNSlocal mDNSBool TunnelClientDeleteMatching(mDNS *const m, ClientTunnel *tun,
// v6Tunnel indicates whether to delete a tunnel whose outer header is IPv6. If false, outer IPv4
// tunnel will be deleted
-mDNSlocal void TunnelClientDeleteAny(mDNS *const m, ClientTunnel *tun, mDNSBool v6Tunnel)
+mDNSlocal void TunnelClientDeleteAny(ClientTunnel *tun, mDNSBool v6Tunnel)
{
ClientTunnel **p;
@@ -5590,7 +4458,7 @@ mDNSlocal void TunnelClientDeleteAny(mDNS *const m, ClientTunnel *tun, mDNSBool
if (old->q.ThisQInterval >= 0)
{
LogInfo("TunnelClientDeleteAny: Stopping query on AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
- mDNS_StopQuery(m, &old->q);
+ mDNS_StopQuery(&mDNSStorage, &old->q);
}
else
{
@@ -5604,8 +4472,9 @@ mDNSlocal void TunnelClientDeleteAny(mDNS *const m, ClientTunnel *tun, mDNSBool
}
}
-mDNSlocal void TunnelClientFinish(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer)
+mDNSlocal void TunnelClientFinish(DNSQuestion *question, const ResourceRecord *const answer)
{
+ mDNS *const m = &mDNSStorage;
mDNSBool needSetKeys = mDNStrue;
ClientTunnel *tun = (ClientTunnel *)question->QuestionContext;
mDNSBool v6Tunnel = mDNSfalse;
@@ -5639,7 +4508,7 @@ mDNSlocal void TunnelClientFinish(mDNS *const m, DNSQuestion *question, const Re
if (!info)
{
LogMsg("TunnelClientFinish: Could not get AuthInfo for %##s", tun->dstname.c);
- ReissueBlockedQuestions(m, &tun->dstname, mDNSfalse);
+ ReissueBlockedQuestions(&tun->dstname, mDNSfalse);
return;
}
@@ -5649,18 +4518,16 @@ mDNSlocal void TunnelClientFinish(mDNS *const m, DNSQuestion *question, const Re
// look for existing tunnels to see whether they have the same information for our peer.
// If not, delete them and need to create a new tunnel. If they are same, just use the
// same tunnel. Do the similar thing if we found a v4Tunnel end point for our peer.
- TunnelClientDeleteAny(m, tun, !v6Tunnel);
- needSetKeys = TunnelClientDeleteMatching(m, tun, v6Tunnel);
+ TunnelClientDeleteAny(tun, !v6Tunnel);
+ needSetKeys = TunnelClientDeleteMatching(tun, v6Tunnel);
if (needSetKeys) LogInfo("TunnelClientFinish: New %s AutoTunnel for %##s %.16a", (v6Tunnel ? "IPv6" : "IPv4"), tun->dstname.c, &tun->rmt_inner);
else LogInfo("TunnelClientFinish: Reusing exiting %s AutoTunnel for %##s %.16a", (v6Tunnel ? "IPv6" : "IPv4"), tun->dstname.c, &tun->rmt_inner);
mStatus result = needSetKeys ? AutoTunnelSetKeys(tun, mDNStrue) : mStatus_NoError;
- static char msgbuf[32];
- mDNS_snprintf(msgbuf, sizeof(msgbuf), "Tunnel setup - %d", result);
- mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.config", result ? "failure" : "success", msgbuf, "");
+ LogInfo("TunnelClientFinish: Tunnel setup result %d", result);
// Kick off any questions that were held pending this tunnel setup
- ReissueBlockedQuestions(m, &tun->dstname, (result == mStatus_NoError) ? mDNStrue : mDNSfalse);
+ ReissueBlockedQuestions(&tun->dstname, (result == mStatus_NoError) ? mDNStrue : mDNSfalse);
}
mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
@@ -5678,10 +4545,7 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
if (tun->tc_state != TC_STATE_AAAA_PEER_RELAY && !answer->rdlength)
{
LogInfo("AutoTunnelCallback NXDOMAIN %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
- static char msgbuf[16];
- mDNS_snprintf(msgbuf, sizeof(msgbuf), "%s lookup", DNSTypeName(question->qtype));
- mDNSASLLog((uuid_t *)&m->asl_uuid, "autotunnel.config", "failure", msgbuf, "");
- UnlinkAndReissueBlockedQuestions(m, tun, mDNSfalse);
+ UnlinkAndReissueBlockedQuestions(tun, mDNSfalse);
return;
}
@@ -5696,19 +4560,19 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
if (!info)
{
LogMsg("AutoTunnelCallback: Could not get AuthInfo for %##s", tun->dstname.c);
- UnlinkAndReissueBlockedQuestions(m, tun, mDNStrue);
+ UnlinkAndReissueBlockedQuestions(tun, mDNStrue);
return;
}
if (mDNSSameIPv6Address(answer->rdata->u.ipv6, info->AutoTunnelInnerAddress))
{
LogInfo("AutoTunnelCallback: suppressing tunnel to self %.16a", &answer->rdata->u.ipv6);
- UnlinkAndReissueBlockedQuestions(m, tun, mDNStrue);
+ UnlinkAndReissueBlockedQuestions(tun, mDNStrue);
return;
}
if (info && mDNSSameIPv6NetworkPart(answer->rdata->u.ipv6, info->AutoTunnelInnerAddress))
{
LogInfo("AutoTunnelCallback: suppressing tunnel to peer %.16a", &answer->rdata->u.ipv6);
- UnlinkAndReissueBlockedQuestions(m, tun, mDNStrue);
+ UnlinkAndReissueBlockedQuestions(tun, mDNStrue);
return;
}
tun->rmt_inner = answer->rdata->u.ipv6;
@@ -5746,7 +4610,7 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
mDNS_StartQuery(m, &tun->q);
return;
}
- TunnelClientFinish(m, question, answer);
+ TunnelClientFinish(question, answer);
return;
case TC_STATE_SRV_PEER:
if (question->qtype != kDNSType_SRV)
@@ -5765,7 +4629,7 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
{
LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_ADDR_PEER", question->qtype);
}
- TunnelClientFinish(m, question, answer);
+ TunnelClientFinish(question, answer);
return;
default:
LogMsg("AutoTunnelCallback: Unknown question %p", question);
@@ -5773,8 +4637,9 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
}
// Must be called with the lock held
-mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
+mDNSexport void AddNewClientTunnel(DNSQuestion *const q)
{
+ mDNS *const m = &mDNSStorage;
ClientTunnel *p = mallocL("ClientTunnel", sizeof(ClientTunnel));
if (!p) return;
AssignDomainName(&p->dstname, &q->qname);
@@ -5828,8 +4693,72 @@ mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
#pragma mark - Power State & Configuration Change Management
#endif
-mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
+mDNSlocal mStatus ReorderInterfaceList()
{
+ // Disable Reorder lists till <rdar://problem/30071012> is fixed to prevent spurious name conflicts
+ return (mStatus_NoError);
+
+ mDNS *const m = &mDNSStorage;
+ nwi_state_t state = nwi_state_copy();
+
+ if (state == mDNSNULL)
+ {
+ LogMsg("NWI State is NULL!");
+ return (mStatus_Invalid);
+ }
+
+ // Get the count of interfaces
+ mDNSu32 count = nwi_state_get_interface_names(state, mDNSNULL, 0);
+ if (count == 0)
+ {
+ LogMsg("Unable to get the ordered list of interface names");
+ nwi_state_release(state);
+ return (mStatus_Invalid);
+ }
+
+ // Get the ordered interface list
+ int i;
+ const char *names[count];
+ count = nwi_state_get_interface_names(state, names, count);
+
+ NetworkInterfaceInfo *newList = mDNSNULL;
+ for (i = count-1; i >= 0; i--)
+ { // Build a new ordered interface list
+ NetworkInterfaceInfo **ptr = &m->HostInterfaces;
+ while (*ptr != mDNSNULL )
+ {
+ if (strcmp((*ptr)->ifname, names[i]) == 0)
+ {
+ NetworkInterfaceInfo *node = *ptr;
+ *ptr = (*ptr)->next;
+ node->next = newList;
+ newList = node;
+ }
+ else
+ ptr = &((*ptr)->next);
+ }
+ }
+
+ // Get to the end of the list
+ NetworkInterfaceInfo *newListEnd = newList;
+ while (newListEnd != mDNSNULL && newListEnd->next != mDNSNULL)
+ newListEnd = newListEnd->next;
+
+ // Add any remaing interfaces to the end of the sorted list
+ if (newListEnd != mDNSNULL)
+ newListEnd->next = m->HostInterfaces;
+
+ // If we have a valid new list, point to that now
+ if (newList != mDNSNULL)
+ m->HostInterfaces = newList;
+
+ nwi_state_release(state);
+ return (mStatus_NoError);
+}
+
+mDNSlocal mStatus UpdateInterfaceList(mDNSs32 utc)
+{
+ mDNS *const m = &mDNSStorage;
mDNSBool foundav4 = mDNSfalse;
mDNSBool foundav6 = mDNSfalse;
struct ifaddrs *ifa = myGetIfAddrs(0);
@@ -5845,30 +4774,41 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
while (ifa)
{
#if LIST_ALL_INTERFACES
- if (ifa->ifa_addr->sa_family == AF_APPLETALK)
- LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_APPLETALK",
- ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
- else if (ifa->ifa_addr->sa_family == AF_LINK)
- LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_LINK",
- ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
- else if (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6)
- LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
- ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
+ if (ifa->ifa_addr)
+ {
+ if (ifa->ifa_addr->sa_family == AF_APPLETALK)
+ LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_APPLETALK",
+ ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
+ else if (ifa->ifa_addr->sa_family == AF_LINK)
+ LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d is AF_LINK",
+ ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
+ else if (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6)
+ LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)",
+ ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
+ }
+ else
+ LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X ifa_addr is NOT set",
+ ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags);
+
if (!(ifa->ifa_flags & IFF_UP))
LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_UP",
- ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
+ ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags,
+ ifa->ifa_addr ? ifa->ifa_addr->sa_family : 0);
if (!(ifa->ifa_flags & IFF_MULTICAST))
LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface not IFF_MULTICAST",
- ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
+ ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags,
+ ifa->ifa_addr ? ifa->ifa_addr->sa_family : 0);
if (ifa->ifa_flags & IFF_POINTOPOINT)
LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT",
- ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
+ ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags,
+ ifa->ifa_addr ? ifa->ifa_addr->sa_family : 0);
if (ifa->ifa_flags & IFF_LOOPBACK)
LogMsg("UpdateInterfaceList: %5s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK",
- ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family);
+ ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags,
+ ifa->ifa_addr ? ifa->ifa_addr->sa_family : 0);
#endif
- if (ifa->ifa_addr->sa_family == AF_LINK)
+ if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK)
{
struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr;
if (sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == sizeof(m->PrimaryMAC) && mDNSSameEthAddress(&m->PrimaryMAC, &zeroEthAddr))
@@ -5929,7 +4869,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
}
else
{
- NetworkInterfaceInfoOSX *i = AddInterfaceToList(m, ifa, utc);
+ NetworkInterfaceInfoOSX *i = AddInterfaceToList(ifa, utc);
if (i && MulticastInterface(i) && i->ifinfo.Advertise)
{
if (ifa->ifa_addr->sa_family == AF_INET)
@@ -5945,8 +4885,8 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
}
// For efficiency, we don't register a loopback interface when other interfaces of that family are available and advertising
- if (!foundav4 && v4Loopback) AddInterfaceToList(m, v4Loopback, utc);
- if (!foundav6 && v6Loopback) AddInterfaceToList(m, v6Loopback, utc);
+ if (!foundav4 && v4Loopback) AddInterfaceToList(v4Loopback, utc);
+ if (!foundav6 && v6Loopback) AddInterfaceToList(v6Loopback, utc);
// Now the list is complete, set the McastTxRx setting for each interface.
NetworkInterfaceInfoOSX *i;
@@ -5957,7 +4897,7 @@ mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
if (i->ifinfo.McastTxRx != txrx)
{
i->ifinfo.McastTxRx = txrx;
- i->Exists = 2; // State change; need to deregister and reregister this interface
+ i->Exists = MulticastStateChanged; // State change; need to deregister and reregister this interface
}
}
@@ -6041,8 +4981,9 @@ mDNSlocal int CountMaskBits(mDNSAddr *mask)
}
// Returns count of non-link local V4 addresses registered (why? -- SC)
-mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
+mDNSlocal int SetupActiveInterfaces(mDNSs32 utc)
{
+ mDNS *const m = &mDNSStorage;
NetworkInterfaceInfoOSX *i;
int count = 0;
@@ -6052,7 +4993,7 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
if (i->Exists)
{
NetworkInterfaceInfo *const n = &i->ifinfo;
- NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifinfo.ifname, AF_UNSPEC);
+ NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(i->ifinfo.ifname, AF_UNSPEC);
if (!primary) LogMsg("SetupActiveInterfaces ERROR! SearchForInterfaceByName didn't find %s", i->ifinfo.ifname);
if (i->Registered && i->Registered != primary) // Sanity check
@@ -6063,6 +5004,8 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
if (!i->Registered)
{
+ InterfaceActivationSpeed activationSpeed;
+
// Note: If i->Registered is set, that means we've called mDNS_RegisterInterface() for this interface,
// so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
// If i->Registered is NOT set, then we haven't registered it and we should not try to deregister it.
@@ -6073,27 +5016,31 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
// If the interface is an old one that went away and came back in less than a minute, then we're in a flapping scenario.
i->Occulting = !(i->ifa_flags & IFF_LOOPBACK) && (utc - i->LastSeen > 0 && utc - i->LastSeen < 60);
- // Temporary fix to handle P2P flapping. P2P reuses the scope-id, mac address and the IP address
- // every time it creates a new interface. We think it is a duplicate and hence consider it
+ // The "p2p*" interfaces used for legacy AirDrop reuse the scope-id, MAC address and the IP address
+ // every time a new interface is created. We think it is a duplicate and hence consider it
// as flashing and occulting, that is, flapping. If an interface is marked as flapping,
// 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.
+ // The same logic applies when the IFEF_DIRECTLINK flag is set on the interface.
if ((strncmp(i->ifinfo.ifname, "p2p", 3) == 0) || i->ifinfo.DirectLink)
{
- LogInfo("SetupActiveInterfaces: %s interface registering %s %s", i->ifinfo.ifname,
- i->Flashing ? " (Flashing)" : "",
- i->Occulting ? " (Occulting)" : "");
- mDNS_RegisterInterface(m, n, 0);
+ activationSpeed = FastActivation;
+ LogInfo("SetupActiveInterfaces: %s DirectLink interface registering", i->ifinfo.ifname);
+ }
+ else if (i->Flashing && i->Occulting)
+ {
+ activationSpeed = SlowActivation;
}
else
{
- mDNS_RegisterInterface(m, n, i->Flashing && i->Occulting);
+ activationSpeed = NormalActivation;
}
+ mDNS_RegisterInterface(m, n, activationSpeed);
+
if (!mDNSAddressIsLinkLocal(&n->ip)) count++;
- LogInfo("SetupActiveInterfaces: Registered %5s(%lu) %.6a InterfaceID %p(%p), primary %p, %#a/%d%s%s%s",
- i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, i, primary, &n->ip, CountMaskBits(&n->mask),
+ LogInfo("SetupActiveInterfaces: Registered %7s(%u) BSSID %.6a Struct addr %p, primary %p, %#a/%d%s%s%s",
+ i->ifinfo.ifname, i->scope_id, &i->BSSID, i, primary, &n->ip, CountMaskBits(&n->mask),
i->Flashing ? " (Flashing)" : "",
i->Occulting ? " (Occulting)" : "",
n->InterfaceActive ? " (Primary)" : "");
@@ -6111,7 +5058,7 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
imr.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
imr.imr_interface = primary->ifa_v4addr;
- if (SearchForInterfaceByName(m, i->ifinfo.ifname, AF_INET) == i)
+ if (SearchForInterfaceByName(i->ifinfo.ifname, AF_INET) == i)
{
LogInfo("SetupActiveInterfaces: %5s(%lu) Doing IP_DROP_MEMBERSHIP for %.4a on %.4a", i->ifinfo.ifname, i->scope_id, &imr.imr_multiaddr, &imr.imr_interface);
mStatus err = setsockopt(m->p->permanentsockets.sktv4, IPPROTO_IP, IP_DROP_MEMBERSHIP, &imr, sizeof(imr));
@@ -6125,7 +5072,7 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
i6mr.ipv6mr_interface = primary->scope_id;
i6mr.ipv6mr_multiaddr = *(struct in6_addr*)&AllDNSLinkGroup_v6.ip.v6;
- if (SearchForInterfaceByName(m, i->ifinfo.ifname, AF_INET6) == i)
+ if (SearchForInterfaceByName(i->ifinfo.ifname, AF_INET6) == i)
{
LogInfo("SetupActiveInterfaces: %5s(%lu) Doing IPV6_LEAVE_GROUP for %.16a on %u", i->ifinfo.ifname, i->scope_id, &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
mStatus err = setsockopt(m->p->permanentsockets.sktv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &i6mr, sizeof(i6mr));
@@ -6154,7 +5101,7 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
// because by the time we get the configuration change notification, the interface is already gone,
// so attempts to unsubscribe fail with EADDRNOTAVAIL (errno 49 "Can't assign requested address").
// <rdar://problem/5585972> IP_ADD_MEMBERSHIP fails for previously-connected removable interfaces
- if (SearchForInterfaceByName(m, i->ifinfo.ifname, AF_INET) == i)
+ if (SearchForInterfaceByName(i->ifinfo.ifname, AF_INET) == i)
{
LogInfo("SetupActiveInterfaces: %5s(%lu) Doing precautionary IP_DROP_MEMBERSHIP for %.4a on %.4a", i->ifinfo.ifname, i->scope_id, &imr.imr_multiaddr, &imr.imr_interface);
mStatus err = setsockopt(m->p->permanentsockets.sktv4, IPPROTO_IP, IP_DROP_MEMBERSHIP, &imr, sizeof(imr));
@@ -6174,7 +5121,7 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
i6mr.ipv6mr_interface = primary->scope_id;
i6mr.ipv6mr_multiaddr = *(struct in6_addr*)&AllDNSLinkGroup_v6.ip.v6;
- if (SearchForInterfaceByName(m, i->ifinfo.ifname, AF_INET6) == i)
+ if (SearchForInterfaceByName(i->ifinfo.ifname, AF_INET6) == i)
{
LogInfo("SetupActiveInterfaces: %5s(%lu) Doing precautionary IPV6_LEAVE_GROUP for %.16a on %u", i->ifinfo.ifname, i->scope_id, &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
mStatus err = setsockopt(m->p->permanentsockets.sktv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &i6mr, sizeof(i6mr));
@@ -6195,10 +5142,10 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
return count;
}
-mDNSlocal void MarkAllInterfacesInactive(mDNS *const m, mDNSs32 utc)
+mDNSlocal void MarkAllInterfacesInactive(mDNSs32 utc)
{
NetworkInterfaceInfoOSX *i;
- for (i = m->p->InterfaceList; i; i = i->next)
+ for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
{
if (i->Exists) i->LastSeen = utc;
i->Exists = mDNSfalse;
@@ -6206,8 +5153,9 @@ mDNSlocal void MarkAllInterfacesInactive(mDNS *const m, mDNSs32 utc)
}
// Returns count of non-link local V4 addresses deregistered (why? -- SC)
-mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
+mDNSlocal int ClearInactiveInterfaces(mDNSs32 utc)
{
+ mDNS *const m = &mDNSStorage;
// First pass:
// If an interface is going away, then deregister this from the mDNSCore.
// We also have to deregister it if the primary interface that it's using for its InterfaceID is going away.
@@ -6218,10 +5166,12 @@ mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
for (i = m->p->InterfaceList; i; i = i->next)
{
// If this interface is no longer active, or its InterfaceID is changing, deregister it
- NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifinfo.ifname, AF_UNSPEC);
+ NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(i->ifinfo.ifname, AF_UNSPEC);
if (i->Registered)
- if (i->Exists == 0 || i->Exists == 2 || i->Registered != primary)
+ if (i->Exists == 0 || i->Exists == MulticastStateChanged || i->Registered != primary)
{
+ InterfaceActivationSpeed activationSpeed;
+
i->Flashing = !(i->ifa_flags & IFF_LOOPBACK) && (utc - i->AppearanceTime < 60);
LogInfo("ClearInactiveInterfaces: Deregistering %5s(%lu) %.6a InterfaceID %p(%p), primary %p, %#a/%d%s%s%s",
i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, i, primary,
@@ -6230,23 +5180,27 @@ mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
i->Occulting ? " (Occulting)" : "",
i->ifinfo.InterfaceActive ? " (Primary)" : "");
- // Temporary fix to handle P2P flapping. P2P reuses the scope-id, mac address and the IP address
+ // "p2p*" interfaces used for legacy AirDrop reuse the scope-id, MAC address and the IP address
// every time it creates a new interface. We think it is a duplicate and hence consider it
// as flashing and occulting. The "core" does not flush the cache for this case. This leads to
// 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.
+ // The same logic applies when the IFEF_DIRECTLINK flag is set on the interface.
if ((strncmp(i->ifinfo.ifname, "p2p", 3) == 0) || i->ifinfo.DirectLink)
{
- LogInfo("ClearInactiveInterfaces: %s interface deregistering %s %s", i->ifinfo.ifname,
- i->Flashing ? " (Flashing)" : "",
- i->Occulting ? " (Occulting)" : "");
- mDNS_DeregisterInterface(m, &i->ifinfo, 0);
+ activationSpeed = FastActivation;
+ LogInfo("ClearInactiveInterfaces: %s DirectLink interface deregistering", i->ifinfo.ifname);
+ }
+ else if (i->Flashing && i->Occulting)
+ {
+ activationSpeed = SlowActivation;
}
else
{
- mDNS_DeregisterInterface(m, &i->ifinfo, i->Flashing && i->Occulting);
+ activationSpeed = NormalActivation;
}
+ mDNS_DeregisterInterface(m, &i->ifinfo, activationSpeed);
+
if (!mDNSAddressIsLinkLocal(&i->ifinfo.ip)) count++;
i->Registered = mDNSNULL;
// Note: If i->Registered is set, that means we've called mDNS_RegisterInterface() for this interface,
@@ -6310,8 +5264,9 @@ mDNSlocal int compare_dns_configs(const void *aa, const void *bb)
return (a->search_order < b->search_order) ? -1 : (a->search_order == b->search_order) ? 0 : 1;
}
-mDNSlocal void UpdateSearchDomainHash(mDNS *const m, MD5_CTX *sdc, char *domain, mDNSInterfaceID InterfaceID)
+mDNSlocal void UpdateSearchDomainHash(MD5_CTX *sdc, char *domain, mDNSInterfaceID InterfaceID)
{
+ mDNS *const m = &mDNSStorage;
char *buf = ".";
mDNSu32 scopeid = 0;
char ifid_buf[16];
@@ -6344,8 +5299,9 @@ mDNSlocal void UpdateSearchDomainHash(mDNS *const m, MD5_CTX *sdc, char *domain,
MD5_Update(sdc, ifid_buf, strlen(ifid_buf) + 1);
}
-mDNSlocal void FinalizeSearchDomainHash(mDNS *const m, MD5_CTX *sdc)
+mDNSlocal void FinalizeSearchDomainHash(MD5_CTX *sdc)
{
+ mDNS *const m = &mDNSStorage;
mDNSu8 md5_hash[MD5_LEN];
MD5_Final(md5_hash, sdc);
@@ -6377,7 +5333,7 @@ mDNSexport const char *DNSScopeToString(mDNSu32 scope)
}
}
-mDNSlocal void ConfigSearchDomains(mDNS *const m, dns_resolver_t *resolver, mDNSInterfaceID interfaceId, mDNSu32 scope, MD5_CTX *sdc, uint64_t generation)
+mDNSlocal void ConfigSearchDomains(dns_resolver_t *resolver, mDNSInterfaceID interfaceId, mDNSu32 scope, MD5_CTX *sdc, uint64_t generation)
{
const char *scopeString = DNSScopeToString(scope);
int j;
@@ -6393,10 +5349,10 @@ mDNSlocal void ConfigSearchDomains(mDNS *const m, dns_resolver_t *resolver, mDNS
if (MakeDomainNameFromDNSNameString(&d, resolver->search[j]) != NULL)
{
static char interface_buf[32];
- mDNS_snprintf(interface_buf, sizeof(interface_buf), "for interface %s", InterfaceNameForID(m, interfaceId));
+ mDNS_snprintf(interface_buf, sizeof(interface_buf), "for interface %s", InterfaceNameForID(&mDNSStorage, interfaceId));
LogInfo("ConfigSearchDomains: (%s) configuring search domain %s %s (generation= %llu)", scopeString,
resolver->search[j], (interfaceId == mDNSInterface_Any) ? "" : interface_buf, generation);
- UpdateSearchDomainHash(m, sdc, resolver->search[j], interfaceId);
+ UpdateSearchDomainHash(sdc, resolver->search[j], interfaceId);
mDNS_AddSearchDomain_CString(resolver->search[j], interfaceId);
}
else
@@ -6408,16 +5364,16 @@ mDNSlocal void ConfigSearchDomains(mDNS *const m, dns_resolver_t *resolver, mDNS
}
else
{
- LogInfo("ConfigSearchDomains: (%s) Ignoring search domain for interface %s", scopeString, InterfaceNameForID(m,interfaceId));
+ LogInfo("ConfigSearchDomains: (%s) Ignoring search domain for interface %s", scopeString, InterfaceNameForID(&mDNSStorage, interfaceId));
}
}
-mDNSlocal mDNSInterfaceID ConfigParseInterfaceID(mDNS *const m, mDNSu32 ifindex)
+mDNSlocal mDNSInterfaceID ConfigParseInterfaceID(mDNSu32 ifindex)
{
NetworkInterfaceInfoOSX *ni;
mDNSInterfaceID interface;
- for (ni = m->p->InterfaceList; ni; ni = ni->next)
+ for (ni = mDNSStorage.p->InterfaceList; ni; ni = ni->next)
{
if (ni->ifinfo.InterfaceID && ni->scope_id == ifindex)
break;
@@ -6442,7 +5398,7 @@ mDNSlocal mDNSInterfaceID ConfigParseInterfaceID(mDNS *const m, mDNSu32 ifindex)
return interface;
}
-mDNSlocal void ConfigNonUnicastResolver(mDNS *const m, dns_resolver_t *r)
+mDNSlocal void ConfigNonUnicastResolver(dns_resolver_t *r)
{
char *opt = r->options;
domainname d;
@@ -6454,17 +5410,19 @@ mDNSlocal void ConfigNonUnicastResolver(mDNS *const m, dns_resolver_t *r)
LogMsg("ConfigNonUnicastResolver: config->resolver bad domain %s", r->domain);
return;
}
- mDNS_AddMcastResolver(m, &d, mDNSInterface_Any, r->timeout);
+ mDNS_AddMcastResolver(&mDNSStorage, &d, mDNSInterface_Any, r->timeout);
}
}
-mDNSlocal void ConfigDNSServers(mDNS *const m, dns_resolver_t *r, mDNSInterfaceID interface, mDNSu32 scope, mDNSu16 resGroupID)
+mDNSlocal void ConfigDNSServers(dns_resolver_t *r, mDNSInterfaceID interface, mDNSu32 scope, mDNSu16 resGroupID)
{
int n;
domainname d;
int serviceID = 0;
mDNSBool cellIntf = mDNSfalse;
mDNSBool reqA, reqAAAA;
+ NetworkInterfaceInfoOSX *info;
+ mDNSBool isExpensive;
if (!r->domain || !*r->domain)
{
@@ -6486,6 +5444,8 @@ mDNSlocal void ConfigDNSServers(mDNS *const m, dns_resolver_t *r, mDNSInterfaceI
#endif
reqA = (r->flags & DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS ? mDNStrue : mDNSfalse);
reqAAAA = (r->flags & DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS ? mDNStrue : mDNSfalse);
+ info = IfindexToInterfaceInfoOSX(interface);
+ isExpensive = info ? info->isExpensive : mDNSfalse;
for (n = 0; n < r->n_nameserver; n++)
{
@@ -6508,8 +5468,8 @@ mDNSlocal void ConfigDNSServers(mDNS *const m, dns_resolver_t *r, mDNSInterfaceI
// Note: this assumes that when the core picks a list of DNSServers for a question,
// it takes the sum of all the timeout values for all DNS servers. By doing this, it
// tries all the DNS servers in a specified timeout
- s = mDNS_AddDNSServer(m, &d, interface, serviceID, &saddr, r->port ? mDNSOpaque16fromIntVal(r->port) : UnicastDNSPort, scope,
- (n == 0 ? (r->timeout ? r->timeout : DEFAULT_UDNS_TIMEOUT) : 0), cellIntf, resGroupID, reqA, reqAAAA, mDNStrue);
+ s = mDNS_AddDNSServer(&mDNSStorage, &d, interface, serviceID, &saddr, r->port ? mDNSOpaque16fromIntVal(r->port) : UnicastDNSPort, scope,
+ (n == 0 ? (r->timeout ? r->timeout : DEFAULT_UDNS_TIMEOUT) : 0), cellIntf, isExpensive, resGroupID, reqA, reqAAAA, mDNStrue);
if (s)
{
LogInfo("ConfigDNSServers(%s): DNS server %#a:%d for domain %##s", DNSScopeToString(scope), &s->addr, mDNSVal16(s->port), d.c);
@@ -6528,7 +5488,7 @@ mDNSlocal void ConfigDNSServers(mDNS *const m, dns_resolver_t *r, mDNSInterfaceI
// "service_specific_resolver" has entries that should be used for Service scoped question i.e., questions that specify
// a service identifier (q->ServiceID)
//
-mDNSlocal void ConfigResolvers(mDNS *const m, dns_config_t *config, mDNSu32 scope, mDNSBool setsearch, mDNSBool setservers, MD5_CTX *sdc, mDNSu16 resGroupID)
+mDNSlocal void ConfigResolvers(dns_config_t *config, mDNSu32 scope, mDNSBool setsearch, mDNSBool setservers, MD5_CTX *sdc, mDNSu16 resGroupID)
{
int i;
dns_resolver_t **resolver;
@@ -6566,12 +5526,12 @@ mDNSlocal void ConfigResolvers(mDNS *const m, dns_config_t *config, mDNSu32 scop
// Parse the interface index
if (r->if_index != 0)
{
- interface = ConfigParseInterfaceID(m, r->if_index);
+ interface = ConfigParseInterfaceID(r->if_index);
}
if (setsearch)
{
- ConfigSearchDomains(m, resolver[i], interface, scope, sdc, config->generation);
+ ConfigSearchDomains(resolver[i], interface, scope, sdc, config->generation);
// Parse other scoped resolvers for search lists
if (!setservers)
@@ -6580,7 +5540,7 @@ mDNSlocal void ConfigResolvers(mDNS *const m, dns_config_t *config, mDNSu32 scop
if (r->port == 5353 || r->n_nameserver == 0)
{
- ConfigNonUnicastResolver(m, r);
+ ConfigNonUnicastResolver(r);
}
else
{
@@ -6589,7 +5549,7 @@ mDNSlocal void ConfigResolvers(mDNS *const m, dns_config_t *config, mDNSu32 scop
if (scope != kScopeNone)
resGroupID++;
- ConfigDNSServers(m, r, interface, scope, resGroupID);
+ ConfigDNSServers(r, interface, scope, resGroupID);
}
}
}
@@ -6622,8 +5582,9 @@ mDNSlocal mDNSBool QuestionValidForDNSTrigger(DNSQuestion *q)
// We set our state appropriately so that if we start receiving answers, trigger the
// upper layer to retry DNS questions.
#if APPLE_OSX_mDNSResponder
-mDNSexport void mDNSPlatformUpdateDNSStatus(mDNS *const m, DNSQuestion *q)
+mDNSexport void mDNSPlatformUpdateDNSStatus(DNSQuestion *q)
{
+ mDNS *const m = &mDNSStorage;
if (!QuestionValidForDNSTrigger(q))
return;
@@ -6640,26 +5601,27 @@ mDNSexport void mDNSPlatformUpdateDNSStatus(mDNS *const m, DNSQuestion *q)
m->p->v6answers = 0;
if (!m->p->v4answers || !m->p->v6answers)
{
- LogInfo("mDNSPlatformUpdateDNSStatus: Trigger needed v4 %d, v6 %d, quesiton %##s (%s)", m->p->v4answers, m->p->v6answers, q->qname.c,
+ LogInfo("mDNSPlatformUpdateDNSStatus: Trigger needed v4 %d, v6 %d, question %##s (%s)", m->p->v4answers, m->p->v6answers, q->qname.c,
DNSTypeName(q->qtype));
}
}
#endif
-mDNSlocal void AckConfigd(mDNS *const m, dns_config_t *config)
+mDNSlocal void AckConfigd(dns_config_t *config)
{
- mDNS_CheckLock(m);
+ mDNS_CheckLock(&mDNSStorage);
// Acking the configuration triggers configd to reissue the reachability queries
- m->p->DNSTrigger = NonZeroTime(m->timenow);
+ mDNSStorage.p->DNSTrigger = NonZeroTime(mDNSStorage.timenow);
_dns_configuration_ack(config, "com.apple.mDNSResponder");
}
// If v4q is non-NULL, it means we have received some answers for "A" type questions
// If v6q is non-NULL, it means we have received some answers for "AAAA" type questions
#if APPLE_OSX_mDNSResponder
-mDNSexport void mDNSPlatformTriggerDNSRetry(mDNS *const m, DNSQuestion *v4q, DNSQuestion *v6q)
+mDNSexport void mDNSPlatformTriggerDNSRetry(DNSQuestion *v4q, DNSQuestion *v6q)
{
+ mDNS *const m = &mDNSStorage;
mDNSBool trigger = mDNSfalse;
mDNSs32 timenow;
@@ -6722,7 +5684,7 @@ mDNSexport void mDNSPlatformTriggerDNSRetry(mDNS *const m, DNSQuestion *v4q, DNS
if (config)
{
mDNS_Lock(m);
- AckConfigd(m, config);
+ AckConfigd(config);
mDNS_Unlock(m);
dns_configuration_free(config);
}
@@ -6877,9 +5839,10 @@ mDNSlocal void SetupDDNSDomains(domainname *const fqdn, DNameListElem **RegDomai
}
// Returns mDNSfalse, if it does not set the configuration i.e., if the DNS configuration did not change
-mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn,
+mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn,
DNameListElem **RegDomains, DNameListElem **BrowseDomains, mDNSBool ackConfig)
{
+ mDNS *const m = &mDNSStorage;
MD5_CTX sdc; // search domain context
static mDNSu16 resolverGroupID = 0;
@@ -6932,7 +5895,7 @@ mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers,
a.ip.v4.b[2] & n.ip.v4.b[2],
a.ip.v4.b[1] & n.ip.v4.b[1],
a.ip.v4.b[0] & n.ip.v4.b[0]);
- UpdateSearchDomainHash(m, &sdc, buf, NULL);
+ UpdateSearchDomainHash(&sdc, buf, NULL);
mDNS_AddSearchDomain_CString(buf, mDNSNULL);
}
ifa = ifa->ifa_next;
@@ -6956,20 +5919,24 @@ mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers,
{
LogInfo("mDNSPlatformSetDNSConfig: config->n_resolver = %d, generation %llu, last %llu", config->n_resolver, config->generation, m->p->LastConfigGeneration);
- // For every network change, the search domain list is updated.
- // This update is done without regard for generation number because it is
- // not an expensive update and it keeps the search domain list in sync (even when
- // a network change occurs, while currently processing a network
- // change).
- //
- // For every DNS configuration change, the DNS server list is updated.
- // This update is NOT done every network change because it may involve
- // updating cache entries which worst-case is expensive. Setting the generation
- // per DNS server list change keeps the list in sync with configd.
-
+ // For every network change, mDNSPlatformSetDNSConfig is called twice. First,
+ // to update the search domain list (in which case, the setsearch bool is set);
+ // and second, to update the DNS server list (in which case, the setservers bool
+ // is set). The code assumes only one of these flags, setsearch or setserver,
+ // will be set when mDNSPlatformSetDNSConfig is called to handle a network change.
+ // The mDNSPlatformSetDNSConfig function also assumes that ackCfg will be set
+ // when setservers is set.
+
+ // The search domains update occurs on every network change to avoid sync issues
+ // that may occur if a network change happens during the processing
+ // of a network change. The dns servers update occurs when the DNS config
+ // changes. The dns servers stay in sync by saving the config's generation number
+ // on every update; and only updating when the generation number changes.
+
+ // If this is a DNS server update and the configuration hasn't changed, then skip update
if (setservers && m->p->LastConfigGeneration == config->generation)
{
- LogInfo("mDNSPlatformSetDNSConfig: generation number %llu same, not processing", config->generation);
+ LogInfo("mDNSPlatformSetDNSConfig(setservers): generation number %llu same, not processing", config->generation);
dns_configuration_free(config);
SetupDDNSDomains(fqdn, RegDomains, BrowseDomains);
return mDNSfalse;
@@ -6985,13 +5952,13 @@ mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers,
// same resolverGroupID.
//
// All non-scoped resolvers use the same resolverGroupID i.e, we treat them all equally.
- ConfigResolvers(m, config, kScopeNone, setsearch, setservers, &sdc, ++resolverGroupID);
+ ConfigResolvers(config, kScopeNone, setsearch, setservers, &sdc, ++resolverGroupID);
resolverGroupID += config->n_resolver;
- ConfigResolvers(m, config, kScopeInterfaceID, setsearch, setservers, &sdc, resolverGroupID);
+ ConfigResolvers(config, kScopeInterfaceID, setsearch, setservers, &sdc, resolverGroupID);
resolverGroupID += config->n_scoped_resolver;
- ConfigResolvers(m, config, kScopeServiceID, setsearch, setservers, &sdc, resolverGroupID);
+ ConfigResolvers(config, kScopeServiceID, setsearch, setservers, &sdc, resolverGroupID);
// Acking provides a hint to other processes that the current DNS configuration has completed
// its update. When configd receives the ack, it publishes a notification.
@@ -7000,12 +5967,21 @@ mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers,
if (ackConfig)
{
// Note: We have to set the generation number here when we are acking.
+ // For every DNS configuration change, we do the following:
+ //
+ // 1) Copy dns configuration, handle search domains change
+ // 2) Copy dns configuration, handle dns server change
+ //
+ // If we update the generation number at step (1), we won't process the
+ // DNS servers the second time because generation number would be the same.
+ // As we ack only when we process dns servers, we set the generation number
+ // during acking.
m->p->LastConfigGeneration = config->generation;
LogInfo("mDNSPlatformSetDNSConfig: Acking configuration setservers %d, setsearch %d", setservers, setsearch);
- AckConfigd(m, config);
+ AckConfigd(config);
}
dns_configuration_free(config);
- if (setsearch) FinalizeSearchDomainHash(m, &sdc);
+ if (setsearch) FinalizeSearchDomainHash(&sdc);
}
}
#endif // MDNS_NO_DNSINFO
@@ -7014,11 +5990,10 @@ mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers,
}
-mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *r)
+mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *r)
{
char buf[256];
- (void)m; // Unused
-
+
CFDictionaryRef dict = SCDynamicStoreCopyValue(NULL, NetworkChangedKey_IPv4);
if (dict)
{
@@ -7054,6 +6029,12 @@ mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4,
// find primary interface in list
while (ifa && (mDNSIPv4AddressIsZero(v4->ip.v4) || mDNSv4AddressIsLinkLocal(&v4->ip.v4) || !HavePrimaryGlobalv6))
{
+ if (!ifa->ifa_addr)
+ {
+ LogMsg("Skip interface, %s, since ifa_addr is not set.", (ifa->ifa_name) ? ifa->ifa_name: "name not found");
+ ifa = ifa->ifa_next;
+ continue;
+ }
mDNSAddr tmp6 = zeroAddr;
if (!strcmp(buf, ifa->ifa_name))
{
@@ -7299,7 +6280,7 @@ mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m)
#endif // ! NO_AWACS
#if !TARGET_OS_EMBEDDED
-mDNSlocal void ProcessConndConfigChanges(mDNS *const m);
+mDNSlocal void ProcessConndConfigChanges(void);
#endif
#endif // APPLE_OSX_mDNSResponder
@@ -7543,7 +6524,7 @@ mDNSlocal void SetDomainSecrets_internal(mDNS *m)
else if (info->AutoTunnelServiceStarted)
needAutoTunnelNAT = true;
- UpdateAutoTunnelDomainStatus(m, info);
+ UpdateAutoTunnelDomainStatus(info);
}
}
@@ -7562,7 +6543,7 @@ mDNSlocal void SetDomainSecrets_internal(mDNS *m)
}
UpdateAnonymousRacoonConfig(m); // Determine whether we need racoon to accept incoming connections
- ProcessConndConfigChanges(m); // Update AutoTunnelInnerAddress values and default ipsec policies as necessary
+ ProcessConndConfigChanges(); // Update AutoTunnelInnerAddress values and default ipsec policies as necessary
}
#endif // APPLE_OSX_mDNSResponder
@@ -7840,8 +6821,9 @@ typedef struct
#include <IOKit/IOKitLib.h>
#include <dns_util.h>
-mDNSlocal mDNSu16 GetPortArray(mDNS *const m, int trans, mDNSIPPort *portarray)
+mDNSlocal mDNSu16 GetPortArray(int trans, mDNSIPPort *portarray)
{
+ mDNS *const m = &mDNSStorage;
const domainlabel *const tp = (trans == mDNSTransport_UDP) ? (const domainlabel *)"\x4_udp" : (const domainlabel *)"\x4_tcp";
int count = 0;
@@ -7913,8 +6895,9 @@ mDNSlocal mDNSBool OnBattery(void)
#define TfrRecordToNIC(RR) \
((!(RR)->resrec.InterfaceID && ((RR)->ForceMCast || IsLocalDomain((RR)->resrec.name))))
-mDNSlocal mDNSu32 CountProxyRecords(mDNS *const m, uint32_t *const numbytes, NetworkInterfaceInfo *const intf, mDNSBool TCPKAOnly, mDNSBool supportsTCPKA)
+mDNSlocal mDNSu32 CountProxyRecords(uint32_t *const numbytes, NetworkInterfaceInfo *const intf, mDNSBool TCPKAOnly, mDNSBool supportsTCPKA)
{
+ mDNS *const m = &mDNSStorage;
*numbytes = 0;
int count = 0;
@@ -7957,8 +6940,9 @@ mDNSlocal mDNSu32 CountProxyRecords(mDNS *const m, uint32_t *const numbytes, Net
return(count);
}
-mDNSlocal void GetProxyRecords(mDNS *const m, DNSMessage *const msg, uint32_t *const numbytes, FatPtr *const records, mDNSBool TCPKAOnly, mDNSBool supportsTCPKA)
+mDNSlocal void GetProxyRecords(DNSMessage *const msg, uint32_t *const numbytes, FatPtr *const records, mDNSBool TCPKAOnly, mDNSBool supportsTCPKA)
{
+ mDNS *const m = &mDNSStorage;
mDNSu8 *p = msg->data;
const mDNSu8 *const limit = p + *numbytes;
InitializeDNSMessage(&msg->h, zeroID, zeroID);
@@ -8013,7 +6997,7 @@ mDNSexport mDNSBool SupportsInNICProxy(NetworkInterfaceInfo *const intf)
return CheckInterfaceSupport(intf, mDNS_IOREG_KEY);
}
-mDNSexport mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const intf, mDNSBool *keepaliveOnly) // Called with the lock held
+mDNSexport mStatus ActivateLocalProxy(NetworkInterfaceInfo *const intf, mDNSBool *keepaliveOnly) // Called with the lock held
{
mStatus result = mStatus_UnknownErr;
mDNSBool TCPKAOnly = mDNSfalse;
@@ -8029,7 +7013,7 @@ mDNSexport mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const
// Only TCP Keepalive records are to be offloaded if
// - The system is on battery
// - OR wake for network access is not set but powernap is enabled
- TCPKAOnly = supportsTCPKA && ((m->SystemWakeOnLANEnabled == mDNS_WakeOnBattery) || onbattery);
+ TCPKAOnly = supportsTCPKA && ((mDNSStorage.SystemWakeOnLANEnabled == mDNS_WakeOnBattery) || onbattery);
#else
(void) onbattery; // unused;
#endif
@@ -8037,15 +7021,48 @@ mDNSexport mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const
io_name_t n1, n2;
IOObjectGetClass(service, n1);
- io_object_t parent;
+ io_object_t parent = IO_OBJECT_NULL;
+
kern_return_t kr = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent);
if (kr != KERN_SUCCESS) LogMsg("ActivateLocalProxy: IORegistryEntryGetParentEntry for %s/%s failed %d", intf->ifname, n1, kr);
else
{
- IOObjectGetClass(parent, n2);
- LogSPS("ActivateLocalProxy: Interface %s service %s parent %s", intf->ifname, n1, n2);
- const CFTypeRef ref = IORegistryEntryCreateCFProperty(parent, CFSTR(mDNS_IOREG_KEY), kCFAllocatorDefault, mDNSNULL);
- if (!ref) LogSPS("ActivateLocalProxy: No mDNS_IOREG_KEY for interface %s/%s/%s", intf->ifname, n1, n2);
+ CFTypeRef ref = mDNSNULL;
+ if (IsAppleTV())
+ {
+ while (service)
+ {
+ ref = IORegistryEntryCreateCFProperty(parent, CFSTR(mDNS_IOREG_KEY), kCFAllocatorDefault, mDNSNULL);
+ if (!ref)
+ {
+ IOObjectRelease(service);
+ service = parent;
+ kr = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent);
+ if (kr != KERN_SUCCESS)
+ {
+ IOObjectGetClass(service, n1);
+ LogMsg("ActivateLocalProxy: IORegistryEntryGetParentEntry for %s/%s failed %d", intf->ifname, n1, kr);
+ parent = IO_OBJECT_NULL;
+ result = mStatus_BadStateErr;
+ break;
+ }
+ }
+ else
+ {
+ IOObjectGetClass(parent, n2);
+ LogSPS("ActivateLocalProxy: Found %s Interface %s parent %s", mDNS_IOREG_KEY, intf->ifname, n2);
+ break;
+ }
+ }
+ }
+ else
+ {
+ IOObjectGetClass(parent, n2);
+ LogSPS("ActivateLocalProxy: Interface %s service %s parent %s", intf->ifname, n1, n2);
+ ref = IORegistryEntryCreateCFProperty(parent, CFSTR(mDNS_IOREG_KEY), kCFAllocatorDefault, mDNSNULL);
+ }
+
+ if (!ref || parent == IO_OBJECT_NULL) LogSPS("ActivateLocalProxy: No mDNS_IOREG_KEY for interface %s/%s/%s", intf->ifname, n1, n2);
else
{
if (CFGetTypeID(ref) != CFStringGetTypeID() || !CFEqual(ref, CFSTR(mDNS_IOREG_VALUE)))
@@ -8063,9 +7080,9 @@ mDNSexport mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const
mDNSOffloadCmd cmd;
mDNSPlatformMemZero(&cmd, sizeof(cmd)); // When compiling 32-bit, make sure top 32 bits of 64-bit pointers get initialized to zero
cmd.command = cmd_mDNSOffloadRR;
- cmd.numUDPPorts = GetPortArray(m, mDNSTransport_UDP, mDNSNULL);
- cmd.numTCPPorts = GetPortArray(m, mDNSTransport_TCP, mDNSNULL);
- cmd.numRRRecords = CountProxyRecords(m, &cmd.rrBufferSize, intf, TCPKAOnly, supportsTCPKA);
+ cmd.numUDPPorts = GetPortArray(mDNSTransport_UDP, mDNSNULL);
+ cmd.numTCPPorts = GetPortArray(mDNSTransport_TCP, mDNSNULL);
+ cmd.numRRRecords = CountProxyRecords(&cmd.rrBufferSize, intf, TCPKAOnly, supportsTCPKA);
cmd.compression = sizeof(DNSMessageHeader);
DNSMessage *msg = (DNSMessage *)mallocL("mDNSOffloadCmd msg", sizeof(DNSMessageHeader) + cmd.rrBufferSize);
@@ -8079,9 +7096,9 @@ mDNSexport mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const
cmd.udpPorts.ptr, cmd.numUDPPorts,
cmd.tcpPorts.ptr, cmd.numTCPPorts);
- if (msg && cmd.rrRecords.ptr) GetProxyRecords(m, msg, &cmd.rrBufferSize, cmd.rrRecords.ptr, TCPKAOnly, supportsTCPKA);
- if (cmd.udpPorts.ptr) cmd.numUDPPorts = GetPortArray(m, mDNSTransport_UDP, cmd.udpPorts.ptr);
- if (cmd.tcpPorts.ptr) cmd.numTCPPorts = GetPortArray(m, mDNSTransport_TCP, cmd.tcpPorts.ptr);
+ if (msg && cmd.rrRecords.ptr) GetProxyRecords(msg, &cmd.rrBufferSize, cmd.rrRecords.ptr, TCPKAOnly, supportsTCPKA);
+ if (cmd.udpPorts.ptr) cmd.numUDPPorts = GetPortArray(mDNSTransport_UDP, cmd.udpPorts.ptr);
+ if (cmd.tcpPorts.ptr) cmd.numTCPPorts = GetPortArray(mDNSTransport_TCP, cmd.tcpPorts.ptr);
char outputData[2];
size_t outputDataSize = sizeof(outputData);
@@ -8098,9 +7115,9 @@ mDNSexport mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const
}
CFRelease(ref);
}
- IOObjectRelease(parent);
+ if (parent != IO_OBJECT_NULL) IOObjectRelease(parent);
}
- IOObjectRelease(service);
+ if (service != IO_OBJECT_NULL) IOObjectRelease(service);
*keepaliveOnly = TCPKAOnly;
return result;
}
@@ -8168,8 +7185,9 @@ mDNSlocal mDNSBool SystemSleepOnlyIfWakeOnLAN(void)
// relay) and host records get deregistered, then SRV (UpdateAllSrvRecords), PTR and TXT.
//
// Also note that returning false here will not delay sleep past the maximum of 10 seconds.
-mDNSexport mDNSBool RecordReadyForSleep(mDNS *const m, AuthRecord *rr)
+mDNSexport mDNSBool RecordReadyForSleep(AuthRecord *rr)
{
+ mDNS *const m = &mDNSStorage;
if (!AuthRecord_uDNS(rr)) return mDNStrue;
if ((rr->resrec.rrtype == kDNSType_AAAA) && SameDomainLabel(rr->namestorage.c, (const mDNSu8 *)"\x0c_autotunnel6"))
@@ -8385,8 +7403,9 @@ mDNSlocal mDNSv6Addr ParseBackToMyMacZone(CFDictionaryRef zones, DomainAuthInfo*
return addr;
}
-mDNSlocal void SetupBackToMyMacInnerAddresses(mDNS *const m, CFDictionaryRef BTMMDict)
+mDNSlocal void SetupBackToMyMacInnerAddresses(CFDictionaryRef BTMMDict)
{
+ mDNS *const m = &mDNSStorage;
DomainAuthInfo* info;
CFDictionaryRef zones = GetBackToMyMacZones(BTMMDict);
mDNSv6Addr newAddr;
@@ -8404,13 +7423,14 @@ mDNSlocal void SetupBackToMyMacInnerAddresses(mDNS *const m, CFDictionaryRef BTM
info->AutoTunnelInnerAddress = newAddr;
DeregisterAutoTunnelHostRecord(m, info);
UpdateAutoTunnelHostRecord(m, info);
- UpdateAutoTunnelDomainStatus(m, info);
+ UpdateAutoTunnelDomainStatus(info);
}
}
// MUST be called holding the lock
-mDNSlocal void ProcessConndConfigChanges(mDNS *const m)
+mDNSlocal void ProcessConndConfigChanges(void)
{
+ mDNS *const m = &mDNSStorage;
CFDictionaryRef dict = CopyConnectivityBackToMyMacDict();
if (!dict)
LogInfo("ProcessConndConfigChanges: No BTMM dictionary");
@@ -8418,7 +7438,7 @@ mDNSlocal void ProcessConndConfigChanges(mDNS *const m)
LogInfo("ProcessConndConfigChanges: relay %.16a", &relayAddr);
- SetupBackToMyMacInnerAddresses(m, dict);
+ SetupBackToMyMacInnerAddresses(dict);
if (dict) CFRelease(dict);
@@ -8432,7 +7452,7 @@ mDNSlocal void ProcessConndConfigChanges(mDNS *const m)
{
DeregisterAutoTunnel6Record(m, info);
UpdateAutoTunnel6Record(m, info);
- UpdateAutoTunnelDomainStatus(m, info);
+ UpdateAutoTunnelDomainStatus(info);
}
// Determine whether we need racoon to accept incoming connections
@@ -8462,8 +7482,9 @@ mDNSlocal mDNSBool IsAppleNetwork(mDNS *const m)
// Called with KQueueLock & mDNS lock
// SetNetworkChanged is allowed to shorten (but not extend) the pause while we wait for configuration changes to settle
-mDNSlocal void SetNetworkChanged(mDNS *const m, mDNSs32 delay)
+mDNSlocal void SetNetworkChanged(mDNSs32 delay)
{
+ mDNS *const m = &mDNSStorage;
mDNS_CheckLock(m);
if (!m->NetworkChanged || m->NetworkChanged - NonZeroTime(m->timenow + delay) > 0)
{
@@ -8475,8 +7496,9 @@ mDNSlocal void SetNetworkChanged(mDNS *const m, mDNSs32 delay)
}
// Called with KQueueLock & mDNS lock
-mDNSlocal void SetKeyChainTimer(mDNS *const m, mDNSs32 delay)
+mDNSlocal void SetKeyChainTimer(mDNSs32 delay)
{
+ mDNS *const m = &mDNSStorage;
// If it's not set or it needs to happen sooner than when it's currently set
if (!m->p->KeyChainTimer || m->p->KeyChainTimer - NonZeroTime(m->timenow + delay) > 0)
{
@@ -8485,8 +7507,9 @@ mDNSlocal void SetKeyChainTimer(mDNS *const m, mDNSs32 delay)
}
}
-mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
+mDNSexport void mDNSMacOSXNetworkChanged(void)
{
+ mDNS *const m = &mDNSStorage;
LogInfo("*** Network Configuration Change *** %d ticks late%s",
m->NetworkChanged ? mDNS_TimeNow(m) - m->NetworkChanged : 0,
m->NetworkChanged ? "" : " (no scheduled configuration change)");
@@ -8500,7 +7523,7 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
struct ifaddrs *ifa = myGetIfAddrs(1);
while (ifa)
{
- if (ifa->ifa_addr->sa_family == AF_INET6)
+ if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6)
{
struct in6_ifreq ifr6;
mDNSPlatformMemZero((char *)&ifr6, sizeof(ifr6));
@@ -8527,7 +7550,7 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
if (tentative)
{
mDNS_Lock(m);
- SetNetworkChanged(m, mDNSPlatformOneSecond / 2);
+ SetNetworkChanged(mDNSPlatformOneSecond / 2);
mDNS_Unlock(m);
return;
}
@@ -8537,15 +7560,16 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
mDNSs32 utc = mDNSPlatformUTC();
m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
m->SystemSleepOnlyIfWakeOnLAN = SystemSleepOnlyIfWakeOnLAN();
- MarkAllInterfacesInactive(m, utc);
- UpdateInterfaceList(m, utc);
- ClearInactiveInterfaces(m, utc);
- SetupActiveInterfaces(m, utc);
+ MarkAllInterfacesInactive(utc);
+ UpdateInterfaceList(utc);
+ ClearInactiveInterfaces(utc);
+ SetupActiveInterfaces(utc);
+ ReorderInterfaceList();
#if APPLE_OSX_mDNSResponder
#if !TARGET_OS_EMBEDDED
mDNS_Lock(m);
- ProcessConndConfigChanges(m);
+ ProcessConndConfigChanges();
mDNS_Unlock(m);
// Scan to find client tunnels whose questions have completed,
@@ -8601,7 +7625,7 @@ mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
{
if (!m->SPSSocket) // Not being Sleep Proxy Server; close any open BPF fds
{
- if (i->BPF_fd >= 0 && CountProxyTargets(m, i, mDNSNULL, mDNSNULL) == 0)
+ if (i->BPF_fd >= 0 && CountProxyTargets(i, mDNSNULL, mDNSNULL) == 0)
CloseBPF(i);
}
else // else, we're Sleep Proxy Server; open BPF fds
@@ -8764,7 +7788,7 @@ mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, v
{
(void)store; // Parameter not used
mDNS *const m = (mDNS *const)context;
- KQueueLock(m);
+ KQueueLock();
mDNS_Lock(m);
//mDNSs32 delay = mDNSPlatformOneSecond * 2; // Start off assuming a two-second delay
@@ -8781,7 +7805,7 @@ mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, v
int c_fast = 0;
// Do immediate network changed processing for "p2p*" interfaces and
- // for interfaces with the IFEF_DIRECTLINK flag set or association with a CarPlay
+ // for interfaces with the IFEF_DIRECTLINK or IFEF_AWDL flag set or association with a CarPlay
// hosted SSID.
{
CFArrayRef labels;
@@ -8812,7 +7836,7 @@ mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, v
// The 4th label (index = 3) should be the interface name.
if (CFStringGetCString(CFArrayGetValueAtIndex(labels, 3), buf, sizeof(buf), kCFStringEncodingUTF8)
- && (strstr(buf, "p2p") || (getExtendedFlags(buf) & IFEF_DIRECTLINK) || IsCarPlaySSID(buf)))
+ && (strstr(buf, "p2p") || (getExtendedFlags(buf) & (IFEF_DIRECTLINK | IFEF_AWDL)) || IsCarPlaySSID(buf)))
{
LogInfo("NetworkChanged: interface %s qualifies for reduced change handling delay", buf);
c_fast++;
@@ -8844,12 +7868,12 @@ mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, v
c_ddns ? "(DynamicDNS) " : "",
c_btmm ? "(BTMM) " : "",
c_v4ll ? "(kSCValNetIPv4ConfigMethodLinkLocal) " : "",
- c_fast ? "(P2P/IFEF_DIRECTLINK/IsCarPlaySSID) " : "",
+ c_fast ? "(P2P/IFEF_DIRECTLINK/IFEF_AWDL/IsCarPlaySSID) " : "",
delay,
(c_ddns || c_btmm) ? " + SetKeyChainTimer" : "");
}
- SetNetworkChanged(m, delay);
+ SetNetworkChanged(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
@@ -8857,12 +7881,12 @@ mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, v
// If we don't, then we will first try to register services in the clear, then later setup the
// DomainAuthInfo, which is incorrect.
if (c_ddns || c_btmm)
- SetKeyChainTimer(m, delay);
+ SetKeyChainTimer(delay);
// Don't try to call mDNSMacOSXNetworkChanged() here -- we're running on the wrong thread
mDNS_Unlock(m);
- KQueueUnlock(m, "NetworkChanged");
+ KQueueUnlock("NetworkChanged");
}
#if APPLE_OSX_mDNSResponder
@@ -8886,7 +7910,7 @@ mDNSlocal void DynamicStoreReconnected(SCDynamicStoreRef store, void *info)
mDNS *const m = (mDNS *const)info;
(void)store;
- KQueueLock(m); // serialize with KQueueLoop()
+ KQueueLock(); // serialize with KQueueLoop()
LogInfo("DynamicStoreReconnected: Reconnected");
@@ -8913,7 +7937,7 @@ mDNSlocal void DynamicStoreReconnected(SCDynamicStoreRef store, void *info)
if (spsStatusDict)
CFDictionaryApplyFunction(spsStatusDict, RefreshSPSStatus, NULL);
#endif
- KQueueUnlock(m, "DynamicStoreReconnected");
+ KQueueUnlock("DynamicStoreReconnected");
}
mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m)
@@ -8971,8 +7995,9 @@ exit:
#if !TARGET_OS_EMBEDDED // don't setup packet filter rules on embedded
-mDNSlocal void mDNSSetPacketFilterRules(mDNS *const m, char * ifname, const ResourceRecord *const excludeRecord)
+mDNSlocal void mDNSSetPacketFilterRules(char * ifname, const ResourceRecord *const excludeRecord)
{
+ mDNS *const m = &mDNSStorage;
AuthRecord *rr;
pfArray_t portArray;
pfArray_t protocolArray;
@@ -9043,7 +8068,7 @@ mDNSexport void mDNSUpdatePacketFilter(const ResourceRecord *const excludeRecord
if (strncmp(intf->ifname, "p2p", 3) == 0)
{
LogInfo("mDNSInitPacketFilter: Setting rules for ifname %s", intf->ifname);
- mDNSSetPacketFilterRules(m, intf->ifname, excludeRecord);
+ mDNSSetPacketFilterRules(intf->ifname, excludeRecord);
break;
}
intf = GetFirstActiveInterface(intf->next);
@@ -9060,16 +8085,11 @@ mDNSexport void mDNSUpdatePacketFilter(const ResourceRecord *const excludeRecord
#endif // !TARGET_OS_EMBEDDED
-// Handle AWDL KEV_DL_MASTER_ELECTED event by restarting queries and advertisements
-// marked to include the AWDL interface.
-mDNSlocal void newMasterElected(mDNS *const m, struct net_event_data * ptr)
+// AWDL should no longer generate KEV_DL_MASTER_ELECTED events, so just log a message if we receive one.
+mDNSlocal void newMasterElected(struct net_event_data * ptr)
{
char ifname[IFNAMSIZ];
mDNSu32 interfaceIndex;
- DNSQuestion *q;
- AuthRecord *rr;
- NetworkInterfaceInfoOSX *infoOSX;
- mDNSInterfaceID InterfaceID;
snprintf(ifname, IFNAMSIZ, "%s%d", ptr->if_name, ptr->if_unit);
interfaceIndex = if_nametoindex(ifname);
@@ -9080,35 +8100,7 @@ mDNSlocal void newMasterElected(mDNS *const m, struct net_event_data * ptr)
return;
}
- LogInfo("newMasterElected: ifname = %s, interfaceIndex = %d", ifname, interfaceIndex);
- infoOSX = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)interfaceIndex);
- if (!infoOSX)
- {
- LogInfo("newMasterElected: interface %s not yet active", ifname);
- return;
- }
- InterfaceID = infoOSX->ifinfo.InterfaceID;
-
- for (q = m->Questions; q; q=q->next)
- {
- if ((!q->InterfaceID && (q->flags & kDNSServiceFlagsIncludeAWDL))
- || q->InterfaceID == InterfaceID)
- {
- LogInfo("newMasterElected: restarting %s query for %##s", DNSTypeName(q->qtype), q->qname.c);
- mDNSCoreRestartQuestion(m, q);
- }
- }
-
- for (rr = m->ResourceRecords; rr; rr=rr->next)
- {
- if ((!rr->resrec.InterfaceID
- && ((rr->ARType == AuthRecordAnyIncludeAWDL) || ((rr->ARType == AuthRecordAnyIncludeAWDLandP2P))))
- || rr->resrec.InterfaceID == InterfaceID)
- {
- LogInfo("newMasterElected: restarting %s announcements for %##s", DNSTypeName(rr->resrec.rrtype), rr->namestorage.c);
- mDNSCoreRestartRegistration(m, rr, -1);
- }
- }
+ LogInfo("newMasterElected: KEV_DL_MASTER_ELECTED received on ifname = %s, interfaceIndex = %d", ifname, interfaceIndex);
}
// An ssth array of all zeroes indicates the peer has no services registered.
@@ -9136,8 +8128,9 @@ mDNSlocal mDNSBool allZeroSSTH(struct opaque_presence_indication *op)
}
// Mark records from this peer for deletion from the cache.
-mDNSlocal void removeCachedPeerRecords(mDNS *const m, mDNSu32 ifindex, mDNSAddr *ap, bool purgeNow)
+mDNSlocal void removeCachedPeerRecords(mDNSu32 ifindex, mDNSAddr *ap, bool purgeNow)
{
+ mDNS *const m = &mDNSStorage;
mDNSu32 slot;
CacheGroup *cg;
CacheRecord *cr;
@@ -9146,7 +8139,7 @@ mDNSlocal void removeCachedPeerRecords(mDNS *const m, mDNSu32 ifindex, mDNSAddr
// Using mDNSPlatformInterfaceIDfromInterfaceIndex() would lead to recursive
// locking issues, see: <rdar://problem/21332983>
- infoOSX = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)ifindex);
+ infoOSX = IfindexToInterfaceInfoOSX((mDNSInterfaceID)(uintptr_t)ifindex);
if (!infoOSX)
{
LogInfo("removeCachedPeerRecords: interface %d not yet active", ifindex);
@@ -9170,7 +8163,7 @@ mDNSlocal void removeCachedPeerRecords(mDNS *const m, mDNSu32 ifindex, mDNSAddr
}
// Handle KEV_DL_NODE_PRESENCE event.
-mDNSlocal void nodePresence(mDNS *const m, struct kev_dl_node_presence * p)
+mDNSlocal void nodePresence(struct kev_dl_node_presence * p)
{
char buf[INET6_ADDRSTRLEN];
struct opaque_presence_indication *op = (struct opaque_presence_indication *) p->node_service_info;
@@ -9190,12 +8183,12 @@ mDNSlocal void nodePresence(mDNS *const m, struct kev_dl_node_presence * p)
peerAddr.ip.v6 = *(mDNSv6Addr*)&p->sin6_node_address.sin6_addr;
LogInfo("nodePresence: ssth is all zeroes, reconfirm cached records for this peer");
- removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr, false);
+ removeCachedPeerRecords(p->sdl_node_address.sdl_index, & peerAddr, false);
}
}
// Handle KEV_DL_NODE_ABSENCE event.
-mDNSlocal void nodeAbsence(mDNS *const m, struct kev_dl_node_absence * p)
+mDNSlocal void nodeAbsence(struct kev_dl_node_absence * p)
{
mDNSAddr peerAddr;
char buf[INET6_ADDRSTRLEN];
@@ -9209,10 +8202,10 @@ mDNSlocal void nodeAbsence(mDNS *const m, struct kev_dl_node_absence * p)
peerAddr.ip.v6 = *(mDNSv6Addr*)&p->sin6_node_address.sin6_addr;
LogInfo("nodeAbsence: immediately purge cached records from this peer");
- removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr, true);
+ removeCachedPeerRecords(p->sdl_node_address.sdl_index, & peerAddr, true);
}
-mDNSlocal void SysEventCallBack(int s1, short __unused filter, void *context)
+mDNSlocal void SysEventCallBack(int s1, short __unused filter, void *context, __unused mDNSBool encounteredEOF)
{
mDNS *const m = (mDNS *const)context;
@@ -9256,13 +8249,13 @@ mDNSlocal void SysEventCallBack(int s1, short __unused filter, void *context)
"?");
if (msg.k.event_code == KEV_DL_NODE_PRESENCE)
- nodePresence(m, (struct kev_dl_node_presence *) &msg.k.event_data);
+ nodePresence((struct kev_dl_node_presence *) &msg.k.event_data);
if (msg.k.event_code == KEV_DL_NODE_ABSENCE)
- nodeAbsence(m, (struct kev_dl_node_absence *) &msg.k.event_data);
+ nodeAbsence((struct kev_dl_node_absence *) &msg.k.event_data);
if (msg.k.event_code == KEV_DL_MASTER_ELECTED)
- newMasterElected(m, (struct net_event_data *) &msg.k.event_data);
+ newMasterElected((struct net_event_data *) &msg.k.event_data);
// We receive network change notifications both through configd and through SYSPROTO_EVENT socket.
// Configd may not generate network change events for manually configured interfaces (i.e., non-DHCP)
@@ -9271,7 +8264,7 @@ mDNSlocal void SysEventCallBack(int s1, short __unused filter, void *context)
// Hence, during wake up, if we see a KEV_DL_LINK_ON (i.e., link is UP), we trigger a network change.
if (msg.k.event_code == KEV_DL_WAKEFLAGS_CHANGED || msg.k.event_code == KEV_DL_LINK_ON)
- SetNetworkChanged(m, mDNSPlatformOneSecond * 2);
+ SetNetworkChanged(mDNSPlatformOneSecond * 2);
#if !TARGET_OS_EMBEDDED // don't setup packet filter rules on embedded
@@ -9288,7 +8281,7 @@ mDNSlocal void SysEventCallBack(int s1, short __unused filter, void *context)
LogInfo("SysEventCallBack: KEV_DL_IF_ATTACHED if_family = %d, if_unit = %d, if_name = %s", p->if_family, p->if_unit, p->if_name);
- mDNSSetPacketFilterRules(m, ifname, NULL);
+ mDNSSetPacketFilterRules(ifname, NULL);
}
}
@@ -9375,7 +8368,7 @@ mDNSlocal OSStatus KeychainChanged(SecKeychainEvent keychainEvent, SecKeychainCa
keychainEvent == kSecDeleteEvent ? "kSecDeleteEvent" :
keychainEvent == kSecUpdateEvent ? "kSecUpdateEvent" : "<Unknown>");
// We're running on the CFRunLoop (Mach port) thread, not the kqueue thread, so we need to grab the KQueueLock before proceeding
- KQueueLock(m);
+ KQueueLock();
mDNS_Lock(m);
// To not read the keychain twice: when BTMM is enabled, changes happen to the keychain
@@ -9389,10 +8382,10 @@ mDNSlocal OSStatus KeychainChanged(SecKeychainEvent keychainEvent, SecKeychainCa
//
// Lastly, non-BTMM WAB cases can use the keychain but not the DynStore, so we need to set
// the timer here, as it will not get set by NetworkChanged().
- SetKeyChainTimer(m, mDNSPlatformOneSecond);
+ SetKeyChainTimer(mDNSPlatformOneSecond);
mDNS_Unlock(m);
- KQueueUnlock(m, "KeychainChanged");
+ KQueueUnlock("KeychainChanged");
}
}
CFRelease(skc);
@@ -9432,14 +8425,14 @@ mDNSlocal void PowerOn(mDNS *const m)
// Hold on to a sleep assertion to allow mDNSResponder to perform its maintenance activities.
// This allows for the network link to come up, DHCP to get an address, mDNS to issue queries etc.
// We will clear this assertion as soon as we think the mainenance activities are done.
- mDNSPlatformPreventSleep(m, DARK_WAKE_TIME, "mDNSResponder:maintenance");
+ mDNSPlatformPreventSleep(DARK_WAKE_TIME, "mDNSResponder:maintenance");
}
mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messageType, void *messageArgument)
{
mDNS *const m = (mDNS *const)refcon;
- KQueueLock(m);
+ KQueueLock();
(void)service; // Parameter not used
debugf("PowerChanged %X %lX", messageType, messageArgument);
@@ -9451,7 +8444,7 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag
case kIOMessageCanSystemPowerOff: LogSPS("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; // E0000240
case kIOMessageSystemWillPowerOff: LogSPS("PowerChanged kIOMessageSystemWillPowerOff"); // E0000250
mDNSCoreMachineSleep(m, true);
- if (m->SleepState == SleepState_Sleeping) mDNSMacOSXNetworkChanged(m);
+ if (m->SleepState == SleepState_Sleeping) mDNSMacOSXNetworkChanged();
break;
case kIOMessageSystemWillNotPowerOff: LogSPS("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260
case kIOMessageCanSystemSleep: LogSPS("PowerChanged kIOMessageCanSystemSleep"); break; // E0000270
@@ -9470,7 +8463,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);
- SetNetworkChanged(m, mDNSPlatformOneSecond * 2);
+ SetNetworkChanged(mDNSPlatformOneSecond * 2);
mDNS_Unlock(m);
break;
@@ -9482,7 +8475,7 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag
{
LogMsg("kIOMessageSystemWillPowerOn: ERROR m->SleepState %d", m->SleepState);
m->SleepState = SleepState_Sleeping;
- mDNSMacOSXNetworkChanged(m);
+ mDNSMacOSXNetworkChanged();
}
PowerOn(m);
break;
@@ -9494,7 +8487,7 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag
else if (messageType == kIOMessageCanSystemSleep)
IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
- KQueueUnlock(m, "PowerChanged Sleep/Wake");
+ KQueueUnlock("PowerChanged Sleep/Wake");
}
// iPhone OS doesn't currently have SnowLeopard's IO Power Management
@@ -9503,7 +8496,7 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag
mDNSlocal void SnowLeopardPowerChanged(void *refcon, IOPMConnection connection, IOPMConnectionMessageToken token, IOPMSystemPowerStateCapabilities eventDescriptor)
{
mDNS *const m = (mDNS *const)refcon;
- KQueueLock(m);
+ KQueueLock();
LogSPS("SnowLeopardPowerChanged %X %X %X%s%s%s%s%s",
connection, token, eventDescriptor,
eventDescriptor & kIOPMSystemPowerStateCapabilityCPU ? " CPU" : "",
@@ -9535,7 +8528,7 @@ mDNSlocal void SnowLeopardPowerChanged(void *refcon, IOPMConnection connection,
// 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);
+ SetNetworkChanged(mDNSPlatformOneSecond * 2);
mDNS_Unlock(m);
}
IOPMConnectionAcknowledgeEvent(connection, token);
@@ -9552,7 +8545,7 @@ mDNSlocal void SnowLeopardPowerChanged(void *refcon, IOPMConnection connection,
m->p->SleepCookie = token;
}
- KQueueUnlock(m, "SnowLeopardPowerChanged Sleep/Wake");
+ KQueueUnlock("SnowLeopardPowerChanged Sleep/Wake");
}
#endif
@@ -9594,10 +8587,9 @@ mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result
}
// Returns true on success and false on failure
-mDNSlocal mDNSBool mDNSMacOSXCreateEtcHostsEntry(mDNS *const m, const domainname *domain, const struct sockaddr *sa, const domainname *cname, char *ifname, AuthHash *auth)
+mDNSlocal mDNSBool mDNSMacOSXCreateEtcHostsEntry(const domainname *domain, const struct sockaddr *sa, const domainname *cname, char *ifname, AuthHash *auth)
{
AuthRecord *rr;
- mDNSu32 slot;
mDNSu32 namehash;
AuthGroup *ag;
mDNSInterfaceID InterfaceID = mDNSInterface_LocalOnly;
@@ -9638,9 +8630,8 @@ mDNSlocal mDNSBool mDNSMacOSXCreateEtcHostsEntry(mDNS *const m, const domainname
rrtype = kDNSType_CNAME;
// Check for duplicates. See whether we parsed an entry before like this ?
- slot = AuthHashSlot(domain);
namehash = DomainNameHashValue(domain);
- ag = AuthGroupForName(auth, slot, namehash, domain);
+ ag = AuthGroupForName(auth, namehash, domain);
if (ag)
{
rr = ag->members;
@@ -9710,8 +8701,8 @@ mDNSlocal mDNSBool mDNSMacOSXCreateEtcHostsEntry(mDNS *const m, const domainname
}
rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
SetNewRData(&rr->resrec, mDNSNULL, 0); // Sets rr->rdatahash for us
- LogInfo("mDNSMacOSXCreateEtcHostsEntry: Adding resource record %s", ARDisplayString(m, rr));
- InsertAuthRecord(m, auth, rr);
+ LogInfo("mDNSMacOSXCreateEtcHostsEntry: Adding resource record %s", ARDisplayString(&mDNSStorage, rr));
+ InsertAuthRecord(&mDNSStorage, auth, rr);
return mDNStrue;
}
@@ -9743,7 +8734,7 @@ mDNSlocal int EtcHostsParseOneName(int start, int length, char *buffer, char **n
return -1;
}
-mDNSlocal void mDNSMacOSXParseEtcHostsLine(mDNS *const m, char *buffer, ssize_t length, AuthHash *auth)
+mDNSlocal void mDNSMacOSXParseEtcHostsLine(char *buffer, ssize_t length, AuthHash *auth)
{
int i;
int ifStart = 0;
@@ -9808,7 +8799,7 @@ mDNSlocal void mDNSMacOSXParseEtcHostsLine(mDNS *const m, char *buffer, ssize_t
freeaddrinfo(gairesults);
return;
}
- mDNSMacOSXCreateEtcHostsEntry(m, &name1d, gairesults->ai_addr, mDNSNULL, ifname, auth);
+ mDNSMacOSXCreateEtcHostsEntry(&name1d, gairesults->ai_addr, mDNSNULL, ifname, auth);
}
else if (i != -1)
{
@@ -9823,7 +8814,7 @@ mDNSlocal void mDNSMacOSXParseEtcHostsLine(mDNS *const m, char *buffer, ssize_t
freeaddrinfo(gairesults);
return;
}
- mDNSMacOSXCreateEtcHostsEntry(m, &first, gairesults->ai_addr, mDNSNULL, ifname, auth);
+ mDNSMacOSXCreateEtcHostsEntry(&first, gairesults->ai_addr, mDNSNULL, ifname, auth);
// /etc/hosts alias discussion:
//
@@ -9867,7 +8858,7 @@ mDNSlocal void mDNSMacOSXParseEtcHostsLine(mDNS *const m, char *buffer, ssize_t
// Ignore if it points to itself
if (!SameDomainName(&first, &name2d))
{
- if (!mDNSMacOSXCreateEtcHostsEntry(m, &name2d, mDNSNULL, &first, ifname, auth))
+ if (!mDNSMacOSXCreateEtcHostsEntry(&name2d, mDNSNULL, &first, ifname, auth))
{
freeaddrinfo(gairesults);
return;
@@ -9891,7 +8882,7 @@ mDNSlocal void mDNSMacOSXParseEtcHostsLine(mDNS *const m, char *buffer, ssize_t
freeaddrinfo(gairesults);
}
-mDNSlocal void mDNSMacOSXParseEtcHosts(mDNS *const m, int fd, AuthHash *auth)
+mDNSlocal void mDNSMacOSXParseEtcHosts(int fd, AuthHash *auth)
{
mDNSBool good;
char buf[ETCHOSTS_BUFSIZE];
@@ -9939,15 +8930,16 @@ mDNSlocal void mDNSMacOSXParseEtcHosts(mDNS *const m, int fd, AuthHash *auth)
LogMsg("mDNSMacOSXParseEtcHosts: Length is zero!");
continue;
}
- mDNSMacOSXParseEtcHostsLine(m, buf, len, auth);
+ mDNSMacOSXParseEtcHostsLine(buf, len, auth);
}
fclose(fp);
}
mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m);
-mDNSlocal int mDNSMacOSXGetEtcHostsFD(mDNS *const m)
+mDNSlocal int mDNSMacOSXGetEtcHostsFD(void)
{
+ mDNS *const m = &mDNSStorage;
#ifdef __DISPATCH_GROUP__
// Can't do this stuff to be notified of changes in /etc/hosts if we don't have libdispatch
static dispatch_queue_t etcq = 0;
@@ -10090,8 +9082,9 @@ mDNSlocal void FlushAllCacheRecords(mDNS *const m)
}
// Add new entries to the core. If justCheck is set, this function does not add, just returns true
-mDNSlocal mDNSBool EtcHostsAddNewEntries(mDNS *const m, AuthHash *newhosts, mDNSBool justCheck)
+mDNSlocal mDNSBool EtcHostsAddNewEntries(AuthHash *newhosts, mDNSBool justCheck)
{
+ mDNS *const m = &mDNSStorage;
AuthGroup *ag;
mDNSu32 slot;
AuthRecord *rr, *primary, *rrnext;
@@ -10105,7 +9098,7 @@ mDNSlocal mDNSBool EtcHostsAddNewEntries(mDNS *const m, AuthHash *newhosts, mDNS
AuthGroup *ag1;
AuthRecord *rr1;
mDNSBool found = mDNSfalse;
- ag1 = AuthGroupForRecord(&m->rrauth, slot, &rr->resrec);
+ ag1 = AuthGroupForRecord(&m->rrauth, &rr->resrec);
if (ag1 && ag1->members)
{
if (!primary) primary = ag1->members;
@@ -10149,8 +9142,9 @@ mDNSlocal mDNSBool EtcHostsAddNewEntries(mDNS *const m, AuthHash *newhosts, mDNS
// Delete entries from the core that are no longer needed. If justCheck is set, this function
// does not delete, just returns true
-mDNSlocal mDNSBool EtcHostsDeleteOldEntries(mDNS *const m, AuthHash *newhosts, mDNSBool justCheck)
+mDNSlocal mDNSBool EtcHostsDeleteOldEntries(AuthHash *newhosts, mDNSBool justCheck)
{
+ mDNS *const m = &mDNSStorage;
AuthGroup *ag;
mDNSu32 slot;
AuthRecord *rr, *rrnext;
@@ -10163,7 +9157,7 @@ mDNSlocal mDNSBool EtcHostsDeleteOldEntries(mDNS *const m, AuthHash *newhosts, m
AuthRecord *rr1;
rrnext = rr->next;
if (rr->RecordCallback != FreeEtcHosts) continue;
- ag1 = AuthGroupForRecord(newhosts, slot, &rr->resrec);
+ ag1 = AuthGroupForRecord(newhosts, &rr->resrec);
if (ag1)
{
rr1 = ag1->members;
@@ -10218,9 +9212,9 @@ mDNSlocal void UpdateEtcHosts(mDNS *const m, void *context)
mDNS_CheckLock(m);
//Delete old entries from the core if they are not present in the newhosts
- EtcHostsDeleteOldEntries(m, newhosts, mDNSfalse);
+ EtcHostsDeleteOldEntries(newhosts, mDNSfalse);
// Add the new entries to the core if not already present in the core
- EtcHostsAddNewEntries(m, newhosts, mDNSfalse);
+ EtcHostsAddNewEntries(newhosts, mDNSfalse);
}
mDNSlocal void FreeNewHosts(AuthHash *newhosts)
@@ -10248,16 +9242,16 @@ mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m)
// As we will be modifying the core, we can only have one thread running at
// any point in time.
- KQueueLock(m);
+ KQueueLock();
mDNSPlatformMemZero(&newhosts, sizeof(AuthHash));
// Get the file desecriptor (will trigger us to start watching for changes)
- int fd = mDNSMacOSXGetEtcHostsFD(m);
+ int fd = mDNSMacOSXGetEtcHostsFD();
if (fd != -1)
{
LogInfo("mDNSMacOSXUpdateEtcHosts: Parsing /etc/hosts fd %d", fd);
- mDNSMacOSXParseEtcHosts(m, fd, &newhosts);
+ mDNSMacOSXParseEtcHosts(fd, &newhosts);
}
else LogInfo("mDNSMacOSXUpdateEtcHosts: /etc/hosts is not present");
@@ -10277,16 +9271,16 @@ mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m)
// in the future and this code does not have to change.
mDNS_Lock(m);
// Add the new entries to the core if not already present in the core
- if (!EtcHostsAddNewEntries(m, &newhosts, mDNStrue))
+ if (!EtcHostsAddNewEntries(&newhosts, mDNStrue))
{
// No new entries to add, check to see if we need to delete any old entries from the
// core if they are not present in the newhosts
- if (!EtcHostsDeleteOldEntries(m, &newhosts, mDNStrue))
+ if (!EtcHostsDeleteOldEntries(&newhosts, mDNStrue))
{
LogInfo("mDNSMacOSXUpdateEtcHosts: No work");
FreeNewHosts(&newhosts);
mDNS_Unlock(m);
- KQueueUnlock(m, "/etc/hosts changed");
+ KQueueUnlock("/etc/hosts changed");
return;
}
}
@@ -10311,7 +9305,7 @@ mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m)
mDNSCoreRestartAddressQueries(m, mDNSfalse, FlushAllCacheRecords, UpdateEtcHosts, &newhosts);
FreeNewHosts(&newhosts);
mDNS_Unlock(m);
- KQueueUnlock(m, "/etc/hosts changed");
+ KQueueUnlock("/etc/hosts changed");
}
#if COMPILER_LIKES_PRAGMA_MARK
@@ -10383,7 +9377,7 @@ mDNSlocal mDNSBool mDNSPlatformInit_CanReceiveUnicast(void)
return(err == 0);
}
-mDNSlocal void CreatePTRRecord(mDNS *const m, const domainname *domain)
+mDNSlocal void CreatePTRRecord(const domainname *domain)
{
AuthRecord *rr;
const domainname *pname = (domainname *)"\x9" "localhost";
@@ -10401,7 +9395,7 @@ mDNSlocal void CreatePTRRecord(mDNS *const m, const domainname *domain)
rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
SetNewRData(&rr->resrec, mDNSNULL, 0); // Sets rr->rdatahash for us
- mDNS_Register(m, rr);
+ mDNS_Register(&mDNSStorage, rr);
}
// Setup PTR records for 127.0.0.1 and ::1. This helps answering them locally rather than relying
@@ -10411,7 +9405,7 @@ mDNSlocal void CreatePTRRecord(mDNS *const m, const domainname *domain)
//
// Note: We could have set this up while parsing the entries in /etc/hosts. But this is kept separate
// intentionally to avoid adding to the complexity of code handling /etc/hosts.
-mDNSlocal void SetupLocalHostRecords(mDNS *const m)
+mDNSlocal void SetupLocalHostRecords(void)
{
char buffer[MAX_REVERSE_MAPPING_NAME];
domainname name;
@@ -10424,7 +9418,7 @@ mDNSlocal void SetupLocalHostRecords(mDNS *const m)
mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.",
ptr[3], ptr[2], ptr[1], ptr[0]);
MakeDomainNameFromDNSNameString(&name, buffer);
- CreatePTRRecord(m, &name);
+ CreatePTRRecord(&name);
}
else LogMsg("SetupLocalHostRecords: ERROR!! inet_pton AF_INET failed");
@@ -10440,11 +9434,15 @@ mDNSlocal void SetupLocalHostRecords(mDNS *const m)
}
mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa.");
MakeDomainNameFromDNSNameString(&name, buffer);
- CreatePTRRecord(m, &name);
+ CreatePTRRecord(&name);
}
else LogMsg("SetupLocalHostRecords: ERROR!! inet_pton AF_INET6 failed");
}
+#if APPLE_OSX_mDNSResponder // Don't compile for dnsextd target
+mDNSlocal void setSameDomainLabelPointer(void);
+#endif
+
// Construction of Default Browse domain list (i.e. when clients pass NULL) is as follows:
// 1) query for b._dns-sd._udp.local on LocalOnly interface
// (.local manually generated via explicit callback)
@@ -10462,6 +9460,10 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
char HINFO_SWstring[256] = "";
mDNSMacOSXSystemBuildNumber(HINFO_SWstring);
+#if APPLE_OSX_mDNSResponder
+ setSameDomainLabelPointer();
+#endif
+
err = mDNSHelperInit();
if (err)
return err;
@@ -10574,10 +9576,6 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
m->p->DNSTrigger = 0;
m->p->LastConfigGeneration = 0;
-#if APPLE_OSX_mDNSResponder
- uuid_generate(m->asl_uuid);
-#endif
-
m->AutoTunnelRelayAddr = zerov6Addr;
NetworkChangedKey_IPv4 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
@@ -10598,8 +9596,9 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
mDNSs32 utc = mDNSPlatformUTC();
m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
myGetIfAddrs(1);
- UpdateInterfaceList(m, utc);
- SetupActiveInterfaces(m, utc);
+ UpdateInterfaceList(utc);
+ SetupActiveInterfaces(utc);
+ ReorderInterfaceList();
// Explicitly ensure that our Keychain operations utilize the system domain.
#ifndef NO_SECURITYFRAMEWORK
@@ -10684,7 +9683,7 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
if (SSLqueue == mDNSNULL) LogMsg("dispatch_queue_create: SSL queue NULL");
mDNSMacOSXUpdateEtcHosts(m);
- SetupLocalHostRecords(m);
+ SetupLocalHostRecords();
return(mStatus_NoError);
}
@@ -10709,19 +9708,7 @@ mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
if (result == mStatus_NoError)
{
mDNSCoreInitComplete(m, mStatus_NoError);
-
-#if !NO_D2D
- // We only initialize if mDNSCore successfully initialized.
- if (D2DInitialize)
- {
- D2DStatus ds = D2DInitialize(CFRunLoopGetMain(), xD2DServiceCallback, m) ;
- if (ds != kD2DSuccess)
- LogMsg("D2DInitialiize failed: %d", ds);
- else
- LogMsg("D2DInitialize succeeded");
- }
-#endif // ! NO_D2D
-
+ initializeD2DPlugins(m);
}
result = DNSSECCryptoInit(m);
return(result);
@@ -10769,20 +9756,11 @@ mDNSexport void mDNSPlatformClose(mDNS *const m)
if (m->p->SysEventNotifier >= 0) { close(m->p->SysEventNotifier); m->p->SysEventNotifier = -1; }
-#if !NO_D2D
- if (D2DTerminate)
- {
- D2DStatus ds = D2DTerminate();
- if (ds != kD2DSuccess)
- LogMsg("D2DTerminate failed: %d", ds);
- else
- LogMsg("D2DTerminate succeeded");
- }
-#endif // ! NO_D2D
+ terminateD2DPlugins();
mDNSs32 utc = mDNSPlatformUTC();
- MarkAllInterfacesInactive(m, utc);
- ClearInactiveInterfaces(m, utc);
+ MarkAllInterfacesInactive(utc);
+ ClearInactiveInterfaces(utc);
CloseSocketSet(&m->p->permanentsockets);
#if APPLE_OSX_mDNSResponder
@@ -10893,8 +9871,9 @@ mDNSexport void * mDNSPlatformMemAllocate(mDNSu32 len) { return(mallocL("mDNSP
#endif
mDNSexport void mDNSPlatformMemFree (void *mem) { freeL("mDNSPlatformMemFree", mem); }
-mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason)
+mDNSexport void mDNSPlatformSetAllowSleep(mDNSBool allowSleep, const char *reason)
{
+ mDNS *const m = &mDNSStorage;
if (allowSleep && m->p->IOPMAssertion)
{
LogInfo("%s Destroying NoIdleSleep power assertion", __FUNCTION__);
@@ -10918,9 +9897,10 @@ mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, co
}
}
-mDNSexport void mDNSPlatformPreventSleep(mDNS *const m, mDNSu32 timeout, const char *reason)
+mDNSexport void mDNSPlatformPreventSleep(mDNSu32 timeout, const char *reason)
{
- if (m->p->IOPMAssertion)
+ mDNS *const m = &mDNSStorage;
+ if (m->p->IOPMAssertion)
{
LogSPS("Sleep Assertion is already being held. Will not attempt to get it again for %d seconds for %s", timeout, reason);
return;
@@ -10954,12 +9934,12 @@ mDNSexport void mDNSPlatformPreventSleep(mDNS *const m, mDNSu32 timeout, const c
#endif
}
-mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
+mDNSexport void mDNSPlatformSendWakeupPacket(mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
{
mDNSu32 ifindex;
// Sanity check
- ifindex = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNStrue);
+ ifindex = mDNSPlatformInterfaceIndexfromInterfaceID(&mDNSStorage, InterfaceID, mDNStrue);
if (ifindex <= 0)
{
LogMsg("mDNSPlatformSendWakeupPacket: ERROR!! Invalid InterfaceID %u", ifindex);
@@ -10990,7 +9970,7 @@ mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
if (AWDLInterfaceID && (InterfaceID == AWDLInterfaceID))
return mDNStrue;
- info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
+ info = IfindexToInterfaceInfoOSX(InterfaceID);
if (info == NULL)
{
// this log message can print when operations are stopped on an interface that has gone away
@@ -11101,9 +10081,9 @@ mDNSexport void mDNSPlatformDispatchAsync(mDNS *const m, void *context, AsyncDis
// If "func" delivers something to the uds socket from the dispatch thread, it will
// not be delivered immediately if not for the Unlock.
dispatch_async(dispatch_get_main_queue(), ^{
- KQueueLock(m);
+ KQueueLock();
func(m, context);
- KQueueUnlock(m, "mDNSPlatformDispatchAsync");
+ KQueueUnlock("mDNSPlatformDispatchAsync");
#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
// KQueueUnlock is a noop. Hence, we need to run kick off the idle loop
// to handle any message that "func" might deliver.
@@ -11195,5 +10175,359 @@ mDNSexport mDNSu32 initializeDeviceInfoTXT(mDNS *m, mDNSu8 *ptr)
return (ptr - bufferStart);
}
+#if APPLE_OSX_mDNSResponder // Don't compile for dnsextd target
+
+// Use the scalar version of SameDomainLabel() by default
+mDNSlocal mDNSBool scalarSameDomainLabel(const mDNSu8 *a, const mDNSu8 *b);
+mDNSlocal mDNSBool vectorSameDomainLabel(const mDNSu8 *a, const mDNSu8 *b);
+mDNSlocal mDNSBool (*SameDomainLabelPointer)(const mDNSu8 *a, const mDNSu8 *b) = scalarSameDomainLabel;
+
+#include <System/machine/cpu_capabilities.h>
+#define _cpu_capabilities ((uint32_t*) _COMM_PAGE_CPU_CAPABILITIES)[0]
+
+#if TARGET_OS_EMBEDDED
+
+#include <arm_neon.h>
+
+// Cache line aligned table that returns 32 for the upper case letters.
+// This will take up 4 cache lines.
+static const __attribute__ ((aligned(64))) uint8_t upper_to_lower_case_table[256] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+// Neon version
+mDNSlocal mDNSBool vectorSameDomainLabel(const mDNSu8 *a, const mDNSu8 *b)
+{
+ const int len = *a++;
+
+ if (len > MAX_DOMAIN_LABEL)
+ {
+ fprintf(stderr, "v: Malformed label (too long)\n");
+ return(mDNSfalse);
+ }
+
+ if (len != *b++)
+ {
+ return(mDNSfalse);
+ }
+
+ uint32_t len_count = len;
+
+ uint8x16_t vA, vB, vARotated, vBRotated, vMaskA, vMaskB;
+
+ uint8x16_t v32 = vdupq_n_u8(32);
+ uint8x16_t v37 = vdupq_n_u8(37);
+ uint8x16_t v101 = vdupq_n_u8(101);
+#if !defined __arm64__
+ uint32x4_t vtemp32;
+ uint32x2_t vtemp32d;
+ uint32_t sum;
+#endif
+
+ while(len_count > 15)
+ {
+ vA = vld1q_u8(a);
+ vB = vld1q_u8(b);
+ a += 16;
+ b += 16;
+
+ //Make vA to lowercase if there is any uppercase.
+ vARotated = vaddq_u8(vA, v37); //Map 'A' ~ 'Z' from '65' ~ '90' to '102' ~ '127'.
+ vMaskA = vcgtq_s8(vARotated, v101); //Check if anything is greater than '101' which means we have uppercase letters.
+ vMaskA = vandq_u8(vMaskA, v32); //Prepare 32 for the elements with uppercase letters.
+ vA = vaddq_u8(vA, vMaskA); //Add 32 only to the uppercase letters to make them lowercase letters.
+
+ //Make vB to lowercase if there is any uppercase.
+ vBRotated = vaddq_u8(vB, v37); //Map 'A' ~ 'Z' from '65' ~ '90' to '102' ~ '127'.
+ vMaskB = vcgtq_s8(vBRotated, v101); //Check if anything is greater than '101' which means we have uppercase letters.
+ vMaskB = vandq_u8(vMaskB, v32); //Prepare 32 for the elements with uppercase letters.
+ vB = vaddq_u8(vB, vMaskB); //Add 32 only to the uppercase letters to make them lowercase letters.
+
+ //Compare vA & vB
+ vA = vceqq_u8(vA, vB);
+
+#if defined __arm64__
+ //View 8-bit element as 32-bit => a3 a2 a1 a0
+ //If min of 4 32-bit values in vA is 0xffffffff, then it means we have 0xff for all 16.
+ if(vminvq_u32(vA) != 0xffffffffU)
+ {
+ return(mDNSfalse);
+
+ }
+#else
+ //See if any element was not same.
+ //View 8-bit element as 16-bit => a7 a6 a5 a4 a3 a2 a1 a0
+ //(a7+a6) (a5+a4) (a3+a2) (a1+a0) => Each will be 0xffff + 0xffff = 0x0001fffe when all same.
+ vtemp32 = vpaddlq_u16(vA);
+ vtemp32d = vpadd_u32(vget_low_u32(vtemp32), vget_high_u32(vtemp32));
+ vtemp32d = vpadd_u32(vtemp32d, vtemp32d);
+ sum = vget_lane_u32(vtemp32d, 0);
+
+ //0x0001fffe + 0x0001fffe + 0x0001fffe + 0x0001fffe = 0x0007fff8U when all same.
+ if(sum != 0x0007fff8U)
+ {
+ return(mDNSfalse);
+ }
+#endif
+
+ len_count -= 16;
+ }
+
+ uint8x8_t vAd, vBd, vARotatedd, vBRotatedd, vMaskAd, vMaskBd;
+
+ uint8x8_t v32d = vdup_n_u8(32);
+ uint8x8_t v37d = vdup_n_u8(37);
+ uint8x8_t v101d = vdup_n_u8(101);
+
+ while(len_count > 7)
+ {
+ vAd = vld1_u8(a);
+ vBd = vld1_u8(b);
+ a += 8;
+ b += 8;
+
+ //Make vA to lowercase if there is any uppercase.
+ vARotatedd = vadd_u8(vAd, v37d); //Map 'A' ~ 'Z' from '65' ~ '90' to '102' ~ '127'.
+ vMaskAd = vcgt_s8(vARotatedd, v101d); //Check if anything is greater than '101' which means we have uppercase letters.
+ vMaskAd = vand_u8(vMaskAd, v32d); //Prepare 32 for the elements with uppercase letters.
+ vAd = vadd_u8(vAd, vMaskAd); //Add 32 only to the uppercase letters to make them lowercase letters.
+
+ //Make vB to lowercase if there is any uppercase.
+ vBRotatedd = vadd_u8(vBd, v37d); //Map 'A' ~ 'Z' from '65' ~ '90' to '102' ~ '127'.
+ vMaskBd = vcgt_s8(vBRotatedd, v101d); //Check if anything is greater than '101' which means we have uppercase letters.
+ vMaskBd = vand_u8(vMaskBd, v32d); //Prepare 32 for the elements with uppercase letters.
+ vBd = vadd_u8(vBd, vMaskBd); //Add 32 only to the uppercase letters to make them lowercase letters.
+
+ //Compare vA & vB
+ vAd = vceq_u8(vAd, vBd);
+
+#if defined __arm64__
+ //View 8-bit element as 32-bit => a1 a0
+ //If min of 2 32-bit values in vAd is 0xffffffff, then it means we have 0xff for all 16.
+ if(vminv_u32(vAd) != 0xffffffffU)
+ {
+ return(mDNSfalse);
+
+ }
+#else
+ //See if any element was not same.
+ //View 8-bit element as 16-bit => a3 a2 a1 a0
+ //(a3+a2) (a1+a0) => Each will be 0xffff + 0xffff = 0x0001fffe when all same.
+ vtemp32d = vpaddl_u16(vAd);
+ vtemp32d = vpadd_u32(vtemp32d, vtemp32d);
+ sum = vget_lane_u32(vtemp32d, 0);
+
+ //0x0001fffe + 0x0001fffe = 0x0003fffc when all same.
+ if(sum != 0x0003fffcU)
+ {
+ return(mDNSfalse);
+ }
+#endif
+
+ len_count -= 8;
+ }
+
+ while(len_count > 0)
+ {
+ mDNSu8 ac = *a++;
+ mDNSu8 bc = *b++;
+
+ ac += upper_to_lower_case_table[ac];
+ bc += upper_to_lower_case_table[bc];
+
+ if (ac != bc)
+ {
+ return(mDNSfalse);
+ }
+
+ len_count -= 1;
+ }
+ return(mDNStrue);
+}
+
+// Use vectorized implementation if it is supported on this platform.
+mDNSlocal void setSameDomainLabelPointer(void)
+{
+ if(_cpu_capabilities & kHasNeon)
+ {
+ // Use Neon Code
+ SameDomainLabelPointer = vectorSameDomainLabel;
+ LogMsg("setSameDomainLabelPointer: using vector code");
+ }
+ else
+ LogMsg("setSameDomainLabelPointer: using scalar code");
+}
+
+#else // TARGET_OS_EMBEDDED
+
+#include <smmintrin.h>
+
+// Cache line aligned table that returns 32 for the upper case letters.
+// This will take up 4 cache lines.
+static const __attribute__ ((aligned(64))) uint8_t upper_to_lower_case_table[256] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+// SSE2 version
+mDNSlocal mDNSBool vectorSameDomainLabel(const mDNSu8 *a, const mDNSu8 *b)
+{
+ const int len = *a++;
+
+ if (len > MAX_DOMAIN_LABEL)
+ {
+ fprintf(stderr, "v: Malformed label (too long)\n");
+ return(mDNSfalse);
+ }
+
+ if (len != *b++)
+ {
+ return(mDNSfalse);
+ }
+
+ uint32_t len_count = len;
+
+ static const __attribute__ ((aligned(16))) unsigned char c_32[16] = { 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 };
+ static const __attribute__ ((aligned(16))) unsigned char c_37[16] = { 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37 };
+ static const __attribute__ ((aligned(16))) unsigned char c_101[16] = { 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101 };
+ __m128i v37 = _mm_load_si128((__m128i*)c_37);
+ __m128i v101 = _mm_load_si128((__m128i*)c_101);
+ __m128i v32 = _mm_load_si128((__m128i*)c_32);
+
+ uint32_t is_equal;
+ __m128i vA, vB, vARotated, vBRotated, vMaskA, vMaskB;
+
+ //AVX code that uses higher bandwidth (more elements per vector) was removed
+ //to speed up the processing on the small sizes.
+ //When I had them, the performance of 1 ~ 8 characters were slower by about 10% ~ 30%.
+ while(len_count > 15)
+ {
+ vA = _mm_loadu_si128((__m128i*)a);
+ vB = _mm_loadu_si128((__m128i*)b);
+ a += 16;
+ b += 16;
+
+ //Make vA to lowercase if there is any uppercase.
+ vARotated = _mm_add_epi8(vA, v37); //Map 'A' ~ 'Z' from '65' ~ '90' to '102' ~ '127'.
+ vMaskA = _mm_cmpgt_epi8(vARotated, v101); //Check if anything is greater than '101' which means we have uppercase letters.
+ vMaskA = _mm_and_si128(vMaskA, v32); //Prepare 32 for the elements with uppercase letters.
+ vA = _mm_add_epi8(vA, vMaskA); //Add 32 only to the uppercase letters to make them lowercase letters.
+
+ //Make vB to lowercase if there is any uppercase.
+ vBRotated = _mm_add_epi8(vB, v37); //Map 'A' ~ 'Z' from '65' ~ '90' to '102' ~ '127'.
+ vMaskB = _mm_cmpgt_epi8(vBRotated, v101); //Check if anything is greater than '101' which means we have uppercase letters.
+ vMaskB = _mm_and_si128(vMaskB, v32); //Prepare 32 for the elements with uppercase letters.
+ vB = _mm_add_epi8(vB, vMaskB); //Add 32 only to the uppercase letters to make them lowercase letters.
+
+ //Compare vA & vB
+ vA = _mm_cmpeq_epi8(vA, vB);
+
+ //Return if any different.
+ is_equal = _mm_movemask_epi8(vA);
+ is_equal = is_equal & 0xffff;
+ if(is_equal != 0xffff)
+ {
+ return(mDNSfalse);
+ }
+
+ len_count -= 16;
+ }
+
+ while(len_count > 0)
+ {
+ mDNSu8 ac = *a++;
+ mDNSu8 bc = *b++;
+
+ //Table will return 32 for upper case letters only.
+ //0 will be returned for all others.
+ ac += upper_to_lower_case_table[ac];
+ bc += upper_to_lower_case_table[bc];
+
+ //Return if a & b are different.
+ if (ac != bc)
+ {
+ return(mDNSfalse);
+ }
+
+ len_count -= 1;
+ }
+ return(mDNStrue);
+}
+
+// Use vectorized implementation if it is supported on this platform.
+mDNSlocal void setSameDomainLabelPointer(void)
+{
+ if(_cpu_capabilities & kHasSSE4_1)
+ {
+ // Use SSE Code
+ SameDomainLabelPointer = vectorSameDomainLabel;
+ LogMsg("setSameDomainLabelPointer: using vector code");
+ }
+ else
+ LogMsg("setSameDomainLabelPointer: using scalar code");
+}
+
+#endif // TARGET_OS_EMBEDDED
+
+// Original SameDomainLabel() implementation.
+mDNSlocal mDNSBool scalarSameDomainLabel(const mDNSu8 *a, const mDNSu8 *b)
+{
+ int i;
+ const int len = *a++;
+
+ if (len > MAX_DOMAIN_LABEL)
+ { debugf("Malformed label (too long)"); return(mDNSfalse); }
+
+ if (len != *b++) return(mDNSfalse);
+ for (i=0; i<len; i++)
+ {
+ mDNSu8 ac = *a++;
+ mDNSu8 bc = *b++;
+ if (mDNSIsUpperCase(ac)) ac += 'a' - 'A';
+ if (mDNSIsUpperCase(bc)) bc += 'a' - 'A';
+ if (ac != bc) return(mDNSfalse);
+ }
+ return(mDNStrue);
+}
+
+mDNSexport mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b)
+{
+ return (*SameDomainLabelPointer)(a, b);
+}
+
+#endif // APPLE_OSX_mDNSResponder
+
+
+#ifdef UNIT_TEST
+#include "../unittests/mdns_macosx_ut.c"
+#endif