summaryrefslogtreecommitdiffstats
path: root/mDNSResponder/mDNSMacOSX
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-19 08:56:09 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-20 11:23:33 +0200
commit4c086a244624bf36865edcfa4309c333d7d7200d (patch)
treee566ffc50a6b6fdb46702ac57c8e7c4088b60b42 /mDNSResponder/mDNSMacOSX
parentmDNSResponder: Update to v765.50.9 (diff)
downloadrtems-libbsd-4c086a244624bf36865edcfa4309c333d7d7200d.tar.bz2
mDNSResponder: Update to v878.1.1
The sources can be obtained via: https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-878.1.1.tar.gz Update #3522.
Diffstat (limited to 'mDNSResponder/mDNSMacOSX')
-rw-r--r--mDNSResponder/mDNSMacOSX/BLE.c1369
-rw-r--r--mDNSResponder/mDNSMacOSX/BLE.h44
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourEvents.c50
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/BonjourTop.xcodeproj/project.pbxproj297
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/BonjourTop.xcodeproj/project.xcworkspace/contents.xcworkspacedata7
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/BonjourTop.179
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/BonjourTop.cpp2049
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/BonjourTop.h577
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/CaptureFile.cpp141
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/CaptureFile.h55
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/CollectBy.cpp314
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/CollectBy.h155
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/DNSFrame.cpp384
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/DNSFrame.h132
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/Frame.cpp201
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/Frame.h66
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/LLRBTree.cpp157
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/LLRBTree.h460
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/bjIPAddr.cpp312
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/bjIPAddr.h56
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/bjMACAddr.cpp11
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/bjMACAddr.h54
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.cpp40
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.h42
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.cpp384
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.h88
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/bjstring.cpp238
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/bjstring.h63
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/bjtypes.h64
-rw-r--r--mDNSResponder/mDNSMacOSX/BonjourTop/source/main.cpp179
-rw-r--r--mDNSResponder/mDNSMacOSX/D2D.c995
-rw-r--r--mDNSResponder/mDNSMacOSX/D2D.h48
-rw-r--r--mDNSResponder/mDNSMacOSX/DNS64.c559
-rw-r--r--mDNSResponder/mDNSMacOSX/DNS64.h39
-rw-r--r--mDNSResponder/mDNSMacOSX/DNS64State.h41
-rw-r--r--mDNSResponder/mDNSMacOSX/DNSProxySupport.c37
-rw-r--r--mDNSResponder/mDNSMacOSX/DNSSECSupport.c2
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/CNDomainBrowserPathUtils.h22
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/CNDomainBrowserPathUtils.m114
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/_CNDomainBrowser.h49
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/_CNDomainBrowser.m190
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/CNDomainBrowserViewController.h51
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/CNDomainBrowserViewController.m350
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/DomainBrowser.h30
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/DomainBrowser.strings18
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/Info.plist26
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/CNDomainBrowserView.h58
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/CNDomainBrowserView.m474
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/DomainBrowser.h30
-rw-r--r--mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/Info.plist26
-rw-r--r--mDNSResponder/mDNSMacOSX/LegacyNATTraversal.c47
-rw-r--r--mDNSResponder/mDNSMacOSX/Metrics.m14
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/add_idle.tiffbin728 -> 0 bytes
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/add_pressed.tiffbin688 -> 0 bytes
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/remove_disabled.tiffbin698 -> 0 bytes
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/remove_idle.tiffbin694 -> 0 bytes
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/remove_pressed.tiffbin656 -> 0 bytes
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/Base.lproj/DNSServiceDiscoveryPref.nib/designable.nib821
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/Base.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nibbin0 -> 45019 bytes
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool-Info.plist37
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.h24
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.m158
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefToolProtocol.h27
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/entitlements.plist8
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/main.m62
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c180
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.h52
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h118
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m514
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/classes.nib59
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/info.nib18
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nibbin21082 -> 0 bytes
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/Info-PreferencePane.plist4
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c235
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.h70
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService-Info.plist41
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService.h22
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService.m21
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/InfoPlist.strings3
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/entitlements.plist10
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/main.m40
-rw-r--r--mDNSResponder/mDNSMacOSX/PreferencePane/ddnswriteconfig.m462
-rwxr-xr-xmDNSResponder/mDNSMacOSX/PreferencePane/installtool94
-rw-r--r--mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h57
-rw-r--r--mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c12
-rw-r--r--mDNSResponder/mDNSMacOSX/Private/xpc_services.c14
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/Contents.json6
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/UIPreferencesBlueCheck.imageset/Contents.json22
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/UIPreferencesBlueCheck.imageset/UIPreferencesBlueCheck.pngbin0 -> 341 bytes
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/UIPreferencesBlueCheck.imageset/UIPreferencesBlueCheck@2x.pngbin0 -> 506 bytes
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourConstants.h15
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSCStore.h40
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSCStore.m84
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSettingsController.h24
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSettingsController.m143
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/CNBrowseDomainsController.h37
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/CNBrowseDomainsController.m710
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/HostnameController.h25
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/HostnameController.m125
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/Info.plist26
-rw-r--r--mDNSResponder/mDNSMacOSX/SettingsBundle/Localizable.strings34
-rw-r--r--mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist30
-rw-r--r--mDNSResponder/mDNSMacOSX/coreBLE.h11
-rw-r--r--mDNSResponder/mDNSMacOSX/coreBLE.m332
-rw-r--r--mDNSResponder/mDNSMacOSX/daemon.c175
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSMacOSX.c2900
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSMacOSX.h29
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSNetMonitor/mDNSNetMonitor.840
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist10
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSResponder-xcodeproj-explanation.txt40
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSResponder.sb25
-rw-r--r--mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj2279
-rw-r--r--mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c5
113 files changed, 17290 insertions, 4328 deletions
diff --git a/mDNSResponder/mDNSMacOSX/BLE.c b/mDNSResponder/mDNSMacOSX/BLE.c
index 85fb810c..4a35ff0b 100644
--- a/mDNSResponder/mDNSMacOSX/BLE.c
+++ b/mDNSResponder/mDNSMacOSX/BLE.c
@@ -15,23 +15,134 @@
* limitations under the License.
*/
+#if ENABLE_BLE_TRIGGERED_BONJOUR
+
#include "mDNSEmbeddedAPI.h"
#include "DNSCommon.h"
#include "mDNSMacOSX.h"
#include "BLE.h"
-#include <pthread.h>
+#include "D2D.h"
+
+#include <dlfcn.h>
#pragma mark - Browse and Registration Request Handling
-// Disable use of BLE discovery APIs by default.
+// When set, enables BLE triggered discovery APIs.
mDNSBool EnableBLEBasedDiscovery = mDNSfalse;
+// When set, the default mode is to promote all client requests made with
+// kDNSServiceInterfaceIndexAny to BLE Triggered Discovery.
+// Requests to promote will be filtered by either a service type whitelist or
+// blacklist as noted below.
+mDNSBool DefaultToBLETriggered = mDNSfalse;
+
+#define USE_WHITELIST 1
+
+#if USE_WHITELIST
+
+// Current list of service types that will have BLE triggers applied by default
+// when DefaultToBLETriggered is set to true.
+
+const char * defaultServiceWhitelist[] = {
+ "\x04_ssh",
+ "\x04_smb",
+ "\x04_rfb",
+ "\x04_ipp",
+ "\x05_ipps",
+ "\x08_printer",
+ 0
+};
+
+// Return true if DefaultToBLETriggered is set and the operation should be
+// promoted to use BLE triggered discovery by default.
+bool shouldUseBLE(mDNSInterfaceID interfaceID, DNS_TypeValues rrtype, domainname *serviceType, domainname *domain)
+{
+ const mDNSu8 ** ptr;
+
+ if (!DefaultToBLETriggered || (interfaceID != mDNSInterface_Any) || !IsLocalDomain(domain))
+ return mDNSfalse;
+
+ // Address records don't have a service type to match on, but we'll trigger them
+ // here to support the case were the DNSServiceQueryRecord() was done using mDNSInterface_Any instead
+ // of the interface that the corresponding SRV record was returned over.
+ if ((rrtype == kDNSType_A) || (rrtype == kDNSType_AAAA))
+ return mDNStrue;
+
+ ptr = (const mDNSu8 **) defaultServiceWhitelist;
+ while (*ptr)
+ {
+ if (SameDomainLabel(*ptr, serviceType->c))
+ return mDNStrue;
+ ptr++;
+ }
+
+ return mDNSfalse;
+}
+
+#else // USE_WHITELIST
+
+// Current list of service types that will NOT have BLE triggers applied by default
+// when DefaultToBLETriggered is set to true.
+
+// _airplay and _airdrop discovery already employ BLE based triggering using Apple service specific
+// BLE beacons. The rest of the entries here are default browses run in a standard OSX install
+// that we don't want to have cluttering up the Bloom filter when using the service blacklist approach.
+
+const char * defaultServiceBlacklist[] = {
+ "\x08_airplay",
+ "\x08_airdrop",
+ "\x05_raop",
+ "\x08_airport",
+ "\x0d_apple-mobdev",
+ "\x06_uscan",
+ "\x07_uscans",
+ "\x08_scanner",
+ "\x0e_apple-mobdev2",
+ "\x04_ipp",
+ "\x05_ipps",
+ "\x07_ippusb",
+ "\x08_printer",
+ "\x0f_pdl-datastream",
+ "\x04_ptp",
+ 0
+};
+
+// Return true if DefaultToBLETriggered is set and the operation should be
+// promoted to use BLE triggered discovery by default.
+bool shouldUseBLE(mDNSInterfaceID interfaceID, DNS_TypeValues rrtype, domainname *serviceType, domainname *domain)
+{
+ (void) rrtype;
+ const mDNSu8 ** ptr;
+
+ if (!DefaultToBLETriggered || (interfaceID != mDNSInterface_Any) || !IsLocalDomain(domain))
+ return mDNSfalse;
+
+ ptr = (const mDNSu8 **) defaultServiceBlacklist;
+ while (*ptr)
+ {
+ if (SameDomainLabel(*ptr, serviceType->c))
+ return mDNSfalse;
+ ptr++;
+ }
+
+ return mDNStrue;
+}
+
+#endif // USE_WHITELIST
+
+// Structure for linked list of BLE responses received that match
+// a given client request.
typedef struct matchingResponses
{
struct matchingResponses * next;
void * response;
} matchingResponses_t;
+// Max size of input key generated by DNSNameCompressionBuildLHS() is MAX_DOMAIN_NAME + 3
+// where the three additional bytes are:
+// two bytes for DNS_TypeValues and one byte for "compression_packet_v1", the D2D compression version number.
+#define MAX_KEY_SIZE MAX_DOMAIN_NAME + 3
+
// Initially used for both the browse and registration lists.
typedef struct requestList
{
@@ -41,22 +152,17 @@ typedef struct requestList
mDNSu16 type;
DNSServiceFlags flags;
mDNSInterfaceID InterfaceID;
-
-// TODO: Possibly restructure the following browse and registration specific
-// members as a union to save a bit of space.
+ serviceHash_t browseHash;
+ serviceHash_t registeredHash;
+ matchingResponses_t * ourResponses;
+ bool triggeredOnAWDL;
// The following fields are only used for browse requests currently
- serviceHash_t browseHash;
- DNSQuestion * question;
- mDNSu8 key[MAX_DOMAIN_LABEL];
+ mDNSu8 key[MAX_KEY_SIZE];
size_t keySize;
- matchingResponses_t * ourResponses;
// The following fields are only used for registration requests currently
- serviceHash_t registeredHash;
- ServiceRecordSet * serviceRecordSet; // service record set in the original request
- AuthRecType savedARType;
- bool triggeredOnAWDL;
+ const ResourceRecord * resourceRecord;
} requestList_t;
// Lists for all DNSServiceBrowse() and DNSServiceRegister() requests using
@@ -64,10 +170,27 @@ typedef struct requestList
static requestList_t* BLEBrowseListHead = NULL;
static requestList_t* BLERegistrationListHead = NULL;
-#define isAutoTriggerRequest(ptr) ((ptr->InterfaceID == kDNSServiceInterfaceIndexAny) && (ptr->flags & kDNSServiceFlagsAutoTrigger))
+// The kDNSServiceFlagsAutoTrigger should only be set for a request that would normally apply to AWDL.
+#define isAutoTriggerRequest(INTERFACE_INDEX, FLAGS) ( (FLAGS & kDNSServiceFlagsAutoTrigger) \
+ && ( (AWDLInterfaceID && (INTERFACE_INDEX == AWDLInterfaceID)) \
+ || ((INTERFACE_INDEX == kDNSServiceInterfaceIndexAny) && (FLAGS & kDNSServiceFlagsIncludeAWDL))))
#pragma mark - Manage list of responses that match this request.
+// Return true if any response matches one of our current registrations.
+mDNSlocal bool responseMatchesRegistrations(void)
+{
+ requestList_t *ptr;
+
+ for (ptr = BLERegistrationListHead; ptr; ptr = ptr->next)
+ {
+ if (ptr->ourResponses)
+ return true;
+ }
+ return false;
+}
+
+// Return true if the response is already in the list of responses for this client request.
mDNSlocal bool inResponseListForRequest(requestList_t *request, void * response)
{
matchingResponses_t * rp;
@@ -130,10 +253,13 @@ mDNSlocal void freeResponseListEntriesForRequest(requestList_t *request)
ptr = ptr->next;
free(tmp);
}
+ request->ourResponses = 0;
}
#pragma mark - Manage request lists
+// Return the address of the pointer to the entry, which can either be the address of "listHead"
+// or the address of the prior entry on the lists "next" pointer.
mDNSlocal requestList_t ** findInRequestList(requestList_t ** listHead, const domainname *const name, mDNSu16 type)
{
requestList_t **ptr = listHead;
@@ -185,332 +311,383 @@ mDNSlocal void removeFromRequestList(requestList_t ** listHead, const domainname
#pragma mark - Hashing and beacon state
-// Simple string hash based on the Bernstein hash.
-
-#define PRIME 31 // small prime number
-#define MODULO (sizeof(serviceHash_t) * 8)
-#define CONVERT_TO_LOWER_CASE(x) (((x) <= 'Z' && (x) >= 'A') ? ((x) | 0x20) : (x))
-
-mDNSlocal serviceHash_t BLELabelHash(const unsigned char *str, unsigned int length)
+// These SipHash routines were copied from CoreUtils-500.9.
+// We use these when running an mDNSRespnder root on a system that does not
+// have the SipHash() routine available and exported in CoreUtils.
+// TODO: This local copy should be removed once we are no longer running mDNSResponder roots
+// on systems that do no include CoreUtils-500.9 or newer.
+
+// Start of code copied from: CoreUtils-500.9
+
+/*! @group BitRotates
+ @abstract Rotates X COUNT bits to the left or right.
+*/
+#define ROTL( X, N, SIZE ) ( ( (X) << (N) ) | ( (X) >> ( (SIZE) - N ) ) )
+#define ROTR( X, N, SIZE ) ( ( (X) >> (N) ) | ( (X) << ( (SIZE) - N ) ) )
+
+#define ROTL64( X, N ) ROTL( (X), (N), 64 )
+#define ROTR64( X, N ) ROTR( (X), (N), 64 )
+
+ #define ReadLittle64( PTR ) \
+ ( (uint64_t)( \
+ ( (uint64_t)( (uint8_t *)(PTR) )[ 0 ] ) | \
+ ( ( (uint64_t)( (uint8_t *)(PTR) )[ 1 ] ) << 8 ) | \
+ ( ( (uint64_t)( (uint8_t *)(PTR) )[ 2 ] ) << 16 ) | \
+ ( ( (uint64_t)( (uint8_t *)(PTR) )[ 3 ] ) << 24 ) | \
+ ( ( (uint64_t)( (uint8_t *)(PTR) )[ 4 ] ) << 32 ) | \
+ ( ( (uint64_t)( (uint8_t *)(PTR) )[ 5 ] ) << 40 ) | \
+ ( ( (uint64_t)( (uint8_t *)(PTR) )[ 6 ] ) << 48 ) | \
+ ( ( (uint64_t)( (uint8_t *)(PTR) )[ 7 ] ) << 56 ) ) )
+
+// Based on <https://131002.net/siphash/>.
+
+#define SipRound() \
+ do \
+ { \
+ v0 += v1; v1 = ROTL64( v1, 13 ); v1 ^= v0; v0 = ROTL64( v0, 32 ); \
+ v2 += v3; v3 = ROTL64( v3, 16 ); v3 ^= v2; \
+ v0 += v3; v3 = ROTL64( v3, 21 ); v3 ^= v0; \
+ v2 += v1; v1 = ROTL64( v1, 17 ); v1 ^= v2; v2 = ROTL64( v2, 32 ); \
+ \
+ } while( 0 )
+
+mDNSlocal uint64_t local_SipHash( const uint8_t inKey[ 16 ], const void *inSrc, size_t inLen )
{
- serviceHash_t hash = 0;
-
- for (unsigned int i = 0; i < length; i++) {
- hash = PRIME * hash + CONVERT_TO_LOWER_CASE(*str);
- str++;
- }
-
- hash %= MODULO;
- LogInfo("BLELabelHash: %d characters hashed to %d", length, hash);
-
- return ((serviceHash_t)1 << hash);
+ const uint8_t * src = (const uint8_t *) inSrc;
+ size_t const left = inLen % 8;
+ const uint8_t * const end = src + ( inLen - left );
+ uint64_t k0, k1, v0, v1, v2, v3, tmp;
+
+ k0 = ReadLittle64( &inKey[ 0 ] );
+ k1 = ReadLittle64( &inKey[ 8 ] );
+ v0 = k0 ^ UINT64_C( 0x736f6d6570736575 ); // 'somepseu'
+ v1 = k1 ^ UINT64_C( 0x646f72616e646f6d ); // 'dorandom'
+ v2 = k0 ^ UINT64_C( 0x6c7967656e657261 ); // 'lygenera'
+ v3 = k1 ^ UINT64_C( 0x7465646279746573 ); // 'tedbytes'
+
+ for( ; src != end; src += 8 )
+ {
+ tmp = ReadLittle64( src );
+ v3 ^= tmp;
+ SipRound();
+ SipRound();
+ v0 ^= tmp;
+ }
+
+ tmp = ( (uint64_t)( inLen & 0xFF ) ) << 56;
+ switch( left )
+ {
+ case 7: tmp |= ( ( (uint64_t) src[ 6 ] ) << 48 );
+ case 6: tmp |= ( ( (uint64_t) src[ 5 ] ) << 40 );
+ case 5: tmp |= ( ( (uint64_t) src[ 4 ] ) << 32 );
+ case 4: tmp |= ( ( (uint64_t) src[ 3 ] ) << 24 );
+ case 3: tmp |= ( ( (uint64_t) src[ 2 ] ) << 16 );
+ case 2: tmp |= ( ( (uint64_t) src[ 1 ] ) << 8 );
+ case 1: tmp |= ( (uint64_t) src[ 0 ] );
+ default: break;
+ }
+ v3 ^= tmp;
+ SipRound();
+ SipRound();
+ v0 ^= tmp;
+ v2 ^= 0xFF;
+ SipRound();
+ SipRound();
+ SipRound();
+ SipRound();
+ return( v0 ^ v1 ^ v2 ^ v3 );
}
-// Hash just the service type not including the protocol or first "_" character initially.
-mDNSlocal serviceHash_t BLEServiceHash(const domainname *const domain)
-{
- const unsigned char *p = domain->c;
- unsigned int length = (unsigned int) *p;
-
- p++;
- if (*p != '_')
- {
- LogInfo("BLEServiceHash: browse type does not begin with a _");
- return 0;
- }
- p++; // skip the '-"
- length--;
+// See <https://spc.apple.com/AppleBLEInfo.html#_wifi_tds> for details.
- if (length > MAX_DOMAIN_LABEL || length == 0)
- {
- LogInfo("BLEServiceHash: invalid browse type length: %d characters", length);
- return 0;
- }
+#define kTDSSipHashKey ( (const uint8_t *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" )
+#define kTDSSipHashCount 5
- return BLELabelHash(p, length);
-}
+#define kSizeCString ( (size_t) -1 )
-// Storage for the current Bonjour BLE beacon data;
-typedef struct BLEBeacon
-{
- serviceHash_t browseHash;
- serviceHash_t registeredHash;
-} BLEBeacon_t;
+// End of code copied from: CoreUtils-500.9
-BLEBeacon_t BLEBeacon;
+// Must link symbol from CoreUtils at runtime to avoid cyclic dependency cycles in the build process.
+static uint64_t (*SipHash_p)( const uint8_t inKey[ 16 ], const void *inSrc, size_t inLen ) = NULL;
-mDNSlocal void addServiceToBeacon(serviceHash_t browseHash, serviceHash_t registeredHash)
+mDNSlocal uint64_t local_TDSBloomFilterMake( uint32_t inBloomCount, const void *inStr, size_t inLen )
{
- bool beaconUpdated = false;
+ uint64_t bloomFilter = 0, hash;
+ uint8_t i;
- if (BLEBeacon.browseHash & browseHash)
- {
- LogInfo("addServiceToBeacon: Bit 0x%x already set in browsing services hash", browseHash);
- }
+ if( inLen == kSizeCString ) inLen = strlen( (const char *) inStr );
+ if (SipHash_p)
+ hash = SipHash_p( kTDSSipHashKey, inStr, inLen );
else
- {
- BLEBeacon.browseHash |= browseHash;
- beaconUpdated = true;
- }
+ hash = local_SipHash( kTDSSipHashKey, inStr, inLen );
- if (BLEBeacon.registeredHash & registeredHash)
- {
- LogInfo("addServiceToBeacon: Bit 0x%x already set in advertising services hash", registeredHash);
- }
- else
+ for( i = 0; i < kTDSSipHashCount; ++i )
{
- BLEBeacon.registeredHash |= registeredHash;
- beaconUpdated = true;
+ bloomFilter |= ( UINT64_C( 1 ) << ( hash % inBloomCount ) );
+ hash /= inBloomCount;
}
-
- if (beaconUpdated)
- updateBLEBeaconAndScan(BLEBeacon.browseHash, BLEBeacon.registeredHash);
+ return( bloomFilter );
}
-// Go through all the existing browses and registrations to get the
-// current hash values for the corresponding BLE beacon.
-// We must do this when any hash bits are removed do accurately generate
-// the correct combination of all currently set hash bits.
-mDNSlocal void updateBeacon()
+mDNSlocal void loadCoreUtils()
{
- requestList_t *ptr;
+ static mDNSBool runOnce = mDNSfalse;
+ static void *CoreUtils_p = mDNSNULL;
+ static const char path[] = "/System/Library/PrivateFrameworks/CoreUtils.framework/CoreUtils";
- BLEBeacon.browseHash = 0;
- BLEBeacon.registeredHash = 0;
-
- for (ptr = BLEBrowseListHead; ptr; ptr = ptr->next)
+ if (!runOnce)
{
- BLEBeacon.browseHash |= ptr->browseHash;
- }
+ runOnce = mDNStrue;
+ if (!CoreUtils_p)
+ {
+ CoreUtils_p = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
+ if (!CoreUtils_p)
+ {
+ LogInfo("loadCoreUtils: dlopen() failed.");
+ return;
+ }
+ }
- for (ptr = BLERegistrationListHead; ptr; ptr = ptr->next)
- {
- BLEBeacon.registeredHash |= ptr->registeredHash;
+ if (!SipHash_p)
+ {
+ SipHash_p = dlsym(CoreUtils_p, "SipHash");
+ if (!SipHash_p)
+ {
+ LogInfo("loadCoreUtils: load of SipHash symbol failed.");
+ return;
+ }
+ }
+ LogInfo("loadCoreUtils: found SipHash symbol.");
}
+}
+
+#define HASH_SIZE 64
+
+mDNSlocal serviceHash_t BLELabelHash(unsigned char *str, unsigned int length)
+{
+ loadCoreUtils();
- updateBLEBeaconAndScan(BLEBeacon.browseHash, BLEBeacon.registeredHash);
+ return local_TDSBloomFilterMake(HASH_SIZE, (const void *) str, (size_t) length);
}
-#pragma mark - Request start/stop
-// Forward declarations for mDNSLocal functions that are called before they are defined.
-mDNSlocal void checkForMatchingResponses(requestList_t *bp);
-mDNSlocal void clearResponseLists();
+// Maximum number of characters in string to hash should be:
+// 2 for initial "s:" or "p:"
+// 16 for "_" followed by up to 15 characters of service type
+// 1 for separating "."
+// 4 for "_udp" or "_tcp"
+// 1 for the terminating NULL byte
+#define MAX_HASH_STRING (2 + 16 + 1 + 4 + 1)
+
+// Maximum service name length, including the initial "_"
+#define MAX_SERVICE_NAME 16
-void start_BLE_browse(DNSQuestion * q, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags, mDNSu8 *key, size_t keySize)
+// Convert the service name and transport protocol to a NULL terminated C string.
+// stringBuf must point to least (MAX_HASH_STRING - 2) bytes of available space.
+mDNSlocal bool serviceNameStringFromDomain(const domainname *const domain, mDNSu8 * stringBuf)
{
- requestList_t * ptr;
+ mDNSu8 * dst = stringBuf;
+ const mDNSu8 * src = domain->c;
+ mDNSu8 len = *src++;
- if (!EnableBLEBasedDiscovery)
+ if (len == 0 || len > MAX_SERVICE_NAME)
{
- LogMsg("start_BLE_browse: EnableBLEBasedDiscovery disabled");
- return;
+ LogInfo("serviceNameStringFromDomain: Invalid name lenght: %d", len);
+ return false;
}
-
- LogInfo("start_BLE_browse: Starting BLE browse for: %##s %s", domain->c, DNSTypeName(type));
-
- ptr = addToRequestList(&BLEBrowseListHead, domain, type, flags);
-
- // If equivalent BLE browse is already running, just return.
- if (ptr->refCount > 1)
+ if (*src != '_')
{
- LogInfo("start_BLE_browse: Dup of existing BLE browse.");
- return;
+ LogInfo("serviceNameStringFromDomain: service name does not begin with a _");
+ return false;
}
+ // Copy the service type
+ while (len--)
+ *dst++ = *src++;
- ptr->browseHash = BLEServiceHash(domain);
- ptr->question = q;
+ *dst++ = '.';
- if (ptr->browseHash == 0)
+ if (!ValidTransportProtocol(src))
{
- LogInfo("BLEServiceHash failed!");
- removeFromRequestList(&BLEBrowseListHead, domain, type);
- return;
+ LogInfo("serviceNameStringFromDomain: Transport protocol name must be _udp or _tcp");
+ return false;
}
+ // copy the transport protocol
+ len = *src++;
+ while (len--)
+ *dst++ = *src++;
- // Save these for use in D2D plugin callback logic.
- memcpy(ptr->key, key, keySize);
- ptr->keySize = keySize;
- // Extract the interface ID for easier access in the requestList_t structure
- ptr->InterfaceID = q->InterfaceID;
-
- addServiceToBeacon(ptr->browseHash, 0);
-
- checkForMatchingResponses(ptr);
+ *dst = 0;
+ return true;
}
-// Stop the browse.
-// Return true if this is the last reference to the browse, false otherwise.
-bool stop_BLE_browse(const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags)
+mDNSlocal bool setBLEServiceHash(const domainname *const domain, requestList_t * ptr)
{
- (void) flags; // not used initially
- requestList_t * ptr;
- bool lastReference = false;
+ // Initialize the string with the "s:" for the browser/seeker hash calculation.
+ mDNSu8 stringBuf[MAX_HASH_STRING] = { 's', ':', '\0' };
- if (!EnableBLEBasedDiscovery)
+ // Append the service name and protocol strings to the initial "s:" string.
+ if (!serviceNameStringFromDomain(domain, &stringBuf[2]))
{
- LogMsg("stop_BLE_browse: EnableBLEBasedDiscovery disabled");
- return lastReference;
+ LogInfo("setBLEServiceHash: serviceNameStringFromDomain() failed!");
+ return false;
}
- LogInfo("stop_BLE_browse: Stopping BLE browse for: %##s %s", domain->c, DNSTypeName(type));
-
- ptr = *(findInRequestList(&BLEBrowseListHead, domain, type));
- if (ptr == 0)
- {
- LogInfo("stop_BLE_browse: No matching browse found.");
- return lastReference;
- }
-
- // If this is the last reference for this browse, update advertising and browsing bits set in
- // the beacon after removing this browse from the list.
- if (ptr->refCount == 1)
- lastReference = true;
+ ptr->browseHash = BLELabelHash(stringBuf, strlen((const char *)stringBuf));
+ LogInfo("setBLEServiceHash: seeker string %s, hashed to 0x%lx", stringBuf, ptr->browseHash);
- removeFromRequestList(&BLEBrowseListHead, domain, type);
+ // Update string to start with "p:" for registration/provider hash calculation.
+ stringBuf[0] = 'p';
- if (lastReference)
- updateBeacon();
+ ptr->registeredHash = BLELabelHash(stringBuf, strlen((const char *)stringBuf));
+ LogInfo("setBLEServiceHash: provider string %s, hashed to 0x%lx", stringBuf, ptr->registeredHash);
+ if (ptr->browseHash && ptr->registeredHash)
+ return true;
+ else
+ return false;
+}
- // If there are no active browse or registration requests, BLE scanning will be disabled.
- // Clear the list of responses received to remove any stale response state.
- if (BLEBrowseListHead == NULL && BLERegistrationListHead == 0)
- clearResponseLists();
+// Indicates we are sending the final beacon with zeroed Bloom filter to let
+// peers know we are no longer actively seeking or providing any services.
+bool finalBeacon = false;
- return lastReference;
-}
+// The last time we walked our response list looking for stale entries.
+mDNSs32 lastScanForStaleResponses;
-extern void internal_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags, DNSQuestion * q);
-extern void internal_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags);
+// Forward declaration.
+mDNSlocal void removeStaleResponses(mDNSs32 currentTime);
-extern void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags);
-extern void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags);
+// Interval at which we scan the response lists to remove any stale entries.
+#define StaleResponseScanInterval 30
-void start_BLE_advertise(ServiceRecordSet * serviceRecordSet, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags)
+// Called from mDNS_Execute() when NextBLEServiceTime is reached.
+void serviceBLE(void)
{
- requestList_t * ptr;
- const domainname * instanceRemoved;
+ // Note, we can access mDNSStorage.timenow since we are called from mDNS_Execute,
+ // which initializes that value by calling mDNS_Lock().
+ mDNSs32 currentTime = mDNSStorage.timenow;
- if (!EnableBLEBasedDiscovery)
- {
- LogMsg("start_BLE_advertise: EnableBLEBasedDiscovery disabled");
- return;
- }
-
- // Just process the SRV record for each service registration. The PTR
- // record already has the service type at the beginning of the domain, but
- // we want to filter out reverse address PTR records at this point in time, so using
- // the SRV record instead.
- if (type != kDNSServiceType_SRV)
- return;
+ // Initialize if zero.
+ if (!lastScanForStaleResponses)
+ lastScanForStaleResponses = NonZeroTime(currentTime - (StaleResponseScanInterval * mDNSPlatformOneSecond));
- if (serviceRecordSet == NULL)
+ if (finalBeacon)
{
- LogInfo("start_BLE_advertise: NULL service record set for: %##s %s, returning", domain->c, DNSTypeName(type));
- return;
- }
- LogInfo("start_BLE_advertise: Starting BLE advertisement for: %##s %s", domain->c, DNSTypeName(type));
+ // We don't expect to do the finalBeacon processing if there are active browse requests,
+ if (BLEBrowseListHead)
+ LogInfo("serviceBLE: finalBeacon set and called with active browse BLE requests ??");
- instanceRemoved = SkipLeadingLabels(domain, 1);
+ // or active registrations but we are not in suppress beacons state.
+ if (BLERegistrationListHead && !suppressBeacons)
+ LogInfo("serviceBLE: finalBeacon set and called with active registrations requests, but not in suppress beacons state ??");
- ptr = addToRequestList(&BLERegistrationListHead, instanceRemoved, type, flags);
+ finalBeacon = false;
+ stopBLEBeacon();
+ }
- // If equivalent BLE registration is already running, just return.
- if (ptr->refCount > 1)
+ if (!BLEBrowseListHead && !BLERegistrationListHead)
{
- LogInfo("start_BLE_advertise: Dup of existing BLE advertisement.");
- return;
+ LogInfo("serviceBLE: no active client requests, disabling service timer");
+ mDNSStorage.NextBLEServiceTime = 0;
}
-
- ptr->registeredHash = BLEServiceHash(instanceRemoved);
- if (ptr->registeredHash == 0)
+ else if ((currentTime - lastScanForStaleResponses) >= (StaleResponseScanInterval * mDNSPlatformOneSecond))
{
- LogInfo("BLEServiceHash failed!");
- removeFromRequestList(&BLERegistrationListHead, instanceRemoved, type);
- return;
+ removeStaleResponses(currentTime);
+ lastScanForStaleResponses = currentTime;
+ mDNSStorage.NextBLEServiceTime = NonZeroTime(currentTime + (StaleResponseScanInterval * mDNSPlatformOneSecond));
}
- ptr->serviceRecordSet = serviceRecordSet;
- // Extract the interface ID for easier access in the requestList_t structure
- ptr->InterfaceID = serviceRecordSet->RR_SRV.resrec.InterfaceID;
-
- addServiceToBeacon(0, ptr->registeredHash);
}
-void stop_BLE_advertise(const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags)
+// Initialize the periodic service timer if we have active requests.
+// The timer is disabled in the next call to serviceBLE() when no requests are active.
+mDNSlocal void updateServiceTimer()
{
- (void) flags; // not used initially
- requestList_t * ptr;
- bool lastReference = false;
- const domainname * instanceRemoved;
-
- if (!EnableBLEBasedDiscovery)
- {
- LogMsg("stop_BLE_advertise: EnableBLEBasedDiscovery disabled");
- return;
- }
+ if (!mDNSStorage.NextBLEServiceTime && (BLEBrowseListHead || BLERegistrationListHead))
+ mDNSStorage.NextBLEServiceTime = NonZeroTime(mDNSStorage.timenow + (StaleResponseScanInterval * mDNSPlatformOneSecond));
+}
- // Just process the SRV record for each service registration. The PTR
- // record already has the service type at the beginning of the domain, but
- // we want to filter out reverse address PTR records at this point in time, so using
- // the SRV record instead.
- if (type != kDNSServiceType_SRV)
- return;
+// Set true when suppressing beacon transmissions for our registrations until we see
+// a peer beacon indicating a browse for one of our services.
+bool suppressBeacons = false;
- LogInfo("stop_BLE_advertise: Stopping BLE advertisement for: %##s %s", domain->c, DNSTypeName(type));
+// Go through all the existing browses and registrations to create the
+// current Bloom filter value for the BLE beacon.
+// Update the current scan and beaconing state appropriately.
+mDNSlocal void updateBeaconAndScanState()
+{
+ requestList_t *ptr;
+ serviceHash_t beaconBloomFilter = 0;
- instanceRemoved = SkipLeadingLabels(domain, 1);
+ updateServiceTimer();
- // Get the request pointer from the indirect pointer returned.
- ptr = *(findInRequestList(&BLERegistrationListHead, instanceRemoved, type));
-
- if (ptr == 0)
+ for (ptr = BLEBrowseListHead; ptr; ptr = ptr->next)
{
- LogInfo("stop_BLE_advertise: No matching advertisement found.");
- return;
+ beaconBloomFilter |= ptr->browseHash;
}
-
- // If this is the last reference for this registration, update advertising and browsing bits set in
- // the beacon before removing this registration from the request list.
- if (ptr->refCount == 1)
+
+ for (ptr = BLERegistrationListHead; ptr; ptr = ptr->next)
{
- lastReference = true;
+ beaconBloomFilter |= ptr->registeredHash;
+ }
- if (isAutoTriggerRequest(ptr) && ptr->triggeredOnAWDL)
+ // If only advertising registered services and not browsing, we don't start the beacon transmission
+ // until we receive a beacon from a peer matching one of our registrations.
+ if (BLERegistrationListHead && !BLEBrowseListHead && !responseMatchesRegistrations())
+ {
+ // If beacons are already suppressed, then no further action to take.
+ if (suppressBeacons)
+ LogInfo("updateBeaconAndScanState: continuing to suppressing beacons");
+ else
{
- // And remove the corresponding advertisements from the AWDL D2D plugin.
- // Do it directly here, since we do not set the kDNSServiceFlagsIncludeAWDL bit in the original client request structure
- // when we trigger the registration over AWDL, we just update the record ARType field, so our caller, external_stop_browsing_for_service()
- // would not call into the D2D plugin to remove the advertisements in this case.
- internal_stop_advertising_service(& ptr->serviceRecordSet->RR_PTR.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
- internal_stop_advertising_service(& ptr->serviceRecordSet->RR_SRV.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
- internal_stop_advertising_service(& ptr->serviceRecordSet->RR_TXT.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ LogInfo("updateBeaconAndScanState: suppressing beacons, no peers currently seeking our services");
+ suppressBeacons = true;
+
+ // If currently beaconing, send a beacon for two seconds with a zeroed Bloom filter indicating we are
+ // no longer browsing for any services so that any matching auto triggered peer registrations have a
+ // chance to see our state change.
+ if (currentlyBeaconing())
+ updateBLEBeacon(0);
+ startBLEScan();
}
}
- removeFromRequestList(&BLERegistrationListHead, instanceRemoved, type);
-
- if (lastReference)
- updateBeacon();
-
- // If there are no active browse or registration requests, BLE scanning will be disabled.
- // Clear the list of responses received to remove any stale response state.
- if (BLEBrowseListHead == NULL && BLERegistrationListHead == 0)
- clearResponseLists();
+ // If beacons had been suppressed and we no longer have services to advertise, no
+ // need to send a beacon with a zeroed Bloom filter for two seconds, just stop
+ // the scan.
+ else if (suppressBeacons == true && beaconBloomFilter == 0)
+ {
+ suppressBeacons = false;
+ stopBLEScan();
+ }
+ // Update the beacon with the current Bloom filter values.
+ else
+ {
+ suppressBeacons = false;
+ updateBLEBeacon(beaconBloomFilter);
+ // Scan unless the Bloom filter is zero, indicating we are not currently
+ // seeking or providing any services.
+ if (beaconBloomFilter)
+ startBLEScan();
+ else
+ stopBLEScan();
+ }
}
-#pragma mark - Response Handling
+#pragma mark - Peer response handling
// Structure used to track the beacons received from various peers.
typedef struct responseList
{
struct responseList * next;
- serviceHash_t browseHash;
- serviceHash_t registeredHash;
- mDNSEthAddr senderMAC;
+ serviceHash_t peerBloomFilter;
+ mDNSs32 recievedTime;
+ mDNSEthAddr peerMac;
} responseList_t;
#define RESPONSE_LIST_NUMBER 8
static responseList_t* BLEResponseListHeads[RESPONSE_LIST_NUMBER];
+// Return the address of the pointer to the entry, which can either be the address of the
+// corresponding BLEResponseListHeads[] entry, or the address of the prior responseList_t entry
+// on the lists "next" pointer.
mDNSlocal responseList_t ** findInResponseList(mDNSEthAddr * ptrToMAC)
{
// Use the least significant byte of the MAC address as our hash index to find the list.
@@ -518,7 +695,7 @@ mDNSlocal responseList_t ** findInResponseList(mDNSEthAddr * ptrToMAC)
for ( ; *ptr; ptr = &(*ptr)->next)
{
- if (memcmp(&(*ptr)->senderMAC, ptrToMAC, sizeof(mDNSEthAddr)) == 0)
+ if (memcmp(&(*ptr)->peerMac, ptrToMAC, sizeof(mDNSEthAddr)) == 0)
break;
}
@@ -526,7 +703,7 @@ mDNSlocal responseList_t ** findInResponseList(mDNSEthAddr * ptrToMAC)
}
-mDNSlocal responseList_t ** addToResponseList(serviceHash_t browseHash, serviceHash_t registeredHash, mDNSEthAddr * ptrToMAC)
+mDNSlocal responseList_t * addToResponseList(serviceHash_t peerBloomFilter, mDNSEthAddr * ptrToMAC)
{
responseList_t **ptr = findInResponseList(ptrToMAC);
@@ -534,12 +711,11 @@ mDNSlocal responseList_t ** addToResponseList(serviceHash_t browseHash, serviceH
{
*ptr = mDNSPlatformMemAllocate(sizeof(**ptr));
mDNSPlatformMemZero(*ptr, sizeof(**ptr));
- (*ptr)->browseHash = browseHash;
- (*ptr)->registeredHash = registeredHash;
- memcpy(& (*ptr)->senderMAC, ptrToMAC, sizeof(mDNSEthAddr));
+ (*ptr)->peerBloomFilter = peerBloomFilter;
+ memcpy(& (*ptr)->peerMac, ptrToMAC, sizeof(mDNSEthAddr));
}
- return ptr;
+ return *ptr;
}
mDNSlocal void removeFromResponseList(mDNSEthAddr * ptrToMAC)
@@ -581,25 +757,8 @@ mDNSlocal void clearResponseLists()
}
}
-// Called from mDNS_Execute() when NextBLEServiceTime is reached
-// to stop the BLE beacon a few seconds after the last request has
-// been stopped. This gives peers a chance to see that this device
-// is no longer browsing for or advertising any services via the
-// BLE beacon.
-void serviceBLE(void)
-{
- mDNSStorage.NextBLEServiceTime = 0;
- if (BLEBrowseListHead || BLERegistrationListHead)
- {
- // We don't expect to be called if there are active requests.
- LogInfo("serviceBLE: called with active BLE requests ??");
- return;
- }
- stopBLEBeacon();
-}
-
-// Called from start_BLE_browse() on the mDNSResonder kqueue thread
-mDNSlocal void checkForMatchingResponses(requestList_t *bp)
+// Check to see if we have cached a response that matches a service for which we just started a browse or registration.
+mDNSlocal void checkCachedResponses(requestList_t *browse, requestList_t *registration)
{
responseList_t *ptr;
@@ -607,28 +766,28 @@ mDNSlocal void checkForMatchingResponses(requestList_t *bp)
{
for (ptr = BLEResponseListHeads[i]; ptr; ptr = ptr->next)
{
- if ((bp->browseHash & ptr->registeredHash) == bp->browseHash)
+ // For browses, we are looking for responses that have a matching registration
+ // and for registrations we are looking for responses that have a matching browse.
+ if ( (browse && (browse->registeredHash & ptr->peerBloomFilter) == browse->registeredHash)
+ || (registration && (registration->browseHash & ptr->peerBloomFilter) == registration->browseHash))
{
- // Clear the registered services hash for the response.
- // The next beacon from this peer will update the hash and our
- // newly started browse will get an add event if there is a match.
- ptr->registeredHash = 0;
+ // Clear the Bloom filter for the response.
+ // The next beacon from this peer will update the filter then autoTrigger
+ // any newly started client requests as appropriate.
+ ptr->peerBloomFilter = 0;
}
}
}
}
// Define a fixed name to use for the instance name denoting that one or more instances
-// of a service are being advetised by peers in their BLE beacons.
+// of a service are being advertised by peers in their BLE beacons.
// Name format is: length byte + bytes of name string + two byte pointer to the PTR record name.
-// See compression_lhs definition in the D2D plugin code for backgound on 0xc027 DNS name compression pointer value.
+// See compression_lhs definition in the D2D plugin code for background on 0xc027 DNS name compression pointer value.
static Byte *BLEinstanceValue = (Byte *) "\x11ThresholdInstance\xc0\x27";
#define BLEValueSize strlen((const char *)BLEinstanceValue)
-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);
-
-// Find each unique browse that matches the registered service hash in the BLE response.
+// Find each local browse that matches the registered service hash in the BLE response.
// Called on the CFRunLoop thread while handling a callback from CoreBluetooth.
// Caller should hold KQueueLock().
mDNSlocal void findMatchingBrowse(responseList_t *response)
@@ -638,7 +797,9 @@ mDNSlocal void findMatchingBrowse(responseList_t *response)
ptr = BLEBrowseListHead;
for ( ; ptr; ptr = ptr->next)
{
- if ((ptr->browseHash & response->registeredHash) == ptr->browseHash)
+ // See if we potentially match a corresponding registration in the beacon.
+ // thus, compare using the "registeredHash" of our browse..
+ if ((ptr->registeredHash & response->peerBloomFilter) == ptr->registeredHash)
{
LogInfo("findMatchingBrowse: Registration in response matched browse for: %##s", ptr->name.c);
@@ -655,20 +816,19 @@ mDNSlocal void findMatchingBrowse(responseList_t *response)
if (ptr->ourResponses == 0)
{
- if (isAutoTriggerRequest(ptr))
+ if (isAutoTriggerRequest(ptr->InterfaceID, ptr->flags))
{
LogInfo("findMatchingBrowse: First BLE response, triggering browse for %##s on AWDL", ptr->name.c);
- ptr->question->flags |= kDNSServiceFlagsIncludeAWDL;
- mDNSCoreRestartQuestion(& mDNSStorage, ptr->question);
// register with the AWDL D2D plugin,
- internal_start_browsing_for_service(ptr->question->InterfaceID, & ptr->name, ptr->type, ptr->question->flags, ptr->question);
+ internal_start_browsing_for_service(ptr->InterfaceID, & ptr->name, ptr->type, ptr->flags);
+ ptr->triggeredOnAWDL = true;
}
// Browse on mDNSInterface_BLE is used to determine if there are one or more instances of the
// service type discoveryed over BLE. If this is the first instance, add the psuedo instance defined by BLEinstanceValue.
- if (ptr->question->InterfaceID == mDNSInterface_BLE)
+ if (ptr->InterfaceID == mDNSInterface_BLE)
{
- xD2DAddToCache(& mDNSStorage, kD2DSuccess, 0, D2DBLETransport, ptr->key, ptr->keySize, BLEinstanceValue, BLEValueSize);
+ xD2DAddToCache(kD2DSuccess, 0, D2DBLETransport, ptr->key, ptr->keySize, BLEinstanceValue, BLEValueSize);
}
}
addToResponseListForRequest(ptr, response);
@@ -680,34 +840,37 @@ mDNSlocal void findMatchingBrowse(responseList_t *response)
// list now. If this is the last matching response, remove the corresponding key from the AWDL D2D plugin
if (removeFromResponseListForRequest(ptr, response) && (ptr->ourResponses == 0))
{
- if (ptr->question->InterfaceID == mDNSInterface_BLE)
+ if (ptr->InterfaceID == mDNSInterface_BLE)
{
- xD2DRemoveFromCache(& mDNSStorage, kD2DSuccess, 0, D2DBLETransport, ptr->key, ptr->keySize, BLEinstanceValue, BLEValueSize);
+ xD2DRemoveFromCache(kD2DSuccess, 0, D2DBLETransport, ptr->key, ptr->keySize, BLEinstanceValue, BLEValueSize);
}
- if (isAutoTriggerRequest(ptr))
+ if (isAutoTriggerRequest(ptr->InterfaceID, ptr->flags))
{
LogInfo("findMatchingBrowse: Last BLE response, disabling browse for %##s on AWDL", ptr->name.c);
- internal_stop_browsing_for_service(ptr->question->InterfaceID, & ptr->name, ptr->type, ptr->question->flags);
+ internal_stop_browsing_for_service(ptr->InterfaceID, & ptr->name, ptr->type, ptr->flags);
+ ptr->triggeredOnAWDL = false;
}
}
}
}
}
-// Find each local registration that matches the service browse hash in the BLE response.
+// Find each local registration that matches the service browse hash BLE response Bloom filter.
// Called on the CFRunLoop thread while handling a callback from CoreBluetooth.
// Caller should hold KQueueLock().
mDNSlocal void findMatchingRegistration(responseList_t *response)
{
- requestList_t *ptr;
+ requestList_t *ptr;
+ bool matchingPeer;
ptr = BLERegistrationListHead;
for ( ; ptr; ptr = ptr->next)
{
- if ((ptr->registeredHash & response->browseHash) == ptr->registeredHash)
+ // See if we potentially match a corresponding browse in the beacon,
+ // thus, compare using the "browseHash" of our registration.
+ if ((ptr->browseHash & response->peerBloomFilter) == ptr->browseHash)
{
-
LogInfo("findMatchingRegistration: Incoming browse matched registration for: %##s", ptr->name.c);
if (inResponseListForRequest(ptr, response))
@@ -722,44 +885,16 @@ mDNSlocal void findMatchingRegistration(responseList_t *response)
// Also pass the registration to the AWDL D2D plugin if this is the first matching peer browse for
// an auto triggered local registration.
- if ((ptr->ourResponses == 0) && isAutoTriggerRequest(ptr))
+ if ((ptr->ourResponses == 0) && isAutoTriggerRequest(ptr->InterfaceID, ptr->flags))
{
- AuthRecType newARType;
-
LogInfo("findMatchingRegistration: First BLE response, triggering registration for %##s on AWDL", ptr->name.c);
- if (ptr->serviceRecordSet == 0)
- {
- LogInfo("findMatchingRegistration: serviceRecordSet pointer is NULL ??");
- continue;
- }
- // Modify the PTR, TXT, and SRV records so that they now apply to AWDL and restart the registration.
- // RR_ADV is not passed to the D2D plugins froma internal_start_advertising_helper(), so we don't do it here either.
-
- if (ptr->flags & kDNSServiceFlagsIncludeAWDL)
+ if (ptr->resourceRecord == 0)
{
- LogInfo("findMatchingRegistration: registration for %##s already applies to AWDL, skipping", ptr->name.c);
+ LogInfo("findMatchingRegistration: resourceRecord pointer is NULL ??");
continue;
}
- // Save the current ARType value to restore when the promotion to use AWDL is stopped.
- ptr->savedARType = ptr->serviceRecordSet->RR_PTR.ARType;
-
- // Preserve P2P attribute if original registration was applied to P2P.
- if (ptr->serviceRecordSet->RR_PTR.ARType == AuthRecordAnyIncludeP2P)
- newARType = AuthRecordAnyIncludeAWDLandP2P;
- else
- newARType = AuthRecordAnyIncludeAWDL;
-
- ptr->serviceRecordSet->RR_PTR.ARType = newARType;
- ptr->serviceRecordSet->RR_SRV.ARType = newARType;
- ptr->serviceRecordSet->RR_TXT.ARType = newARType;
- mDNSCoreRestartRegistration(& mDNSStorage, & ptr->serviceRecordSet->RR_PTR, -1);
- mDNSCoreRestartRegistration(& mDNSStorage, & ptr->serviceRecordSet->RR_SRV, -1);
- mDNSCoreRestartRegistration(& mDNSStorage, & ptr->serviceRecordSet->RR_TXT, -1);
-
- internal_start_advertising_service(& ptr->serviceRecordSet->RR_PTR.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
- internal_start_advertising_service(& ptr->serviceRecordSet->RR_SRV.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
- internal_start_advertising_service(& ptr->serviceRecordSet->RR_TXT.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ internal_start_advertising_service(ptr->resourceRecord, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
// indicate the registration has been applied to the AWDL interface
ptr->triggeredOnAWDL = true;
}
@@ -772,51 +907,113 @@ mDNSlocal void findMatchingRegistration(responseList_t *response)
// If a previous response from this peer had matched the browse, remove that response from the
// list now. If this is the last matching response for a local auto triggered registration,
// remove the advertised key/value pairs from the AWDL D2D plugin.
- if (removeFromResponseListForRequest(ptr, response) && (ptr->ourResponses == 0) && isAutoTriggerRequest(ptr))
+ if (removeFromResponseListForRequest(ptr, response) && (ptr->ourResponses == 0) && isAutoTriggerRequest(ptr->InterfaceID, ptr->flags))
{
LogInfo("findMatchingRegistration: Last BLE response, disabling registration for %##s on AWDL", ptr->name.c);
// Restore the saved ARType and call into the AWDL D2D plugin to stop the corresponding record advertisements over AWDL.
- ptr->serviceRecordSet->RR_PTR.ARType = ptr->savedARType;
- ptr->serviceRecordSet->RR_SRV.ARType = ptr->savedARType;
- ptr->serviceRecordSet->RR_TXT.ARType = ptr->savedARType;
- internal_stop_advertising_service(& ptr->serviceRecordSet->RR_PTR.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
- internal_stop_advertising_service(& ptr->serviceRecordSet->RR_SRV.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
- internal_stop_advertising_service(& ptr->serviceRecordSet->RR_TXT.resrec, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ internal_stop_advertising_service(ptr->resourceRecord, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ ptr->triggeredOnAWDL = false;
}
}
}
+
+ // If beacons for our registrations had been suppressed, see if we now have a match and need to restart them.
+ matchingPeer = responseMatchesRegistrations();
+ if (suppressBeacons && matchingPeer)
+ {
+ LogInfo("findMatchingRegistration: peer searching for our service, starting beacon transmission");
+ updateBeaconAndScanState();
+
+ if (suppressBeacons == true)
+ LogInfo("findMatchingRegistration: NOTE: suppressBeacons is true after updateBeaconAndScanState() call ??");
+ }
+ // If we have only registrations, but no matching peers, we can suppress beacons until we get a matching peer beacon.
+ else if (!suppressBeacons && !matchingPeer && BLERegistrationListHead && !BLEBrowseListHead)
+ {
+ LogInfo("findMatchingRegistration: no peer beacons match our registrations, suppressing beacon transmission");
+ suppressBeacons = true;
+ stopBLEBeacon();
+ }
+}
+
+
+// Time limit before a beacon is aged out of our received list.
+#define MAX_RESPONSE_AGE 10
+
+// If we have responses from peers that are more than MAX_RESPONSE_AGE seconds
+// old, remove them since a peer with active requests should be beaconing multiple
+// times per second if still within BLE range.
+mDNSlocal void removeStaleResponses(mDNSs32 currentTime)
+{
+ responseList_t **ptr;
+
+ for (unsigned int i = 0; i < RESPONSE_LIST_NUMBER; i++)
+ {
+ ptr = & BLEResponseListHeads[i];
+ while (*ptr)
+ {
+ if ((currentTime - (*ptr)->recievedTime) > (MAX_RESPONSE_AGE * mDNSPlatformOneSecond))
+ {
+ responseList_t * tmp;
+
+ // Clear the Bloom filter so that it will be removed from any matching response list
+ // by the following calls.
+ (*ptr)->peerBloomFilter = 0;
+
+ LogInfo("removeStaleResponses: clearing stale response from peer MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ (*ptr)->peerMac.b[0], (*ptr)->peerMac.b[1], (*ptr)->peerMac.b[2], (*ptr)->peerMac.b[3], (*ptr)->peerMac.b[4], (*ptr)->peerMac.b[5]);
+
+ findMatchingBrowse(*ptr);
+ findMatchingRegistration(*ptr);
+
+ // Unlink and free the response structure
+ tmp = *ptr;
+ *ptr = (*ptr)->next;
+ mDNSPlatformMemFree(tmp);
+ }
+ // Move to the next response on this linked list.
+ else
+ ptr = & (*ptr)->next;
+ }
+ }
}
// Called on CFRunLoop thread during CoreBluetooth beacon response processing.
// Thus, must call KQueueLock() prior to calling any core mDNSResponder routines to register records, etc.
-void responseReceived(serviceHash_t browseHash, serviceHash_t registeredHash, mDNSEthAddr * ptrToMAC)
+void responseReceived(serviceHash_t peerBloomFilter, mDNSEthAddr * ptrToMAC)
{
- responseList_t ** ptr;
+ responseList_t * ptr;
- KQueueLock(& mDNSStorage);
- ptr = findInResponseList(ptrToMAC);
- if (*ptr == 0)
+ KQueueLock();
+ mDNS_Lock(& mDNSStorage); // Must lock to initialize mDNSStorage.timenow
+
+ ptr = *(findInResponseList(ptrToMAC));
+ if (ptr == 0)
{
// Only add to list if peer is actively browsing or advertising.
- if (browseHash || registeredHash)
+ if (peerBloomFilter)
{
LogInfo("responseReceived: First beacon of this type, adding to list");
- LogInfo("responseReceived: browseHash = 0x%x, registeredHash = 0x%x",
- browseHash, registeredHash);
- LogInfo("responseReceived: sender MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ LogInfo("responseReceived: peerBloomFilter = 0x%lx", peerBloomFilter);
+ LogInfo("responseReceived: peer MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
ptrToMAC->b[0], ptrToMAC->b[1], ptrToMAC->b[2], ptrToMAC->b[3], ptrToMAC->b[4], ptrToMAC->b[5]);
- ptr = addToResponseList(browseHash, registeredHash, ptrToMAC);
+ ptr = addToResponseList(peerBloomFilter, ptrToMAC);
+ // Update the received time.
+ ptr->recievedTime = mDNSStorage.timenow;
// See if we are browsing for any of the peers advertised services.
- findMatchingBrowse(*ptr);
+ findMatchingBrowse(ptr);
// See if we have a registration that matches the peer's browse.
- findMatchingRegistration(*ptr);
+ findMatchingRegistration(ptr);
}
}
- else // have entry from this MAC in the list
+ else // Have an entry from this MAC in the list.
{
- if (((*ptr)->browseHash == browseHash) && ((*ptr)->registeredHash == registeredHash))
+ // Update the received time.
+ ptr->recievedTime = mDNSStorage.timenow;
+
+ if (ptr->peerBloomFilter == peerBloomFilter)
{
// A duplicate of a current entry.
#if VERBOSE_BLE_DEBUG
@@ -828,20 +1025,17 @@ void responseReceived(serviceHash_t browseHash, serviceHash_t registeredHash, mD
else
{
LogInfo("responseReceived: Update of previous beacon");
- LogInfo("responseReceived: browseHash = 0x%x, registeredHash = 0x%x",
- browseHash, registeredHash);
+ LogInfo("responseReceived: peerBloomFilter = 0x%lx", peerBloomFilter);
LogInfo("responseReceived: sender MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
ptrToMAC->b[0], ptrToMAC->b[1], ptrToMAC->b[2], ptrToMAC->b[3], ptrToMAC->b[4], ptrToMAC->b[5]);
- (*ptr)->browseHash = browseHash;
- (*ptr)->registeredHash = registeredHash;
-
- findMatchingBrowse(*ptr);
- findMatchingRegistration(*ptr);
+ ptr->peerBloomFilter = peerBloomFilter;
+ findMatchingBrowse(ptr);
+ findMatchingRegistration(ptr);
}
// If peer is no longer browsing or advertising, remove from list.
- if ((browseHash == 0) && (registeredHash == 0))
+ if (peerBloomFilter == 0)
{
LogInfo("responseReceived: Removing peer entry from the list");
@@ -849,5 +1043,450 @@ void responseReceived(serviceHash_t browseHash, serviceHash_t registeredHash, mD
}
}
- KQueueUnlock(& mDNSStorage, "BLE responseReceived");
+ mDNS_Unlock(& mDNSStorage); // Calling mDNS_Unlock is what gives m->NextScheduledEvent its new value
+ KQueueUnlock("BLE responseReceived");
+}
+
+#pragma mark - Client request handling
+
+void start_BLE_browse(mDNSInterfaceID InterfaceID, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags, mDNSu8 *key, size_t keySize)
+{
+ requestList_t * ptr;
+ const domainname *serviceType = domain;
+
+ if (!EnableBLEBasedDiscovery)
+ {
+ LogMsg("start_BLE_browse: EnableBLEBasedDiscovery disabled");
+ return;
+ }
+
+ if (keySize > MAX_KEY_SIZE)
+ {
+ LogMsg("start_BLE_browse: keySize = %d, maximum allowable is %d", keySize, MAX_KEY_SIZE);
+ return;
+ }
+
+ // Verify that the request to be auto triggered applies to AWDL, or is using the pseudo interface for
+ // BLE threshold browsing.
+ if (!isAutoTriggerRequest(InterfaceID, flags) && (InterfaceID != mDNSInterface_BLE))
+ {
+ LogMsg("start_BLE_browse: invalid request: InterfaceID = %d, flags = 0x%x", InterfaceID, flags);
+ return;
+ }
+
+ // Address records don't have a service type to hash and match on, so pass them directly to the D2D plugin.
+ if ((type == kDNSType_A) || (type == kDNSType_AAAA))
+ {
+ LogInfo("start_BLE_browse: Passing directly to D2D layer: %##s %s", domain->c, DNSTypeName(type));
+ internal_start_browsing_for_service(InterfaceID, domain, type, flags);
+ return;
+ }
+
+ // Skip the instance to get to the service type for non PTR records
+ if (type != kDNSType_PTR)
+ serviceType = SkipLeadingLabels(domain, 1);
+
+ LogInfo("start_BLE_browse: Starting BLE service type browse for: %##s %s", domain->c, DNSTypeName(type));
+
+ ptr = addToRequestList(&BLEBrowseListHead, domain, type, flags);
+
+ // If equivalent BLE browse is already running, just return.
+ if (ptr->refCount > 1)
+ {
+ LogInfo("start_BLE_browse: Dup of existing BLE browse.");
+ return;
+ }
+
+ if (!setBLEServiceHash(serviceType, ptr))
+ {
+ LogInfo("setBLEServiceHash failed!");
+ removeFromRequestList(&BLEBrowseListHead, domain, type);
+ return;
+ }
+
+ // Save these for use in D2D plugin callback logic.
+ memcpy(ptr->key, key, keySize);
+ ptr->keySize = keySize;
+ ptr->InterfaceID = InterfaceID;
+
+ mDNS_Lock(& mDNSStorage); // Must lock to initialize mDNSStorage.timenow.
+ updateBeaconAndScanState();
+ mDNS_Unlock(& mDNSStorage); // Updates mDNSStorage.NextScheduledEvent.
+ checkCachedResponses(ptr, NULL);
+}
+
+// Stop the browse.
+// Return true if this is the last reference to the browse, false otherwise.
+bool stop_BLE_browse(mDNSInterfaceID InterfaceID, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags)
+{
+ (void) flags; // not used initially
+ requestList_t * ptr;
+ bool lastReference = false;
+
+ if (!EnableBLEBasedDiscovery)
+ {
+ LogMsg("stop_BLE_browse: EnableBLEBasedDiscovery disabled");
+ return lastReference;
+ }
+
+ // Address records don't have a service type to hash and match on, so pass them directly to the D2D plugin.
+ if ((type == kDNSType_A) || (type == kDNSType_AAAA))
+ {
+ LogInfo("stop_BLE_browse: Passing directly to D2D layer: %##s %s", domain->c, DNSTypeName(type));
+ internal_stop_browsing_for_service(InterfaceID, domain, type, flags);
+ return lastReference;
+ }
+
+ LogInfo("stop_BLE_browse: Stopping BLE service type browse for: %##s %s", domain->c, DNSTypeName(type));
+
+ ptr = *(findInRequestList(&BLEBrowseListHead, domain, type));
+ if (ptr == 0)
+ {
+ LogInfo("stop_BLE_browse: No matching browse found.");
+ return lastReference;
+ }
+
+ // If this is the last reference for this browse, and it was autoTriggered on AWDL,
+ // remove the request from the AWDL pluggin.
+ if (ptr->refCount == 1)
+ {
+ lastReference = true;
+
+ if (isAutoTriggerRequest(ptr->InterfaceID, ptr->flags) && ptr->triggeredOnAWDL)
+ {
+ internal_stop_browsing_for_service(ptr->InterfaceID, & ptr->name, ptr->type, ptr->flags);
+ ptr->triggeredOnAWDL = false;
+ }
+ }
+
+ removeFromRequestList(&BLEBrowseListHead, domain, type);
+
+ mDNS_Lock(& mDNSStorage); // Must lock to initialize mDNSStorage.timenow.
+ if (lastReference)
+ updateBeaconAndScanState();
+ mDNS_Unlock(& mDNSStorage); // Updates mDNSStorage.NextScheduledEvent.
+
+ // If there are no active browse or registration requests, BLE scanning will be disabled.
+ // Clear the list of responses received to remove any stale response state.
+ if (BLEBrowseListHead == NULL && BLERegistrationListHead == 0)
+ clearResponseLists();
+
+ return lastReference;
+}
+
+void start_BLE_advertise(const ResourceRecord *const resourceRecord, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags)
+{
+ requestList_t * ptr;
+ const domainname * serviceType = domain;
+
+ if (!EnableBLEBasedDiscovery)
+ {
+ LogMsg("start_BLE_advertise: EnableBLEBasedDiscovery disabled");
+ return;
+ }
+
+ if (resourceRecord == NULL)
+ {
+ LogInfo("start_BLE_advertise: NULL resourceRecord for: %##s %s, returning", domain->c, DNSTypeName(type));
+ return;
+ }
+
+ // Verify that the request to be auto triggered applies to AWDL, or is using the pseudo interface for
+ // BLE threshold browsing.
+ if (!isAutoTriggerRequest(resourceRecord->InterfaceID, flags) && (resourceRecord->InterfaceID != mDNSInterface_BLE))
+ {
+ LogMsg("start_BLE_advertise: invalid request: InterfaceID = %d, flags = 0x%x", resourceRecord->InterfaceID, flags);
+ return;
+ }
+
+ LogInfo("start_BLE_advertise: Starting BLE service type advertisement for: %##s %s", domain->c, DNSTypeName(type));
+
+ // Skip the instance to get to the service type for non PTR records
+ if (type != kDNSType_PTR)
+ serviceType = SkipLeadingLabels(domain, 1);
+
+ ptr = addToRequestList(&BLERegistrationListHead, domain, type, flags);
+
+ // If equivalent BLE registration is already running, just return.
+ if (ptr->refCount > 1)
+ {
+ LogInfo("start_BLE_advertise: Dup of existing BLE advertisement.");
+ return;
+ }
+
+ if (!setBLEServiceHash(serviceType, ptr))
+ {
+ LogInfo("setBLEServiceHash failed!");
+ removeFromRequestList(&BLERegistrationListHead, domain, type);
+ return;
+ }
+ ptr->resourceRecord = resourceRecord;
+ ptr->InterfaceID = resourceRecord->InterfaceID;
+
+ mDNS_Lock(& mDNSStorage); // Must lock to initialize mDNSStorage.timenow.
+ updateBeaconAndScanState();
+ mDNS_Unlock(& mDNSStorage); // Updates mDNSStorage.NextScheduledEvent.
+ checkCachedResponses(NULL, ptr);
+}
+
+void stop_BLE_advertise(const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags)
+{
+ (void) flags; // not used initially
+ requestList_t * ptr;
+ bool lastReference = false;
+
+ LogInfo("stop_BLE_advertise: Stopping BLE service type advertisement for: %##s %s", domain->c, DNSTypeName(type));
+
+ // Get the request pointer from the indirect pointer returned.
+ ptr = *(findInRequestList(&BLERegistrationListHead, domain, type));
+
+ if (ptr == 0)
+ {
+ LogInfo("stop_BLE_advertise: No matching advertisement found.");
+ return;
+ }
+
+ // If this is the last reference for this registration, and it was autoTriggered on AWDL,
+ // remove the request from the AWDL pluggin.
+ if (ptr->refCount == 1)
+ {
+ lastReference = true;
+
+ if (isAutoTriggerRequest(ptr->InterfaceID, ptr->flags) && ptr->triggeredOnAWDL)
+ {
+ // And remove the corresponding advertisements from the AWDL D2D plugin if we had previously
+ // passed this advertisement request to the plugin.
+ internal_stop_advertising_service(ptr->resourceRecord, (ptr->flags | kDNSServiceFlagsIncludeAWDL));
+ ptr->triggeredOnAWDL = false;
+ }
+ }
+ removeFromRequestList(&BLERegistrationListHead, domain, type);
+
+ mDNS_Lock(& mDNSStorage); // Must lock to initialize mDNSStorage.timenow.
+ // If this is the last reference for this registration, update advertising and browsing bits set in the beacon.
+ if (lastReference)
+ updateBeaconAndScanState();
+ mDNS_Unlock(& mDNSStorage); // Updates mDNSStorage.NextScheduledEvent.
+
+ // If there are no active browse or registration requests, BLE scanning will be disabled.
+ // Clear the list of responses received to remove any stale response state.
+ if (BLEBrowseListHead == NULL && BLERegistrationListHead == 0)
+ clearResponseLists();
}
+
+#ifdef UNIT_TEST
+#pragma mark - Unit test support routines
+
+// These unit test support routines are called from unittests/ framework
+// and are not compiled for the mDNSResponder runtime code paths.
+
+#define MAX_ENTRIES 42
+#define FAILED exit(1)
+
+mDNSlocal void BLE_requestListTests(void)
+{
+ const domainname *domainArray[] = { (const domainname*)"\x6" "_test0" "\x4" "_tcp" "\x5" "local",
+ (const domainname*)"\x6" "_test1" "\x4" "_tcp" "\x5" "local",
+ (const domainname*)"\x6" "_test2" "\x4" "_tcp" "\x5" "local",
+ (const domainname*)"\x6" "_test3" "\x4" "_tcp" "\x5" "local",
+ (const domainname*)"\x6" "_test4" "\x4" "_tcp" "\x5" "local",
+ };
+
+ mDNSu16 type = kDNSServiceType_PTR;
+ DNSServiceFlags flags = 0;
+ requestList_t * ptr;
+ void * response = 0;
+ int i;
+ int numOfdomains = sizeof(domainArray)/sizeof(domainArray[0]);
+
+ printf("BLE_requestListTests() entry:\n");
+
+ // Basic request list unit tests.
+ for (i = 0; i < numOfdomains; i++)
+ {
+ ptr = addToRequestList(&BLEBrowseListHead, domainArray[i], type, flags);
+
+ if (ptr == NULL)
+ {
+ printf("addToRequestList() FAILED:\n");
+ FAILED;
+ }
+ }
+ for (i = 0; i < numOfdomains; i++)
+ {
+ // should now find the entry
+ if (*(findInRequestList(&BLEBrowseListHead, domainArray[i], type)) == 0)
+ {
+ printf("findInRequestList() did not find valid entry FAILED:\n");
+ FAILED;
+ }
+ // but not find an entry with the same domain, but different type
+ if (*(findInRequestList(&BLEBrowseListHead, domainArray[i], kDNSServiceType_NULL)) != 0)
+ {
+ printf("findInRequestList() invalid entry matched FAILED:\n");
+ FAILED;
+ }
+ }
+ // remove all the entries
+ for (i = 0; i < numOfdomains; i++)
+ {
+ removeFromRequestList(&BLEBrowseListHead, domainArray[i], type);
+ }
+ // and sanity check the list is now empty
+ if (BLEBrowseListHead)
+ {
+ printf("BLEBrowseListHead not empty after all entries removed.\n");
+ FAILED;
+ }
+
+ // Identical request reference count management tests.
+ // Add identical requests to the list and verify the corresponding refCount is managed correctly
+ for (i = 0; i < MAX_ENTRIES; i++)
+ {
+ ptr = addToRequestList(&BLEBrowseListHead, domainArray[0], type, flags);
+
+ if (ptr == NULL)
+ {
+ printf("addToRequestList() of duplicate request FAILED:\n");
+ FAILED;
+ }
+ }
+
+ if (ptr->refCount != MAX_ENTRIES)
+ {
+ printf("refCount = %d, should be %d\n", ptr->refCount, MAX_ENTRIES);
+ FAILED;
+ }
+
+ // Remove all but one entry
+ for (i = 0; i < (MAX_ENTRIES - 1); i++)
+ {
+ removeFromRequestList(&BLEBrowseListHead, domainArray[0], type);
+ }
+ if (ptr->refCount != 1)
+ {
+ printf("refCount = %d, should be %d\n", ptr->refCount, 1);
+ FAILED;
+ }
+
+ // Basic response list unit tests.
+ // Note that responses per request are not checked for duplicates at this level, so
+ // we can unit test with the same (NULL) response pointer to add multiple responses.
+
+ // add MAX_ENTRIES responses
+ for (i = 0; i < MAX_ENTRIES; i++)
+ addToResponseListForRequest(ptr, response);
+
+ // remove the responses, counting that MAX_ENTRIES were removed
+ i = 0;
+ while (inResponseListForRequest(ptr, response) && removeFromResponseListForRequest(ptr, response))
+ {
+ i++;
+ }
+ if (i != MAX_ENTRIES)
+ {
+ printf("removed %d responses, should have been %d\n", i, MAX_ENTRIES);
+ FAILED;
+ }
+
+ // response list should be empty at this point
+ if (ptr->ourResponses)
+ {
+ printf("response list should be empty\n");
+ FAILED;
+ }
+
+ // add MAX_ENTRIES responses
+ for (i = 0; i < MAX_ENTRIES; i++)
+ addToResponseListForRequest(ptr, response);
+
+ // free them all
+ freeResponseListEntriesForRequest(ptr);
+
+ if (ptr->ourResponses)
+ {
+ printf("freeResponseListEntriesForRequest() should have removed all responses\n");
+ FAILED;
+ }
+}
+
+mDNSlocal mDNSEthAddr etherAddress[] = {
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x06 } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x07 } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e } },
+ { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f } },
+};
+
+mDNSlocal void BLE_responseListTests(void)
+{
+ int numOfEtherAddresses = sizeof(etherAddress)/sizeof(etherAddress[0]);
+ int i;
+
+ printf("BLE_responseListTests() entry:\n");
+
+ // Just use the index as to generate the peerBloomFilter value to vary it per entry.
+ for (i = 0; i < numOfEtherAddresses; i++)
+ (void)addToResponseList(1 << i, &etherAddress[i]);
+
+ // Verify all entries are found.
+ for (i = 0; i < numOfEtherAddresses; i++)
+ {
+ if (*(findInResponseList(&etherAddress[i])) == 0)
+ {
+ printf("findInResponseList() did not find entry in list\n");
+ FAILED;
+ }
+ }
+
+ // Remove all entries.
+ for (i = 0; i < numOfEtherAddresses; i++)
+ removeFromResponseList(&etherAddress[i]);
+
+ // Sanity check that all response lists are empty
+ for (i = 0; i < RESPONSE_LIST_NUMBER; i++)
+ {
+ if (BLEResponseListHeads[i])
+ {
+ printf("BLEResponseListHeads[%d] not empty after removeFromResponseList() calls \n", i);
+ FAILED;
+ }
+ }
+
+ // Add them back again.
+ for (i = 0; i < numOfEtherAddresses; i++)
+ (void)addToResponseList(1 << i, &etherAddress[i]);
+
+ // And verify that clearResponseLists() clears all entries.
+ clearResponseLists();
+ for (i = 0; i < RESPONSE_LIST_NUMBER; i++)
+ {
+ if (BLEResponseListHeads[i])
+ {
+ printf("BLEResponseListHeads[%d] not empty after clearResponseLists() call\n", i);
+ FAILED;
+ }
+ }
+}
+
+void BLE_unitTest(void)
+{
+ BLE_requestListTests();
+ BLE_responseListTests();
+ printf("All BLE.c unit tests PASSED.\n");
+}
+
+#endif // UNIT_TEST
+
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
diff --git a/mDNSResponder/mDNSMacOSX/BLE.h b/mDNSResponder/mDNSMacOSX/BLE.h
index 970c8faf..1b91e6c2 100644
--- a/mDNSResponder/mDNSMacOSX/BLE.h
+++ b/mDNSResponder/mDNSMacOSX/BLE.h
@@ -18,37 +18,51 @@
#ifndef _BLE_H_
#define _BLE_H_
+#if ENABLE_BLE_TRIGGERED_BONJOUR
+
#include "dns_sd.h"
-#include "dns_sd_private.h"
+#include "dns_sd_internal.h"
+
+typedef unsigned long serviceHash_t;
-typedef unsigned int serviceHash_t;
+bool shouldUseBLE(mDNSInterfaceID interfaceID, DNS_TypeValues rrtype, domainname *serviceType, domainname *domain);
-void start_BLE_browse(DNSQuestion * q, const domainname *const typeDomain, DNS_TypeValues type, DNSServiceFlags flags,
+void start_BLE_browse(mDNSInterfaceID InterfaceID, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags,
mDNSu8 *key, size_t keySize);
-bool stop_BLE_browse(const domainname *const typeDomain, DNS_TypeValues type, DNSServiceFlags flags);
+bool stop_BLE_browse(mDNSInterfaceID InterfaceID, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags);
-void start_BLE_advertise(ServiceRecordSet * serviceRecordSet, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags);
-void stop_BLE_advertise(const domainname *const typeDomain, DNS_TypeValues type, DNSServiceFlags flags);
+void start_BLE_advertise(const ResourceRecord *const resourceRecord, const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags);
+void stop_BLE_advertise(const domainname *const domain, DNS_TypeValues type, DNSServiceFlags flags);
-void responseReceived(serviceHash_t browseHash, serviceHash_t registeredHash, mDNSEthAddr *ptrToMAC);
+void responseReceived(serviceHash_t peerBloomFilter, mDNSEthAddr *ptrToMAC);
void serviceBLE(void);
// C interfaces to Objective-C beacon management code.
-void updateBLEBeaconAndScan(serviceHash_t browseHash, serviceHash_t registeredHash);
+void updateBLEBeacon(serviceHash_t bloomFilter);
void stopBLEBeacon(void);
+void startBLEScan(void);
+void stopBLEScan(void);
+bool currentlyBeaconing(void);
+
+extern bool suppressBeacons;
+extern bool finalBeacon;
extern mDNS mDNSStorage;
extern mDNSBool EnableBLEBasedDiscovery;
+extern mDNSBool DefaultToBLETriggered;
+
+extern mDNSInterfaceID AWDLInterfaceID;
+#define applyToBLE(interface, flags) ((interface == mDNSInterface_BLE) || (((interface == mDNSInterface_Any) || (interface == AWDLInterfaceID)) && (flags & kDNSServiceFlagsAutoTrigger)))
+
+#ifdef UNIT_TEST
+#pragma mark - Unit test declarations
-// TODO: Add the following to a local D2D.h file
-#include <DeviceToDeviceManager/DeviceToDeviceManager.h>
+// Unit test entry points, which are not used in the mDNSResponder runtime code paths.
+void BLE_unitTest(void);
-// Just define as the current max value for now.
-// TODO: Will need to define in DeviceToDeviceManager.framework if we convert this
-// BLE discovery code to a D2D plugin.
-#define D2DBLETransport D2DTransportMax
+#endif // UNIT_TEST
-#define applyToBLE(interface, flags) ((interface == mDNSInterface_BLE) || ((interface == mDNSInterface_Any) && (flags & kDNSServiceFlagsAutoTrigger)))
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
#endif /* _BLE_H_ */
diff --git a/mDNSResponder/mDNSMacOSX/BonjourEvents.c b/mDNSResponder/mDNSMacOSX/BonjourEvents.c
index e06106e8..9456ab1c 100644
--- a/mDNSResponder/mDNSMacOSX/BonjourEvents.c
+++ b/mDNSResponder/mDNSMacOSX/BonjourEvents.c
@@ -21,7 +21,7 @@
#include <UserEventAgentInterface.h>
#include <stdio.h>
#include <stdlib.h>
-#include <asl.h>
+#include <os/log.h>
#include <xpc/xpc.h>
@@ -344,19 +344,19 @@ static void ManageEventsCallback(UserEventAgentLaunchdAction action, CFNumberRef
return;
}
// Launchd wants us to add a launch event for this token and matching dictionary.
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s calling AddEventToPlugin", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s calling AddEventToPlugin", sPluginIdentifier, __FUNCTION__);
AddEventToPlugin((BonjourUserEventsPlugin*)vContext, token, (CFDictionaryRef)eventMatchDict);
}
else if (action == kUserEventAgentLaunchdRemove)
{
// Launchd wants us to remove the event hook we setup for this token / matching dictionary.
// Note: eventMatchDict can be NULL for Remove.
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s calling RemoveEventToPlugin", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s calling RemoveEventToPlugin", sPluginIdentifier, __FUNCTION__);
RemoveEventFromPlugin((BonjourUserEventsPlugin*)vContext, token);
}
else
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s unknown callback event\n", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s unknown callback event\n", sPluginIdentifier, __FUNCTION__);
}
}
@@ -443,13 +443,13 @@ void AddEventToPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken,
// Add to the correct dictionary.
if (onAdd)
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Adding browser to AddEvents", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: Adding browser to AddEvents", sPluginIdentifier, __FUNCTION__);
AddEventDictionary(eventDictionary, plugin->_onAddEvents, browser);
}
if (onRemove)
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Adding browser to RemoveEvents", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: Adding browser to RemoveEvents", sPluginIdentifier, __FUNCTION__);
AddEventDictionary(eventDictionary, plugin->_onRemoveEvents, browser);
}
@@ -484,26 +484,26 @@ void RemoveEventFromPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdT
if (onAddEvents)
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Calling RemoveEventFromArray for OnAddEvents", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: Calling RemoveEventFromArray for OnAddEvents", sPluginIdentifier, __FUNCTION__);
RemoveEventFromArray(onAddEvents, launchdToken);
// Is the array now empty, clean up
if (CFArrayGetCount(onAddEvents) == 0)
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Removing the browser from AddEvents", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: Removing the browser from AddEvents", sPluginIdentifier, __FUNCTION__);
CFDictionaryRemoveValue(plugin->_onAddEvents, browser);
}
}
if (onRemoveEvents)
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Calling RemoveEventFromArray for OnRemoveEvents", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: Calling RemoveEventFromArray for OnRemoveEvents", sPluginIdentifier, __FUNCTION__);
RemoveEventFromArray(onRemoveEvents, launchdToken);
// Is the array now empty, clean up
if (CFArrayGetCount(onRemoveEvents) == 0)
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Removing the browser from RemoveEvents", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: Removing the browser from RemoveEvents", sPluginIdentifier, __FUNCTION__);
CFDictionaryRemoveValue(plugin->_onRemoveEvents, browser);
}
}
@@ -531,12 +531,12 @@ void RemoveEventFromPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdT
// If no one else is useing our browser, clean up!
if (!othersUsingBrowser)
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Removing browser %p from _browsers", sPluginIdentifier, __FUNCTION__, browser);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: Removing browser %p from _browsers", sPluginIdentifier, __FUNCTION__, browser);
CFDictionaryRemoveValue(plugin->_browsers, browser); // This triggers release and dealloc of the browser
}
else
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Decrementing browsers %p count", sPluginIdentifier, __FUNCTION__, browser);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: Decrementing browsers %p count", sPluginIdentifier, __FUNCTION__, browser);
// Decrement my reference count (it was incremented when it was added to _browsers in CreateBrowser)
NetBrowserInfoRelease(NULL, browser);
}
@@ -575,7 +575,7 @@ NetBrowserInfo* CreateBrowser(BonjourUserEventsPlugin* plugin, CFStringRef type,
if ((CFStringCompare(browserType, type, kCFCompareCaseInsensitive) == kCFCompareEqualTo) &&
(CFStringCompare(browserDomain, domain, kCFCompareCaseInsensitive) == kCFCompareEqualTo))
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: found a duplicate browser\n", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: found a duplicate browser\n", sPluginIdentifier, __FUNCTION__);
browser = browsers[i];
NetBrowserInfoRetain(NULL, browser);
break;
@@ -663,11 +663,11 @@ void AddEventDictionary(CFDictionaryRef eventDict, CFMutableDictionaryRef allEve
{
eventsForBrowser = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
CFDictionarySetValue(allEventsDictionary, key, eventsForBrowser);
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s creating a new array", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s creating a new array", sPluginIdentifier, __FUNCTION__);
}
else
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s Incrementing refcount", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s Incrementing refcount", sPluginIdentifier, __FUNCTION__);
CFRetain(eventsForBrowser);
}
@@ -695,7 +695,7 @@ void RemoveEventFromArray(CFMutableArrayRef array, CFNumberRef launchdToken)
if (CFEqual(token, launchdToken)) // This is the same event?
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s found token", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s found token", sPluginIdentifier, __FUNCTION__);
CFArrayRemoveValueAtIndex(array, i); // Remove the event,
break; // The token should only exist once, so it makes no sense to continue.
}
@@ -704,7 +704,7 @@ void RemoveEventFromArray(CFMutableArrayRef array, CFNumberRef launchdToken)
++i; // If it's not us, advance.
}
}
- if (i == count) asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s did not find token", sPluginIdentifier, __FUNCTION__);
+ if (i == count) os_log_info(OS_LOG_DEFAULT, "%s:%s did not find token", sPluginIdentifier, __FUNCTION__);
}
#pragma mark -
@@ -751,7 +751,7 @@ void ServiceBrowserCallback (DNSServiceRef sdRef,
static int msgCount = 0;
if (msgCount < 1000)
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s Can not create CFString for serviceName %s", sPluginIdentifier, __FUNCTION__, serviceName);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s Can not create CFString for serviceName %s", sPluginIdentifier, __FUNCTION__, serviceName);
msgCount++;
}
return;
@@ -759,12 +759,12 @@ void ServiceBrowserCallback (DNSServiceRef sdRef,
if (flags & kDNSServiceFlagsAdd)
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s calling HandleTemporaryEventsForService Add\n", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s calling HandleTemporaryEventsForService Add\n", sPluginIdentifier, __FUNCTION__);
HandleTemporaryEventsForService(plugin, browser, cfServiceName, plugin->_onAddEvents);
}
else
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s calling HandleTemporaryEventsForService Remove\n", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s calling HandleTemporaryEventsForService Remove\n", sPluginIdentifier, __FUNCTION__);
HandleTemporaryEventsForService(plugin, browser, cfServiceName, plugin->_onRemoveEvents);
}
@@ -804,7 +804,7 @@ void HandleTemporaryEventsForService(BonjourUserEventsPlugin* plugin, NetBrowser
// Signal Event: This is edge trigger. When the action has been taken, it will not
// be remembered anymore.
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s HandleTemporaryEventsForService signal\n", sPluginIdentifier, __FUNCTION__);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s HandleTemporaryEventsForService signal\n", sPluginIdentifier, __FUNCTION__);
CFNumberGetValue(token, kCFNumberLongLongType, &tokenUint64);
xpc_object_t jobRequest = _CFXPCCreateXPCObjectFromCFObject(dict);
@@ -903,7 +903,7 @@ NetBrowserInfo* NetBrowserInfoCreate(CFStringRef serviceType, CFStringRef domain
outObj->refCount = 1;
outObj->browserRef = browserRef;
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: created new object %p", sPluginIdentifier, __FUNCTION__, outObj);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: created new object %p", sPluginIdentifier, __FUNCTION__, outObj);
free(cServiceType);
@@ -927,7 +927,7 @@ const void* NetBrowserInfoRetain(CFAllocatorRef allocator, const void* info)
return NULL;
++obj->refCount;
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Incremented ref count on %p, count %d", sPluginIdentifier, __FUNCTION__, obj->browserRef, (int)obj->refCount);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: Incremented ref count on %p, count %d", sPluginIdentifier, __FUNCTION__, obj->browserRef, (int)obj->refCount);
return obj;
}
@@ -947,14 +947,14 @@ void NetBrowserInfoRelease(CFAllocatorRef allocator, const void* info)
if (obj->refCount == 1)
{
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: DNSServiceRefDeallocate %p", sPluginIdentifier, __FUNCTION__, obj->browserRef);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: DNSServiceRefDeallocate %p", sPluginIdentifier, __FUNCTION__, obj->browserRef);
DNSServiceRefDeallocate(obj->browserRef);
free(obj);
}
else
{
--obj->refCount;
- asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: Decremented ref count on %p, count %d", sPluginIdentifier, __FUNCTION__, obj->browserRef, (int)obj->refCount);
+ os_log_info(OS_LOG_DEFAULT, "%s:%s: Decremented ref count on %p, count %d", sPluginIdentifier, __FUNCTION__, obj->browserRef, (int)obj->refCount);
}
}
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/BonjourTop.xcodeproj/project.pbxproj b/mDNSResponder/mDNSMacOSX/BonjourTop/BonjourTop.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..9f313d5f
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/BonjourTop.xcodeproj/project.pbxproj
@@ -0,0 +1,297 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ F22E4EBF1728621600876C2D /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22E4EBE1728621600876C2D /* main.cpp */; };
+ F22E4EC11728621600876C2D /* BonjourTop.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = F22E4EC01728621600876C2D /* BonjourTop.1 */; };
+ F22E4EDF172863F100876C2D /* bjIPAddr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22E4EDC1728635200876C2D /* bjIPAddr.cpp */; };
+ F22E4EE0172863FB00876C2D /* bjMACAddr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22E4EC91728635200876C2D /* bjMACAddr.cpp */; };
+ F22E4EE1172863FE00876C2D /* bjsocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22E4ED71728635200876C2D /* bjsocket.cpp */; };
+ F22E4EE21728640500876C2D /* bjstring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22E4EDB1728635200876C2D /* bjstring.cpp */; };
+ F22E4EE31728640800876C2D /* bjStringtoStringMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22E4ED01728635200876C2D /* bjStringtoStringMap.cpp */; };
+ F22E4EE41728640C00876C2D /* BonjourTop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22E4EDE1728635200876C2D /* BonjourTop.cpp */; };
+ F22E4EE51728640E00876C2D /* CaptureFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22E4ECA1728635200876C2D /* CaptureFile.cpp */; };
+ F22E4EE61728641100876C2D /* CollectBy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22E4ECC1728635200876C2D /* CollectBy.cpp */; };
+ F22E4EE71728641400876C2D /* DNSFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22E4ED91728635200876C2D /* DNSFrame.cpp */; };
+ F22E4EE81728641800876C2D /* LLRBTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22E4EC81728635200876C2D /* LLRBTree.cpp */; };
+ F22E4EE91728653E00876C2D /* Frame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22E4ED51728635200876C2D /* Frame.cpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ F22E4EB91728621500876C2D /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ F22E4EC11728621600876C2D /* BonjourTop.1 in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ F22E4EBB1728621500876C2D /* bonjourtop */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = bonjourtop; sourceTree = BUILT_PRODUCTS_DIR; };
+ F22E4EBE1728621600876C2D /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+ F22E4EC01728621600876C2D /* BonjourTop.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = BonjourTop.1; sourceTree = "<group>"; };
+ F22E4EC71728635200876C2D /* bjtypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bjtypes.h; sourceTree = "<group>"; };
+ F22E4EC81728635200876C2D /* LLRBTree.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LLRBTree.cpp; sourceTree = "<group>"; };
+ F22E4EC91728635200876C2D /* bjMACAddr.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bjMACAddr.cpp; sourceTree = "<group>"; };
+ F22E4ECA1728635200876C2D /* CaptureFile.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CaptureFile.cpp; sourceTree = "<group>"; };
+ F22E4ECB1728635200876C2D /* CollectBy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CollectBy.h; sourceTree = "<group>"; };
+ F22E4ECC1728635200876C2D /* CollectBy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CollectBy.cpp; sourceTree = "<group>"; };
+ F22E4ECD1728635200876C2D /* bjstring.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bjstring.h; sourceTree = "<group>"; };
+ F22E4ECF1728635200876C2D /* bjMACAddr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bjMACAddr.h; sourceTree = "<group>"; };
+ F22E4ED01728635200876C2D /* bjStringtoStringMap.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bjStringtoStringMap.cpp; sourceTree = "<group>"; };
+ F22E4ED11728635200876C2D /* bjStringtoStringMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bjStringtoStringMap.h; sourceTree = "<group>"; };
+ F22E4ED21728635200876C2D /* LLRBTree.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LLRBTree.h; sourceTree = "<group>"; };
+ F22E4ED31728635200876C2D /* Frame.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Frame.h; sourceTree = "<group>"; };
+ F22E4ED41728635200876C2D /* CaptureFile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CaptureFile.h; sourceTree = "<group>"; };
+ F22E4ED51728635200876C2D /* Frame.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Frame.cpp; sourceTree = "<group>"; };
+ F22E4ED61728635200876C2D /* bjsocket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bjsocket.h; sourceTree = "<group>"; };
+ F22E4ED71728635200876C2D /* bjsocket.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bjsocket.cpp; sourceTree = "<group>"; };
+ F22E4ED81728635200876C2D /* DNSFrame.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DNSFrame.h; sourceTree = "<group>"; };
+ F22E4ED91728635200876C2D /* DNSFrame.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DNSFrame.cpp; sourceTree = "<group>"; };
+ F22E4EDA1728635200876C2D /* BonjourTop.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BonjourTop.h; sourceTree = "<group>"; };
+ F22E4EDB1728635200876C2D /* bjstring.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bjstring.cpp; sourceTree = "<group>"; };
+ F22E4EDC1728635200876C2D /* bjIPAddr.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bjIPAddr.cpp; sourceTree = "<group>"; };
+ F22E4EDD1728635200876C2D /* bjIPAddr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bjIPAddr.h; sourceTree = "<group>"; };
+ F22E4EDE1728635200876C2D /* BonjourTop.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BonjourTop.cpp; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ F22E4EB81728621500876C2D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ F22E4EB21728621500876C2D = {
+ isa = PBXGroup;
+ children = (
+ F22E4EBD1728621500876C2D /* source */,
+ F22E4EBC1728621500876C2D /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ F22E4EBC1728621500876C2D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ F22E4EBB1728621500876C2D /* bonjourtop */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ F22E4EBD1728621500876C2D /* source */ = {
+ isa = PBXGroup;
+ children = (
+ F22E4EDC1728635200876C2D /* bjIPAddr.cpp */,
+ F22E4EDD1728635200876C2D /* bjIPAddr.h */,
+ F22E4EC91728635200876C2D /* bjMACAddr.cpp */,
+ F22E4ECF1728635200876C2D /* bjMACAddr.h */,
+ F22E4ED71728635200876C2D /* bjsocket.cpp */,
+ F22E4ED61728635200876C2D /* bjsocket.h */,
+ F22E4EDB1728635200876C2D /* bjstring.cpp */,
+ F22E4ECD1728635200876C2D /* bjstring.h */,
+ F22E4ED01728635200876C2D /* bjStringtoStringMap.cpp */,
+ F22E4ED11728635200876C2D /* bjStringtoStringMap.h */,
+ F22E4EC71728635200876C2D /* bjtypes.h */,
+ F22E4EC01728621600876C2D /* BonjourTop.1 */,
+ F22E4EDE1728635200876C2D /* BonjourTop.cpp */,
+ F22E4EDA1728635200876C2D /* BonjourTop.h */,
+ F22E4ECA1728635200876C2D /* CaptureFile.cpp */,
+ F22E4ED41728635200876C2D /* CaptureFile.h */,
+ F22E4ECC1728635200876C2D /* CollectBy.cpp */,
+ F22E4ECB1728635200876C2D /* CollectBy.h */,
+ F22E4ED91728635200876C2D /* DNSFrame.cpp */,
+ F22E4ED81728635200876C2D /* DNSFrame.h */,
+ F22E4ED51728635200876C2D /* Frame.cpp */,
+ F22E4ED31728635200876C2D /* Frame.h */,
+ F22E4EC81728635200876C2D /* LLRBTree.cpp */,
+ F22E4ED21728635200876C2D /* LLRBTree.h */,
+ F22E4EBE1728621600876C2D /* main.cpp */,
+ );
+ path = source;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ F22E4EBA1728621500876C2D /* BonjourTop */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F22E4EC41728621600876C2D /* Build configuration list for PBXNativeTarget "BonjourTop" */;
+ buildPhases = (
+ F22E4EB71728621500876C2D /* Sources */,
+ F22E4EB81728621500876C2D /* Frameworks */,
+ F22E4EB91728621500876C2D /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = BonjourTop;
+ productName = BonjourTop;
+ productReference = F22E4EBB1728621500876C2D /* bonjourtop */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ F22E4EB31728621500876C2D /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0500;
+ ORGANIZATIONNAME = Apple;
+ };
+ buildConfigurationList = F22E4EB61728621500876C2D /* Build configuration list for PBXProject "BonjourTop" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = F22E4EB21728621500876C2D;
+ productRefGroup = F22E4EBC1728621500876C2D /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ F22E4EBA1728621500876C2D /* BonjourTop */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ F22E4EB71728621500876C2D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F22E4EE0172863FB00876C2D /* bjMACAddr.cpp in Sources */,
+ F22E4EE61728641100876C2D /* CollectBy.cpp in Sources */,
+ F22E4EE21728640500876C2D /* bjstring.cpp in Sources */,
+ F22E4EE41728640C00876C2D /* BonjourTop.cpp in Sources */,
+ F22E4EBF1728621600876C2D /* main.cpp in Sources */,
+ F22E4EE51728640E00876C2D /* CaptureFile.cpp in Sources */,
+ F22E4EE31728640800876C2D /* bjStringtoStringMap.cpp in Sources */,
+ F22E4EE1172863FE00876C2D /* bjsocket.cpp in Sources */,
+ F22E4EE81728641800876C2D /* LLRBTree.cpp in Sources */,
+ F22E4EE91728653E00876C2D /* Frame.cpp in Sources */,
+ F22E4EDF172863F100876C2D /* bjIPAddr.cpp in Sources */,
+ F22E4EE71728641400876C2D /* DNSFrame.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ F22E4EC21728621600876C2D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ F22E4EC31728621600876C2D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ F22E4EC51728621600876C2D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ "OTHER_LDFLAGS[arch=*]" = "-lncurses";
+ PRODUCT_NAME = bonjourtop;
+ };
+ name = Debug;
+ };
+ F22E4EC61728621600876C2D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ "OTHER_LDFLAGS[arch=*]" = "-lncurses";
+ PRODUCT_NAME = bonjourtop;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ F22E4EB61728621500876C2D /* Build configuration list for PBXProject "BonjourTop" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F22E4EC21728621600876C2D /* Debug */,
+ F22E4EC31728621600876C2D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F22E4EC41728621600876C2D /* Build configuration list for PBXNativeTarget "BonjourTop" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F22E4EC51728621600876C2D /* Debug */,
+ F22E4EC61728621600876C2D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = F22E4EB31728621500876C2D /* Project object */;
+}
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/BonjourTop.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/mDNSResponder/mDNSMacOSX/BonjourTop/BonjourTop.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..919434a6
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/BonjourTop.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:">
+ </FileRef>
+</Workspace>
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/BonjourTop.1 b/mDNSResponder/mDNSMacOSX/BonjourTop/source/BonjourTop.1
new file mode 100644
index 00000000..6836139c
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/BonjourTop.1
@@ -0,0 +1,79 @@
+.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
+.\"See Also:
+.\"man mdoc.samples for a complete listing of options
+.\"man mdoc for the short list of editing options
+.\"/usr/share/misc/mdoc.template
+.Dd 4/24/13 \" DATE
+.Dt BonjourTop 1 \" Program name and manual section number
+.Os Darwin
+.Sh NAME \" Section Header - required - don't modify
+.Nm BonjourTop,
+.\" The following lines are read in generating the apropos(man -k) database. Use only key
+.\" words here as the database is built based on the words here and in the .ND line.
+.Nm Other_name_for_same_program(),
+.Nm Yet another name for the same program.
+.\" Use .Nm macro to designate other names for the documented program.
+.Nd This line parsed for whatis database.
+.Sh SYNOPSIS \" Section Header - required - don't modify
+.Nm
+.Op Fl abcd \" [-abcd]
+.Op Fl a Ar path \" [-a path]
+.Op Ar file \" [file]
+.Op Ar \" [file ...]
+.Ar arg0 \" Underlined argument - use .Ar anywhere to underline
+arg2 ... \" Arguments
+.Sh DESCRIPTION \" Section Header - required - don't modify
+Use the .Nm macro to refer to your program throughout the man page like such:
+.Nm
+Underlining is accomplished with the .Ar macro like this:
+.Ar underlined text .
+.Pp \" Inserts a space
+A list of items with descriptions:
+.Bl -tag -width -indent \" Begins a tagged list
+.It item a \" Each item preceded by .It macro
+Description of item a
+.It item b
+Description of item b
+.El \" Ends the list
+.Pp
+A list of flags and their descriptions:
+.Bl -tag -width -indent \" Differs from above in tag removed
+.It Fl a \"-a flag as a list item
+Description of -a flag
+.It Fl b
+Description of -b flag
+.El \" Ends the list
+.Pp
+.\" .Sh ENVIRONMENT \" May not be needed
+.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
+.\" .It Ev ENV_VAR_1
+.\" Description of ENV_VAR_1
+.\" .It Ev ENV_VAR_2
+.\" Description of ENV_VAR_2
+.\" .El
+.Sh FILES \" File used or created by the topic of the man page
+.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
+.It Pa /usr/share/file_name
+FILE_1 description
+.It Pa /Users/joeuser/Library/really_long_file_name
+FILE_2 description
+.El \" Ends the list
+.\" .Sh DIAGNOSTICS \" May not be needed
+.\" .Bl -diag
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .El
+.Sh SEE ALSO
+.\" List links in ascending order by section, alphabetically within a section.
+.\" Please do not reference files that do not exist without filing a bug report
+.Xr a 1 ,
+.Xr b 1 ,
+.Xr c 1 ,
+.Xr a 2 ,
+.Xr b 2 ,
+.Xr a 3 ,
+.Xr b 3
+.\" .Sh BUGS \" Document known, unremedied bugs
+.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/BonjourTop.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/BonjourTop.cpp
new file mode 100644
index 00000000..ff201c9f
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/BonjourTop.cpp
@@ -0,0 +1,2049 @@
+//
+// BonjourTop.cpp
+// TestTB
+//
+// Created by Terrin Eager on 9/26/12.
+//
+//
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <ncurses.h>
+
+#include "BonjourTop.h"
+#include "DNSFrame.h"
+#include "CaptureFile.h"
+#include "bjsocket.h"
+#include "bjstring.h"
+
+#include <sys/sysctl.h>
+#include <mach/mach.h>
+
+#define SERVICE_IPV4 0
+#define SERVICE_IPV6 1
+#define APP_IPV4 2
+#define APP_IPV6 3
+
+#define TRACE_PLATFORM_UNKNOWN 0
+#define TRACE_PLATFORM_OSX 1
+#define TRACE_PLATFORM_iOS 2
+#define TRACE_PLATFORM_APPLE_TV 3
+#define TRACE_PLATFORM_NON_APPLE_PLATFORM 4
+#define DISCOVERYD_TRACE_PLATFORM_OSX (1 | 0x80)
+#define DISCOVERYD_TRACE_PLATFORM_iOS (2 | 0x80)
+#define DISCOVERYD_TRACE_PLATFORM_APPLE_TV (3 | 0x80)
+#define DISCOVERYD_TRACE_PLATFORM_NON_APPLE_PLATFORM (4 | 0x80)
+
+int CDeviceNode::nCreateCount = 0;
+static integer_t Usage(void);
+
+char CVSFileNameExample[] ="BonjourTop";
+char DeviceNameExample[] ="BonjourTopDevice.csv";
+
+char Service2App[][50] = {
+ // Service_Name, Application_Name, Browse_OS_Type, Register_OS_Type
+ "_device-info._tcp.local.", "Device-Info", "?" , "?",
+ "_rfb._tcp.local.", "Finder", "X" , "?",
+ "_afpovertcp._tcp.local.", "Finder", "?" , "X",
+ "_adisk._tcp.local.", "Finder", "?" , "X",
+ "_odisk._tcp.local.", "Finder", "?" , "X",
+ "_smb._tcp.local.", "Finder", "X" , "X",
+ "_smb2._tcp.local.", "Finder", "X" , "X",
+ "_workstation._tcp.local.", "Finder", "X" , "X",
+ "_kerberos.", "Finder", "X" , "X",
+ "_nfs._tcp.local.", "Finder", "X" , "X",
+ "_ftp._tcp.local.", "Finder", "X" , "X",
+
+ "_appletv._tcp.local.", "AppleTV", "?" , "t",
+ "_appletv-v2._tcp.local.", "AppleTV", "?" , "?",
+ "_appletv-pair._tcp.local.", "AppleTV", "?" , "?",
+
+ "A", "LinkLocal", "?" , "?",
+ "AAAA", "LinkLocal", "?" , "?",
+ "*.ip6.arpa.", "LinkLocal", "?" , "?",
+ "*.arpa.", "LinkLocal", "?" , "?",
+
+ "_airplay._tcp.local.", "AirPlay", "?" , "t",
+ "_airplayTXT", "AirPlay","?" , "t",
+ "_raop._tcp.local.", "AirPlay","?" , "?",
+
+ "_ubd._tcp.local.", "Ubiquity", "?" , "?",
+ "_ubiquity._tcp.local.", "Ubiquity", "?" , "?",
+ "_ubiquityV1._tcp.local.", "Ubiquity", "?" , "?",
+ "_ubiquityV2._tcp.local.", "Ubiquity", "?" , "?",
+
+ " _ipps._tcp.local.", "Printing", "?" , "?",
+ "_ipp._tcp.local.", "Printing", "?" , "?",
+ "_ipps._tcp.local.", "Printing", "?" , "?",
+ "_ipp-tls._tcp.local.", "Printing", "?" , "?",
+ "_printer._tcp.local.", "Printing", "?" , "?",
+ "_scanner._tcp.local.", "Printing", "?" , "?",
+ "_pdl-datastream._tcp.local.", "Printing", "?" , "?",
+ "_fax-ipp._tcp.local.", "Printing", "?" , "?",
+
+ "_apple-mobdev._tcp.local.", "iTunes-WiFiSync","?" , "i",
+ "_daap._tcp.local.", "iTunes", "?" , "?",
+
+ "_sftp-ssh._tcp.local.", "Terminal", "?" , "X",
+ "_ssh._tcp.local.", "Terminal", "?" , "X",
+
+ "_sleep-proxy._udp.local.", "Sleep Proxy", "?" , "?",
+ "_keepalive._dns-sd._udp.local.","Sleep Proxy", "X" , "?",
+ "_services._dns-sd._udp.local.", "Services", "?" , "?",
+ "ANY *.ip6.arpa.", "Sleep Proxy", "?" , "?",
+ "ANY *.arpa.", "Sleep Proxy", "?" , "?",
+
+ "AirPort_presence._tcp.local.", "AirPort", "?" , "?",
+ "_airport._tcp.local.", "AirPort", "?" , "?",
+ "_presence._tcp.local.", "iChat", "X" , "X",
+ "_home-sharing._tcp.local.", "HomeSharing", "?" , "X",
+
+ "_ptp._tcp.local.", "iPhoto", "?" , "X",
+ "_ica-networking2._tcp.local.", "iPhoto", "X" , "X",
+ "_mobileiphoto._udp.local.", "iPhoto", "?" , "?",
+ "_mobileiphoto2._udp.local.", "iPhoto", "?" , "?",
+ "_dpap._tcp.local.", "iPhoto", "?" , "X",
+ "_airdrop._tcp.local.", "AirDrop", "?" , "?",
+ "_http._tcp.local.", "Safari", "X" , "X",
+ "_net-assistant._udp.local.","Apple Remote Desktop","X" , "X",
+ "_servermgr._tcp.local.", "OSX Server", "X" , "X",
+ ""
+};
+
+char DeviceInfo2DeviceOS[][50] = {
+ // deviceModel, deviceType
+ "MacBookAir", "X",
+ "MacBookPro", "X",
+ "Macmini", "X",
+ "iMac", "X",
+ "MacPro", "X",
+ "MacBook", "X",
+ "AAPLJ15", "X",
+ "AAPLJ41", "X",
+ "AAPLJ43", "X",
+ "AAPLJ45", "X",
+ "AAPLJ90", "X",
+ "AAPLJ17", "X",
+ "PowerMac", "X",
+
+
+ "J33AP", "t",
+ "J33iAP", "t",
+ "J71AP", "i",
+ "J72AP", "i",
+ "J75AP", "i",
+ "J85DEV", "i",
+ "K66AP", "t",
+ "N41AP", "i",
+ "N42AP", "i",
+ "N48AP", "i",
+ "N51AP", "i",
+ "N53AP", "i",
+ "N78AP", "i",
+ "P101AP", "i",
+ "P102AP", "i",
+ "P103AP", "i",
+ "P105AP", "i",
+ "P106AP", "i",
+ "P107AP", "i",
+ "AirPort", "b",
+ "TimeCapsule", "b",
+ ""
+};
+
+char Name2DeviceOS[][50] = {
+ // Name contains, osType
+ "iPhone", "i",
+ "phone", "i",
+ "Phone", "i",
+ "iPod", "i",
+ "iPad", "i",
+ "ipad", "i",
+ "Apple-TV", "t",
+ "AppleTV", "t",
+ "MacBook", "X",
+ "macbook", "X",
+ "iMac", "X",
+ "macmini", "X",
+ ""
+};
+
+BJ_UINT64 Hash(const char* pStr);
+BJ_UINT64 Hash2(char* pStr);
+
+
+CSocketStats::CSocketStats()
+{
+ Init();
+
+}
+void CSocketStats::Init()
+{
+ m_nFrameCount = 0;
+
+ m_nQuestionOnlyFrames = 0;
+ m_nAnswerOnlyFrames = 0;
+ m_nQandAFrames = 0;
+
+ m_SampleDay = 0;
+}
+
+void CSocketStats::Clear()
+{
+ Init();
+}
+
+CBonjourTop::CBonjourTop()
+{
+
+ m_bCursers = true;
+ m_pTcpDumpFileName = NULL;
+ m_pExportFileName = CVSFileNameExample;
+ m_DeviceFileName = DeviceNameExample;
+
+ m_nFrameCount = 0;
+ m_nTotalBytes = 0;
+
+ m_StartTime = m_EndTime = time(NULL);
+
+ m_SnapshotSeconds = 0;
+
+ m_MinAnswerCountForTruncatedFrames = 0;
+ m_AvgAnswerCountForTruncatedFrames = 0;
+ m_MaxAnswerCountForTruncatedFrames = 0;
+
+ window_size_changed = false;
+ m_bImportExportDeviceMap = false;
+
+ // loadup application mapping
+ for(int i=0; Service2App[i][0] != 0;)
+ {
+ BJString a(Service2App[i++]);
+
+ m_Service2AppMap.FindwithAddRecord(&a)->value = Service2App[i++];
+ m_Service2osBrowseMap.FindwithAddRecord(&a)->value = Service2App[i++];
+ m_Service2osRegisterMap.FindwithAddRecord(&a)->value = Service2App[i++];
+
+ }
+
+
+ m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_APP;
+ // m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_SERVICE;
+
+ Usage();
+
+}
+
+static int CbClearDataDevice(const void* pNode, const void*)
+{
+ CDeviceNode* pDeviceRecord = (CDeviceNode*)pNode;
+
+ pDeviceRecord->ClearData();
+ return 0;
+}
+
+void CBonjourTop::Reset()
+{
+ m_nFrameCount = 0;
+ m_nTotalBytes = 0;
+
+ m_MinAnswerCountForTruncatedFrames = 0;
+ m_AvgAnswerCountForTruncatedFrames = 0;
+ m_MaxAnswerCountForTruncatedFrames = 0;
+
+ m_StartTime = m_EndTime = time(NULL);
+
+ m_ServicePtrCache.ClearAll();
+ m_ApplPtrCache.ClearAll();
+
+ m_ServicePtrCacheIPv6.ClearAll();
+ m_ApplPtrCacheIPv6.ClearAll();
+
+ // Clear all data in the map
+ m_AppBreakdownIPv4OSX.clear();
+ m_AppBreakdownIPv4iOS.clear();
+ m_AppBreakdownIPv6OSX.clear();
+ m_AppBreakdownIPv6iOS.clear();
+
+ m_ServiceBreakdownIPv4OSX.clear();
+ m_ServiceBreakdownIPv4iOS.clear();
+ m_ServiceBreakdownIPv6OSX.clear();
+ m_ServiceBreakdownIPv6iOS.clear();
+
+ // Clear Socket Status
+ for (int i = 0; i < NUM_SOCKET_STATUS; i++)
+ {
+ m_SocketStatus[i].Clear();
+ }
+
+ for (int i = 0; i < HOURS_IN_DAY; i++)
+ {
+ for (int j = 0; j < MINUTES_IN_HOUR; j++)
+ {
+ m_MinSnapshot[i][j].Clear();
+ }
+ }
+
+ CDeviceNode* pDeviceNode = m_DeviceMap.GetRoot();
+ if (pDeviceNode)
+ {
+ pDeviceNode->CallBack(&CbClearDataDevice,NULL);
+ }
+
+}
+
+void CBonjourTop::SetIPAddr(const char* pStr)
+{
+ m_IPv4Addr.Set(pStr);
+
+}
+
+void CBonjourTop::UpdateRecord(CStringTree& Cache,CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye)
+{
+ BJ_UINT64 nHashValue = 0;
+ char deviceOS = '?';
+
+ nHashValue = Hash(RecordName.GetBuffer());
+ CStringNode* pRecord = Cache.Find(&nHashValue);
+ if (pRecord == NULL)
+ {
+ pRecord = (CStringNode*) Cache.FindwithAddRecord(&nHashValue);
+ strcpy(pRecord->m_Value, RecordName.GetBuffer());
+ }
+
+ if (pRecord == NULL)
+ return;
+ CDeviceNode dummyDevice;
+ CDeviceNode *device = &dummyDevice;
+ CIPDeviceNode *pipNode = m_IPtoNameMap.Find(&m_Frame.m_SourceIPAddress);
+
+ device = (pipNode)? pipNode->pDeviceNode : &dummyDevice;
+ pRecord->m_nBytes += 10 + nBytes;
+ deviceOS = device->GetDeviceOS();
+ device->frameTotal.Increment(m_nFrameCount);
+
+ if (pRecord->m_nLastFrameIndex != m_nFrameCount)
+ {
+ pRecord->m_nLastFrameIndex = m_nFrameCount;
+
+ pRecord->m_nFrames++;
+ if (deviceOS == 't' || deviceOS == 'i')
+ {
+ pRecord->m_nFramesiOS++;
+ }
+ else if (deviceOS == 'X')
+ {
+ pRecord->m_nFramesOSX++;
+ }
+ }
+
+ // Update Total Device Count
+ if (pRecord->m_DeviceTotalTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
+ {
+ pRecord->m_nDeviceTotalCount++;
+ pRecord->m_DeviceTotalTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
+ }
+
+ if (m_Frame.IsQueryFrame())
+ {
+ GetOSTypeFromQuery(pDNSRecord, ServiceName);
+ device->questionFrame.Increment(m_nFrameCount);
+ if (pRecord->m_nLastQueryFrameIndex != m_nFrameCount)
+ {
+ pRecord->m_nLastQueryFrameIndex = m_nFrameCount;
+
+ pRecord->m_nQuestionFrames++;
+
+ if (deviceOS == 't' || deviceOS == 'i')
+ {
+ pRecord->m_nQuestionFramesiOS++;
+ }
+ else if (deviceOS == 'X')
+ {
+ pRecord->m_nQuestionFramesOSX++;
+ }
+
+ if (pRecord->m_DeviceAskingTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
+ {
+ pRecord->m_nDeviceAskingCount++;
+ pRecord->m_DeviceAskingTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
+ }
+ }
+ }
+ else
+ {
+ GetOSTypeFromRegistration(pDNSRecord,ServiceName);
+
+ device->answerFrame.Increment(m_nFrameCount);
+ if (pRecord->m_nLastRespondsFrameIndex != m_nFrameCount)
+ {
+ pRecord->m_nLastRespondsFrameIndex = m_nFrameCount;
+
+ pRecord->m_nAnswerFrames++;
+ if (deviceOS == 't' || deviceOS == 'i')
+ {
+ pRecord->m_nAnswerFramesiOS++;
+ }
+ else if (deviceOS == 'X')
+ {
+ pRecord->m_nAnswerFramesOSX++;
+ }
+
+ if (bGoodbye)
+ {
+ pRecord->m_nGoodbyeFrames++;
+ }
+
+ if (pRecord->m_DeviceAnsweringTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
+ {
+ pRecord->m_nDeviceAnsweringCount++;
+ pRecord->m_DeviceAnsweringTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
+ }
+ }
+ }
+
+ if (m_Frame.IsWakeFrame())
+ {
+ if (pRecord->m_nLastWakeFrameIndex != m_nFrameCount)
+ {
+ pRecord->m_nLastWakeFrameIndex = m_nFrameCount;
+ if (pRecord->m_lastQUFrameTime +1000000ll < m_Frame.GetTime() || pRecord->m_lastQUFrameTime == 0) // last qu frame has been over 1 sec
+ {
+ pRecord->m_nWakeFrames++;
+ pRecord->m_lastQUFrameTime = m_Frame.GetTime();
+ device->QUFrame.Increment(m_nFrameCount);
+ }
+ pRecord->m_lastQUFrameTime = m_Frame.GetTime();
+ }
+ }
+
+
+}
+
+void CBonjourTop::UpdateShortRecordHelper(BJ_UINT32 cacheType, BJ_UINT32 tracePlatform, BJ_UINT32 traceVersion, char deviceOS, CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye)
+{
+ bool isOSX = false;
+ BJString versionNumber = "mDNSResponder-";
+ const int version_max_length = 11; // largest number is 0xffffffff = 4294967295
+ char versionChar[version_max_length];
+
+ CStringShortTree *cache;
+ map<BJString, CStringShortTree*>* myMap;
+
+ if ((tracePlatform | 0x80) == tracePlatform)
+ {
+ versionNumber = "Discoveryd-";
+ }
+
+ snprintf(versionChar, sizeof(versionChar), "%u", 0); // Set versionChar to "0" by default
+ if (tracePlatform == TRACE_PLATFORM_UNKNOWN) // Pre iOS 7 or Pre OSX 10.9
+ {
+ if (deviceOS == 'i' || deviceOS == 't') // Pre iOS 7
+ {
+ isOSX = false;
+ }
+ else if (deviceOS == 'X') // Pre OSX 10.9
+ {
+ isOSX = true;
+ }
+ }
+ else if ((tracePlatform == TRACE_PLATFORM_OSX) || (tracePlatform == DISCOVERYD_TRACE_PLATFORM_OSX)) // >= OSX 10.9
+ {
+ isOSX = true;
+ snprintf(versionChar, sizeof(versionChar), "%u", traceVersion);
+ }
+ else if ((tracePlatform == TRACE_PLATFORM_iOS) || (tracePlatform == DISCOVERYD_TRACE_PLATFORM_iOS)) // >= iOS 7.x
+ {
+ isOSX = false;
+ snprintf(versionChar, sizeof(versionChar), "%u", traceVersion);
+ }
+ else if ((tracePlatform == TRACE_PLATFORM_APPLE_TV) || (tracePlatform == DISCOVERYD_TRACE_PLATFORM_APPLE_TV))
+ {
+ snprintf(versionChar, sizeof(versionChar), "%u", traceVersion);
+ }
+
+ versionNumber += (const char*)versionChar;
+
+ switch (cacheType) {
+ case SERVICE_IPV4:
+ if (isOSX)
+ {
+ myMap = &m_ServiceBreakdownIPv4OSX;
+ }
+ else
+ {
+ myMap = &m_ServiceBreakdownIPv4iOS;
+ }
+ break;
+ case SERVICE_IPV6:
+ if (isOSX)
+ {
+ myMap = &m_ServiceBreakdownIPv6OSX;
+ }
+ else
+ {
+ myMap = &m_ServiceBreakdownIPv6iOS;
+ }
+ break;
+ case APP_IPV4:
+ if (isOSX)
+ {
+ myMap = &m_AppBreakdownIPv4OSX;
+ }
+ else
+ {
+ myMap = &m_AppBreakdownIPv4iOS;
+ }
+ break;
+ case APP_IPV6:
+ if (isOSX)
+ {
+ myMap = &m_AppBreakdownIPv6OSX;
+ }
+ else
+ {
+ myMap = &m_AppBreakdownIPv6iOS;
+ }
+ break;
+
+ default:
+ return;
+ break;
+ }
+
+ if (myMap->find(versionNumber) == myMap->end()) // Version number not found. Create new record
+ {
+ myMap->insert(std::pair<BJString, CStringShortTree*>(versionNumber, new CStringShortTree()));
+ }
+ cache = (*myMap)[versionNumber];
+ UpdateShortRecord(cache, pDNSRecord, RecordName, ServiceName, nBytes, bGoodbye);
+}
+
+void CBonjourTop::UpdateShortRecord(CStringShortTree* Cache,CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye)
+{
+ if (Cache == NULL)
+ {
+ return;
+ }
+
+ BJ_UINT64 nHashValue = 0;
+ char deviceOS = '?';
+
+ nHashValue = Hash(RecordName.GetBuffer());
+ CStringShortNode* pRecord = Cache->Find(&nHashValue);
+ if (pRecord == NULL)
+ {
+ pRecord = (CStringShortNode*) Cache->FindwithAddRecord(&nHashValue);
+ strcpy(pRecord->m_Value, RecordName.GetBuffer());
+ }
+
+ if (pRecord == NULL)
+ {
+ return;
+ }
+
+ CDeviceNode dummyDevice;
+ CDeviceNode *device = &dummyDevice;
+ CIPDeviceNode *pipNode = m_IPtoNameMap.Find(&m_Frame.m_SourceIPAddress);
+
+ device = (pipNode)? pipNode->pDeviceNode : &dummyDevice;
+ pRecord->m_nBytes += 10 + nBytes;
+ deviceOS = device->GetDeviceOS();
+ device->frameTotal.Increment(m_nFrameCount);
+
+ if (pRecord->m_nLastFrameIndex != m_nFrameCount)
+ {
+ pRecord->m_nLastFrameIndex = m_nFrameCount;
+ pRecord->m_nFrames++;
+ }
+
+ // Update Total Device Count
+ if (pRecord->m_DeviceTotalTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
+ {
+ pRecord->m_nDeviceTotalCount++;
+ pRecord->m_DeviceTotalTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
+ }
+
+ if (m_Frame.IsQueryFrame())
+ {
+ GetOSTypeFromQuery(pDNSRecord, ServiceName);
+ device->questionFrame.Increment(m_nFrameCount);
+ if (pRecord->m_nLastQueryFrameIndex != m_nFrameCount)
+ {
+ pRecord->m_nLastQueryFrameIndex = m_nFrameCount;
+
+ pRecord->m_nQuestionFrames++;
+
+ if (pRecord->m_DeviceAskingTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
+ {
+ pRecord->m_nDeviceAskingCount++;
+ pRecord->m_DeviceAskingTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
+ }
+
+ }
+ }
+ else
+ {
+ GetOSTypeFromRegistration(pDNSRecord,ServiceName);
+
+ device->answerFrame.Increment(m_nFrameCount);
+ if (pRecord->m_nLastRespondsFrameIndex != m_nFrameCount)
+ {
+ pRecord->m_nLastRespondsFrameIndex = m_nFrameCount;
+
+ pRecord->m_nAnswerFrames++;
+
+ if (bGoodbye)
+ {
+ pRecord->m_nGoodbyeFrames++;
+ }
+
+ if (pRecord->m_DeviceAnsweringTree.Find(&m_Frame.m_SourceIPAddress) == NULL)
+ {
+ pRecord->m_nDeviceAnsweringCount++;
+ pRecord->m_DeviceAnsweringTree.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
+ }
+ }
+ }
+
+ if (m_Frame.IsWakeFrame())
+ {
+ if (pRecord->m_nLastWakeFrameIndex != m_nFrameCount)
+ {
+ pRecord->m_nLastWakeFrameIndex = m_nFrameCount;
+ if (pRecord->m_lastQUFrameTime +1000000ll < m_Frame.GetTime() || pRecord->m_lastQUFrameTime == 0) // last qu frame has been over 1 sec
+ {
+ pRecord->m_nWakeFrames++;
+ pRecord->m_lastQUFrameTime = m_Frame.GetTime();
+ device->QUFrame.Increment(m_nFrameCount);
+ }
+ pRecord->m_lastQUFrameTime = m_Frame.GetTime();
+ }
+ }
+
+
+}
+
+void CBonjourTop::GetOSTypeFromQuery(CDNSRecord *pDNSRecord,BJString& ServiceName)
+{
+ if (pDNSRecord->m_RecType == DNS_TYPE_PTR)
+ {
+ StringMapNode* pStringNode = m_Service2osBrowseMap.Find(&ServiceName);
+ if (pStringNode && *pStringNode->value.GetBuffer() != '?')
+ {
+ CIPDeviceNode *ipNode = m_IPtoNameMap.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
+ if (ipNode->pDeviceNode)
+ {
+ StringMapNode* pStringNode_temp = m_Service2osBrowseMap.Find(&ServiceName);
+ ipNode->pDeviceNode->SetDeviceOS(*pStringNode_temp->value.GetBuffer(),ServiceName.GetBuffer());
+ }
+ }
+ }
+}
+
+void CBonjourTop::GetOSTypeFromRegistration(CDNSRecord *pDNSRecord,BJString& ServiceName)
+{
+ CDeviceNode* deviceNode = NULL;
+ BJString sDeviceName;
+
+ if (pDNSRecord->m_RecType == DNS_TYPE_PTR)
+ {
+ BJString sInstanceName;
+ pDNSRecord->GetRdata(sInstanceName,0,99);
+ CDNSRecord* pSRVRecord = m_Frame.FindAdditionRecord(sInstanceName, DNS_TYPE_SRV);
+ if (pSRVRecord)
+ {
+ pSRVRecord->GetRdata(sDeviceName,0,1);
+ }
+ else
+ {
+ sDeviceName = sInstanceName;
+ }
+ deviceNode = m_DeviceMap.Find(&sDeviceName);
+ }
+
+ // Name guess
+ if (Name2OSType(sDeviceName,deviceNode))
+ return;
+
+ StringMapNode* pStringNode = m_Service2osRegisterMap.Find(&ServiceName);
+
+ if (pStringNode == NULL || *pStringNode->value.GetBuffer() == '?')
+ return;
+
+
+
+ if (sDeviceName.GetLength() > 0)
+ {
+ // update global device table with os type
+ if (deviceNode)
+ {
+ deviceNode->SetDeviceOS(*pStringNode->value.GetBuffer(),ServiceName.GetBuffer());
+ }
+ }
+}
+bool CBonjourTop::Name2OSType(BJString name,CDeviceNode* device)
+{
+ if (device == NULL)
+ return false;
+ // try to set device type from common names
+ for (int i=0; Name2DeviceOS[i][0] != 0; i +=2)
+ {
+ if (name.Contains(Name2DeviceOS[i]))
+ {
+ device->SetDeviceOS(Name2DeviceOS[i+1][0], "Name Mapping");
+ return true;
+ }
+ }
+ return false;
+}
+void CBonjourTop::ProcessFrame(BJ_UINT8* pBuffer,BJ_INT32 nLength,BJ_UINT64 nFrameTime)
+{
+
+ m_Frame.ParseDNSFrame(pBuffer, nLength, nFrameTime);
+
+ if (m_Collection.IsValid())
+ {
+ // setup static collectby
+ CollectByPacketCount::nFrameIndex = m_nFrameCount;
+ CollectBySameSubnetDiffSubnet::bSameSubnet = m_Frame.m_SourceIPAddress.IsIPv6()? true: m_IPv4Addr.IsSameSubNet(&m_Frame.m_SourceIPAddress);
+ m_Collection.ProcessFrame(&m_Frame);
+ return;
+ }
+
+ if (m_Frame.IsTruncatedFrame())
+ {
+ if (m_Frame.GetAnswerCount() > 0)
+ {
+ if (m_AvgAnswerCountForTruncatedFrames)
+ {
+ m_AvgAnswerCountForTruncatedFrames += m_Frame.GetAnswerCount();
+ m_AvgAnswerCountForTruncatedFrames /=2;
+ }
+ else
+ m_AvgAnswerCountForTruncatedFrames += m_Frame.GetAnswerCount();
+
+ if (m_MinAnswerCountForTruncatedFrames > m_Frame.GetAnswerCount() || m_MinAnswerCountForTruncatedFrames == 0)
+ m_MinAnswerCountForTruncatedFrames = m_Frame.GetAnswerCount();
+ if (m_MaxAnswerCountForTruncatedFrames < m_Frame.GetAnswerCount())
+ m_MaxAnswerCountForTruncatedFrames = m_Frame.GetAnswerCount();
+
+ }
+ }
+
+ // find min snapshot bucket
+ time_t now = time(NULL);
+ struct tm* timeStruct = localtime(&now);
+ if (m_MinSnapshot[timeStruct->tm_hour][timeStruct->tm_min].m_SampleDay != timeStruct->tm_mday)
+ {
+ //Reset Snapshot 24 hour wrap around
+ m_MinSnapshot[timeStruct->tm_hour][timeStruct->tm_min].Init();
+ m_MinSnapshot[timeStruct->tm_hour][timeStruct->tm_min].m_SampleDay = timeStruct->tm_mday;
+
+ }
+ m_MinSnapshot[timeStruct->tm_hour][timeStruct->tm_min].m_nFrameCount++;
+
+ if (m_Frame.GetQuestionCount() == 0 && m_Frame.GetAnswerCount() > 0)
+ m_SocketStatus[0].m_nAnswerOnlyFrames++;
+ else if (m_Frame.GetQuestionCount() > 0 && m_Frame.GetAnswerCount() == 0)
+ m_SocketStatus[0].m_nQuestionOnlyFrames++;
+ else
+ m_SocketStatus[0].m_nQandAFrames++;
+
+ BJString InstanceName;
+ BJString RecordName;
+ BJString ApplRecordName;
+
+ /// first get the name to address
+ for (int dnsItemsIndex =m_Frame.GetQuestionCount(); dnsItemsIndex < m_Frame.GetMaxRecords();dnsItemsIndex++)
+ {
+ CDNSRecord* pDNSRecord = m_Frame.GetDnsRecord(dnsItemsIndex);
+ if (pDNSRecord == NULL)
+ continue;
+
+ if (pDNSRecord->m_RecType == DNS_TYPE_A)
+ {
+ BJString sName;
+ pDNSRecord->GetDnsRecordName(sName, 0, 1);
+ BJIPAddr ip;
+ ip.Setv4Raw(pDNSRecord->GetStartofRdata());
+
+ CDeviceNode* device = m_DeviceMap.FindwithAddRecord(&sName);
+ device->ipAddressv4 = ip;
+
+ // create ip to name mapping
+ CIPDeviceNode* pipNode = m_IPtoNameMap.FindwithAddRecord(&ip);
+
+ if (pipNode->pDeviceNode && pipNode->pDeviceNode->bIPName && pipNode->pDeviceNode->m_Key != device->m_Key)
+ {
+ pipNode->pDeviceNode->bDuplicate = true;
+ device->MergeData(pipNode->pDeviceNode);
+ pipNode->pDeviceNode->ClearData();
+ // remap IPv6
+ if (!pipNode->pDeviceNode->ipAddressv6.IsEmpty())
+ {
+ CIPDeviceNode* ipv6Node = m_IPtoNameMap.Find(&pipNode->pDeviceNode->ipAddressv6);
+ if (ipv6Node)
+ ipv6Node->pDeviceNode = device;
+ }
+ }
+
+ pipNode->pDeviceNode = device;
+ Name2OSType(sName,device);
+ }
+
+ if (pDNSRecord->m_RecType == DNS_TYPE_AAAA)
+ {
+ BJString sName;
+ pDNSRecord->GetDnsRecordName(sName, 0, 1);
+ BJIPAddr ip;
+ ip.Setv6Raw(pDNSRecord->GetStartofRdata());
+
+ if (ip.IsIPv6LinkLocal())
+ {
+ CDeviceNode* device = m_DeviceMap.FindwithAddRecord(&sName);
+ device->ipAddressv6 = ip;
+
+ // create ip to name mapping
+ CIPDeviceNode* pipNode = m_IPtoNameMap.FindwithAddRecord(&ip);
+
+ if (pipNode->pDeviceNode && pipNode->pDeviceNode->bIPName && pipNode->pDeviceNode->m_Key != device->m_Key)
+ {
+ pipNode->pDeviceNode->bDuplicate = true;
+ device->MergeData(pipNode->pDeviceNode);
+ pipNode->pDeviceNode->ClearData();
+ // remap IPv4
+ if (!pipNode->pDeviceNode->ipAddressv4.IsEmpty())
+ {
+ CIPDeviceNode* ipv4Node = m_IPtoNameMap.Find(&pipNode->pDeviceNode->ipAddressv4);
+ if (ipv4Node)
+ ipv4Node->pDeviceNode = device;
+ }
+ }
+
+ pipNode->pDeviceNode = device;
+ Name2OSType(sName,device);
+ }
+ }
+ if (pDNSRecord->m_RecType == DNS_TYPE_SRV)
+ { // Save SVR to Target
+ BJString sName;
+ pDNSRecord->GetDnsRecordName(sName, 0, 1);
+ StringMapNode *node = SVRtoDeviceName.FindwithAddRecord(&sName);
+ pDNSRecord->GetRdata(node->value, 0, 1);
+ }
+ }
+
+ CIPDeviceNode* pipNode = m_IPtoNameMap.FindwithAddRecord(&m_Frame.m_SourceIPAddress);
+ CDeviceNode* device = pipNode->pDeviceNode;
+ if (device == NULL)
+ {
+ // find the device by mac address
+ CMACAddrDeviceNode *macDevice = m_MACtoDevice.FindwithAddRecord(&m_Frame.m_SourceMACAddress);
+ device = macDevice->device;
+ if (device == NULL)
+ {
+ // auto create a device record
+ BJString name = m_Frame.m_SourceIPAddress.GetString();
+ device = m_DeviceMap.FindwithAddRecord(&name);
+ device->bIPName = true;
+ macDevice->device = device;
+ }
+
+ if (m_Frame.m_SourceIPAddress.IsIPv4())
+ device->ipAddressv4 = m_Frame.m_SourceIPAddress;
+ else
+ device->ipAddressv6 = m_Frame.m_SourceIPAddress;
+ if (device->macAddress.IsEmpty())
+ device->macAddress = m_Frame.m_SourceMACAddress;
+
+ pipNode->pDeviceNode = device;
+ }
+ device->bHasFrames = true;
+ // update mac address
+ if (m_Frame.IsQueryFrame() || device->GetDeviceOS() == 'i' ) // iOS don't use BSP so we can use SourceIP
+ {
+ if (m_Frame.m_SourceIPAddress.IsIPv4())
+ device->ipAddressv4 = m_Frame.m_SourceIPAddress;
+ if (m_Frame.m_SourceIPAddress.IsIPv6())
+ device->ipAddressv6 =m_Frame.m_SourceIPAddress;
+ device->macAddress = m_Frame.m_SourceMACAddress;
+ }
+
+ BJ_UINT8 traceplatform = TRACE_PLATFORM_UNKNOWN;
+ BJ_UINT32 traceversion = 0;
+ BJMACAddr traceMac;
+ if (device /*&& device->GetDeviceOS() == '?' */&& m_Frame.GetTracingInfo(traceplatform, traceversion, traceMac))
+ {
+ // printf("Tracing Data found platform=%d traceversion=%d\n",traceplatform,traceversion);
+ char platformMap[]= "?Xitw";
+ device->SetDeviceOS((traceplatform < 5) ? platformMap[traceplatform] : '?', "EDNS0 Trace");
+ if ((traceplatform == TRACE_PLATFORM_OSX) || (traceplatform == DISCOVERYD_TRACE_PLATFORM_OSX))
+ {
+ device->bOSXWithEDNSField = true;
+ }
+ else if ((traceplatform == TRACE_PLATFORM_iOS) || (traceplatform == DISCOVERYD_TRACE_PLATFORM_iOS))
+ {
+ device->biOSWithEDNSField = true;
+ }
+ }
+
+ for (int dnsItemsIndex =0; dnsItemsIndex < m_Frame.GetQuestionCount()+m_Frame.GetAnswerCount();dnsItemsIndex++)
+ {
+ RecordName = "";
+ ApplRecordName = "";
+ InstanceName = "";
+ // printf("Name = %s\n", GetDnsRecordName(&Frame,dnsItemsIndex,tempBuffer,sizeof(tempBuffer),0));
+
+ CDNSRecord* pDNSRecord = m_Frame.GetDnsRecord(dnsItemsIndex);
+ if (pDNSRecord == NULL)
+ continue;
+
+ pDNSRecord->GetDnsRecordName(RecordName,0,99);
+ InstanceName = RecordName;
+
+ if (RecordName.Contains("_kerberos."))
+ {
+ RecordName = "_kerberos.";
+ }
+ else
+ pDNSRecord->GetDnsRecordName(RecordName, (pDNSRecord->m_RecType == DNS_TYPE_PTR)?0:1,99);
+
+ if (pDNSRecord->m_RecType == DNS_TYPE_PTR)
+ {
+ if (RecordName.Contains(".ip6.arpa."))
+ RecordName = "*.ip6.arpa.";
+ else if (RecordName.Contains(".arpa."))
+ RecordName = "*.arpa.";
+ }
+ if (pDNSRecord->m_RecType == DNS_TYPE_A)
+ RecordName = "A";
+ if (pDNSRecord->m_RecType == DNS_TYPE_AAAA)
+ RecordName = "AAAA";
+ if (pDNSRecord->m_RecType == 255)
+ {
+ if (RecordName.Contains(".ip6.arpa."))
+ RecordName = "ANY *.ip6.arpa.";
+ else if (RecordName.Contains(".arpa."))
+ RecordName = "ANY *.arpa.";
+ else
+ RecordName = "Any";
+ }
+ if (RecordName.Contains("_sub."))
+ {
+ pDNSRecord->GetDnsRecordName(RecordName,2,99); /// skip first label and _sub. label
+ }
+
+ BJ_UINT32 nBytes = pDNSRecord->m_nNameLength + pDNSRecord->m_nRdataLen;
+
+ m_nTotalBytes += 10 + nBytes;
+
+ if (m_Frame.m_SourceIPAddress.IsIPv4())
+ {
+ UpdateRecord(m_ServicePtrCache,pDNSRecord,RecordName,RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
+ UpdateShortRecordHelper(SERVICE_IPV4, traceplatform, traceversion, device->GetDeviceOS(), pDNSRecord, RecordName, RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
+ }
+ else
+ {
+ UpdateRecord(m_ServicePtrCacheIPv6,pDNSRecord,RecordName,RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
+ UpdateShortRecordHelper(SERVICE_IPV6, traceplatform, traceversion, device->GetDeviceOS(), pDNSRecord, RecordName, RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
+ }
+
+ // Add application to cache
+ if (RecordName.GetLength() != 0)
+ {
+
+ ApplRecordName = RecordName;
+ StringMapNode* pNode;
+ pNode = m_Service2AppMap.Find(&ApplRecordName);
+ if (pNode && ApplRecordName.GetBuffer() != NULL)
+ {
+ ApplRecordName = pNode->value.GetBuffer();
+ if ( ApplRecordName == "Device-Info")
+ {
+ // find device record
+ BJString svrName;
+ pDNSRecord->GetDnsRecordName(svrName, 0, 1);
+ StringMapNode *nodeName = SVRtoDeviceName.Find(&svrName);
+
+ CDeviceNode* pDeviceNode = nodeName ? m_DeviceMap.Find(&nodeName->value) : NULL;
+
+ if (pDeviceNode)
+ {
+ BJString DeviceInfo;
+ DeviceInfo.Set((char*)pDNSRecord->GetStartofRdata(),MIN(pDNSRecord->m_nRdataLen,50));
+ char osType = '?';
+
+ for (int i=0; DeviceInfo2DeviceOS[i][0] != 0; i+=2)
+ {
+ if (DeviceInfo.Contains(DeviceInfo2DeviceOS[i]))
+ {
+ osType = *DeviceInfo2DeviceOS[i+1];
+ if (pDeviceNode->GetDeviceOS() != *DeviceInfo2DeviceOS[i])
+ {
+ pDeviceNode->SetDeviceOS(osType,"_device-info._tcp.local.");
+ pDeviceNode->SetModel(DeviceInfo2DeviceOS[i]);
+ }
+ break;
+ }
+ }
+
+
+ if (osType == 'X' || (pDeviceNode && pDeviceNode->GetDeviceOS() == 'X'))
+ ApplRecordName = "Finder";
+ if (osType == 't' || (pDeviceNode && pDeviceNode->GetDeviceOS() == 't'))
+ ApplRecordName = "AirPlay";
+
+ if (pDeviceNode && pDeviceNode->GetDeviceOS() == '?' && pDNSRecord->m_nRdataLen > 0)
+ {
+ BJString DeviceInfo_temp;
+ DeviceInfo_temp.Set((char*)pDNSRecord->GetStartofRdata(),MIN(pDNSRecord->m_nRdataLen,25));
+ }
+ }
+ }
+ }
+ else
+ {
+ ApplRecordName = "Other";
+ }
+
+ if (m_Frame.m_SourceIPAddress.IsIPv4())
+ {
+ UpdateRecord(m_ApplPtrCache,pDNSRecord,ApplRecordName,RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
+ UpdateShortRecordHelper(APP_IPV4, traceplatform, traceversion, device->GetDeviceOS(), pDNSRecord, ApplRecordName, RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
+
+ }
+ else
+ {
+ UpdateRecord(m_ApplPtrCacheIPv6,pDNSRecord,ApplRecordName,RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
+ UpdateShortRecordHelper(APP_IPV6, traceplatform, traceversion, device->GetDeviceOS(), pDNSRecord, ApplRecordName, RecordName, nBytes, (pDNSRecord->m_nTTL == 0));
+ }
+
+ }
+
+ }
+}
+
+
+class CSortOptions
+{
+
+public:
+ CStringTree m_SortedCache;
+ int m_nSortCol;
+
+};
+static int CbPrintResults(const void* pNode, const void* pParam)
+{
+ CStringNode* pRecord = (CStringNode*)pNode;
+ CSortOptions* pSortedOption = (CSortOptions*)pParam;
+
+ CStringNode* pNewRecord;
+
+ BJ_UINT64 SortKey =0;
+ switch (pSortedOption->m_nSortCol) {
+ case 0:
+ SortKey = Hash2(pRecord->m_Value); // cheat the sort to the first 8 char
+ break;
+ case 1:
+ SortKey = pRecord->m_nBytes;
+ break;
+ case 2:
+ SortKey = pRecord->m_nFrames;
+ break;
+ case 3:
+ SortKey = pRecord->m_nQuestionFrames;
+ break;
+ case 4:
+ SortKey = pRecord->m_nAnswerFrames;
+ break;
+ default:
+ break;
+ }
+
+
+ pNewRecord = pSortedOption->m_SortedCache.AddRecord(&SortKey);
+
+ if (pNewRecord)
+ {
+ pNewRecord->CopyNode(pRecord);
+
+ }
+
+ return 0;
+}
+
+#if 0 // Not used
+static int CbPrintUnknownDevice(const void* pNode, const void*)
+{
+ CDeviceNode* pDeviceRecord = (CDeviceNode*)pNode;
+
+ if (pDeviceRecord->GetDeviceOS() != '?')
+ return 0;
+
+ // printf("%s %s\n",pDeviceRecord->m_Key.GetBuffer(), pDeviceRecord->macAddress.GetString());
+ return 0;
+
+}
+#endif
+
+static int CbBuildMacMap(const void* pNode, const void* pParam)
+{
+ CDeviceNode* pDeviceNode = (CDeviceNode*)pNode;
+ CMACAddrTree* pMacMap = (CMACAddrTree*)pParam;
+
+
+ BJMACAddr vendorMac;
+ vendorMac.CopyVendor(pDeviceNode->macAddress);
+ if (vendorMac.IsEmpty())
+ return 0;
+
+
+
+ if (pDeviceNode->GetDeviceOS() == '?')
+ {
+ // try to set device type from MAC address
+ CMACAddrNode* pMacRecord = pMacMap->Find(&vendorMac);
+ if (pMacRecord != NULL && pDeviceNode->GetDeviceOS() == '?')
+ {
+ pDeviceNode->SetDeviceOS(pMacRecord->deviceOS, "MAC Mapping");
+// printf("update device %s %c\n",vendorMac.GetStringVendor(),pMacRecord->deviceOS);
+ }
+
+ if (pDeviceNode->GetDeviceOS() == '?')
+ return 0;
+ }
+
+
+ CMACAddrNode* pMacRecord = pMacMap->Find(&vendorMac);
+ if (pMacRecord == NULL)
+ {
+ pMacRecord = pMacMap->FindwithAddRecord(&vendorMac);
+ pMacRecord->deviceOS = pDeviceNode->GetDeviceOS();
+ pMacRecord->model = pDeviceNode->model;
+ pMacRecord->method = pDeviceNode->settingService;
+ }
+ else
+ {
+ // Check mapping
+ /// if (pMacRecord && pMacRecord->deviceOS != pDeviceNode->GetDeviceOS())
+ // printf("Mac Mapping Bad deviceOS %c != %c %s %s %s\n", pMacRecord->deviceOS, pDeviceNode->GetDeviceOS(),pMacRecord->method.GetBuffer(), pDeviceNode->settingService.GetBuffer(),vendorMac.GetStringVendor());
+ // if (pMacRecord && !(pMacRecord->model == pDeviceNode->model) && pMacRecord->model.GetLength() > 0 && pDeviceNode->model.GetLength() > 0)
+ // printf("Mac Mapping Bad model %s != %s\n", pMacRecord->model.GetBuffer(), pDeviceNode->model.GetBuffer());
+
+ }
+ return 0;
+
+}
+
+CStringNode* CBonjourTop::GetCurrentDisplayRoot(BJString &sTitle)
+{
+ CStringNode* pRecord = NULL;
+
+ switch(m_CurrentDisplay)
+ {
+ case BJ_DISPLAY_APP:
+ pRecord = m_ApplPtrCache.GetRoot();
+ sTitle = "Application (IPv4)";
+ break;
+ case BJ_DISPLAY_APPv6:
+ pRecord = m_ApplPtrCacheIPv6.GetRoot();
+ sTitle = "Application (IPv6)";
+ break;
+ case BJ_DISPLAY_SERVICE:
+ pRecord = m_ServicePtrCache.GetRoot();
+ sTitle = "Services (IPv4)";
+ break;
+ case BJ_DISPLAY_SERVICEv6:
+ pRecord = m_ServicePtrCacheIPv6.GetRoot();
+ sTitle = "Services (IPv6)";
+ break;
+ case BJ_DISPLAY_24_MIN:
+ printf("Error");
+ break;
+ }
+ return pRecord;
+}
+void CBonjourTop::UpdateOSCounts()
+{
+
+
+ CDeviceNode* pDeviceNode = m_DeviceMap.GetRoot();
+ if (pDeviceNode)
+ {
+ pDeviceNode->CallBack(&CbBuildMacMap,&m_MacMap);
+ // pDeviceNode->CallBack(&CbPrintUnknownDevice,NULL);
+ }
+
+
+ // Update Application Caches
+ CStringNode* pCacheRoot = m_ApplPtrCache.GetRoot();
+
+ if (pCacheRoot)
+ {
+ pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
+ }
+ pCacheRoot = m_ApplPtrCacheIPv6.GetRoot();
+
+ if (pCacheRoot)
+ {
+ pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
+ }
+
+ // Update Service caches
+ pCacheRoot = m_ServicePtrCache.GetRoot();
+
+ if (pCacheRoot)
+ {
+ pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
+ }
+ pCacheRoot = m_ServicePtrCacheIPv6.GetRoot();
+
+ if (pCacheRoot)
+ {
+ pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
+ }
+
+
+}
+void CBonjourTop::PrintResults(int nSortCol, bool bSortAsc)
+{
+
+ BJString sTitle;
+ GetCurrentDisplayRoot(sTitle);
+ device_count devCount;
+ BJString sTableTitle;
+
+ UpdateOSCounts();
+
+ /////
+ BJ_UINT64 nRate = 0;
+ BJ_UINT64 nElapsedTime = m_EndTime-m_StartTime;
+ if (nElapsedTime > 0)
+ {
+ nRate = (m_nFrameCount *3600) /nElapsedTime;
+ }
+ if (m_bCursers)
+ {
+ resizeterm(0,0);
+ clear();
+
+ printw("While running the follow keys may be used:\n");
+ printw("[p = sort by Packets (default)], [b = sort by Bytes], [n = sort by Name]\n");
+ printw("[a = Display Application Names (default)], [s = Display Services Names], [t = Display 24 hour packet per min]\n");
+ printw("[o = flip sort order], [e = export to BonjourTop.csv], [q = quit]\n\n");
+
+ printw("Total Packets: %llu, Total Bytes: %llu, Elapse Time: %lld sec, Rate: %llu packet/hr\n",m_nFrameCount,m_nTotalBytes,nElapsedTime,nRate);
+ printw("IPv4 multicast: %llu, IPv6 multicast: %llu, IPv4 Unicast: %lld, IPv6 Unicast: %llu\n",m_SocketStatus[0].m_nFrameCount,m_SocketStatus[1].m_nFrameCount,m_SocketStatus[2].m_nFrameCount,m_SocketStatus[3].m_nFrameCount);
+ printw("IPv4 Wrong subnet: %llu, IPv6 Wrong subnet: %llu\n",m_SocketStatus[4].m_nFrameCount,m_SocketStatus[5].m_nFrameCount);
+ printw("QuestionOnly Packets: %llu, AnswerOnly Packets: %llu, Q&A Packets %llu\n",m_SocketStatus[0].m_nQuestionOnlyFrames,m_SocketStatus[0].m_nAnswerOnlyFrames,m_SocketStatus[0].m_nQandAFrames);
+ printw("AnswerCount for truncated frames(min,avg,max): %llu,%llu,%llu\n\n",m_MinAnswerCountForTruncatedFrames,m_AvgAnswerCountForTruncatedFrames,m_MaxAnswerCountForTruncatedFrames);
+
+ bzero(&devCount, sizeof(devCount));
+ m_DeviceMap.GetDeviceOSTypes(m_DeviceMap.GetRoot(),NULL, devCount);
+ printw("Total Devices: %llu, iOS Devices: %llu(>= iOS7: %llu), OSX Devices %llu(>= OSX 10.9: %llu)\n",devCount.iOS+devCount.OSX+devCount.unknownOS,devCount.iOS, devCount.iOSWithEDNSField, devCount.OSX,devCount.OSXWithEDNSField);
+ }
+ else
+ {
+ printf("\nTotal Packets: %llu, Total Bytes: %llu, Elapse Time: %lld sec, Rate: %llu packet/hr\n",m_nFrameCount,m_nTotalBytes,nElapsedTime,nRate);
+ printf("IPv4 multicast: %llu, IPv6 multicast: %llu, IPv4 Unicast: %lld, IPv6 Unicast: %llu\n",m_SocketStatus[0].m_nFrameCount,m_SocketStatus[1].m_nFrameCount,m_SocketStatus[2].m_nFrameCount,m_SocketStatus[3].m_nFrameCount);
+ printf("IPv4 Wrong subnet: %llu, IPv6 Wrong subnet: %llu\n",m_SocketStatus[4].m_nFrameCount,m_SocketStatus[5].m_nFrameCount);
+ printf("QuestionOnly Packets: %llu, AnswerOnly Packets: %llu, Q&A Packets %llu\n",m_SocketStatus[0].m_nQuestionOnlyFrames,m_SocketStatus[0].m_nAnswerOnlyFrames,m_SocketStatus[0].m_nQandAFrames);
+
+ bzero(&devCount, sizeof(devCount));
+ m_DeviceMap.GetDeviceOSTypes(m_DeviceMap.GetRoot(),NULL, devCount);
+
+ printf("Total Devices: %llu, iOS Devices: %llu(>= iOS7: %llu), OSX Devices %llu(>= OSX 10.9: %llu), unknown Devices %llu\n",devCount.iOS+devCount.OSX+devCount.unknownOS,devCount.iOS, devCount.iOSWithEDNSField,devCount.OSX,devCount.OSXWithEDNSField,devCount.unknownOS);
+ printf("AnswerCount for truncated frames(min,avg,max): %llu,%llu,%llu\n\n",m_MinAnswerCountForTruncatedFrames,m_AvgAnswerCountForTruncatedFrames,m_MaxAnswerCountForTruncatedFrames);
+ }
+ PrintDetailResults(nSortCol, bSortAsc);
+ if (m_bCursers)
+ refresh();
+}
+void CBonjourTop::PrintDetailResults(int nSortCol, bool bSortAsc)
+{
+ BJString sTitle;
+ CStringNode* pCacheRoot = GetCurrentDisplayRoot(sTitle);
+
+ if (m_bCursers)
+ {
+ if(m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_24_MIN)
+ {
+ printw(" ");
+ for(int i=0;i<24;i++)
+ printw(" %02d ",i);
+ printw("\n");
+ }
+ else
+ {
+ printw("\n%s\n",sTitle.GetBuffer());
+ printw(" %- 30s %10s %10s%24s%24s%24s%24s%24s\n","","","Total","Question","Answer","Asking","Answering", "Total");
+ printw(" %- 30s %10s%24s%24s%24s %23s%24s%24s %11s %10s\n","Name","Bytes","Packets( iOS/ OSX)","Packets( iOS/ OSX)","Packets( iOS/ OSX)","Devices( iOS/ OSX)","Devices( iOS/ OSX)","Devices( iOS/ OSX)", "QU Bit","Goodbye");
+ }
+ }
+ else
+ {
+ if(m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_24_MIN)
+ {
+
+ }
+ else
+ {
+ printf("\n%s\n",sTitle.GetBuffer());
+ printf(" %-30s %10s %10s%24s%24s%24s%24s%24s\n","","","Total","Question","Answer","Asking","Answering", "Total");
+ printf(" %-30s %10s%24s%24s%24s %23s%24s%24s %11s %10s\n","Name","Bytes","Packets( iOS/ OSX)","Packets( iOS/ OSX)","Packets( iOS/ OSX)","Devices( iOS/ OSX)","Devices( iOS/ OSX)","Devices( iOS/ OSX)", "QU Bit","Goodbye");
+ }
+ }
+ if (m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_24_MIN)
+ {
+
+ for(int m=0;m<60;m++)
+ {
+ printw(" %02d ",m);
+ for (int h=0;h<24;h++)
+ printw("%5d ",m_MinSnapshot[h][m].m_nFrameCount);
+ printw("\n");
+ }
+ }
+ else
+ {
+ // sort list
+ CSortOptions SortOptions;
+ SortOptions.m_nSortCol = nSortCol;
+
+ if (pCacheRoot)
+ pCacheRoot->UpdateOSTypeCounts(&m_DeviceMap,&m_IPtoNameMap);
+
+ if (pCacheRoot)
+ pCacheRoot->CallBack(&CbPrintResults,&SortOptions);
+
+ // print list
+
+ CStringNode* pRecord = SortOptions.m_SortedCache.GetRoot();
+ BJ_UINT32 nIndex = 1;
+
+ if (pRecord)
+ pRecord->Print(m_bCursers,bSortAsc, nIndex,0,40);
+ }
+
+
+}
+
+void CBonjourTop::LiveCapture()
+{
+ /// Live Capture
+ const BJ_UINT16 BonjourPort = 5353;
+ BJSocket Sockv4;
+ BJSocket Sockv6;
+ BJSelect SockSelect;
+
+ Sockv4.CreateListenerIPv4(interfaceName);
+ Sockv6.CreateListenerIPv6(interfaceName);
+
+ SockSelect.Add(Sockv4);
+ SockSelect.Add(Sockv6);
+
+
+ m_StartTime = time(NULL);
+
+ bool bSortAsc = false;
+ int nSortCol = 1;
+
+ while (1)
+ {
+ SockSelect.Add(Sockv4);
+ SockSelect.Add(Sockv6);
+
+ int result = SockSelect.Wait(1);
+ if (result < 0)
+ {
+ // if SockSelect.Wait failed due to an interrupt, then we want to continue processing the packets
+ if (errno == EINTR)
+ {
+ continue;
+ }
+ printf("Error in Select\n");
+ break;
+ }
+
+ if (SockSelect.IsReady(Sockv4))
+ {
+
+ int recvsize = Sockv4.Read();
+
+ if ((recvsize != 0) &&
+ (Sockv4.GetSrcAddr()->GetPortNumber() == BonjourPort))
+ {
+ m_nFrameCount++;
+ m_SocketStatus[Sockv4.IsMulticastPacket()? 0:2].m_nFrameCount++;
+
+ if (!m_IPv4Addr.IsSameSubNet(Sockv4.GetSrcAddr()))
+ {
+ m_SocketStatus[4].m_nFrameCount++;
+ }
+ m_Frame.m_SourceIPAddress = *Sockv4.GetSrcAddr();
+ ProcessFrame(Sockv4.GetBuffer(),recvsize,Sockv4.m_CurrentFrame.GetTime());
+ }
+ }
+
+ if (SockSelect.IsReady(Sockv6))
+ {
+ int recvsize = Sockv6.Read();
+ if ((recvsize != 0) &&
+ (Sockv6.GetSrcAddr()->GetPortNumber() == BonjourPort))
+ {
+ m_nFrameCount++;
+ m_SocketStatus[Sockv6.IsMulticastPacket()? 1:3].m_nFrameCount++;
+ m_Frame.m_SourceIPAddress = *Sockv6.GetSrcAddr();
+
+ ProcessFrame(Sockv6.GetBuffer(),recvsize,Sockv6.m_CurrentFrame.GetTime());
+ }
+ }
+
+ if (m_bCursers)
+ {
+ int ch = getch();
+ switch (ch)
+ {
+ case 'o':
+ bSortAsc = !bSortAsc;
+ result = 0; // force an update
+ break;
+ case 'n':
+ nSortCol = 0;
+ result = 0; // force an update
+ break;
+ case 'b':
+ nSortCol = 1;
+ result = 0; // force an update
+ break;
+ case 'p':
+ if (nSortCol == 2)
+ nSortCol = 3;
+ else if (nSortCol == 3)
+ nSortCol = 4;
+ else
+ nSortCol = 2;
+ result = 0; // force an update
+ break;
+ case 'a':
+ case 'A':
+ if (m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_APP)
+ m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_APPv6;
+ else
+ m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_APP;
+
+ result = 0;
+ break;
+ case 's':
+ case 'S':
+ if (m_CurrentDisplay == CBonjourTop::BJ_DISPLAY_SERVICE)
+ m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_SERVICEv6;
+ else
+ m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_SERVICE;
+ result = 0;
+ break;
+ case 't':
+ case 'T':
+ m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_24_MIN;
+ result = 0;
+ break;
+ case 'q':
+ return;
+ case 'e':
+ ExportResults();
+ printf("\a");
+ break;
+ case KEY_RESIZE:
+ endwin();
+ initscr();
+ result = 0; // force an update
+ break;
+ case KEY_DOWN:
+ result = 0; // force an update
+ break;
+ }
+ if (window_size_changed)
+ {
+ endwin();
+ initscr();
+ window_size_changed = false;
+ }
+ }
+ if (m_EndTime != time(NULL) || result == 0)
+ {
+ m_EndTime = time(NULL);
+ PrintResults(nSortCol,bSortAsc);
+ if (m_SnapshotSeconds && (time(NULL) - m_StartTime) > m_SnapshotSeconds)
+ {
+ ExportResults();
+ if (m_bImportExportDeviceMap)
+ {
+ WriteDeviceFile();
+ WriteVendorFile();
+ }
+ Reset();
+ }
+ }
+ }
+}
+
+
+
+void CBonjourTop::CaptureFile()
+{
+ CCaptureFile CaptureFile;
+ BJIPAddr* pIPSrcAddr;
+ BJIPAddr* pIPDestAddr;
+
+ CIPAddrMap LocalSubnetIPv6;
+
+
+ CaptureFile.Open(m_pTcpDumpFileName);
+
+ m_StartTime = 0;
+ int nFrameIndex = 0;
+
+ while (CaptureFile.NextFrame())
+ {
+ nFrameIndex++;
+
+ BJ_UINT8* pBonjourBuffer = (BJ_UINT8*)CaptureFile.m_CurrentFrame.GetBonjourStart();
+ if (!pBonjourBuffer)
+ continue;
+
+ m_nFrameCount++;
+ m_nTotalBytes += CaptureFile.GetWiredLength();
+
+ pIPSrcAddr = CaptureFile.m_CurrentFrame.GetSrcIPAddr();
+ pIPDestAddr = CaptureFile.m_CurrentFrame.GetDestIPAddr();
+ m_Frame.m_SourceIPAddress = *CaptureFile.m_CurrentFrame.GetSrcIPAddr();;
+ m_Frame.m_SourceMACAddress = *CaptureFile.m_CurrentFrame.GetSrcMACAddr();
+
+ if (pIPSrcAddr->IsIPv4())
+ {
+ // check fragment flag
+ BJ_UINT8* pIP = CaptureFile.m_CurrentFrame.GetIPStart();
+ BJ_UINT16 flags = * ((BJ_UINT16*)(pIP+6));
+ if (flags)
+ continue;
+
+ if (!m_IPv4Addr.IsEmptySubnet())
+ {
+ if (m_IPv4Addr.IsSameSubNet(pIPSrcAddr))
+ {
+ BJ_UINT8* pSourceMac = CaptureFile.m_CurrentFrame.GetEthernetStart()+6;
+ BJIPAddr IPv6Addr;
+ IPv6Addr.CreateLinkLocalIPv6(pSourceMac);
+ LocalSubnetIPv6.FindwithAddRecord(&IPv6Addr);
+
+ }
+ else
+ {
+ m_SocketStatus[4].m_nFrameCount++;
+
+ if (!m_Collection.IsValid())
+ continue;
+ }
+ }
+ m_SocketStatus[(pIPDestAddr->IsBonjourMulticast())?0:2].m_nFrameCount++;
+ }
+ if (pIPSrcAddr->IsIPv6())
+ {
+ if (!LocalSubnetIPv6.Find(pIPSrcAddr) && !m_IPv4Addr.IsEmptySubnet())
+ {
+ m_SocketStatus[5].m_nFrameCount++;
+ if (!m_Collection.IsValid())
+ continue;
+ }
+ m_SocketStatus[(pIPDestAddr->IsBonjourMulticast())?1:3].m_nFrameCount++;
+ }
+
+ ProcessFrame(pBonjourBuffer,CaptureFile.GetBufferLen((pBonjourBuffer)),CaptureFile.m_CurrentFrame.GetTime());
+
+ }
+ m_EndTime = CaptureFile.GetDeltaTime();
+
+ PrintResults(2,false);
+ if ( m_CurrentDisplay == BJ_DISPLAY_APP)
+ m_CurrentDisplay = BJ_DISPLAY_APPv6;
+ else
+ m_CurrentDisplay = BJ_DISPLAY_SERVICEv6;
+
+ PrintDetailResults(2,false);
+
+}
+
+void CBonjourTop::ExportPtrCache(FILE* hFile, BJString sTitle,CStringNode* pRoot)
+{
+ fprintf(hFile,"%s\n",sTitle.GetBuffer());
+ fprintf(hFile,"Name,Bytes,Total Packets,Total Packets iOS,Total Packets OSX,Question Packets,Question Packets iOS,Question Packets OSX,Answer Packets,Answer Packets iOS,Answer Packets OSX,Asking Devices, Asking Devices iOS,Asking Devices OSX,Answering Devices,Answering Devices iOS,Answering Devices OSX,Total Devices,Total Devices iOS, Total Devices OSX,QU Bit,Goodbye\n");
+
+ if (pRoot)
+ pRoot->Export(hFile);
+}
+
+void CBonjourTop::ExportShortCacheHelper(FILE* hFile, BJString sTitle, CStringShortNode* pRoot)
+{
+ fprintf(hFile,"%s\n",sTitle.GetBuffer());
+ fprintf(hFile,"Name,Bytes,Total Packets,Question Packets,Answer Packets,Asking Devices,Answering Devices,Total Devices,QU Bit,Goodbye\n");
+
+ if (pRoot)
+ {
+ pRoot->Export(hFile);
+ }
+
+}
+
+void CBonjourTop::ExportShortCache(FILE* hFile, BJString sTitle, map<BJString, CStringShortTree*>* myMap)
+{
+ CStringShortTree* cache;
+ BJString versionNumber;
+
+ fprintf(hFile,"%s\n",sTitle.GetBuffer());
+
+ for (map<BJString, CStringShortTree*>::iterator it = myMap->begin(); it != myMap->end(); ++it)
+ {
+ versionNumber = (*it).first;
+ cache = (*it).second;
+
+ ExportShortCacheHelper(hFile, versionNumber, cache->GetRoot());
+ }
+}
+
+void CBonjourTop::ExportResults()
+{
+
+ BJString sTempFileName;
+ device_count devCount;
+ sTempFileName = m_pExportFileName;
+
+ if (m_SnapshotSeconds)
+ {
+ BJString sTimeStamp;
+ sTimeStamp.Format(time(NULL), BJString::BJSS_TIME);
+ sTempFileName += "_";
+ sTempFileName += sTimeStamp;
+ }
+ sTempFileName += ".csv";
+
+ if (m_Collection.IsValid())
+ {
+ m_Collection.ExportCollection(sTempFileName);
+ return;
+ }
+
+ FILE* hFile = fopen(sTempFileName.GetBuffer(),"w");
+
+ if (hFile == NULL)
+ {
+ printf("file open failed %s\n",m_pExportFileName);
+ return;
+ }
+
+ fprintf(hFile,"Total Number of Frames, %llu\n",m_nFrameCount);
+ fprintf(hFile,"Total Number of Bytes, %llu\n",m_nTotalBytes);
+ fprintf(hFile,"Total Number of Sec, %llu\n",m_EndTime-m_StartTime);
+
+ bzero(&devCount, sizeof(devCount));
+ m_DeviceMap.GetDeviceOSTypes(m_DeviceMap.GetRoot(),NULL, devCount);
+ fprintf(hFile,"Total Number of Devices, %llu\n\n",devCount.iOS+devCount.OSX+devCount.unknownOS);
+ fprintf(hFile,"Total Number of iOS Devices, %llu\n",devCount.iOS);
+ fprintf(hFile,"Total Number of iOS Devices (>= iOS7), %llu\n", devCount.iOSWithEDNSField);
+ fprintf(hFile,"Total Number of OSX Devices, %llu\n",devCount.OSX);
+ fprintf(hFile,"Total Number of OSX Devices (>= OSX 10.9), %llu\n",devCount.OSXWithEDNSField);
+
+ fprintf(hFile,"IPv4 multicast, %llu\n",m_SocketStatus[0].m_nFrameCount);
+ fprintf(hFile,"IPv6 multicast, %llu\n",m_SocketStatus[1].m_nFrameCount);
+ fprintf(hFile,"IPv4 Unicast, %llu\n",m_SocketStatus[2].m_nFrameCount);
+ fprintf(hFile,"IPv6 Unicast, %llu\n",m_SocketStatus[3].m_nFrameCount);
+ fprintf(hFile,"IPv4 Wrong subnet, %llu\n",m_SocketStatus[4].m_nFrameCount);
+ fprintf(hFile,"IPv6 Wrong subnet, %llu\n\n",m_SocketStatus[5].m_nFrameCount);
+
+ fprintf(hFile,"QuestionOnly Packets, %llu\n", m_SocketStatus[0].m_nQuestionOnlyFrames);
+ fprintf(hFile,"AnswerOnly Packets, %llu\n", m_SocketStatus[0].m_nAnswerOnlyFrames);
+ fprintf(hFile,"Q&A Packets, %llu\n\n", m_SocketStatus[0].m_nQandAFrames);
+
+ fprintf(hFile,"AnswerCount for truncated frames min, %llu\n", m_MinAnswerCountForTruncatedFrames);
+ fprintf(hFile,"AnswerCount for truncated frames avg, %llu\n", m_AvgAnswerCountForTruncatedFrames);
+ fprintf(hFile,"AnswerCount for truncated frames max, %llu\n\n", m_MaxAnswerCountForTruncatedFrames);
+
+ // Export Cache
+ UpdateOSCounts();
+ ExportPtrCache(hFile,"Application IPv4 Cache",m_ApplPtrCache.GetRoot());
+ ExportShortCache(hFile, "OSX", &m_AppBreakdownIPv4OSX);
+ ExportShortCache(hFile, "iOS", &m_AppBreakdownIPv4iOS);
+
+ ExportPtrCache(hFile,"Application IPv6 Cache",m_ApplPtrCacheIPv6.GetRoot());
+ ExportShortCache(hFile, "OSX", &m_AppBreakdownIPv6OSX);
+ ExportShortCache(hFile, "iOS", &m_AppBreakdownIPv6iOS);
+
+ ExportPtrCache(hFile,"Service IPv4 Cache",m_ServicePtrCache.GetRoot());
+ ExportShortCache(hFile, "OSX", &m_ServiceBreakdownIPv4OSX);
+ ExportShortCache(hFile, "iOS", &m_ServiceBreakdownIPv4iOS);
+
+ ExportPtrCache(hFile,"Service IPv6 Cache",m_ServicePtrCacheIPv6.GetRoot());
+ ExportShortCache(hFile, "OSX", &m_ServiceBreakdownIPv6OSX);
+ ExportShortCache(hFile, "iOS", &m_ServiceBreakdownIPv6iOS);
+
+ /// min snapshot table
+
+ fprintf(hFile,"Min Snapshot table\n");
+
+ for (int h=0;h<24;h++)
+ {
+ for(int m=0;m<60;m++)
+ {
+ if (m_MinSnapshot[h][m].m_nFrameCount)
+ {
+ fprintf(hFile,"%02d:%02d,%llu\n",h,m,m_MinSnapshot[h][m].m_nFrameCount);
+ }
+ }
+
+ }
+
+ fclose(hFile);
+
+}
+
+void CBonjourTop::WriteDeviceFile()
+{
+ BJString sTempFileName;
+ BJString sTimeStamp;
+
+ sTempFileName = m_DeviceFileName;
+ sTimeStamp.Format(time(NULL), BJString::BJSS_TIME);
+ sTempFileName += "_";
+ sTempFileName += sTimeStamp;
+ sTempFileName += ".csv";
+
+ FILE* hFile = fopen(sTempFileName.GetBuffer(),"w");
+
+ if (hFile == NULL)
+ {
+ printf("file open failed %s\n",sTempFileName.GetBuffer());
+ return;
+ }
+
+ fprintf(hFile,"\"Name\",\"IPv4Address\",\"IPv6Address\",\"MACAddress\",O,\"Model\",\"Method\",\"total frames\",\"question frames\",\"QU frames\",\"answer frames\"\n");
+
+ CDeviceNode *pDeviceNode = m_DeviceMap.GetRoot();
+
+ if (pDeviceNode)
+ pDeviceNode->Export(hFile);
+
+ fclose(hFile);
+
+ printf("devicemap count %llu %d\n",m_DeviceMap.GetCount(),CDeviceNode::nCreateCount);
+
+}
+
+void CBonjourTop::WriteVendorFile()
+{
+ BJString sTempFileName = "BonjourTopVendor";
+ BJString sTimeStamp;
+
+ sTimeStamp.Format(time(NULL), BJString::BJSS_TIME);
+ sTempFileName += "_";
+ sTempFileName += sTimeStamp;
+ sTempFileName += ".csv";
+
+ FILE* hFile = fopen(sTempFileName.GetBuffer(),"w");
+
+ if (hFile == NULL)
+ {
+ printf("file open failed %s\n",sTempFileName.GetBuffer());
+ return;
+ }
+ fprintf(hFile,"\"MACAddress\",O,\"Model\",\"Method\"\n");
+
+ CMACAddrNode *node = m_MacMap.GetRoot();
+
+ if (node)
+ node->Export(hFile);
+
+ fclose(hFile);
+}
+
+void CBonjourTop::WindowSizeChanged()
+{
+ window_size_changed = true;
+}
+
+BJ_UINT64 Hash(const char* pStr)
+{
+ // to fix
+ BJ_UINT64 hash = 0;
+ int c;
+
+ while ((c = *pStr++))
+ hash += c;
+
+ return hash;
+
+
+}
+
+BJ_UINT64 Hash2(char* pStr)
+{
+ // to fix
+ BJ_UINT64 hash = 0;
+ int c;
+ int i = 0;
+
+ while ((c = *pStr++) && i++ < 8)
+ {
+ hash = hash << 8;
+ hash |= c;
+ }
+
+ return hash;
+
+
+}
+
+static integer_t Usage(void)
+{
+ task_t targetTask = mach_task_self();
+ struct task_basic_info ti;
+ mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
+
+ kern_return_t kr = task_info(targetTask, TASK_BASIC_INFO_64,
+ (task_info_t) &ti, &count);
+ if (kr != KERN_SUCCESS)
+ {
+ printf("Kernel returned error during memory usage query");
+ return 0;
+ }
+
+ // On Mac OS X, the resident_size is in bytes, not pages!
+ // (This differs from the GNU Mach kernel)
+ // return ti.resident_size;
+ return ti.user_time.seconds;
+}
+
+///////////////
+
+
+/* CStringNode */
+
+void CStringNode::UpdateOSTypeCounts(CDeviceMap* pGlobalDeviceMap,CIPAddrMap *pIp2NameMap)
+{
+ if (m_rbLeft)
+ ((CStringNode*)m_rbLeft)->UpdateOSTypeCounts(pGlobalDeviceMap,pIp2NameMap);
+ if (m_rbRight)
+ ((CStringNode*)m_rbRight)->UpdateOSTypeCounts(pGlobalDeviceMap,pIp2NameMap);
+
+ BJ_UINT64 nDeviceUnknown = 0;
+ m_nDeviceAskingiOSCount = 0;
+ m_nDeviceAskingOSXCount = 0;
+ m_nDeviceAnsweringiOSCount = 0;
+ m_nDeviceAnsweringOSXCount = 0;
+ m_nDeviceTotaliOSCount = 0;
+ m_nDeviceTotalOSXCount = 0;
+ m_DeviceAskingTree.GetDeviceOSTypes(m_DeviceAskingTree.GetRoot(),pIp2NameMap,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount,nDeviceUnknown);
+ if (m_DeviceAskingTree.GetCount() != m_nDeviceAskingiOSCount + m_nDeviceAskingOSXCount+nDeviceUnknown)
+ {
+ nDeviceUnknown = 0;
+ }
+ nDeviceUnknown = 0;
+ m_DeviceAnsweringTree.GetDeviceOSTypes(m_DeviceAnsweringTree.GetRoot(),pIp2NameMap,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount,nDeviceUnknown);
+ if (m_DeviceAnsweringTree.GetCount() != m_nDeviceAnsweringiOSCount + m_nDeviceAnsweringOSXCount+nDeviceUnknown)
+ {
+ nDeviceUnknown = 0;
+ }
+ nDeviceUnknown = 0;
+ m_DeviceTotalTree.GetDeviceOSTypes(m_DeviceTotalTree.GetRoot(), pIp2NameMap, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, nDeviceUnknown);
+ if (m_DeviceTotalTree.GetCount() != m_nDeviceTotaliOSCount + m_nDeviceTotalOSXCount + nDeviceUnknown)
+ {
+ nDeviceUnknown = 0;
+ }
+}
+
+void CStringNode::Print(bool bCursers,bool bDescendingSort,BJ_UINT32 &nIndex, BJ_UINT32 nStartIndex,BJ_UINT32 nEndIndex)
+{
+ if (bDescendingSort)
+ {
+ if (m_rbLeft)
+ ((CStringNode*)m_rbLeft)->Print(bCursers,bDescendingSort,nIndex,nStartIndex,nEndIndex);
+
+ if (nIndex >= nStartIndex && nIndex <= nEndIndex)
+ {
+ if (bCursers)
+ {
+ printw("%3d. %-30s %10llu %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu %10llu\n",nIndex,(char*)&(m_Value),m_nBytes,m_nFrames, m_nFramesiOS, m_nFramesOSX, m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX, m_nAnswerFrames,m_nAnswerFramesiOS, m_nAnswerFramesOSX, m_nDeviceAskingCount,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount, m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount, m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, m_nWakeFrames,m_nGoodbyeFrames);
+
+ }
+ else
+ {
+ printf("%3d. %-30s %10llu %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu %10llu\n",nIndex,(char*)&(m_Value),m_nBytes,m_nFrames, m_nFramesiOS, m_nFramesOSX, m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX, m_nAnswerFrames,m_nAnswerFramesiOS, m_nAnswerFramesOSX, m_nDeviceAskingCount,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount, m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount, m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, m_nWakeFrames,m_nGoodbyeFrames);
+
+ }
+ }
+ nIndex++;
+ if (m_rbRight)
+ ((CStringNode*)m_rbRight)->Print(bCursers,bDescendingSort,nIndex,nStartIndex,nEndIndex);
+ }
+ else
+ {
+ if (m_rbRight)
+ ((CStringNode*)m_rbRight)->Print(bCursers,bDescendingSort,nIndex,nStartIndex,nEndIndex);
+
+ if (nIndex >= nStartIndex && nIndex <= nEndIndex)
+ {
+ if (bCursers)
+ {
+ printw("%3d. %-30s %10llu %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu %10llu\n",nIndex,(char*)&(m_Value),m_nBytes,m_nFrames, m_nFramesiOS, m_nFramesOSX, m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX, m_nAnswerFrames,m_nAnswerFramesiOS, m_nAnswerFramesOSX, m_nDeviceAskingCount,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount, m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount, m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, m_nWakeFrames,m_nGoodbyeFrames);
+ }
+ else
+ {
+ printf("%3d. %-30s %10llu %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu(%5llu/%5llu) %10llu %10llu\n",nIndex,(char*)&(m_Value),m_nBytes,m_nFrames, m_nFramesiOS, m_nFramesOSX, m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX, m_nAnswerFrames,m_nAnswerFramesiOS, m_nAnswerFramesOSX, m_nDeviceAskingCount,m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount, m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount, m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount, m_nWakeFrames,m_nGoodbyeFrames);
+ }
+ }
+ nIndex++;
+ if (m_rbLeft)
+ ((CStringNode*)m_rbLeft)->Print(bCursers,bDescendingSort,nIndex,nStartIndex,nEndIndex);
+ }
+
+}
+void CStringNode::Export(FILE* hFile)
+{
+ fprintf(hFile, "%s,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n",
+ (char*)&(m_Value),m_nBytes,
+ m_nFrames, m_nFramesiOS, m_nFramesOSX,
+ m_nQuestionFrames, m_nQuestionFramesiOS, m_nQuestionFramesOSX,
+ m_nAnswerFrames, m_nAnswerFramesiOS, m_nAnswerFramesOSX,
+ m_nDeviceAskingCount, m_nDeviceAskingiOSCount,m_nDeviceAskingOSXCount,
+ m_nDeviceAnsweringCount,m_nDeviceAnsweringiOSCount,m_nDeviceAnsweringOSXCount,
+ m_nDeviceTotalCount, m_nDeviceTotaliOSCount, m_nDeviceTotalOSXCount,
+ m_nWakeFrames,m_nGoodbyeFrames);
+
+ if (m_rbLeft)
+ ((CStringNode*)m_rbLeft)->Export(hFile);
+ if (m_rbRight)
+ ((CStringNode*)m_rbRight)->Export(hFile);
+
+}
+
+/* CStringShortNode */
+
+void CStringShortNode::Export(FILE *hFile)
+{
+ fprintf(hFile, "%s,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n",
+ (char*)&(m_Value),m_nBytes,
+ m_nFrames, m_nQuestionFrames, m_nAnswerFrames,
+ m_nDeviceAskingCount, m_nDeviceAnsweringCount, m_nDeviceTotalCount,
+ m_nWakeFrames,m_nGoodbyeFrames);
+
+
+ if (m_rbLeft)
+ {
+ ((CStringShortNode*)m_rbLeft)->Export(hFile);
+ }
+ if (m_rbRight)
+ {
+ ((CStringShortNode*)m_rbRight)->Export(hFile);
+ }
+}
+
+/* CDeviceMap */
+
+void CDeviceMap::GetDeviceOSTypes(CDeviceNode *node, CDeviceMap *pGlobalDeviceMap, device_count& dev_cnt)
+{
+ if (node == NULL)
+ return;
+
+ GetDeviceOSTypes(dynamic_cast<CDeviceNode*>(node->m_rbLeft),pGlobalDeviceMap, dev_cnt);
+ GetDeviceOSTypes(dynamic_cast<CDeviceNode*>(node->m_rbRight),pGlobalDeviceMap, dev_cnt);
+
+ if (node->bDuplicate || !node->bHasFrames)
+ return;
+
+ char deviceType = '?';
+ if (pGlobalDeviceMap)
+ {
+ CDeviceNode* globalDevice = pGlobalDeviceMap->Find(&node->m_Key);
+ if (globalDevice)
+ {
+ deviceType = globalDevice->GetDeviceOS();
+
+ if (globalDevice->bOSXWithEDNSField && deviceType == 'X')
+ {
+ dev_cnt.OSXWithEDNSField++;
+ }
+ else if (globalDevice->biOSWithEDNSField && (deviceType == 't' || deviceType == 'i'))
+ {
+ dev_cnt.iOSWithEDNSField++;
+ }
+ }
+ }
+ else
+ {
+ deviceType = node->GetDeviceOS();
+ if (node->bOSXWithEDNSField && deviceType == 'X')
+ {
+ dev_cnt.OSXWithEDNSField++;
+ }
+ else if (node->biOSWithEDNSField && (deviceType == 't' || deviceType == 'i'))
+ {
+ dev_cnt.iOSWithEDNSField++;
+ }
+ }
+ switch (deviceType)
+ {
+ case 'i':
+ case 't':
+ dev_cnt.iOS++;
+ break;
+ case 'X':
+ dev_cnt.OSX++;
+ break;
+ default:
+ dev_cnt.unknownOS++;
+ break;
+ }
+}
+
+void CIPAddrMap::GetDeviceOSTypes(CIPDeviceNode* node, CIPAddrMap* pGobalMap, BJ_UINT64& iOS,BJ_UINT64& OSX,BJ_UINT64& unknowOS)
+{
+ if (node == NULL)
+ return;
+
+ GetDeviceOSTypes(dynamic_cast<CIPDeviceNode*>(node->m_rbLeft),pGobalMap, iOS, OSX, unknowOS);
+ GetDeviceOSTypes(dynamic_cast<CIPDeviceNode*>(node->m_rbRight),pGobalMap,iOS, OSX, unknowOS);
+
+ char deviceType = '?';
+ if (pGobalMap)
+ {
+ CIPDeviceNode *ipDevice = pGobalMap->Find(&node->m_Key);
+
+ if (ipDevice && ipDevice->pDeviceNode )
+ deviceType = ipDevice->pDeviceNode->GetDeviceOS();
+
+ }
+
+ switch (deviceType)
+ {
+ case 'i':
+ case 't':
+ iOS++;
+ break;
+ case 'X':
+ OSX++;
+ break;
+ default:
+ unknowOS++;
+ }
+
+}
+
+
+///////////
+
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/BonjourTop.h b/mDNSResponder/mDNSMacOSX/BonjourTop/source/BonjourTop.h
new file mode 100644
index 00000000..9a678c0d
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/BonjourTop.h
@@ -0,0 +1,577 @@
+//
+// BonjourTop.h
+// TestTB
+//
+// Created by Terrin Eager on 9/26/12.
+//
+//
+
+#ifndef __TestTB__BonjourTop__
+#define __TestTB__BonjourTop__
+
+#include <iostream>
+#include <stdio.h>
+#include <map>
+#include <utility>
+
+#include "bjtypes.h"
+#include "bjsocket.h"
+#include "LLRBTree.h"
+#include "DNSFrame.h"
+#include "bjStringtoStringMap.h"
+#include "bjstring.h"
+
+#include "CollectBy.h"
+
+using namespace std;
+
+typedef struct device_count {
+ BJ_UINT64 iOS = 0;
+ BJ_UINT64 OSX = 0;
+ BJ_UINT64 unknownOS = 0;
+ BJ_UINT64 OSXWithEDNSField = 0;
+ BJ_UINT64 iOSWithEDNSField = 0;
+} device_count;
+
+class CSocketStats
+{
+public:
+ CSocketStats();
+ void Init();
+ void Clear();
+ BJ_UINT64 m_nFrameCount;
+
+ BJ_UINT64 m_nQuestionOnlyFrames;
+ BJ_UINT64 m_nAnswerOnlyFrames;
+ BJ_UINT64 m_nQandAFrames;
+
+ BJ_INT32 m_SampleDay;
+
+};
+
+class FrameCount
+{
+public:
+ FrameCount() { count = 0;lastFrameNumber = -1;};
+ void Increment(BJ_UINT64 frameNumber)
+ {
+ if (frameNumber != lastFrameNumber)
+ count++;
+ lastFrameNumber = frameNumber;
+
+ };
+ BJ_UINT64 GetValue() const {return count;};
+ void Reset() { count = 0;lastFrameNumber = -1;};
+ FrameCount &operator+=(const FrameCount &src) { count += src.count; return *this;};
+
+private:
+ BJ_UINT64 count;
+ BJ_UINT64 lastFrameNumber;
+};
+
+////////////////
+class CDeviceMap;
+class CDeviceNode;
+
+class CIPDeviceNode : public CRBNode<BJIPAddr>
+{
+public:
+ CIPDeviceNode(BJIPAddr* pSrc) {m_Key = *pSrc; /* temp deviceOS = '?';lastQUFrame = 0;*/pDeviceNode=NULL;};
+ CIPDeviceNode(){ /*deviceOS = '?';lastQUFrame = 0; */pDeviceNode=NULL;};
+ ~CIPDeviceNode(){};
+ inline virtual BJ_COMPARE Compare(BJIPAddr* pKey) {return m_Key.Compare(pKey);};
+ inline virtual void CopyNode(CRBNode* pSrc)
+ {
+ m_Key.Set(((BJIPAddr*)pSrc)->Getin6_addr());
+ pDeviceNode = ((CIPDeviceNode*)pSrc)->pDeviceNode;
+ };
+ void Init() {};
+ void Clear() {};
+
+
+ CDeviceNode* pDeviceNode;
+
+};
+
+class CIPAddrMap: public CLLRBTree<BJIPAddr,CIPDeviceNode>
+{
+public:
+ void GetDeviceOSTypes(CIPDeviceNode* node, CIPAddrMap* pGobalMap, BJ_UINT64& iOS,BJ_UINT64& OSX,BJ_UINT64& unknowOS);
+};
+
+////////////////////
+class CDeviceNode : public CRBNode<BJString>
+{
+public:
+ CDeviceNode(BJString* pSrc) {m_Key = *pSrc; deviceOS = '?'; bOSXWithEDNSField = false; biOSWithEDNSField = false; bDuplicate = false; bIPName = false; bHasFrames = false; nCreateCount++;};
+ CDeviceNode(){deviceOS = '?'; bDuplicate = false; bIPName = false; bHasFrames = false; nCreateCount++;};
+ ~CDeviceNode(){nCreateCount--;};
+ inline virtual BJ_COMPARE Compare(BJString* pKey) {return m_Key.Compare(*pKey);};
+ inline virtual void CopyNode(CRBNode* pSource)
+ {
+ m_Key = pSource->m_Key;
+ deviceOS = dynamic_cast<CDeviceNode*>(pSource)->deviceOS;
+ model = dynamic_cast<CDeviceNode*>(pSource)->model;
+ settingService = dynamic_cast<CDeviceNode*>(pSource)->settingService;
+ macAddress = dynamic_cast<CDeviceNode*>(pSource)->macAddress;
+ ipAddressv4 = dynamic_cast<CDeviceNode*>(pSource)->ipAddressv4;
+ ipAddressv6 = dynamic_cast<CDeviceNode*>(pSource)->ipAddressv6;
+ bOSXWithEDNSField = dynamic_cast<CDeviceNode*>(pSource)->bOSXWithEDNSField;
+ biOSWithEDNSField = dynamic_cast<CDeviceNode*>(pSource)->biOSWithEDNSField;
+ bHasFrames = dynamic_cast<CDeviceNode*>(pSource)->bHasFrames;
+ };
+ inline virtual void MergeData(CDeviceNode* src)
+ {
+ deviceOS = src->deviceOS;
+ model = src->model;
+ settingService = src->settingService;
+ macAddress = src->macAddress;
+ bOSXWithEDNSField = src->bOSXWithEDNSField;
+ biOSWithEDNSField = src->biOSWithEDNSField;
+
+ frameTotal += src->frameTotal;
+ questionFrame += src->questionFrame;
+ QUFrame += src->QUFrame;
+ answerFrame += src->answerFrame;
+ bHasFrames |= src->bHasFrames;
+ };
+ void ClearData()
+ {
+ frameTotal.Reset();
+ questionFrame.Reset();
+ QUFrame.Reset();
+ answerFrame.Reset();
+ bHasFrames = false;
+ }
+ void Init() {deviceOS = '?';};
+
+ void Clear() {};
+ char GetDeviceOS() {return deviceOS;};
+ void SetDeviceOS(char t,const char* pSettingService)
+ {
+ BJString EDNS0 = "EDNS0 Trace";
+ if (pSettingService == NULL)
+ printf("SetDeviceOS: pSettingService is NULL\n");
+
+ if (settingService != EDNS0 || EDNS0 == pSettingService)
+ {
+ settingService = pSettingService;;
+ deviceOS = t;
+ }
+ // if ( t != deviceOS && deviceOS != '?' && (deviceOS != 'b' ))
+ // printf("SetDeviceOS: %s deviceOS not equal %c by %s != %c by %s\n", m_Key.GetBuffer(),deviceOS,settingService.GetBuffer(),t,pSettingService);
+ };
+ void SetModel(char* pModel) {model = pModel;};
+ void Export(FILE* file)
+ {
+ // fprintf(hFile,"Name,IPAddress,MACAddress,OSType,Model,Method\n");
+ if (m_rbRight)
+ dynamic_cast<CDeviceNode*>(m_rbRight)->Export(file);
+
+ if (!bDuplicate || frameTotal.GetValue() > 0)
+ {
+ fprintf(file,"\"%s\",\"%s\",\"%s\",\"%s\",%c,\"%s\",\"%s\",%llu,%llu,%llu,%llu\n",
+ m_Key.GetBuffer(),
+ ipAddressv4.GetString(),
+ ipAddressv6.GetString(),
+ macAddress.GetString(),
+ deviceOS,
+ model.GetBuffer()?model.GetBuffer():" ",
+ (bDuplicate)?"dup":settingService.GetBuffer()?settingService.GetBuffer():" ",
+ frameTotal.GetValue(),
+ questionFrame.GetValue(),
+ QUFrame.GetValue(),
+ answerFrame.GetValue());
+ }
+
+ if (m_rbLeft)
+ dynamic_cast<CDeviceNode*>(m_rbLeft)->Export(file);
+ };
+
+ BJMACAddr macAddress;
+ BJIPAddr ipAddressv4;
+ BJIPAddr ipAddressv6;
+ BJString model;
+ BJString settingService;
+ bool biOSWithEDNSField;
+ bool bOSXWithEDNSField;
+ bool bDuplicate;
+ bool bIPName;
+ bool bHasFrames;
+
+ FrameCount frameTotal;
+ FrameCount questionFrame;
+ FrameCount QUFrame;
+ FrameCount answerFrame;
+ static int nCreateCount;
+
+private:
+ char deviceOS;
+};
+
+class CDeviceMap: public CLLRBTree<BJString,CDeviceNode>
+{
+public:
+ void GetDeviceOSTypes(CDeviceNode *node, CDeviceMap *pGobalMap, device_count& dev_cnt);
+};
+
+//////////////
+class CMACAddrNode: public CRBNode<BJMACAddr>
+{
+public:
+ CMACAddrNode(BJMACAddr* pSrc) {m_Key.Set(pSrc->Get()); deviceOS = '?'; };
+ CMACAddrNode(){deviceOS = '?';};
+ ~CMACAddrNode(){};
+ inline virtual BJ_COMPARE Compare(BJMACAddr* pKey) {return m_Key.Compare(pKey);};
+ inline virtual void CopyNode(CRBNode* pSource)
+ {
+ m_Key.Set( pSource->m_Key.Get());
+ deviceOS = dynamic_cast<CMACAddrNode*>(pSource)->deviceOS;
+ model = dynamic_cast<CMACAddrNode*>(pSource)->model;
+ method = dynamic_cast<CMACAddrNode*>(pSource)->method;
+ };
+ void Export(FILE* file)
+ {
+ if (m_rbRight)
+ dynamic_cast<CMACAddrNode*>(m_rbRight)->Export(file);
+
+
+ fprintf(file,"\"%s\",%c,\"%s\",\"%s\"\n",
+ m_Key.GetString(),
+ deviceOS,
+ model.GetBuffer()?model.GetBuffer():" ",
+ method.GetBuffer()?method.GetBuffer():" ");
+
+
+ if (m_rbLeft)
+ dynamic_cast<CMACAddrNode*>(m_rbLeft)->Export(file);
+ };
+
+ void Init() {deviceOS = '?';};
+ void Clear(){};
+ char deviceOS;
+ BJString model;
+ BJString method;
+
+};
+
+class CMACAddrTree: public CLLRBTree<BJMACAddr,CMACAddrNode>
+{
+public:
+
+};
+class CMACAddrDeviceNode: public CRBNode<BJMACAddr>
+{
+public:
+ CMACAddrDeviceNode(BJMACAddr* pSrc) {m_Key.Set(pSrc->Get()); device = NULL; };
+ CMACAddrDeviceNode(){device = NULL;};
+ ~CMACAddrDeviceNode(){};
+ inline virtual BJ_COMPARE Compare(BJMACAddr* pKey) {return m_Key.Compare(pKey);};
+ inline virtual void CopyNode(CRBNode* pSource)
+ {
+ m_Key.Set( pSource->m_Key.Get());
+ device = dynamic_cast<CMACAddrDeviceNode*>(pSource)->device;
+ };
+ void Init() {device = NULL;};
+ void Clear(){};
+ CDeviceNode *device;
+
+};
+
+class CMACDeviceMap: public CLLRBTree<BJMACAddr,CMACAddrDeviceNode>
+{
+
+};
+
+/////////////
+
+class CStringNode : public CRBNode<BJ_UINT64>
+{
+public:
+ CStringNode(){Init();};
+ CStringNode ( BJ_UINT64* Key) { Init(); m_Key = *Key;};
+ inline virtual BJ_COMPARE Compare(BJ_UINT64* pKey)
+ {
+
+ if (m_Key < *pKey)
+ return (BJ_GT);
+ else if (m_Key > *pKey)
+ return (BJ_LT);
+ else
+ return (BJ_EQUAL);
+ }
+ inline virtual void CopyNode(CRBNode* pSource)
+ {
+ CStringNode* pSrc = (CStringNode*) pSource;
+
+ // m_Key = pSrc->m_Key;
+ m_nBytes = pSrc->m_nBytes;
+ m_nFrames = pSrc->m_nFrames;
+ m_nFramesiOS = pSrc->m_nFramesiOS;
+ m_nFramesOSX = pSrc->m_nFramesOSX;
+ m_nQuestionFrames = pSrc->m_nQuestionFrames;
+ m_nQuestionFramesiOS = pSrc->m_nQuestionFramesiOS;
+ m_nQuestionFramesOSX = pSrc->m_nQuestionFramesOSX;
+ m_nAnswerFrames = pSrc->m_nAnswerFrames;
+ m_nAnswerFramesiOS = pSrc->m_nAnswerFramesiOS;
+ m_nAnswerFramesOSX = pSrc->m_nAnswerFramesOSX;
+ strcpy(m_Value,pSrc->m_Value);
+ m_nDeviceAskingCount = pSrc->m_nDeviceAskingCount;
+ m_nDeviceAskingiOSCount = pSrc->m_nDeviceAskingiOSCount;
+ m_nDeviceAskingOSXCount = pSrc->m_nDeviceAskingOSXCount;
+ m_nDeviceAnsweringCount = pSrc->m_nDeviceAnsweringCount;
+ m_nDeviceAnsweringiOSCount = pSrc->m_nDeviceAnsweringiOSCount;
+ m_nDeviceAnsweringOSXCount = pSrc->m_nDeviceAnsweringOSXCount;
+ m_nDeviceTotalCount = pSrc->m_nDeviceTotalCount;
+ m_nDeviceTotaliOSCount = pSrc->m_nDeviceTotaliOSCount;
+ m_nDeviceTotalOSXCount = pSrc->m_nDeviceTotalOSXCount;
+ m_nWakeFrames = pSrc->m_nWakeFrames;
+ m_nLastWakeFrameIndex = pSrc->m_nLastWakeFrameIndex;
+ m_nGoodbyeFrames = pSrc->m_nGoodbyeFrames;
+ }
+
+ inline void Init() {
+ m_nBytes = 0;
+ m_nFrames = m_nFramesiOS = m_nFramesOSX = m_nQuestionFrames = m_nQuestionFramesiOS = m_nQuestionFramesOSX = m_nAnswerFrames = m_nAnswerFramesiOS = m_nAnswerFramesOSX = 0;
+ m_nLastFrameIndex = 0;
+ m_nLastQueryFrameIndex = 0;
+ m_nLastRespondsFrameIndex = 0;
+ m_nDeviceAskingCount = m_nDeviceAskingiOSCount = m_nDeviceAskingOSXCount = 0;
+ m_nDeviceAnsweringCount = m_nDeviceAnsweringiOSCount = m_nDeviceAnsweringOSXCount = 0;
+ m_nDeviceTotalCount = m_nDeviceTotaliOSCount = m_nDeviceTotalOSXCount = 0;
+ m_nWakeFrames = 0;
+ m_nGoodbyeFrames = 0;
+ m_lastQUFrameTime = 0;
+ };
+ inline void Clear() {};
+
+ void UpdateOSTypeCounts(CDeviceMap* pGobalMap,CIPAddrMap *pIp2NameMap);
+
+ void Print(bool bCursers,bool bDescendingSort,BJ_UINT32 &nIndex,BJ_UINT32 nStartIndex,BJ_UINT32 nEndIndex);
+ void Export(FILE* hFile);
+
+ // BJ_UINT64 m_Key;
+ char m_Value[255];
+ BJ_UINT64 m_nBytes;
+ BJ_UINT64 m_nFrames;
+ BJ_UINT64 m_nFramesiOS;
+ BJ_UINT64 m_nFramesOSX;
+ BJ_UINT64 m_nQuestionFrames;
+ BJ_UINT64 m_nQuestionFramesiOS;
+ BJ_UINT64 m_nQuestionFramesOSX;
+ BJ_UINT64 m_nAnswerFrames;
+ BJ_UINT64 m_nAnswerFramesiOS;
+ BJ_UINT64 m_nAnswerFramesOSX;
+ BJ_UINT64 m_nLastFrameIndex;
+ BJ_UINT64 m_nLastQueryFrameIndex;
+ BJ_UINT64 m_nLastRespondsFrameIndex;
+ BJ_UINT64 m_nLastWakeFrameIndex;
+ CIPAddrMap m_DeviceAskingTree;
+ BJ_UINT64 m_nDeviceAskingCount;
+ BJ_UINT64 m_nDeviceAskingiOSCount;
+ BJ_UINT64 m_nDeviceAskingOSXCount;
+ CIPAddrMap m_DeviceAnsweringTree;
+ BJ_UINT64 m_nDeviceAnsweringCount;
+ BJ_UINT64 m_nDeviceAnsweringiOSCount;
+ BJ_UINT64 m_nDeviceAnsweringOSXCount;
+ CIPAddrMap m_DeviceTotalTree;
+ BJ_UINT64 m_nDeviceTotalCount;
+ BJ_UINT64 m_nDeviceTotaliOSCount;
+ BJ_UINT64 m_nDeviceTotalOSXCount;
+ BJ_UINT64 m_nWakeFrames;
+ BJ_UINT64 m_lastQUFrameTime;
+ BJ_UINT64 m_nGoodbyeFrames;
+};
+
+class CStringTree: public CLLRBTree<BJ_UINT64,CStringNode>
+{
+public:
+
+};
+
+///////////
+
+class CStringShortNode: public CRBNode<BJ_UINT64>
+{
+public:
+ CStringShortNode(BJ_UINT64* key) {Init(); m_Key = *key;};
+ inline virtual BJ_COMPARE Compare(BJ_UINT64* pKey)
+ {
+
+ if (m_Key < *pKey)
+ return (BJ_GT);
+ else if (m_Key > *pKey)
+ return (BJ_LT);
+ else
+ return (BJ_EQUAL);
+ }
+
+ inline virtual void CopyNode(CRBNode* pSource)
+ {
+ CStringShortNode* pSrc = (CStringShortNode*) pSource;
+
+ // m_Key = pSrc->m_Key;
+ m_nBytes = pSrc->m_nBytes;
+ m_nFrames = pSrc->m_nFrames;
+ m_nQuestionFrames = pSrc->m_nQuestionFrames;
+ m_nAnswerFrames = pSrc->m_nAnswerFrames;
+ strcpy(m_Value,pSrc->m_Value);
+ m_nDeviceAskingCount = pSrc->m_nDeviceAskingCount;
+ m_nDeviceAnsweringCount = pSrc->m_nDeviceAnsweringCount;
+ m_nDeviceTotalCount = pSrc->m_nDeviceTotalCount;
+ m_nWakeFrames = pSrc->m_nWakeFrames;
+ m_nLastWakeFrameIndex = pSrc->m_nLastWakeFrameIndex;
+ m_nGoodbyeFrames = pSrc->m_nGoodbyeFrames;
+ }
+
+ inline void Init() {
+ m_nBytes = 0;
+ m_nFrames = m_nQuestionFrames = m_nAnswerFrames = 0;
+ m_nLastFrameIndex = m_nLastQueryFrameIndex = m_nLastRespondsFrameIndex = m_nLastWakeFrameIndex = 0;
+ m_nDeviceAskingCount = m_nDeviceAnsweringCount = m_nDeviceTotalCount = 0;
+ m_nWakeFrames = m_lastQUFrameTime = m_nGoodbyeFrames = 0;
+ };
+ inline void Clear(){};
+
+ void Export(FILE* hFile);
+
+ // BJ_UINT64 m_Key;
+ char m_Value[255];
+ BJ_UINT64 m_nBytes;
+ BJ_UINT64 m_nFrames;
+ BJ_UINT64 m_nQuestionFrames;
+ BJ_UINT64 m_nAnswerFrames;
+ BJ_UINT64 m_nLastFrameIndex;
+ BJ_UINT64 m_nLastQueryFrameIndex;
+ BJ_UINT64 m_nLastRespondsFrameIndex;
+ BJ_UINT64 m_nLastWakeFrameIndex;
+ CIPAddrMap m_DeviceAskingTree;
+ BJ_UINT64 m_nDeviceAskingCount;
+ CIPAddrMap m_DeviceAnsweringTree;
+ BJ_UINT64 m_nDeviceAnsweringCount;
+ CIPAddrMap m_DeviceTotalTree;
+ BJ_UINT64 m_nDeviceTotalCount;
+ BJ_UINT64 m_nWakeFrames;
+ BJ_UINT64 m_lastQUFrameTime;
+ BJ_UINT64 m_nGoodbyeFrames;
+};
+
+class CStringShortTree: public CLLRBTree<BJ_UINT64, CStringShortNode>
+{
+public:
+};
+
+///////////
+
+
+class CBonjourTop
+{
+public:
+ CBonjourTop();
+
+ void SetIPAddr(const char*);
+ void LiveCapture();
+ void CaptureFile();
+
+ void PrintResults(int nSortCol, bool bSortAsc);
+ void UpdateOSCounts();
+ void PrintDetailResults(int nSortCol, bool bSortAsc);
+ void ExportResults();
+ void Reset();
+
+ void WriteDeviceFile();
+ void WriteVendorFile();
+
+ void ProcessFrame(BJ_UINT8* pBuffer,BJ_INT32 nLength, BJ_UINT64 frameTime);
+ bool Name2OSType(BJString name,CDeviceNode* device);
+
+ void UpdateRecord(CStringTree &Cache,CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye);
+
+ void UpdateShortRecordHelper(BJ_UINT32 cacheType, BJ_UINT32 tracePlatform, BJ_UINT32 traceVersion, char deviceOS, CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye);
+
+ void UpdateShortRecord(CStringShortTree* Cache,CDNSRecord* pDNSRecord,BJString& RecordName,BJString& ServiceName,BJ_UINT32 nBytes,bool bGoodbye);
+
+ void GetOSTypeFromQuery(CDNSRecord *pDNSRecord,BJString& ServiceName);
+ void GetOSTypeFromRegistration(CDNSRecord *pDNSRecord,BJString& ServiceName);
+
+ CStringNode* GetCurrentDisplayRoot(BJString &sTitle);
+ void ExportPtrCache(FILE* hFile, BJString sTitle, CStringNode* pRoot);
+ void ExportShortCache(FILE* hFile, BJString sTitle, map<BJString, CStringShortTree*>* myMap);
+ void ExportShortCacheHelper(FILE* hFile, BJString sTitle, CStringShortNode* pRoot);
+
+ void WindowSizeChanged();
+
+ bool m_bCursers;
+ const char* m_pTcpDumpFileName;
+ const char* m_pExportFileName;
+ bool window_size_changed;
+ bool m_bImportExportDeviceMap;
+ BJString m_DeviceFileName;
+
+ CDNSFrame m_Frame;
+
+#define NUM_SOCKET_STATUS 6
+#define HOURS_IN_DAY 24
+#define MINUTES_IN_HOUR 60
+
+ CSocketStats m_SocketStatus[NUM_SOCKET_STATUS];
+
+ CSocketStats m_MinSnapshot[HOURS_IN_DAY][MINUTES_IN_HOUR];
+
+ BJ_UINT64 m_nFrameCount;
+ BJ_UINT64 m_nTotalBytes;
+ long m_StartTime;
+ long m_EndTime;
+ BJ_UINT64 m_MinAnswerCountForTruncatedFrames;
+ BJ_UINT64 m_AvgAnswerCountForTruncatedFrames;
+ BJ_UINT64 m_MaxAnswerCountForTruncatedFrames;
+
+ BJIPAddr m_IPv4Addr;
+
+ BJStringtoStringMap m_Service2AppMap;
+
+ BJStringtoStringMap m_Service2osRegisterMap;
+ BJStringtoStringMap m_Service2osBrowseMap;
+
+ enum BJ_DISPLAY_MODE_ENUM {
+ BJ_DISPLAY_APP,
+ BJ_DISPLAY_APPv6,
+ BJ_DISPLAY_SERVICE,
+ BJ_DISPLAY_SERVICEv6,
+ BJ_DISPLAY_24_MIN
+ } m_CurrentDisplay ;
+
+ BJ_INT32 m_SnapshotSeconds;
+
+ CStringTree m_ServicePtrCache;
+ CStringTree m_ApplPtrCache;
+
+ CStringTree m_ServicePtrCacheIPv6;
+ CStringTree m_ApplPtrCacheIPv6;
+
+ map<BJString, CStringShortTree*> m_ServiceBreakdownIPv4OSX;
+ map<BJString, CStringShortTree*> m_ServiceBreakdownIPv4iOS;
+ map<BJString, CStringShortTree*> m_ServiceBreakdownIPv6OSX;
+ map<BJString, CStringShortTree*> m_ServiceBreakdownIPv6iOS;
+
+ map<BJString, CStringShortTree*> m_AppBreakdownIPv4OSX;
+ map<BJString, CStringShortTree*> m_AppBreakdownIPv4iOS;
+ map<BJString, CStringShortTree*> m_AppBreakdownIPv6OSX;
+ map<BJString, CStringShortTree*> m_AppBreakdownIPv6iOS;
+
+ CDeviceMap m_DeviceMap;
+
+ CMACAddrTree m_MacMap;
+ CIPAddrMap m_IPtoNameMap;
+ CMACDeviceMap m_MACtoDevice;
+ BJStringtoStringMap SVRtoDeviceName;
+
+ Collection m_Collection;
+
+ BJString interfaceName;
+ BJString filterApplicationName;
+
+
+};
+
+#endif /* defined(__TestTB__BonjourTop__) */
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/CaptureFile.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/CaptureFile.cpp
new file mode 100644
index 00000000..5dc33497
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/CaptureFile.cpp
@@ -0,0 +1,141 @@
+//
+// CaptureFile.cpp
+// TestTB
+//
+// Created by Terrin Eager on 9/14/12.
+//
+//
+
+#include "CaptureFile.h"
+#include <stdio.h>
+#include <pcap.h>
+#include <sys/types.h>
+
+#define BJ_MAX_PACKET (1024*20)
+
+struct packetheader
+{
+ __uint32_t sec;
+ __uint32_t usec;
+ __uint32_t captureLen;
+ __uint32_t origLen;
+
+};
+
+
+CCaptureFile::CCaptureFile()
+{
+ m_pFileHeader = NULL;
+ m_pFrameData = NULL;
+ m_pFrameHeader = NULL;
+ m_hFile = NULL;
+
+ m_nFirstFrameTime = 0;
+
+ if (!Init())
+ Clear();
+}
+CCaptureFile::~CCaptureFile()
+{
+ Clear();
+}
+
+bool CCaptureFile::Init()
+{
+ m_pFileHeader = new BJ_UINT8[sizeof(pcap_file_header)];
+ m_pFrameHeader = new BJ_UINT8[sizeof(packetheader)];
+ m_pFrameData = new BJ_UINT8[BJ_MAX_PACKET];
+
+ return (m_pFrameHeader && m_pFrameData && m_pFileHeader);
+}
+
+bool CCaptureFile::Clear()
+{
+ delete m_pFileHeader; m_pFileHeader = NULL;
+ delete m_pFrameData; m_pFrameData = NULL;
+ delete m_pFrameHeader; m_pFrameHeader = NULL;
+
+ fclose(m_hFile); m_hFile = NULL;
+ return true;
+}
+
+bool CCaptureFile::Open(const char* pFileName)
+{
+ m_hFile = fopen(pFileName, "r");
+
+ if (!m_hFile)
+ {
+ printf("Failed to open %s\n",pFileName);
+ return false;
+ }
+
+
+ fread(m_pFileHeader, sizeof(pcap_file_header), 1,m_hFile);
+
+ // pcap_file_header* pHeader = (pcap_file_header*)m_pFileHeader;
+ // int magic = pHeader->magic;
+ // int nType = pHeader->linktype;
+
+ pcap_file_header* pHeader = (pcap_file_header*)m_pFileHeader;
+ m_datalinkType = (Frame::BJ_DATALINKTYPE) pHeader->linktype;
+ m_CurrentFrame.SetDatalinkType(m_datalinkType);
+ return true;
+}
+
+bool CCaptureFile::NextFrame()
+{
+ packetheader* pFrameHeader = NULL;
+
+ if(!m_hFile)
+ return false;
+
+ if (fread(m_pFrameHeader,1,sizeof(packetheader),m_hFile)< sizeof(packetheader))
+ return false;
+
+ pFrameHeader = (packetheader*) m_pFrameHeader;
+
+ m_nWireLen = pFrameHeader->origLen;
+ m_TimeSec = pFrameHeader->sec;
+ if (m_nFirstFrameTime == 0)
+ m_nFirstFrameTime = m_TimeSec;
+ m_nCaptureLen = pFrameHeader->captureLen; // to do handle frames bigger than buffer
+
+ long nSkip = 0;
+ if (m_nCaptureLen > BJ_MAX_PACKET)
+ { // force truncate the packet ...
+ nSkip = m_nCaptureLen - BJ_MAX_PACKET;
+ m_nCaptureLen = BJ_MAX_PACKET;
+ }
+
+ if (fread(m_pFrameData,1,m_nCaptureLen,m_hFile) < m_nCaptureLen)
+ return false;
+
+ if (nSkip)
+ fseek(m_hFile, nSkip, SEEK_CUR);
+
+ m_CurrentFrame.Set(m_pFrameData, m_nCaptureLen,pFrameHeader->sec*1000000ll + pFrameHeader->usec);
+
+
+ return true;
+}
+
+bool CCaptureFile::Close()
+{
+
+ return true;
+}
+
+__uint32_t CCaptureFile::GetDeltaTime()
+{
+ return m_TimeSec-m_nFirstFrameTime;
+}
+
+__uint32_t CCaptureFile::GetBufferLen(BJ_UINT8* pStart)
+{
+ return m_nCaptureLen - (__uint32_t) (pStart - m_pFrameData);
+}
+
+
+
+
+
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/CaptureFile.h b/mDNSResponder/mDNSMacOSX/BonjourTop/source/CaptureFile.h
new file mode 100644
index 00000000..ea625bac
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/CaptureFile.h
@@ -0,0 +1,55 @@
+//
+// CaptureFile.h
+// TestTB
+//
+// Created by Terrin Eager on 9/14/12.
+//
+//
+
+#ifndef __TestTB__CaptureFile__
+#define __TestTB__CaptureFile__
+
+#include <iostream>
+#include "bjtypes.h"
+#include "bjsocket.h"
+#include "Frame.h"
+
+class CCaptureFile
+{
+public:
+ CCaptureFile();
+ virtual ~CCaptureFile();
+ bool Open(const char* pFileName);
+ bool NextFrame();
+ bool Close();
+
+ Frame m_CurrentFrame;
+
+
+
+ __uint32_t GetDeltaTime();
+
+ __uint32_t GetBufferLen(BJ_UINT8* pStart);
+
+ __uint32_t GetWiredLength(){ return m_nWireLen;};
+
+
+private:
+ bool Init();
+ bool Clear();
+
+ FILE* m_hFile;
+ BJ_UINT8* m_pFrameHeader;
+ BJ_UINT8* m_pFrameData;
+ BJ_UINT8* m_pFileHeader;
+ __uint32_t m_nCaptureLen;
+ __uint32_t m_nWireLen;
+ __uint32_t m_TimeSec;
+
+ __uint32_t m_nFirstFrameTime;
+
+ Frame::BJ_DATALINKTYPE m_datalinkType;
+
+};
+
+#endif /* defined(__TestTB__CaptureFile__) */
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/CollectBy.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/CollectBy.cpp
new file mode 100644
index 00000000..9387fcab
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/CollectBy.cpp
@@ -0,0 +1,314 @@
+//
+// CollectBy.cpp
+// TestTB
+//
+// Created by Terrin Eager on 3/17/13.
+//
+//
+
+#include <iostream>
+#include "bjtypes.h"
+#include "DNSFrame.h"
+#include "bjstring.h"
+#include "LLRBTree.h"
+
+#include "CollectBy.h"
+
+
+//////////////////////
+// Collection
+void Collection::Init(BJ_COLLECTBY_TYPE collectByList[])
+{
+ CollectByAbstract* pLastCollectBy = nullptr;
+
+ for (int i=0; i<20 && collectByList[i] != CBT_NOT_SET;i++)
+ {
+ m_CollectByList[i] = collectByList[i];
+ if (i==0)
+ {
+ m_pHeaderCollectBy = Factory(m_CollectByList[i]);
+ pLastCollectBy = m_pHeaderCollectBy;
+ m_pFirstCollectBy = pLastCollectBy->Factory();
+ }
+ else
+ {
+ pLastCollectBy->pNext = Factory(m_CollectByList[i]);
+ pLastCollectBy = pLastCollectBy->pNext;
+ }
+ }
+}
+
+void Collection::ProcessFrame(CDNSFrame* pFrame)
+{
+ m_pFirstCollectBy->Collect(pFrame,m_pHeaderCollectBy->pNext);
+}
+
+void Collection::ExportCollection(BJString sFileName)
+{
+ FILE* hFile = fopen(sFileName.GetBuffer(),"w");
+
+ if (hFile == NULL)
+ {
+ printf("file open failed %s\n",sFileName.GetBuffer());
+ return;
+ }
+
+ // Export Header Line
+ CollectByAbstract *collectBy = m_pHeaderCollectBy;
+ BJString sHeader;
+ while (collectBy)
+ {
+ if (sHeader.GetBufferLength() != 0)
+ sHeader += ",";
+ sHeader += collectBy->GetTitle();
+ collectBy = collectBy->pNext;
+ }
+ fprintf(hFile, "%s\n",sHeader.GetBuffer());
+
+ m_pFirstCollectBy->Export(hFile,"");
+
+ fclose(hFile);
+}
+
+CollectByAbstract* Collection::Factory(BJ_COLLECTBY_TYPE type)
+{
+ switch (type)
+ {
+ case CBT_NOT_SET:
+ return NULL;
+ case CBT_SERVICE:
+ return new CollectByService();
+ case CBT_REQUEST_RESPONDS:
+ return new CollectByRequestResponds();
+ case CBT_SAME_DIFF_SUBNET:
+ return new CollectBySameSubnetDiffSubnet();
+ case CBT_IP_ADDRESS_TYPE:
+ return new CollectByIPAddressType();
+ case CBT_PACKET:
+ return new CollectByPacketCount();
+ default:
+ return NULL;
+ }
+
+}
+
+/////////////
+// CollectByService
+
+void CServiceNode::Export(FILE* hFile,BJString sPrevColumns)
+{
+ if (pNext)
+ {
+ BJString sTemp = sPrevColumns;
+ if (sPrevColumns.GetBufferLength())
+ sTemp += ",";
+ sTemp += m_Key;
+ pNext->Export(hFile,sTemp);
+ }
+ if (m_rbLeft)
+ dynamic_cast<CServiceNode*>(m_rbLeft)->Export(hFile,sPrevColumns);
+ if (m_rbRight)
+ dynamic_cast<CServiceNode*>(m_rbRight)->Export(hFile,sPrevColumns);
+}
+
+void CollectByService::Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy)
+{
+ for (int dnsItemsIndex =0; dnsItemsIndex < pFrame->GetQuestionCount()+pFrame->GetAnswerCount();dnsItemsIndex++)
+ {
+ BJString RecordName;
+ CDNSRecord* pDNSRecord = pFrame->GetDnsRecord(dnsItemsIndex);
+ if (pDNSRecord == NULL)
+ continue;
+
+ pDNSRecord->GetDnsRecordName(RecordName,0,99);
+
+ if (RecordName.Contains("_kerberos."))
+ {
+ RecordName = "_kerberos.";
+ }
+ else
+ pDNSRecord->GetDnsRecordName(RecordName, (pDNSRecord->m_RecType == 12)?0:1,99);
+
+ if (pDNSRecord->m_RecType == 12)
+ {
+ if (RecordName.Contains(".ip6.arpa."))
+ RecordName = "*.ip6.arpa.";
+ else if (RecordName.Contains(".arpa."))
+ RecordName = "*.arpa.";
+ }
+ if (pDNSRecord->m_RecType == 1)
+ RecordName = "A";
+ if (pDNSRecord->m_RecType == 28)
+ RecordName = "AAAA";
+ if (pDNSRecord->m_RecType == 255)
+ {
+ if (RecordName.Contains(".ip6.arpa."))
+ RecordName = "ANY *.ip6.arpa.";
+ else if (RecordName.Contains(".arpa."))
+ RecordName = "ANY *.arpa.";
+ else
+ RecordName = "Any";
+ }
+ if (RecordName.Contains("_sub."))
+ {
+ pDNSRecord->GetDnsRecordName(RecordName,2,99); /// skip first label and _sub. label
+ }
+
+
+ CServiceNode *pNode= m_Cache.FindwithAddRecord(&RecordName);
+ if (pNode->pNext == NULL)
+ pNode->pNext = nextCollectBy->Factory();
+ pNode->pNext->Collect(pFrame,nextCollectBy?nextCollectBy->pNext:NULL);
+
+ }
+
+}
+
+
+
+
+void CollectByService::Export(FILE* hFile,BJString sPrevColumns)
+{
+
+ // loop thur list
+ CServiceNode *pNode = m_Cache.GetRoot();
+
+ if (pNode)
+ pNode->Export(hFile,sPrevColumns);
+}
+
+/////////////
+// CollectByRequestResponds
+void CollectByRequestResponds::Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy)
+{
+ if (pFrame->IsQueryFrame())
+ {
+ if (pRequestNext == NULL)
+ pRequestNext = nextCollectBy->Factory();
+ pRequestNext->Collect(pFrame, nextCollectBy?nextCollectBy->pNext:NULL);
+ }
+ else
+ {
+ if (pRespondsNext == NULL)
+ pRespondsNext = nextCollectBy->Factory();
+ pRespondsNext->Collect(pFrame, nextCollectBy?nextCollectBy->pNext:NULL);
+ }
+}
+
+void CollectByRequestResponds::Export(FILE* hFile,BJString sPrevColumns)
+{
+ if (pRequestNext)
+ {
+ BJString sTemp = sPrevColumns;
+ if (sPrevColumns.GetBufferLength())
+ sTemp += ",";
+ sTemp += "Request";
+ pRequestNext->Export(hFile,sTemp);
+ }
+ if (pRespondsNext)
+ {
+ BJString sTemp = sPrevColumns;
+ if (sPrevColumns.GetBufferLength())
+ sTemp += ",";
+ sTemp += "Responds";
+ pRespondsNext->Export(hFile,sTemp);
+ }
+}
+/////////////
+// CollectByIPAddressType
+void CollectByIPAddressType::Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy)
+{
+ if (pFrame->m_SourceIPAddress.IsIPv4())
+ {
+ if (pIPv4Next == NULL)
+ pIPv4Next = nextCollectBy->Factory();
+ pIPv4Next->Collect(pFrame, nextCollectBy?nextCollectBy->pNext:NULL);
+ }
+ if (pFrame->m_SourceIPAddress.IsIPv6())
+ {
+ if (pIPv6Next == NULL)
+ pIPv6Next = nextCollectBy->Factory();
+ pIPv6Next->Collect(pFrame, nextCollectBy?nextCollectBy->pNext:NULL);
+ }
+}
+void CollectByIPAddressType::Export(FILE* hFile,BJString sPrevColumns)
+{
+ if (pIPv4Next)
+ {
+ BJString sTemp = sPrevColumns;
+ if (sPrevColumns.GetBufferLength())
+ sTemp += ",";
+ sTemp += "IPv4";
+ pIPv4Next->Export(hFile,sTemp);
+ }
+ if (pIPv6Next)
+ {
+ BJString sTemp = sPrevColumns;
+ if (sPrevColumns.GetBufferLength())
+ sTemp += ",";
+ sTemp += "IPv6";
+ pIPv6Next->Export(hFile,sTemp);
+ }
+}
+/////////////
+// CollectBySameSubnetDiffSubnet:
+
+// static
+bool CollectBySameSubnetDiffSubnet::bSameSubnet = true;
+
+void CollectBySameSubnetDiffSubnet::Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy)
+{
+ if (bSameSubnet)
+ {
+ if (pSameSubnetNext == NULL)
+ pSameSubnetNext = nextCollectBy->Factory();
+ pSameSubnetNext->Collect(pFrame, nextCollectBy?nextCollectBy->pNext:NULL);
+ }
+ else
+ {
+ if (pDiffSubnetNext == NULL)
+ pDiffSubnetNext = nextCollectBy->Factory();
+ pDiffSubnetNext->Collect(pFrame, nextCollectBy?nextCollectBy->pNext:NULL);
+ }
+
+}
+void CollectBySameSubnetDiffSubnet::Export(FILE* hFile,BJString sPrevColumns)
+{
+ if (pSameSubnetNext)
+ {
+ BJString sTemp = sPrevColumns;
+ if (sPrevColumns.GetBufferLength())
+ sTemp += ",";
+ sTemp += "SameSubnet";
+ pSameSubnetNext->Export(hFile,sTemp);
+ }
+ if (pDiffSubnetNext)
+ {
+ BJString sTemp = sPrevColumns;
+ if (sPrevColumns.GetBufferLength())
+ sTemp += ",";
+ sTemp += "WrongSubnet";
+ pDiffSubnetNext->Export(hFile,sTemp);
+ }
+}
+/////////////
+// CollectByPacketCount
+
+// staticCollectByPacketCount
+BJ_INT64 CollectByPacketCount::nFrameIndex = 0;
+
+void CollectByPacketCount::Collect(CDNSFrame* ,CollectByAbstract* )
+{
+ if (nFrameIndex != nLastFrameIndex)
+ {
+ nFrameCount++;
+ nLastFrameIndex = nFrameIndex;
+ }
+}
+void CollectByPacketCount::Export(FILE* hFile,BJString sPrevColumns)
+{
+
+ fprintf(hFile,"%s,%llu\n",sPrevColumns.GetBuffer(),nFrameCount);
+}
+
+
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/CollectBy.h b/mDNSResponder/mDNSMacOSX/BonjourTop/source/CollectBy.h
new file mode 100644
index 00000000..80ff0d58
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/CollectBy.h
@@ -0,0 +1,155 @@
+//
+// CollectBy.h
+// TestTB
+//
+// Created by Terrin Eager on 3/17/13.
+//
+//
+
+#ifndef __TestTB__CollectBy__
+#define __TestTB__CollectBy__
+
+#include <iostream>
+#include "bjtypes.h"
+#include "DNSFrame.h"
+#include "bjstring.h"
+#include "LLRBTree.h"
+
+
+// Service request/Respond v4/v6 sameSubnet/DifferentSubnet
+
+enum BJ_COLLECTBY_TYPE
+{
+ CBT_NOT_SET,
+ CBT_SERVICE,
+ CBT_REQUEST_RESPONDS,
+ CBT_SAME_DIFF_SUBNET,
+ CBT_IP_ADDRESS_TYPE,
+ CBT_PACKET
+};
+
+class CollectByAbstract;
+class Collection
+{
+public:
+ Collection() {m_pHeaderCollectBy = NULL;m_pFirstCollectBy = NULL;};
+
+ void Init(BJ_COLLECTBY_TYPE collectByList[]);
+ void ProcessFrame(CDNSFrame* pFrame);
+
+ void ExportCollection(BJString sFileName);
+ bool IsValid() { return (m_pFirstCollectBy != NULL);};
+private:
+ CollectByAbstract* Factory(BJ_COLLECTBY_TYPE type);
+
+ BJ_COLLECTBY_TYPE m_CollectByList[20];
+ CollectByAbstract* m_pHeaderCollectBy;
+ CollectByAbstract* m_pFirstCollectBy;
+
+};
+
+class CollectByAbstract
+{
+public:
+ CollectByAbstract()
+ {
+ pNext = NULL;
+ }
+
+ virtual void Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy)=0;
+ virtual const char* GetTitle()=0;
+ virtual CollectByAbstract* Factory()=0;
+ virtual void Export(FILE* hFile,BJString sPrevColumns)=0;
+
+ CollectByAbstract* pNext;
+};
+/////////////
+// Service
+class CServiceNode : public CRBNode<BJString>
+{
+public:
+ CServiceNode() {pNext = NULL;};
+ CServiceNode(BJString* pKey){ m_Key = *pKey;};
+ ~CServiceNode(){};
+ inline virtual BJ_COMPARE Compare(BJString* pKey) { return m_Key.Compare(*pKey);};
+ inline virtual void CopyNode(CRBNode* pSource) {pNext = dynamic_cast<CServiceNode*>(pSource)->pNext;} ;
+ inline virtual void Init(){};
+ inline virtual void Clear() {};
+ void Export(FILE* hFile,BJString sPrevColumns);
+ CollectByAbstract* pNext;
+
+};
+
+class CServiceToCollectByMap : public CLLRBTree<BJString, CServiceNode>
+{
+public:
+
+
+};
+
+class CollectByService:public CollectByAbstract
+{
+public:
+ virtual void Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy);
+ virtual const char* GetTitle() {return "Service";};
+ virtual CollectByAbstract* Factory(){ return new CollectByService();};
+ virtual void Export(FILE* hFile,BJString sPrevColumns);
+private:
+ CServiceToCollectByMap m_Cache;
+};
+
+class CollectByRequestResponds:public CollectByAbstract
+{
+public:
+ virtual void Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy);
+ virtual const char* GetTitle() {return "Request/Responds";};
+ virtual CollectByAbstract* Factory(){ return new CollectByRequestResponds();};
+ virtual void Export(FILE* hFile,BJString sPrevColumns);
+
+private:
+ CollectByAbstract* pRequestNext;
+ CollectByAbstract* pRespondsNext;
+};
+
+class CollectByIPAddressType:public CollectByAbstract
+{
+public:
+ virtual void Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy);
+ virtual const char* GetTitle() {return "V4/V6";};
+ virtual CollectByAbstract* Factory(){ return new CollectByIPAddressType();};
+ virtual void Export(FILE* hFile,BJString sPrevColumns);
+private:
+ CollectByAbstract* pIPv4Next;
+ CollectByAbstract* pIPv6Next;
+};
+
+class CollectBySameSubnetDiffSubnet:public CollectByAbstract
+{
+public:
+ virtual void Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy);
+ virtual const char* GetTitle() {return "SameSubnet/DiffSubnet";};
+ virtual CollectByAbstract* Factory(){ return new CollectBySameSubnetDiffSubnet();};
+ virtual void Export(FILE* hFile,BJString sPrevColumns);
+
+ static bool bSameSubnet;
+private:
+ CollectByAbstract* pSameSubnetNext;
+ CollectByAbstract* pDiffSubnetNext;
+};
+
+class CollectByPacketCount:public CollectByAbstract
+{
+
+public:
+ virtual void Collect(CDNSFrame* pFrame,CollectByAbstract* nextCollectBy);
+ virtual const char* GetTitle() {return "Packets";};
+ virtual CollectByAbstract* Factory(){ return new CollectByPacketCount();};
+ virtual void Export(FILE* hFile,BJString sPrevColumns);
+
+ BJ_INT64 nFrameCount;
+ BJ_INT64 nLastFrameIndex;
+ static BJ_INT64 nFrameIndex;
+};
+
+
+#endif /* defined(__TestTB__CollectBy__) */
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/DNSFrame.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/DNSFrame.cpp
new file mode 100644
index 00000000..1e8586a0
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/DNSFrame.cpp
@@ -0,0 +1,384 @@
+//
+// DNSFrame.cpp
+// TestTB
+//
+// Created by Terrin Eager on 9/26/12.
+//
+//
+
+#include "DNSFrame.h"
+
+#define DNS_LABEL_MAX_LENGTH 63
+#define DNS_NAME_MAX_LENGTH 255
+
+void CDNSRecord::GetDnsRecordName(BJString& ReturnString,int nLabelToSkip,int nMaxLabel)
+{
+ GetDnsRecordNameFromBuffer(m_pStartofRec, ReturnString, nLabelToSkip, nMaxLabel);
+}
+
+void CDNSRecord::GetDnsRecordNameFromBuffer(BJ_UINT8* pBuffer,BJString& ReturnString,int nLabelToSkip,int nMaxLabel)
+{
+ BJ_UINT8* pNameBuffer = NULL;
+ int nOffset = 0;
+ // char* pTemp = pReturnBuffer;
+ int nCharCount = 0;
+ int nSkippedLabels = 0;
+ int nLabelProcessed = 0;
+ ReturnString.Set(NULL,255);
+
+ if (ReturnString.GetBuffer() == NULL)
+ return;
+
+ pNameBuffer = pBuffer;
+ if (pNameBuffer == NULL)
+ {
+ return;
+ }
+
+ while (ReturnString.GetBufferLength() < 1024)
+ {
+ nCharCount = *pNameBuffer++;
+ if (nCharCount == 0)
+ break;
+
+ if ((nCharCount&(DNS_NAME_OFFSET_MASK)) == DNS_NAME_OFFSET_MASK)
+ {
+ nOffset = *pNameBuffer++;
+ nOffset |= (nCharCount&(~DNS_NAME_OFFSET_MASK)) << 8;
+ pNameBuffer = m_pDNSFrame->GetBuffer() + nOffset;
+ continue;
+ }
+
+ if (nCharCount > DNS_LABEL_MAX_LENGTH)
+ {
+ printf("label too long %d\n",nCharCount);
+ break;
+ }
+
+ if (ReturnString.GetLength() + nCharCount + 1 > DNS_NAME_MAX_LENGTH) // + 1 is for the '.' added later on
+ {
+ printf("Name exceeded limit allowed for DNS: %d\n", ReturnString.GetLength() + nCharCount + 1);
+ break;
+ }
+
+ if (nLabelToSkip > nSkippedLabels)
+ {
+ nSkippedLabels++;
+ pNameBuffer += nCharCount;
+ continue;
+ }
+ ReturnString.Append((char*)pNameBuffer, nCharCount);
+ pNameBuffer+= nCharCount;
+ nLabelProcessed++;
+
+ if (nLabelProcessed >= nMaxLabel)
+ return;
+
+ ReturnString += ".";
+ }
+}
+
+
+
+
+CDNSFrame::CDNSFrame()
+{
+
+ for(int nIndex=0; nIndex < MAX_DNS_RECORDS_PER_FRAME; nIndex++)
+ m_dnsItems[nIndex].m_pDNSFrame = this;
+
+}
+
+CDNSRecord* CDNSFrame::GetDnsRecord(int nIndex)
+{
+ if (nIndex > m_nMaxItems)
+ return NULL;
+ return &m_dnsItems[nIndex];
+}
+
+bool CDNSFrame::ParseDNSFrame(BJ_UINT8* pBuffer,BJ_INT32 nLength, BJ_UINT64 frameTime)
+{
+ if (pBuffer == NULL)
+ return false;
+
+ int nIndex = 0;
+
+ m_Servicev4Address.Empty();
+ m_Servicev6Address.Empty();
+
+ m_pStartBuffer = pBuffer;
+ m_nFrameLen = (BJ_UINT32) nLength;
+
+ m_pCurrentBuffer = m_pStartBuffer;
+ m_pEndBuffer = m_pStartBuffer + m_nFrameLen;
+ m_Time = frameTime;
+
+ m_nId = PF_GET_UINT16(m_pStartBuffer,0);
+ m_nFlags = PF_GET_UINT16(m_pStartBuffer,2);
+ m_nQuestionCount = PF_GET_UINT16(m_pStartBuffer,4);
+ m_nAnswersCount = PF_GET_UINT16(m_pStartBuffer,6);
+ m_NSCOUNT = PF_GET_UINT16(m_pStartBuffer,8);
+ m_ARCOUNT = PF_GET_UINT16(m_pStartBuffer,10);
+
+ m_nMaxItems = 0;
+
+
+
+ // printf("FrameNum= %d,nQuestionCount= %d nAnswersCount= %d NSCOUNT= %d ARCOUNT= %d\n",nFrameCount++,m_nQuestionCount, m_nAnswersCount,m_NSCOUNT, m_ARCOUNT);
+
+ m_pCurrentBuffer = m_pStartBuffer + 12;
+
+
+ for (nIndex =0; nIndex < m_nQuestionCount;nIndex++)
+ {
+ // printf("FramePosition= %ld ",m_pCurrentBuffer);
+ ParseDnsRecord(CDNSRecord::Question);
+
+ }
+ for (nIndex =0; nIndex < m_nAnswersCount;nIndex++)
+ {
+ // printf("FramePosition= %ld ",m_pCurrentBuffer);
+ ParseDnsRecord(CDNSRecord::Answer);
+ }
+ for (nIndex =0; nIndex < m_NSCOUNT;nIndex++)
+ {
+ // printf("FramePosition= %ld ",m_pCurrentBuffer);
+ ParseDnsRecord(CDNSRecord::Answer);
+ }
+ for (nIndex =0; nIndex < m_ARCOUNT;nIndex++)
+ {
+ // printf("FramePosition= %ld ",m_pCurrentBuffer);
+ ParseDnsRecord(CDNSRecord::Answer);
+ CDNSRecord* pRecord = &m_dnsItems[m_nMaxItems-1];
+ if (pRecord->m_RecType == DNS_TYPE_AAAA && m_Servicev6Address.IsEmpty())
+ {
+ m_Servicev6Address.Setv6Raw(pRecord->GetStartofRdata());
+ }
+ if (pRecord->m_RecType == DNS_TYPE_A && m_Servicev4Address.IsEmpty())
+ {
+ m_Servicev4Address.Setv4Raw(pRecord->GetStartofRdata());
+ }
+ }
+ //
+ /// for (dnsItemsIndex =0; dnsItemsIndex < m_nQuestionCount+m_nAnswersCount;dnsItemsIndex++)
+ /// {
+ /// printf("Name = %s\n", GetDnsRecordName(&Frame,dnsItemsIndex,tempBuffer,sizeof(tempBuffer)));
+ // }
+ return true;
+}
+
+BJ_BOOL CDNSFrame::ParseDnsRecord(CDNSRecord::dnsItemType eItemType)
+{
+ unsigned char nCharCount = 0;
+ BJ_UINT8* pTemp = m_pCurrentBuffer;
+ CDNSRecord* pRecord = &m_dnsItems[m_nMaxItems++];
+
+ //temp
+ BJ_UINT16 nRdataLen = 0;
+ BJ_UINT16 nRdataLen2 = 0;
+
+ if (pTemp > m_pEndBuffer)
+ {
+ printf("Error in ParseDnsRecord pBuffer > pEndBuffer\n");
+ pRecord->m_pStartofRec = NULL;
+ pRecord->m_nNameLength = 0;
+ return false;
+ }
+
+
+ pRecord->m_pStartofRec = pTemp;
+ pRecord->m_nNameLength = 0;
+ pRecord->m_nRdataLen = 0;
+
+
+ // Skip over Name;
+ while (pTemp < m_pEndBuffer)
+ {
+ nCharCount = *pTemp;
+ pTemp++;
+
+ if (nCharCount == 0)
+ break;
+
+ if ((nCharCount&(DNS_NAME_OFFSET_MASK)) == DNS_NAME_OFFSET_MASK)
+ { // offset string
+ pTemp++;
+ break;
+ }
+
+ if (nCharCount > DNS_LABEL_MAX_LENGTH)
+ {
+ printf("%d. label too long %d\n",m_nMaxItems-1,nCharCount);
+ }
+
+ if (pTemp + nCharCount < m_pEndBuffer)
+ pTemp += nCharCount;
+ else
+ pTemp = m_pEndBuffer;
+ }
+
+ pRecord->m_nNameLength = (BJ_UINT32)(pTemp - pRecord->m_pStartofRec);
+
+ if (eItemType == CDNSRecord::Question)
+ {
+ pRecord->m_RecType = PF_GET_UINT16(pTemp,0);
+ pRecord->m_RecClass = PF_GET_UINT16(pTemp,2);
+ pRecord->m_nTTL = PF_GET_UINT16(pTemp,4);
+
+ // printf("Namelen=%u, Type=%u, class=%u, TTL=%u, RDLength=%u\n", m_dnsItems[ndnsIndex].nNameLength,nType,nClass,nTTL,nRdataLen);
+
+ pTemp += 4;
+ }
+ else
+ {
+
+ pRecord->m_RecType = PF_GET_UINT16(pTemp,0);
+ pRecord->m_RecClass = PF_GET_UINT16(pTemp,2);
+
+ pRecord->m_nTTL = PF_GET_UINT32(pTemp,4);
+ pRecord->m_nRdataLen = PF_GET_UINT16(pTemp,8);
+ if (nRdataLen > 1024*10)
+ {
+ printf("large Rdata ??");
+ nRdataLen2 = (pTemp[8] << 8) | pTemp[9];
+
+ }
+ // printf("Namelen=%u, Type=%u, class=%u, TTL=%u, RDLength=%u\n", m_dnsItems[ndnsIndex].nNameLength,m_dnsItems[ndnsIndex].RecType,nClass,nTTL,m_dnsItems[ndnsIndex].nRdataLen);
+ pTemp += 10 + pRecord->m_nRdataLen;
+ }
+
+ m_pCurrentBuffer = pTemp;
+
+ return true;
+}
+
+BJ_BOOL CDNSFrame::IsQueryFrame()
+{
+ return !(m_nFlags&0x8000);
+}
+
+#define UNICAST_RESPONDS_REQUESTED 0x8000
+BJ_BOOL CDNSFrame::IsWakeFrame()
+{
+
+ for (int i=0; i < m_nQuestionCount; i++)
+ {
+ if (m_dnsItems[i].m_RecType == DNS_TYPE_PTR && m_dnsItems[i].m_RecClass & UNICAST_RESPONDS_REQUESTED)
+ return true;
+ }
+
+ return false;
+}
+#define DNS_HEADER_TRUNCATEED 0x0200
+BJ_BOOL CDNSFrame::IsTruncatedFrame()
+{
+ return (m_nFlags&DNS_HEADER_TRUNCATEED);
+}
+
+
+BJ_BOOL CDNSFrame::HasOnlyService(BJString sName, BJ_INT16 nRecType)
+{
+ /* if (IsQueryFrame())
+ {
+ for (int i=0; i < m_nQuestionCount; i++)
+ {
+ CBJString sRecordName;
+ m_dnsItems[i].GetDnsRecordName(sRecordName, 0);
+ if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
+ return false;
+
+ if (!sRecordName.Contains(sName.GetBuffer()))
+ return false;
+ }
+ }
+ else*/
+ {
+ for (int i=0; i < m_nQuestionCount+m_nAnswersCount; i++)
+ {
+ BJString sRecordName;
+ m_dnsItems[i].GetDnsRecordName(sRecordName, 0,99);
+ if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
+ return false;
+
+ if (!sRecordName.Contains(sName.GetBuffer()))
+ return false;
+ }
+
+
+ }
+
+
+ return true;
+}
+
+CDNSRecord* CDNSFrame::FindAdditionRecord(BJString& sName,BJ_INT16 nRecType)
+{
+ for (int i = 0; i < m_nMaxItems; i++)
+ {
+ if (m_dnsItems[i].m_RecType != nRecType && nRecType != -1)
+ continue;
+ BJString sRecordName;
+ m_dnsItems[i].GetDnsRecordName(sRecordName, 0,99);
+ if (sRecordName == sName)
+ return &m_dnsItems[i];
+ }
+ return NULL;
+}
+
+void CDNSFrame::SetAddress(BJIPAddr *pSourceIPAddress,BJMACAddr *pSourceMACAddress)
+{
+ m_SourceIPAddress = *pSourceIPAddress;
+ m_SourceMACAddress = *pSourceMACAddress;
+
+
+}
+
+
+bool CDNSFrame::GetTracingInfo(BJ_UINT8 &platform, BJ_UINT32 &version, BJMACAddr &)
+{
+ // Find OPT record
+ for (int i = m_nQuestionCount + m_nAnswersCount + m_NSCOUNT; i < m_nMaxItems; i++)
+ {
+ if (m_dnsItems[i].m_RecType == DNS_TYPE_OPT)
+ {
+ BJ_UINT8* rdata = m_dnsItems[i].GetStartofRdata();
+
+ BJ_UINT8* rdataEnd = rdata + m_dnsItems[i].m_nRdataLen;
+
+ while (rdata < rdataEnd)
+ {
+ BJ_UINT16 type = PF_GET_UINT16(rdata,0);
+ BJ_UINT16 len = PF_GET_UINT16(rdata,2);
+
+ if (type == DNS_EDNS0_TRACE)
+ {
+ platform = PF_GET_UINT8(rdata,4);
+ if (len == 3) // EDNS field of length 3 <rdar://15101783>
+ {
+ version = static_cast<BJ_UINT32>(PF_GET_UINT16(rdata,5));
+ }
+ else if (len == 5) // EDNS field of length 5 <rdar://15235603>
+ {
+ version = static_cast<BJ_UINT32>(PF_GET_UINT32(rdata, 5));
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+ }
+
+
+ rdata += sizeof(BJ_UINT16)*2 + len;
+ }
+
+ }
+ }
+ return false;
+
+}
+
+
+
+
+
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/DNSFrame.h b/mDNSResponder/mDNSMacOSX/BonjourTop/source/DNSFrame.h
new file mode 100644
index 00000000..8e7ded7c
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/DNSFrame.h
@@ -0,0 +1,132 @@
+//
+// DNSFrame.h
+// TestTB
+//
+// Created by Terrin Eager on 9/26/12.
+//
+//
+
+#ifndef __TestTB__DNSFrame__
+#define __TestTB__DNSFrame__
+
+#include <iostream>
+#include "bjtypes.h"
+#include "bjstring.h"
+#include "bjIPAddr.h"
+#include "bjMACAddr.h"
+
+#define MAX_DNS_RECORDS_PER_FRAME 500
+
+#define DNS_TYPE_PTR 12
+#define DNS_TYPE_SRV 33
+#define DNS_TYPE_TXT 16
+#define DNS_TYPE_A 1
+#define DNS_TYPE_AAAA 28
+#define DNS_TYPE_OPT 41
+
+#define DNS_EDNS0_TRACE 65001
+
+class CDNSFrame;
+
+
+
+
+class CDNSRecord
+{
+public:
+ typedef enum {Question,Answer,ns,ar} dnsItemType;
+
+ void GetDnsRecordName(BJString& ReturnString,int nLabelToSkip,int nMaxLabel);
+ void GetDnsRecordNameFromBuffer(BJ_UINT8* pBuffer,BJString& ReturnString,int nLabelToSkip,int nMaxLabel);
+
+ BJ_UINT8* GetStartofRdata() {return m_pStartofRec+m_nNameLength+10;}; // 10 = type(2) +class(2) + ttl(4) + datalen(2)
+ void GetRdata(BJString& ReturnString,int nLabelToSkip,int nMaxLabel)
+ {
+ if (m_RecType == DNS_TYPE_SRV)
+ GetDnsRecordNameFromBuffer(GetStartofRdata()+6, ReturnString, nLabelToSkip, nMaxLabel); // 6 = Priority + Weight + Port
+ else
+ GetDnsRecordNameFromBuffer(GetStartofRdata(), ReturnString, nLabelToSkip, nMaxLabel);
+ }
+ dnsItemType m_dnsType;
+ BJ_UINT8* m_pStartofRec;
+ BJ_UINT32 m_nNameLength;
+ BJ_INT16 m_RecType;
+ BJ_INT16 m_RecClass;
+ BJ_UINT32 m_nTTL;
+ BJ_UINT32 m_nRdataLen;
+
+ CDNSFrame* m_pDNSFrame;
+};
+
+
+
+class CDNSFrame
+{
+public:
+
+ CDNSFrame();
+ bool ParseDNSFrame(BJ_UINT8* pBuffer,BJ_INT32 nLength,BJ_UINT64 frameTime);
+
+
+ CDNSRecord* GetDnsRecord(int nIndex);
+ CDNSRecord* FindAdditionRecord(BJString& sName, BJ_INT16 nType);
+
+ BJ_UINT16 GetQuestionCount() {return m_nQuestionCount;};
+ BJ_UINT16 GetAnswerCount(){return m_nAnswersCount;};
+ BJ_UINT16 GetMaxRecords(){return m_nMaxItems;};
+ BJ_UINT8* GetBuffer() { return m_pStartBuffer;};
+
+ BJ_BOOL ParseDnsRecord(CDNSRecord::dnsItemType eItemType);
+
+ BJ_BOOL IsQueryFrame();
+ BJ_BOOL IsWakeFrame();
+ BJ_BOOL IsTruncatedFrame();
+
+ BJ_BOOL HasOnlyService(BJString sName, BJ_INT16 nRecType);
+
+ void SetAddress(BJIPAddr *SourceIPAddress,BJMACAddr *SourceMACAddress);
+
+ bool GetTracingInfo(BJ_UINT8 &platform, BJ_UINT32 &version, BJMACAddr &mac);
+
+ BJ_UINT64 GetTime() {return m_Time;};
+
+
+ BJIPAddr m_Servicev4Address;
+ BJIPAddr m_Servicev6Address;
+
+ BJIPAddr m_SourceIPAddress;
+ BJMACAddr m_SourceMACAddress;
+
+protected:
+
+
+ BJ_UINT8* m_pStartBuffer;
+ BJ_UINT8* m_pEndBuffer;
+ BJ_UINT8* m_pCurrentBuffer;
+ BJ_INT32 m_nBufferLen;
+
+ BJ_INT32 m_nFrameLen;
+
+ // Header
+ BJ_UINT16 m_nId;
+ BJ_UINT16 m_nFlags;
+
+ BJ_UINT16 m_nQuestionCount;
+ BJ_UINT16 m_nAnswersCount;
+ BJ_UINT16 m_NSCOUNT;
+ BJ_UINT16 m_ARCOUNT;
+
+
+ CDNSRecord m_dnsItems[MAX_DNS_RECORDS_PER_FRAME];
+
+ int m_nMaxItems;
+
+ BJ_UINT64 m_Time;
+
+};
+
+
+
+
+
+#endif /* defined(__TestTB__DNSFrame__) */
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/Frame.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/Frame.cpp
new file mode 100644
index 00000000..bbc1d821
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/Frame.cpp
@@ -0,0 +1,201 @@
+//
+// Frame.cpp
+// TestTB
+//
+// Created by Terrin Eager on 1/19/13.
+//
+//
+
+#include "Frame.h"
+
+#define EthernetHeaderStart 14
+
+void Frame::Set(BJ_UINT8* data,BJ_UINT32 len,BJ_UINT64 t)
+{
+ frameData = data;
+ length = len;
+ frameTime = t;
+}
+
+BJ_UINT8* Frame::GetEthernetStart()
+{
+ //todo Support other media types
+ return frameData;
+}
+BJ_UINT8* Frame::GetIPStart()
+{
+ BJ_UINT8* ether = GetEthernetStart();
+
+ return ether + 14;
+
+}
+BJ_UINT8* Frame::GetUDPStart()
+{
+ BJ_UINT8* ip = GetIPStart();
+
+ BJ_UINT16 nSize = *((__uint16_t*) (ip));
+ BJ_UINT16 nVerison = (nSize&0xf0) >> 4;
+ if (nVerison == 0x4)
+ {
+ m_bCurrentFrameIPversion = 4;
+
+ nSize &= 0x0f;
+ nSize *= 4;
+
+
+ BJ_UINT8 nProtocol = *(ip+9);
+
+ if (nProtocol != 17) // Not UDP
+ return NULL;
+ }
+ else if (nVerison == 0x6)
+ {
+ m_bCurrentFrameIPversion = 6;
+ BJ_UINT8 nProtocol = *(ip+6);
+
+ if (nProtocol != 17) // Not UDP
+ return NULL;
+ nSize = 40;
+
+ }
+
+ return ip+nSize;
+}
+
+BJ_UINT8* Frame::GetBonjourStart()
+{
+ BJ_UINT8* udp = GetUDPStart();
+
+
+ if (udp == NULL)
+ return NULL;
+
+ BJ_UINT16 nSourcePort = *((__uint16_t*)(udp));
+ BJ_UINT16 nDestPort = *((__uint16_t*)(udp+2));
+ BJ_UINT16 nBonjourPort = htons(5353);
+
+ if (nSourcePort == nBonjourPort && nDestPort == nBonjourPort)
+ return (udp+8);
+ else
+ return NULL;
+
+}
+
+
+
+BJIPAddr* Frame::GetSrcIPAddr()
+{
+ BJ_UINT8* ip = GetIPStart();
+
+ BJ_UINT16 nSize = (__uint16_t) (*ip);
+ BJ_UINT16 nVerison = (nSize&0xf0) >> 4;
+ if (nVerison == 0x4)
+ {
+ m_bCurrentFrameIPversion = 4;
+
+ struct in_addr* ipi_addr;
+
+ ipi_addr = (in_addr*)(ip+12);
+
+ sourceIPAddr.Set(ipi_addr);
+
+ }
+ else if (nVerison == 0x6)
+ {
+ m_bCurrentFrameIPversion = 6;
+ BJ_UINT8* ipi_addr;
+
+ ipi_addr = (ip+8);
+
+ sourceIPAddr.Setv6Raw(ipi_addr);
+
+ }
+
+ return &sourceIPAddr;
+}
+
+BJIPAddr* Frame::GetDestIPAddr()
+{
+ BJ_UINT8* ip = GetIPStart();
+
+ BJ_UINT16 nSize = *((__uint16_t*) (ip));
+ BJ_UINT16 nVerison = (nSize&0xf0) >> 4;
+ if (nVerison == 0x4)
+ {
+ m_bCurrentFrameIPversion = 4;
+
+ struct in_addr* ipi_addr;
+
+ ipi_addr = (in_addr*)(ip+16);
+
+ destIPAddr.Set(ipi_addr);
+
+ }
+ else if (nVerison == 0x6)
+ {
+ m_bCurrentFrameIPversion = 6;
+ struct in6_addr* ipi_addr;
+
+ ipi_addr = (in6_addr*)(ip+24);
+
+ destIPAddr.Set(ipi_addr);
+
+ }
+ return &destIPAddr;
+}
+
+BJMACAddr* Frame::GetSrcMACAddr()
+{
+ sourceMACAddr.Set(GetEthernetStart()+6);
+
+ return &sourceMACAddr;
+}
+
+BJMACAddr* Frame::GetDestMACAddr()
+{
+ destMACAddr.Set(GetEthernetStart());
+
+ return &destMACAddr;
+}
+
+void Frame::SetDatalinkType(BJ_DATALINKTYPE datalinkType)
+{
+ m_datalinkType = datalinkType;
+}
+
+BJ_UINT32 Frame::GetLinklayerHeaderLength()
+{
+ switch (m_datalinkType)
+ {
+ case (BJ_DLT_EN10MB):
+ return EthernetHeaderStart;
+ case (BJ_DLT_IEEE802_11):
+ return Get80211HeaderLength();
+ default:
+ // Default to Ethernet
+ return EthernetHeaderStart;
+ }
+}
+
+BJ_UINT32 Frame::Get80211HeaderLength()
+{
+ // XXX: 802.11 header is tricky since it has no "length" field.
+ // We should look at "FrameControl" and derive the length manually for each frame.
+ BJ_UINT16 * frameControl = (BJ_UINT16*)GetEthernetStart();
+
+ // [SubType] [Type - Ver]
+
+ bool isFrameData = (0x0C & *frameControl) == 0x08;
+ bool isQosData = ((0xF0 & *frameControl) == 0x80) && isFrameData;
+
+ if (isQosData)
+ {
+ //Standard (24) + QoS (2) + LLC (3) + SNAP (5)
+ return 24 + 2 + 3 + 5;
+ }
+ else
+ {
+ //Standard (24) + LLC (3) + SNAP (5)
+ return 24 + 3 + 5;
+ }
+}
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/Frame.h b/mDNSResponder/mDNSMacOSX/BonjourTop/source/Frame.h
new file mode 100644
index 00000000..f8e3ade6
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/Frame.h
@@ -0,0 +1,66 @@
+//
+// Frame.h
+// TestTB
+//
+// Created by Terrin Eager on 1/19/13.
+//
+//
+
+#ifndef __TestTB__Frame__
+#define __TestTB__Frame__
+
+#include "bjtypes.h"
+#include "bjIPAddr.h"
+#include "bjMACAddr.h"
+
+class Frame
+{
+public:
+ void Set(BJ_UINT8* data,BJ_UINT32 len,BJ_UINT64 t);
+ BJ_UINT8* GetEthernetStart();
+ BJ_UINT8* GetIPStart();
+ BJ_UINT8* GetUDPStart();
+ BJ_UINT8* GetBonjourStart();
+
+ BJIPAddr* GetSrcIPAddr();
+ BJIPAddr* GetDestIPAddr();
+
+ BJMACAddr* GetSrcMACAddr();
+ BJMACAddr* GetDestMACAddr();
+
+ int m_bCurrentFrameIPversion;
+
+ BJ_UINT64 GetTime(){ return frameTime; };
+
+ enum BJ_DATALINKTYPE {
+ BJ_DLT_EN10MB = 1,
+ BJ_DLT_IEEE802_11=105
+ };
+
+ void SetDatalinkType (BJ_DATALINKTYPE datalinkType);
+private:
+
+ BJ_UINT32 GetLinklayerHeaderLength();
+
+ //Get the header length of the current 802.11 frame.
+ BJ_UINT32 Get80211HeaderLength();
+
+ BJ_UINT8* frameData;
+ BJ_UINT32 length;
+
+ BJIPAddr sourceIPAddr;
+ BJIPAddr destIPAddr;
+
+ BJMACAddr sourceMACAddr;
+ BJMACAddr destMACAddr;
+
+ BJ_UINT64 frameTime; // in microseconds
+
+
+ BJ_DATALINKTYPE m_datalinkType = BJ_DLT_EN10MB;
+
+
+};
+
+
+#endif /* defined(__TestTB__Frame__) */
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/LLRBTree.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/LLRBTree.cpp
new file mode 100644
index 00000000..37ce9d76
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/LLRBTree.cpp
@@ -0,0 +1,157 @@
+//
+// LLRBTree.cpp
+// TestTB
+//
+// Created by Terrin Eager on 7/9/12.
+//
+//
+
+#include "LLRBTree.h"
+
+
+
+#include <stdio.h>
+#import <stdlib.h>
+#include <string.h>
+#include <curses.h>
+
+#include "bjtypes.h"
+
+#include <time.h>
+
+void test3();
+
+
+
+
+
+
+////////////////////
+
+////////////////
+// test case
+// Integrity checks
+
+/*********************
+BJ_BOOL isBST(CRBNode* pRecord, BJ_UINT64 min, BJ_UINT64 max);
+BJ_BOOL is234(CRBNode* pRecord);
+BJ_BOOL isBalanced(CLLRBTree* pCache);
+BJ_BOOL isBalancedNode(CRBNode* pRecord, int black);
+
+BJ_BOOL check(CLLRBTree* pCache)
+{ // Is this tree a red-black tree?
+ BJ_BOOL bBST = isBST(pCache->GetRoot(),pCache->minRecord(pCache->GetRoot())->nKey,pCache->maxRecord(pCache->GetRoot())->nKey);
+ BJ_BOOL b234 = is234(pCache->GetRoot());
+ BJ_BOOL bisBalanced = isBalanced(pCache);
+
+ printf("Bst=%d,234=%d, Balanced=%d",bBST,b234,bisBalanced);
+
+ return bBST && b234 && bisBalanced;
+}
+
+
+BJ_BOOL isBST(CRBNode* pRecord, BJ_UINT64 min, BJ_UINT64 max)
+{ // Are all the values in the BST rooted at x between min and max,
+ // and does the same property hold for both subtrees?
+ if (pRecord == NULL) return 1;
+ if ((pRecord->nKey > min) || (max > pRecord->nKey)) return 0;
+ return isBST(pRecord->m_rbLeft, min, pRecord->nKey) && isBST(pRecord->m_rbRight, pRecord->nKey, max);
+}
+BJ_BOOL is234(CRBNode* pRecord)
+{ // Does the tree have no red right links, and at most two (left)
+ // red links in a row on any path?
+ if (pRecord == NULL) return 1;
+ if (IsRed(pRecord->m_rbRight)) return 0;
+ if (IsRed(pRecord))
+ if (IsRed(pRecord->m_rbLeft))
+ if (IsRed(pRecord->m_rbLeft->m_rbLeft)) return 0;
+ return is234(pRecord->m_rbLeft) && is234(pRecord->m_rbRight);
+}
+
+BJ_BOOL isBalanced(CLLRBTree* pCache)
+{ // Do all paths from root to leaf have same number of black edges?
+ int black = 0; // number of black links on path from root to min
+ CRBNode* pRecord = pCache->m_Root;
+ while (pRecord != NULL)
+ {
+ if (!IsRed(pRecord)) black++;
+ pRecord = pRecord->m_rbLeft;
+ }
+ return isBalancedNode(pCache->root, black);
+}
+
+BJ_BOOL isBalancedNode(CRBNode* pRecord, int black)
+{ // Does every path from the root to a leaf have the given number
+ // of black links?
+ if (pRecord == NULL && black == 0) return 1;
+ else if (pRecord == NULL && black != 0) return 0;
+ if (!IsRed(pRecord)) black--;
+ return isBalancedNode(pRecord->m_rbLeft, black) && isBalancedNode(pRecord->m_rbRight, black);
+}
+****************/
+
+/**
+// sample code for testing
+void CStringNode_test()
+{
+ CStringTree Cache;
+
+
+ char DummyData[] = {'a','b','d','x'};
+ BJ_UINT64 i = 0;
+ CStringNode* pRecord;
+
+ while (i++ < sizeof(DummyData))
+ {
+
+ pRecord = (CStringNode*)Cache.FindwithAddRecord(&i);
+ if (pRecord)
+ pRecord->m_Value[0] = DummyData[i];
+ }
+
+ i = 2;
+ pRecord = (CStringNode*)Cache.Find(&i);
+
+
+ test3();
+
+}
+
+void test3()
+{
+ // float nSaveCPU =0;
+
+ CStringTree Cache;
+
+ CStringNode test;
+
+
+ BJ_UINT64 i = 0;
+ long starttime = clock();
+ float elapsedtime = 0;
+ CStringNode* pRecord;
+
+ // nSaveCPU = getCPUtime();
+ while (i++ < 1000000)
+ {
+ pRecord = (CStringNode*) Cache.FindwithAddRecord(&i);
+ if (pRecord)
+ memccpy(pRecord->m_Value, "test",4, 1);
+
+ // snprintf(pRecord->m_Value,sizeof(pRecord->m_Value),"%llx",key.m_nKey);
+ }
+ elapsedtime = clock() - starttime;
+ elapsedtime /= CLOCKS_PER_SEC;
+
+ // elapsedtime = getCPUtime() - nSaveCPU;
+
+ printf("Test elapsed time %f, check = %d\n",elapsedtime,0);
+
+
+
+
+}
+
+*****/
+///////////////
+
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/LLRBTree.h b/mDNSResponder/mDNSMacOSX/BonjourTop/source/LLRBTree.h
new file mode 100644
index 00000000..7b7ea0f9
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/LLRBTree.h
@@ -0,0 +1,460 @@
+//
+// LLRBTree.h
+// TestTB
+//
+// Created by Terrin Eager on 7/9/12.
+//
+// based on rbtree.h but converted to C++
+// ll from http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf
+
+#ifndef __TestTB__LLRBTree__
+#define __TestTB__LLRBTree__
+
+#include <iostream>
+#include "bjtypes.h"
+#include <sys/socket.h>
+#include "bjstring.h"
+#include "bjIPAddr.h"
+
+template <class KeyType>
+class CRBNode
+{
+public:
+ CRBNode() {m_bIsRed = true; m_rbLeft = m_rbRight = NULL;};
+ virtual ~CRBNode();
+
+ inline virtual BJ_COMPARE Compare(KeyType* pKey) = 0; // Key values are equal
+
+ inline virtual void CopyNode(CRBNode* pSource) = 0;
+ inline virtual void Init()=0;
+ inline virtual void Clear()=0;
+
+ CRBNode* GetMinNode();
+ CRBNode* GetMaxNode();
+
+
+ inline CRBNode* RotateNodeLeft();
+ inline CRBNode* RotateNodeRight();
+
+
+ CRBNode* AddRecord(CRBNode* pNewRecord);
+
+ void FlipColor();
+
+ BJ_UINT64 GetCount();
+
+ CRBNode* Fixup();
+
+ CRBNode* MoveRedLeft();
+ CRBNode* MoveRedRight();
+
+ void CallBack(int(*callback)(const void*, const void*),void* pParam);
+
+
+ bool m_bIsRed;
+
+//protected:
+ KeyType m_Key;
+ CRBNode* m_rbLeft;
+ CRBNode* m_rbRight;
+
+
+};
+
+template <class KeyType, class NodeType>
+class CLLRBTree
+{
+
+public:
+ CLLRBTree();
+ virtual ~CLLRBTree() { if (m_Root) delete m_Root;};
+
+ NodeType* Find(KeyType* pKey);
+
+ NodeType* FindwithAddRecord(KeyType* pKey);
+ NodeType* AddRecord(KeyType* pKey);
+ void RemoveRecord(KeyType* pKey);
+
+ NodeType* GetRoot() { return m_Root;};
+ void ClearAll() { delete m_Root; m_Root = NULL;};
+
+ BJ_UINT64 GetCount();
+
+
+ NodeType* GetMinNode();
+ NodeType* GetMaxNode();
+
+ NodeType* deleteMin(NodeType* pRecord);
+
+
+private:
+ NodeType* RemoveRecord(NodeType* pRecord,KeyType* pKey);
+
+ virtual NodeType* newNode(KeyType* pKey) { return new NodeType(pKey);}
+ virtual void freeNode(NodeType * pNode){ delete pNode;};
+
+
+ NodeType* m_Root;
+
+
+};
+/////////////////
+
+
+template<class KeyType>
+CRBNode<KeyType>::~CRBNode()
+{
+ if (m_rbLeft)
+ delete m_rbLeft;
+ if (m_rbRight)
+ delete m_rbRight;
+
+}
+
+
+
+
+template<class KeyType>
+CRBNode<KeyType>* CRBNode<KeyType>::RotateNodeLeft()
+{
+ CRBNode<KeyType>* pTemp = m_rbRight;
+ m_rbRight = pTemp->m_rbLeft;
+ pTemp->m_rbLeft = this;
+ pTemp->m_bIsRed = pTemp->m_rbLeft->m_bIsRed;
+ pTemp->m_rbLeft->m_bIsRed = 1;
+
+ return pTemp;
+}
+
+
+template<class KeyType>
+CRBNode<KeyType>* CRBNode<KeyType>::RotateNodeRight()
+{
+ CRBNode<KeyType>* pTemp = m_rbLeft;
+ m_rbLeft = pTemp->m_rbRight;
+ pTemp->m_rbRight = this;
+ pTemp->m_bIsRed = pTemp->m_rbRight->m_bIsRed;
+ pTemp->m_rbRight->m_bIsRed = 1;
+
+ return pTemp;
+}
+
+template<class KeyType>
+BJ_UINT64 CRBNode<KeyType>::GetCount()
+{
+ BJ_UINT64 Num = 1;
+ if (m_rbLeft)
+ Num += m_rbLeft->GetCount();
+ if (m_rbRight)
+ Num += m_rbRight->GetCount();
+
+ return Num;
+
+}
+
+template<class KeyType>
+void CRBNode<KeyType>::FlipColor()
+{
+ m_bIsRed = !m_bIsRed;
+ if (m_rbLeft)
+ m_rbLeft->m_bIsRed = !m_rbLeft->m_bIsRed;
+ if (m_rbRight)
+ m_rbRight->m_bIsRed = !m_rbRight->m_bIsRed;
+
+}
+
+template<class KeyType>
+CRBNode<KeyType>* CRBNode<KeyType>::Fixup()
+{
+ // fix the tree balance
+ CRBNode<KeyType>* pNode = this;
+
+ if (m_rbRight && m_rbRight->m_bIsRed) // fix right leaning reds on the way up
+ pNode = RotateNodeLeft();
+
+ if (pNode && pNode->m_rbLeft && pNode->m_rbLeft->m_bIsRed && pNode->m_rbLeft->m_rbLeft && pNode->m_rbLeft->m_rbLeft->m_bIsRed) // fix two reds in a row on the way up
+ pNode = RotateNodeRight();
+
+ if (pNode && pNode->m_rbRight && pNode->m_rbRight->m_bIsRed && pNode->m_rbLeft && pNode->m_rbLeft->m_bIsRed) //split 4-nodes on the way up
+ pNode->FlipColor();
+
+ return pNode;
+}
+
+template<class KeyType>
+CRBNode<KeyType>* CRBNode<KeyType>::MoveRedLeft()
+{
+ CRBNode* pNode = this;
+ FlipColor();
+
+ if (m_rbRight && m_rbRight->m_rbLeft && m_rbRight->m_rbLeft->m_bIsRed)
+ {
+ m_rbRight = m_rbRight->RotateNodeRight();
+ pNode = RotateNodeLeft();
+ if (pNode)
+ pNode->FlipColor();
+ }
+ return pNode;
+}
+
+template<class KeyType>
+CRBNode<KeyType>* CRBNode<KeyType>::MoveRedRight()
+{
+ CRBNode* pNode = this;
+ FlipColor();
+
+ if (m_rbLeft && m_rbLeft->m_rbLeft && m_rbLeft->m_rbLeft->m_bIsRed)
+ {
+ pNode = RotateNodeRight();
+ if (pNode)
+ pNode->FlipColor();
+ }
+
+ return pNode;
+}
+template<class KeyType>
+CRBNode<KeyType>* CRBNode<KeyType>::AddRecord(CRBNode* pNewRecord)
+{
+
+ switch (Compare(&pNewRecord->m_Key))
+ {
+ case BJ_GT:
+ if (m_rbRight)
+ m_rbRight = m_rbRight->AddRecord(pNewRecord);
+ else
+ m_rbRight = pNewRecord;
+
+ break;
+ case BJ_LT:
+ if (m_rbLeft)
+ m_rbLeft = m_rbLeft->AddRecord(pNewRecord);
+ else
+ m_rbLeft = pNewRecord;
+
+ break;
+ default: // equal
+ pNewRecord->m_bIsRed = false;
+ pNewRecord->m_rbLeft = m_rbLeft;
+ m_rbLeft = pNewRecord;
+ return this;
+ };
+
+ // fix the tree balance
+ CRBNode* pRecord = this;
+
+ // fix the tree balance
+
+ if (pRecord && pRecord->m_rbRight && pRecord->m_rbRight->m_bIsRed) // fix right leaning reds on the way up
+ pRecord = pRecord->RotateNodeLeft();
+
+ if (pRecord && pRecord->m_rbLeft && pRecord->m_rbLeft->m_bIsRed && pRecord->m_rbLeft->m_rbLeft && pRecord->m_rbLeft->m_rbLeft->m_bIsRed) // fix two reds in a row on the way up
+ pRecord = pRecord->RotateNodeRight();
+
+ if (pRecord && pRecord->m_rbRight && pRecord->m_rbRight->m_bIsRed && pRecord->m_rbLeft && pRecord->m_rbLeft->m_bIsRed) //split 4-nodes on the way up
+ pRecord->FlipColor();
+
+
+ return pRecord;
+}
+
+
+
+template<class KeyType>
+CRBNode<KeyType>* CRBNode<KeyType>::GetMinNode()
+{
+ CRBNode* pRecord = this;
+ while (pRecord && pRecord->m_rbLeft)
+ pRecord = pRecord->m_rbLeft;
+
+ return pRecord;
+}
+template<class KeyType>
+CRBNode<KeyType>* CRBNode<KeyType>::GetMaxNode()
+{
+ CRBNode* pRecord = this;
+ while (pRecord && pRecord->m_rbRight)
+ pRecord = pRecord->m_rbRight;
+
+ return pRecord;
+}
+
+template<class KeyType>
+void CRBNode<KeyType>::CallBack(int(*callback)(const void*, const void*),void* pParam)
+{
+
+ if (m_rbLeft)
+ m_rbLeft->CallBack(callback,pParam);
+
+ callback(this,pParam);
+
+ if (m_rbRight)
+ m_rbRight->CallBack(callback,pParam);
+
+
+}
+
+
+
+///////////
+template<class KeyType,class NodeType>
+CLLRBTree<KeyType,NodeType>::CLLRBTree()
+{
+ m_Root = NULL;
+}
+
+template<class KeyType,class NodeType>
+NodeType* CLLRBTree<KeyType,NodeType>::Find(KeyType* pKey)
+{
+
+ CRBNode<KeyType>* pNode = m_Root;
+
+ while (pNode)
+ {
+ switch (pNode->Compare(pKey))
+ {
+ case BJ_GT:
+ pNode = pNode->m_rbRight;
+ break;
+ case BJ_LT:
+ pNode = pNode->m_rbLeft;
+ break;
+ default:
+ return (NodeType*)pNode;
+ break;
+ }
+ }
+
+ return NULL;
+
+}
+
+template<class KeyType,class NodeType>
+NodeType* CLLRBTree<KeyType,NodeType>::AddRecord(KeyType* pKey)
+{
+ NodeType* pRecord = newNode(pKey);
+ if (m_Root)
+ m_Root = (NodeType*) m_Root->AddRecord(pRecord);
+ else
+ m_Root = pRecord;
+
+ if (m_Root)
+ m_Root->m_bIsRed = false;
+
+ return pRecord;
+}
+
+template<class KeyType,class NodeType>
+NodeType* CLLRBTree<KeyType,NodeType>::FindwithAddRecord(KeyType* pKey)
+{
+ NodeType* pRecord = NULL;
+
+ pRecord = Find(pKey);
+
+ if (pRecord == NULL)
+ pRecord = AddRecord(pKey);
+
+ return pRecord;
+}
+
+template<class KeyType,class NodeType>
+void CLLRBTree<KeyType,NodeType>::RemoveRecord(KeyType* pKey)
+{
+ m_Root = RemoveRecord(m_Root,pKey);
+}
+
+template<class KeyType,class NodeType>
+NodeType* CLLRBTree<KeyType,NodeType>::deleteMin(NodeType* pRecord)
+{
+ if (pRecord->m_rbLeft == NULL)
+ {
+ freeNode(pRecord);
+ return NULL;
+ }
+
+ if (!(pRecord->m_rbLeft && pRecord->m_rbLeft->m_bIsRed) && !(pRecord->m_rbLeft && pRecord->m_rbLeft->m_rbLeft &&pRecord->m_rbLeft->m_rbLeft->m_bIsRed))
+ pRecord = (NodeType*)pRecord->MoveRedLeft();
+
+ pRecord->m_rbLeft = deleteMin((NodeType*)pRecord->m_rbLeft);
+
+ return (NodeType*)pRecord->Fixup();
+}
+
+template<class KeyType,class NodeType>
+NodeType* CLLRBTree<KeyType,NodeType>::RemoveRecord(NodeType* pRecord,KeyType* pKey)
+{
+ NodeType* pTempRecord = NULL;
+
+ if (pRecord == NULL)
+ return NULL;
+
+ if (pRecord->Compare(pKey) == BJ_LT)
+ {
+ if (!(pRecord->m_rbLeft &&pRecord->m_rbLeft->m_bIsRed) && !(pRecord->m_rbLeft && pRecord->m_rbLeft->m_rbLeft &&pRecord->m_rbLeft->m_rbLeft->m_bIsRed))
+ pRecord->MoveRedLeft();
+ pRecord = RemoveRecord((NodeType*)pRecord->m_rbLeft, pKey);
+ }
+ else
+ {
+ if (pRecord->m_rbLeft &&pRecord->m_rbLeft->m_bIsRed)
+ pRecord->RotateNodeRight();
+
+ if(pRecord->Compare(pKey) == BJ_EQUAL && pRecord->m_rbRight == NULL)
+ {
+ freeNode(pRecord);
+ return NULL;
+ }
+
+ if (!(pRecord->m_rbRight && pRecord->m_rbRight->m_bIsRed) && !(pRecord->m_rbRight && pRecord->m_rbRight->m_rbLeft && pRecord->m_rbRight->m_rbLeft->m_bIsRed))
+ pRecord = (NodeType*)pRecord->MoveRedRight();
+
+ if (pRecord->Compare(pKey) == BJ_EQUAL)
+ {
+ pTempRecord = (NodeType*)pRecord->GetMinNode();
+ pRecord->CopyNode(pTempRecord);
+ pRecord->m_rbRight = deleteMin((NodeType*)pRecord->m_rbRight);
+ }
+ else
+ {
+ pRecord->m_rbRight = RemoveRecord((NodeType*)pRecord->m_rbRight, pKey);
+ }
+ }
+ return pRecord?(NodeType*)pRecord->Fixup():NULL;
+}
+
+
+
+
+template<class KeyType,class NodeType>
+BJ_UINT64 CLLRBTree<KeyType,NodeType>::GetCount()
+{
+ if (m_Root)
+ return m_Root->GetCount();
+ else
+ return 0;
+}
+
+template<class KeyType,class NodeType>
+NodeType* CLLRBTree<KeyType,NodeType>::GetMinNode()
+{
+ if (m_Root)
+ return m_Root->GetMinNode();
+ else
+ return NULL;
+
+}
+
+template<class KeyType,class NodeType>
+NodeType* CLLRBTree<KeyType,NodeType>::GetMaxNode()
+{
+ if (m_Root)
+ return m_Root->GetMaxNode();
+ else
+ return NULL;
+
+}
+
+
+
+
+
+#endif /* defined(__TestTB__LLRBTree__) */
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjIPAddr.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjIPAddr.cpp
new file mode 100644
index 00000000..188f962e
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjIPAddr.cpp
@@ -0,0 +1,312 @@
+//
+// bjIPAddr.cpp
+// TestTB
+//
+// Created by Terrin Eager on 1/19/13.
+//
+//
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "bjIPAddr.h"
+#include "bjstring.h"
+
+
+// static
+sockaddr_storage BJIPAddr::emptySockAddrStorage;
+
+
+
+BJIPAddr::BJIPAddr()
+{
+ memset(&emptySockAddrStorage,0,sizeof(emptySockAddrStorage));
+ Empty();
+}
+
+BJIPAddr::BJIPAddr(const BJIPAddr& src)
+{
+ memcpy(&sockAddrStorage,&src.sockAddrStorage,sizeof(sockAddrStorage));
+ IPv4SubNet = src.IPv4SubNet;
+}
+void BJIPAddr::Empty()
+{
+ memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
+ IPv4SubNet = 0;
+
+}
+
+bool BJIPAddr::IsBonjourMulticast()
+{
+ bool bResult = false;
+
+ struct in_addr BonjourMulicastAddrIPv4= {0xFB0000E0};
+
+ struct in6_addr BonjourMulicastAddrIPv6 = {{{ 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB }}};
+
+
+ if (sockAddrStorage.ss_family == AF_INET)
+ {
+ struct sockaddr_in* pAddrIn = (sockaddr_in*) &sockAddrStorage;
+ return (pAddrIn->sin_addr.s_addr == BonjourMulicastAddrIPv4.s_addr);
+ }
+
+ if (sockAddrStorage.ss_family == AF_INET6)
+ {
+ struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
+ return (memcmp(&pAddrIn->sin6_addr,&BonjourMulicastAddrIPv6,sizeof(in6_addr)) == 0);
+ }
+
+
+ return bResult;
+
+}
+
+bool BJIPAddr::IsSameSubNet(BJIPAddr* pCheckAddr)
+{
+
+ if (IPv4SubNet == 0)
+ return true;
+
+ if (!pCheckAddr->IsIPv4())
+ return true;
+
+ in_addr_t Mask = 0xFFFFFFFF;
+
+ Mask = Mask << (32-IPv4SubNet);
+
+ endian_swap(Mask);
+
+ struct sockaddr_in* pMyAddrIn = (sockaddr_in*) &sockAddrStorage;
+ in_addr_t myNetworkAddress = pMyAddrIn->sin_addr.s_addr & Mask;
+
+ struct sockaddr_in* pCheckAddrIn = (sockaddr_in*) pCheckAddr->GetRawValue();
+ in_addr_t CheckNetworkAddress = pCheckAddrIn->sin_addr.s_addr & Mask;
+
+
+ return (myNetworkAddress == CheckNetworkAddress);
+}
+
+
+bool BJIPAddr::IsIPv4()
+{
+ return (sockAddrStorage.ss_family == AF_INET);
+}
+
+bool BJIPAddr::IsIPv6()
+{
+ return (sockAddrStorage.ss_family == AF_INET6);
+}
+
+bool BJIPAddr::IsIPv6LinkLocal()
+{
+ struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
+ return (pAddrIn->sin6_addr.__u6_addr.__u6_addr8[0] == 0xfe &&
+ pAddrIn->sin6_addr.__u6_addr.__u6_addr8[1] == 0x80);
+}
+bool BJIPAddr::IsEmpty()
+{
+ return (memcmp(&sockAddrStorage,&emptySockAddrStorage,sizeof(sockAddrStorage)) == 0);
+}
+
+bool BJIPAddr::IsEmptySubnet()
+{
+ return (IPv4SubNet == 0);
+}
+
+void BJIPAddr::Setv6(const char* pIPaddr)
+{
+ memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
+ struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
+
+ if (inet_pton(AF_INET6, pIPaddr, &pAddrIn->sin6_addr) && memcmp(&sockAddrStorage,&emptySockAddrStorage,sizeof(sockAddrStorage)) == 0)
+ pAddrIn->sin6_family = AF_INET6;
+}
+
+void BJIPAddr::Set(const char* pIPaddr)
+{
+ memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
+
+ if (pIPaddr == NULL || strlen(pIPaddr) == 0)
+ return;
+
+ BJString sIPAddr;
+ BJString sMask;
+
+ const char* pSeperator = strstr(pIPaddr,"/");
+ if (pSeperator)
+ {
+ sIPAddr.Set(pIPaddr, (BJ_UINT32)(pSeperator - pIPaddr));
+ sMask.Set(pSeperator+1);
+ }
+ else
+ {
+ sIPAddr.Set(pIPaddr);
+ }
+
+ struct sockaddr_in* pAddrIn = (sockaddr_in*) &sockAddrStorage;
+ pAddrIn->sin_family = AF_INET;
+ pAddrIn->sin_addr.s_addr = inet_addr(sIPAddr.GetBuffer());
+
+ IPv4SubNet = sMask.GetUINT32();
+
+}
+void BJIPAddr::Setv4Raw(BJ_UINT8* ipi4_addr)
+{
+
+ memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
+ struct sockaddr_in* pAddrIn = (sockaddr_in*) &sockAddrStorage;
+ pAddrIn->sin_family = AF_INET;
+ memcpy(&pAddrIn->sin_addr, ipi4_addr, sizeof(pAddrIn->sin_addr));
+
+}
+void BJIPAddr::Setv6Raw(BJ_UINT8* ipi6_addr)
+{
+
+ memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
+ struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
+
+ pAddrIn->sin6_family = AF_INET6;
+ memcpy(&pAddrIn->sin6_addr, ipi6_addr, sizeof(pAddrIn->sin6_addr));
+}
+
+void BJIPAddr::Set(struct in6_addr* ipi6_addr)
+{
+
+ memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
+ struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
+
+ pAddrIn->sin6_family = AF_INET6;
+ memcpy(&pAddrIn->sin6_addr, ipi6_addr, sizeof(pAddrIn->sin6_addr));
+}
+
+void BJIPAddr::Set(struct in_addr* ip_addr)
+{
+
+ memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
+ struct sockaddr_in* pAddrIn = (sockaddr_in*) &sockAddrStorage;
+ pAddrIn->sin_family = AF_INET;
+ pAddrIn->sin_addr = *ip_addr;
+}
+
+void BJIPAddr::Set(struct sockaddr_storage* pStorage)
+{
+ memcpy(&sockAddrStorage,pStorage,sizeof(sockAddrStorage));
+}
+
+sockaddr_storage* BJIPAddr::GetRawValue()
+{
+ return &sockAddrStorage;
+}
+
+struct in6_addr* BJIPAddr::Getin6_addr()
+{
+ struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
+ return &pAddrIn->sin6_addr;
+}
+
+BJ_UINT16 BJIPAddr::GetPortNumber()
+{
+ BJ_UINT16 port = 0;
+ if (sockAddrStorage.ss_family == AF_INET)
+ {
+ struct sockaddr_in* pAddrIn = (struct sockaddr_in*)&sockAddrStorage;
+ port = ntohs(pAddrIn->sin_port);
+ }
+ else if (sockAddrStorage.ss_family == AF_INET6)
+ {
+ struct sockaddr_in6* pAddrIn = (struct sockaddr_in6*)&sockAddrStorage;
+ port = ntohs(pAddrIn->sin6_port);
+ }
+ return port;
+}
+
+BJ_COMPARE BJIPAddr::Compare(BJIPAddr* pIPAddr)
+{
+ if (sockAddrStorage.ss_family > pIPAddr->sockAddrStorage.ss_family)
+ return BJ_GT;
+ if (sockAddrStorage.ss_family < pIPAddr->sockAddrStorage.ss_family)
+ return BJ_LT;
+
+ if (sockAddrStorage.ss_family == AF_INET)
+ {
+ struct sockaddr_in* pMyAddrIn = (sockaddr_in*) &sockAddrStorage;
+ struct sockaddr_in* pAddrIn = (sockaddr_in*) &pIPAddr->sockAddrStorage;
+ if (pMyAddrIn->sin_addr.s_addr > pAddrIn->sin_addr.s_addr)
+ return BJ_GT;
+ if (pMyAddrIn->sin_addr.s_addr < pAddrIn->sin_addr.s_addr)
+ return BJ_LT;
+ return BJ_EQUAL;
+
+ }
+ else
+ {
+ struct sockaddr_in6* pMyAddrIn = (sockaddr_in6*) &sockAddrStorage;
+ struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &pIPAddr->sockAddrStorage;
+
+ int result = memcmp(&pMyAddrIn->sin6_addr, &pAddrIn->sin6_addr, sizeof(sockaddr_in6));
+
+ if (result > 0)
+ return BJ_GT;
+ if (result < 0)
+ return BJ_LT;
+ return BJ_EQUAL;
+ }
+
+
+}
+
+/*
+
+ take the mac address: for example 52:74:f2:b1:a8:7f
+ throw ff:fe in the middle: 52:74:f2:ff:fe:b1:a8:7f
+ reformat to IPv6 notation 5274:f2ff:feb1:a87f
+ convert the first octet from hexadecimal to binary: 52 -> 01010010
+ invert the bit at position 6 (counting from 0): 01010010 -> 01010000
+ convert octet back to hexadecimal: 01010000 -> 50
+ replace first octet with newly calculated one: 5074:f2ff:feb1:a87f
+ prepend the link-local prefix: fe80::5074:f2ff:feb1:a87f
+ */
+
+void BJIPAddr::CreateLinkLocalIPv6(BJ_UINT8* pmac)
+{
+ memset(&sockAddrStorage,0,sizeof(sockAddrStorage));
+ struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
+
+ pAddrIn->sin6_family = AF_INET6;
+
+ pAddrIn->sin6_addr.__u6_addr.__u6_addr8[0] = 0xfe;
+ pAddrIn->sin6_addr.__u6_addr.__u6_addr8[1] = 0x80;
+
+ pAddrIn->sin6_addr.__u6_addr.__u6_addr8[8] = *pmac;
+ pAddrIn->sin6_addr.__u6_addr.__u6_addr8[8] ^= 1 << 1; // invert 6 bit
+ pAddrIn->sin6_addr.__u6_addr.__u6_addr8[9] = *(pmac+1);
+ pAddrIn->sin6_addr.__u6_addr.__u6_addr8[10] = *(pmac+2);
+
+ pAddrIn->sin6_addr.__u6_addr.__u6_addr8[11] = 0xff;
+ pAddrIn->sin6_addr.__u6_addr.__u6_addr8[12] = 0xfe;
+
+
+ pAddrIn->sin6_addr.__u6_addr.__u6_addr8[13] = *(pmac+3);
+ pAddrIn->sin6_addr.__u6_addr.__u6_addr8[14] = *(pmac+4);
+ pAddrIn->sin6_addr.__u6_addr.__u6_addr8[15] = *(pmac+5);
+
+
+}
+
+char* BJIPAddr::GetString()
+{
+ memset(stringbuffer,0,sizeof(stringbuffer));
+ if (IsIPv6())
+ {
+ struct sockaddr_in6* pAddrIn = (sockaddr_in6*) &sockAddrStorage;
+ inet_ntop(AF_INET6, &pAddrIn->sin6_addr, stringbuffer, sizeof(stringbuffer));
+ }
+ else
+ {
+ struct sockaddr_in* pAddrIn = (sockaddr_in*) &sockAddrStorage;
+ inet_ntop(AF_INET, &pAddrIn->sin_addr, stringbuffer, sizeof(stringbuffer));
+ }
+ return stringbuffer;
+}
+
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjIPAddr.h b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjIPAddr.h
new file mode 100644
index 00000000..579355a6
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjIPAddr.h
@@ -0,0 +1,56 @@
+//
+// bjIPAddr.h
+// TestTB
+//
+// Created by Terrin Eager on 1/19/13.
+//
+//
+
+#ifndef __TestTB__bjIPAddr__
+#define __TestTB__bjIPAddr__
+
+#include <iostream>
+#include <sys/socket.h>
+#include "bjtypes.h"
+
+class BJIPAddr
+{
+public:
+ BJIPAddr();
+ BJIPAddr(const BJIPAddr& src);
+
+ void Empty();
+
+ bool IsBonjourMulticast();
+ bool IsSameSubNet(BJIPAddr* addr);
+
+ bool IsIPv4();
+ bool IsIPv6();
+ bool IsIPv6LinkLocal();
+ bool IsEmpty();
+ bool IsEmptySubnet();
+
+ void Set(const char* addr);
+ void Setv6(const char* addr);
+ void Set(struct in6_addr* ipi6_addr);
+ void Set(struct in_addr* ip_addr);
+ void Set(struct sockaddr_storage* sockStorage);
+ void Setv4Raw(BJ_UINT8* ipi4_addr);
+ void Setv6Raw(BJ_UINT8* ipi6_addr);
+
+ sockaddr_storage* GetRawValue();
+ struct in6_addr* Getin6_addr();
+
+ void CreateLinkLocalIPv6(BJ_UINT8* mac);
+ BJ_COMPARE Compare(BJIPAddr* addr);
+ BJ_UINT16 GetPortNumber();
+ char* GetString();
+private:
+ sockaddr_storage sockAddrStorage;
+ BJ_INT32 IPv4SubNet;
+ char stringbuffer[100];
+ static sockaddr_storage emptySockAddrStorage;
+};
+
+
+#endif /* defined(__TestTB__bjIPAddr__) */
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjMACAddr.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjMACAddr.cpp
new file mode 100644
index 00000000..78d2a8db
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjMACAddr.cpp
@@ -0,0 +1,11 @@
+//
+// bjMACAddr.cpp
+// TestTB
+//
+// Created by Terrin Eager on 3/23/13.
+//
+//
+
+
+#include "bjMACAddr.h"
+
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjMACAddr.h b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjMACAddr.h
new file mode 100644
index 00000000..ced95507
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjMACAddr.h
@@ -0,0 +1,54 @@
+//
+// bjMACAddr.h
+// TestTB
+//
+// Created by Terrin Eager on 3/23/13.
+//
+//
+
+#ifndef __TestTB__bjMACAddr__
+#define __TestTB__bjMACAddr__
+
+#include <iostream>
+#include <sys/socket.h>
+#include "bjtypes.h"
+
+class BJMACAddr
+{
+public:
+ BJMACAddr() { memset(addr,0,sizeof(addr));};
+ BJMACAddr(const BJMACAddr& Src) { memcpy(addr,Src.addr,sizeof(addr)); };
+
+ void operator=(const BJMACAddr& Src) { memcpy(addr,Src.addr,sizeof(addr)); };
+
+ void Set(unsigned char* newAddr) {memcpy(addr,newAddr,sizeof(addr));};
+ void SetString(char* newAddrString)
+ {
+ int newAddr[6] = {0,0,0,0,0,0};
+ sscanf(newAddrString, "%02X:%02X:%02X:%02X:%02X:%02X", &newAddr[0],&newAddr[1],&newAddr[2],&newAddr[3],&newAddr[4],&newAddr[5]);
+ for (int i=0; i< 6; i++)
+ addr[i] = newAddr[i];
+ };
+ unsigned char* Get() {return addr;};
+
+ void CopyVendor(BJMACAddr& src) { memset(addr,0,sizeof(addr)); memcpy(addr,src.addr,4);}; // 3 is standar vendor But 4 is better with apple products
+
+ char* GetString() {sprintf(buffer,"%02X:%02X:%02X:%02X:%02X:%02X", addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]); return buffer;};
+ char* GetStringVendor() {sprintf(buffer,"%02X:%02X:%02X", addr[0],addr[1],addr[2]); return buffer;};
+ BJ_COMPARE Compare(BJMACAddr* compareAddr)
+ {
+ int result = memcmp(addr, compareAddr->addr, sizeof(addr));
+ if (result > 0)
+ return BJ_GT;
+ if (result < 0)
+ return BJ_LT;
+ return BJ_EQUAL;
+ };
+ bool IsEmpty() { return (addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]) == 0;};
+
+private:
+ unsigned char addr[6];
+ char buffer[25];
+};
+
+#endif /* defined(__TestTB__bjMACAddr__) */
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.cpp
new file mode 100644
index 00000000..3c5db739
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.cpp
@@ -0,0 +1,40 @@
+//
+// bjStringtoStringMap.cpp
+// TestTB
+//
+// Created by Terrin Eager on 12/21/12.
+//
+//
+
+#include "bjStringtoStringMap.h"
+
+/////////////////////
+
+StringMapNode::StringMapNode()
+{
+
+
+}
+
+StringMapNode::StringMapNode(BJString* pKey)
+{
+ m_Key = *pKey;
+}
+
+StringMapNode::~StringMapNode()
+{
+
+}
+
+void StringMapNode::CopyNode(CRBNode* pSource)
+{
+ m_Key = ((StringMapNode*)pSource)->m_Key;
+}
+
+BJ_COMPARE StringMapNode::Compare(BJString* pKey)
+{
+
+ return m_Key.Compare(*pKey);
+
+}
+
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.h b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.h
new file mode 100644
index 00000000..4e44d9d5
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjStringtoStringMap.h
@@ -0,0 +1,42 @@
+//
+// bjStringtoStringMap.h
+// TestTB
+//
+// Created by Terrin Eager on 12/21/12.
+//
+//
+
+#ifndef __TestTB__bjStringtoStringMap__
+#define __TestTB__bjStringtoStringMap__
+
+#include <iostream>
+#include "bjstring.h"
+#include "LLRBTree.h"
+
+class StringMapNode : public CRBNode<BJString>
+{
+public:
+ StringMapNode();
+ StringMapNode(BJString* pKey);
+ ~StringMapNode();
+ inline virtual BJ_COMPARE Compare(BJString* pKey);
+ inline virtual void CopyNode(CRBNode* pSource);
+ inline virtual void Init(){};
+ inline virtual void Clear() {};
+
+
+ BJString value;
+
+};
+
+class BJStringtoStringMap : public CLLRBTree<BJString, StringMapNode>
+{
+public:
+
+
+};
+
+
+
+
+#endif /* defined(__TestTB__bjStringtoStringMap__) */
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.cpp
new file mode 100644
index 00000000..da3ce4ad
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.cpp
@@ -0,0 +1,384 @@
+//
+// bjsocket.cpp
+// TestTB
+//
+// Created by Terrin Eager on 10/24/12.
+//
+//
+#define __APPLE_USE_RFC_2292
+
+#include <unistd.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+
+#include "bjsocket.h"
+#include "bjstring.h"
+
+
+////////////////////////////
+/// BJSocket
+///////////////////////////
+const BJ_UINT16 BonjourPort = 5353;
+
+BJSocket::BJSocket()
+{
+ socketHandle = 0;
+ buffer = NULL;
+ IPVersion = 0;
+ interfaceID = 0;
+}
+
+BJSocket::~BJSocket()
+{
+
+}
+
+bool BJSocket::Init()
+{
+
+ socketHandle = 0;
+ buffer = (BJ_UINT8*)malloc(MAX_FRAME_SIZE);
+
+ if (buffer == NULL)
+ return false;
+
+ //Setup msghdr;
+ memset(&socketMsghdr, '\0', sizeof(socketMsghdr));
+ socketMsghdr.msg_name = &peerAddr;
+ socketMsghdr.msg_namelen = sizeof(peerAddr);
+ socketMsghdr.msg_iov = socketIovec;
+ socketMsghdr.msg_iovlen = 1;
+ socketIovec[0].iov_base = (char *) buffer;
+ socketIovec[0].iov_len = MAX_FRAME_SIZE;
+
+
+ socketMsghdr.msg_control = socketCmsghdr;
+ socketMsghdr.msg_controllen = sizeof(socketCmsghdr);
+
+ return true;
+
+}
+
+bool BJSocket::CreateListenerIPv4(BJString interfaceName)
+{
+ bool bResult = true;
+ const int onoptval = 1;
+
+ if (socketHandle)
+ Close();
+
+ Init();
+
+
+ if (interfaceName.GetLength() > 0)
+ interfaceID = if_nametoindex(interfaceName.GetBuffer());
+
+
+ socketHandle = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
+// socketHandle = socket(PF_INET,SOCK_DGRAM,IPPROTO_RAW);
+
+ if (-1 == setsockopt(socketHandle,SOL_SOCKET,SO_REUSEPORT,&onoptval,sizeof(onoptval)))
+ {
+ printf("setsockopt for SO_REUSEPORT failed");
+ Close();
+ return false;
+ }
+
+ JoinMulticastv4(interfaceName);
+
+ // set PktInfo to get dest address
+
+ if (-1 == setsockopt(socketHandle, IPPROTO_IP, IP_PKTINFO, &onoptval, sizeof(onoptval)))
+ {
+ printf("setsockopt for IP_PKTINFO failed");
+ Close();
+ return false;
+ }
+
+ // bind to socket
+
+ struct sockaddr_in sa;
+ memset(&sa,0,sizeof(sockaddr_in));
+ sa.sin_len = sizeof(sockaddr_in);
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = INADDR_ANY;
+ sa.sin_port = htons(BonjourPort);
+
+ if (-1 == bind(socketHandle,(struct sockaddr*)&sa,sizeof(sa)))
+ {
+ printf("error in bind: %s\n",strerror(errno));
+ Close();
+ return false;
+ }
+ IPVersion = 4;
+
+ return bResult;
+}
+
+bool BJSocket::CreateListenerIPv6(BJString interfaceName)
+{
+ bool bResult = true;
+ const int onoptval=1;
+
+ if (socketHandle)
+ Close();
+
+ Init();
+
+ if (interfaceName.GetLength() > 0)
+ interfaceID = if_nametoindex(interfaceName.GetBuffer());
+
+ socketHandle = socket(PF_INET6,SOCK_DGRAM,IPPROTO_UDP);
+
+ if (-1 == setsockopt(socketHandle,SOL_SOCKET,SO_REUSEPORT,&onoptval,sizeof(onoptval)))
+ {
+ printf("setsockopt for SO_REUSEPORT failed");
+ Close();
+ return false;
+ }
+
+ JoinMulticastv6(interfaceName);
+
+ // set PktInfo to get dest address
+ if (-1 == setsockopt(socketHandle, IPPROTO_IPV6, IPV6_PKTINFO, &onoptval, sizeof(onoptval)))
+ {
+ printf("setsockopt for IP_PKTINFO failed");
+ Close();
+ return false;
+ }
+
+ // bind to socket
+ struct sockaddr_in6 sa6;
+ memset(&sa6,0,sizeof(sockaddr_in6));
+ sa6.sin6_len = sizeof(sockaddr_in6);
+ sa6.sin6_family = AF_INET6;
+ sa6.sin6_addr = in6addr_any;
+ sa6.sin6_port = htons(BonjourPort);
+
+ if (-1 == bind(socketHandle,(struct sockaddr*)&sa6,sizeof(sa6)))
+ {
+ printf("error in bind: %s\n",strerror(errno));
+ Close();
+ return false;
+ }
+ IPVersion = 6;
+
+ return bResult;
+}
+
+bool BJSocket::Close()
+{
+ bool bResult = true;
+
+ if (socketHandle)
+ close(socketHandle);
+
+ socketHandle = 0;
+
+ return bResult;
+}
+
+int BJSocket::Read()
+{
+ int nLength = (int) recvmsg(socketHandle, &socketMsghdr,0);
+ if (!CheckInterface())
+ return 0;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ m_CurrentFrame.Set(buffer-14-40-8,nLength,tv.tv_sec*1000000ll + tv.tv_usec);
+ return nLength;
+}
+
+BJIPAddr* BJSocket::GetSrcAddr()
+{
+ sourceAddr.Set(&peerAddr);
+ return &sourceAddr;
+}
+
+BJIPAddr* BJSocket::GetDestAddr()
+{
+
+ struct cmsghdr *cmsg;
+
+ for(cmsg = CMSG_FIRSTHDR(&socketMsghdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&socketMsghdr, cmsg))
+ {
+
+ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO)
+ {
+ struct in_pktinfo* pPktInfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+
+ destAddr.Set(&pPktInfo->ipi_addr);
+ }
+ if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO)
+ {
+ struct in6_pktinfo* pPktInfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
+ destAddr.Set(&pPktInfo->ipi6_addr);
+ }
+ }
+ return &destAddr;
+}
+
+bool BJSocket::CheckInterface()
+{
+ if (interfaceID ==0)
+ return true;
+ struct cmsghdr *cmsg;
+
+ bool bFound = false;
+
+ for(cmsg = CMSG_FIRSTHDR(&socketMsghdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&socketMsghdr, cmsg))
+ {
+
+ if ((cmsg->cmsg_level == IPPROTO_IP) && cmsg->cmsg_type == IP_PKTINFO)
+ {
+ bFound = true;
+ struct in_pktinfo* pPktInfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+ if (pPktInfo->ipi_ifindex == interfaceID)
+ return true;
+ else
+ {
+ if (pPktInfo->ipi_ifindex != 4)
+ {
+ sourceAddr.Set(&peerAddr);
+ printf("address:%d %s \n",pPktInfo->ipi_ifindex,sourceAddr.GetString());
+ }
+ }
+ }
+ if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO)
+ {
+ bFound = true;
+ struct in6_pktinfo* pPktInfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
+ if (pPktInfo->ipi6_ifindex == interfaceID)
+ return true;
+ }
+ }
+ if (!bFound)
+ printf("PKTINFO not found \n");
+ return false;
+}
+
+bool BJSocket::IsMulticastPacket()
+{
+ return GetDestAddr()->IsBonjourMulticast();
+
+}
+
+int BJSocket::GetSockectHandle()
+{
+ return socketHandle;
+}
+
+BJ_UINT8* BJSocket::GetBuffer()
+{
+ return buffer;
+}
+
+void BJSocket::JoinMulticastv4(BJString interfaceName)
+{
+ if (interfaceName.GetLength() == 0)
+ {
+ // join Multicast group
+ struct ip_mreq imr;
+ imr.imr_multiaddr.s_addr = inet_addr( "224.0.0.251");
+ imr.imr_interface.s_addr = INADDR_ANY;
+ if (-1 == setsockopt(socketHandle, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)))
+ {
+ printf("setsockopt for IP_ADD_MEMBERSHIP failed");
+ }
+ return;
+ }
+
+ struct ifaddrs *ifa, *orig;
+
+ getifaddrs(&ifa);
+
+ orig = ifa;
+
+ for ( ; ifa; ifa = ifa->ifa_next)
+ {
+ if (interfaceName == ifa->ifa_name && ifa->ifa_addr->sa_family == AF_INET)
+ {
+ struct sockaddr_in *ifa_addr = (struct sockaddr_in *)ifa->ifa_addr;
+ struct ip_mreq imr;
+ imr.imr_multiaddr.s_addr = inet_addr( "224.0.0.251");
+ imr.imr_interface.s_addr = ifa_addr->sin_addr.s_addr;
+ if (-1 == setsockopt(socketHandle, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)))
+ {
+ printf("setsockopt for IP_ADD_MEMBERSHIP failed");
+ }
+ }
+ }
+
+ freeifaddrs(orig);
+
+}
+
+void BJSocket::JoinMulticastv6(BJString interfaceName)
+{
+
+ if (interfaceName.GetLength() == 0)
+ return;
+
+ // join Multicast group
+ struct in6_addr BonjourMultiaddr = {{{ 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB }}};
+ struct ipv6_mreq i6mr;
+ memset(&i6mr,0,sizeof(i6mr));
+ memcpy(&i6mr.ipv6mr_multiaddr, &BonjourMultiaddr, sizeof(BonjourMultiaddr));
+ if (interfaceName.GetLength() > 0)
+ i6mr.ipv6mr_interface = interfaceID;
+ else
+ i6mr.ipv6mr_interface = __IPV6_ADDR_SCOPE_SITELOCAL;
+ int err = setsockopt(socketHandle, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr));
+ if (err < 0 && (errno != EADDRINUSE))
+ {
+ printf("setsockopt for IPV6_JOIN_GROUP failed %d",errno);
+ }
+}
+
+////////////////////////////////////////
+// BJSelect
+///////////////////////////////////////
+
+
+BJSelect::BJSelect()
+{
+ FD_ZERO(&socketSet);
+ maxSocket = 0;
+
+}
+
+bool BJSelect::Add(BJSocket& s)
+{
+ int sock = s.GetSockectHandle();
+ FD_SET(sock, &socketSet);
+ if (sock > maxSocket)
+ maxSocket = sock;
+
+ return true;
+
+}
+
+int BJSelect::Wait(int sec)
+{
+ struct timeval tv;
+ memset(&tv, 0, sizeof(tv));
+ tv.tv_sec = sec;
+
+ int result = select(maxSocket+1, &socketSet, NULL, NULL, &tv);
+ return result;
+
+}
+
+bool BJSelect::IsReady(BJSocket& Socket)
+{
+ int bIsSet = FD_ISSET(Socket.GetSockectHandle(), &socketSet);
+ return (bIsSet != 0);
+}
+
+
+
+
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.h b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.h
new file mode 100644
index 00000000..c85e3841
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjsocket.h
@@ -0,0 +1,88 @@
+//
+// bjsocket.h
+// TestTB
+//
+// Created by Terrin Eager on 10/24/12.
+//
+//
+
+#ifndef __TestTB__bjsocket__
+#define __TestTB__bjsocket__
+
+#include <iostream>
+
+#include <sys/socket.h>
+
+#include "bjtypes.h"
+#include "bjIPAddr.h"
+#include "bjstring.h"
+
+#include "Frame.h"
+
+
+class BJSocket
+{
+public:
+
+ BJSocket();
+ virtual ~BJSocket();
+
+ bool Init();
+
+ bool CreateListenerIPv4(BJString interfaceName);
+ bool CreateListenerIPv6(BJString interfaceName);
+
+ bool Close();
+
+ int Read();
+
+ Frame m_CurrentFrame;
+
+ bool IsMulticastPacket();
+
+ int GetSockectHandle();
+
+ BJ_UINT8* GetBuffer();
+ BJIPAddr* GetSrcAddr();
+ BJIPAddr* GetDestAddr();
+
+private:
+ void JoinMulticastv4(BJString interfaceName);
+ void JoinMulticastv6(BJString interfaceName);
+
+ bool CheckInterface();
+
+ BJ_UINT32 interfaceID;
+
+ int socketHandle;
+ BJ_UINT8* buffer;
+
+
+ int IPVersion;
+ BJIPAddr sourceAddr;
+ BJIPAddr destAddr;
+
+ struct msghdr socketMsghdr;
+ sockaddr_storage peerAddr;
+ struct iovec socketIovec[1];
+ struct cmsghdr socketCmsghdr[10];
+
+};
+
+class BJSelect
+{
+public:
+ BJSelect();
+
+ bool Add(BJSocket& s);
+ int Wait(int sec);
+
+ bool IsReady(BJSocket& s);
+
+private:
+ fd_set socketSet;
+ int maxSocket;
+
+};
+
+#endif /* defined(__TestTB__bjsocket__) */
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjstring.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjstring.cpp
new file mode 100644
index 00000000..5a6fcdf1
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjstring.cpp
@@ -0,0 +1,238 @@
+//
+// bjstring.cpp
+// TestTB
+//
+// Created by Terrin Eager on 9/26/12.
+//
+//
+
+#include "bjstring.h"
+#include <time.h>
+
+
+BJString::BJString()
+{
+ buffer = NULL;
+ length = 0;
+}
+
+BJString::BJString(const BJString& scr)
+{
+ buffer = NULL;
+ length = 0;
+ Set(scr.GetBuffer());
+}
+BJString::BJString(const char* str)
+{
+ buffer = NULL;
+ length = 0;
+ Set(str);
+}
+
+BJString::~BJString()
+{
+ delete[] buffer;
+ buffer = NULL;
+}
+
+
+BJString& BJString::operator=(const char* str)
+{
+ Set(str);
+ return *this;
+}
+
+BJString& BJString::operator=(const BJString& str)
+{
+ Set(str.GetBuffer());
+ return *this;
+}
+bool BJString::operator==(const char* str)
+{
+ if (buffer == NULL && str == NULL)
+ return true;
+ if (buffer == NULL || str == NULL)
+ return false;
+
+ return (strcmp(str,buffer) == 0);
+}
+bool BJString::operator==(const BJString& str)
+{
+ if (buffer == NULL && str.GetBuffer() == NULL)
+ return true;
+ if (buffer == NULL || str.GetBuffer() == NULL)
+ return false;
+ return (strcmp(str.GetBuffer(),buffer) == 0);
+}
+
+bool BJString::operator<(const BJString& str) const
+{
+ const char* myBuff = GetBuffer();
+ const char* otherBuff = str.GetBuffer();
+
+ if (myBuff == NULL && otherBuff == NULL)
+ return false;
+ if (myBuff != NULL && otherBuff == NULL)
+ return false;
+ if (myBuff == NULL && otherBuff != NULL)
+ return true;
+
+ int cmp = strcmp(myBuff, otherBuff);
+
+ if (cmp < 0)
+ return true;
+ else
+ return false;
+
+}
+
+BJ_COMPARE BJString::Compare(const BJString& str)
+{
+ const char* myBuff = GetBuffer();
+ const char* otherBuff = str.GetBuffer();
+
+ if (myBuff == NULL && otherBuff == NULL)
+ return BJ_EQUAL;
+ if (myBuff != NULL && otherBuff == NULL)
+ return BJ_GT;
+ if (myBuff == NULL && otherBuff != NULL)
+ return BJ_LT;
+
+ int cmp = strcmp(myBuff, otherBuff);
+
+ if (cmp > 0)
+ return (BJ_GT);
+ else if (cmp < 0)
+ return (BJ_LT);
+ else
+ return (BJ_EQUAL);
+
+}
+
+BJString& BJString::operator+=(const char* str)
+{
+ if (buffer == NULL)
+ return operator=(str);
+ if (str == NULL)
+ return *this;
+
+ BJString temp = buffer;
+ Create((BJ_UINT32)(strlen(buffer) + strlen(str)));
+ strcpy(buffer,temp.GetBuffer());
+ strcat(buffer,str);
+ return *this;
+}
+BJString& BJString::operator+=(const BJString&str)
+{
+ operator+=(str.GetBuffer());
+ return *this;
+}
+
+
+const char* BJString::GetBuffer() const
+{
+ return buffer;
+}
+
+void BJString::Set(const char* str)
+{
+
+ BJ_UINT32 len = str?(BJ_UINT32)strlen(str):0;
+ if (len > 255)
+ len = 250;
+ Create(len);
+ if (buffer && str)
+ strcpy(buffer, str);
+
+}
+void BJString::Set(const char* str, BJ_UINT32 len)
+{
+ Create(len);
+ if (buffer)
+ {
+ if (str)
+ strncpy(buffer, str, len);
+ else
+ memset(buffer, 0, length);
+ }
+}
+
+void BJString::Append(const char* str, BJ_UINT32 len)
+{
+ if (length < (strlen(buffer) + strlen(str)))
+ {
+ BJString temp = buffer;
+ Create((BJ_UINT32)(strlen(buffer) + strlen(str)));
+ if (buffer && temp.buffer)
+ strcpy(buffer,temp.GetBuffer());
+ }
+ strncat(buffer,str,len);
+}
+
+bool BJString::Contains(const char* str)
+{
+ if (buffer == NULL && str == NULL)
+ return true;
+ if (buffer == NULL || str == NULL)
+ return false;
+ return (strstr(buffer,str) != NULL);
+}
+
+BJ_UINT32 BJString::GetUINT32()
+{
+ if (buffer == NULL)
+ return 0;
+
+ return atoi(buffer);
+}
+
+void BJString::Format(BJ_UINT64 number,BJ_FORMAT_STYLE style)
+{
+ switch (style) {
+ case BJSS_BYTE:
+ Create(32);
+ sprintf(buffer,"%llu",number);
+ break;
+ case BJSS_TIME:
+ {
+ char formatedTime[24];
+ time_t timeValue = number;
+ struct tm* timeStruct = localtime(&timeValue);
+ strftime(formatedTime, sizeof(formatedTime), "%Y-%m-%d_%T_%a", timeStruct);
+ Set(formatedTime);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+
+void BJString::Create(BJ_UINT32 len)
+{
+ if (length >= len)
+ {
+ if (length > 0)
+ memset(buffer, 0, len+1);
+ return;
+ }
+
+ if (buffer)
+ {
+ delete buffer;
+ buffer = NULL;
+ length = 0;
+ }
+
+ buffer = new char[len+1];
+ if (buffer)
+ {
+ memset(buffer, 0, len+1);
+ length = len;
+ }
+}
+
+BJ_UINT32 BJString::GetLength()
+{
+ return buffer?(BJ_UINT32)strlen(buffer):0;
+}
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjstring.h b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjstring.h
new file mode 100644
index 00000000..67a78f89
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjstring.h
@@ -0,0 +1,63 @@
+//
+// bjstring.h
+// TestTB
+//
+// Created by Terrin Eager on 9/26/12.
+//
+//
+
+#ifndef __TestTB__bjstring__
+#define __TestTB__bjstring__
+
+#include <iostream>
+#include "bjtypes.h"
+
+class BJString
+{
+
+public:
+ BJString();
+ BJString(const BJString& scr);
+ BJString(const char* str);
+ virtual ~BJString();
+
+ BJString& operator=(const char* str);
+ BJString& operator=(const BJString& str);
+ bool operator==(const char* str);
+ bool operator!=(const char* str){return !operator==(str);};
+ bool operator==(const BJString& str);
+ bool operator!=(const BJString& str) {return !operator==(str);};
+ bool operator<(const BJString& str) const;
+
+ BJ_COMPARE Compare(const BJString& str);
+
+
+ BJString& operator+=(const char* str);
+ BJString& operator+=(const BJString& str);
+
+ const char* GetBuffer() const;
+
+ void Set(const char* str);
+ void Set(const char* str,BJ_UINT32 len);
+
+ void Append(const char* str, BJ_UINT32 len);
+
+ bool Contains(const char* str);
+
+ BJ_UINT32 GetUINT32();
+
+ enum BJ_FORMAT_STYLE {BJSS_BYTE,BJSS_TIME} ;
+ void Format(BJ_UINT64 number,BJ_FORMAT_STYLE style);
+
+ BJ_UINT32 GetLength();
+
+ BJ_UINT32 GetBufferLength(){return length;};
+
+private:
+
+ void Create(BJ_UINT32 len);
+ char* buffer;
+ BJ_UINT32 length;
+};
+
+#endif /* defined(__TestTB__bjstring__) */
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjtypes.h b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjtypes.h
new file mode 100644
index 00000000..59de2732
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/bjtypes.h
@@ -0,0 +1,64 @@
+//
+// bjtypes.h
+// TestTB
+//
+// Created by Terrin Eager on 4/24/12.
+//
+//
+
+
+#ifndef TestTB_bjtypes_h
+#define TestTB_bjtypes_h
+typedef bool BJ_BOOL;
+
+typedef char BJ_INT8;
+typedef unsigned char BJ_UINT8;
+
+typedef short int BJ_INT16;
+typedef unsigned short int BJ_UINT16;
+
+typedef int BJ_INT32;
+typedef unsigned int BJ_UINT32;
+
+typedef long long BJ_INT64;
+typedef unsigned long long BJ_UINT64;
+
+#define DNS_NAME_OFFSET_MASK 0xc0
+
+#define MAX_FRAME_SIZE 0x2800
+
+
+enum BJ_COMPARE {BJ_GT,BJ_LT,BJ_EQUAL};
+
+#define PF_GET_UINT8(pBuffer,offset) ( (BJ_UINT8)pBuffer[offset] )
+#define PF_GET_UINT16(pBuffer,offset) ((((BJ_UINT16)pBuffer[offset]) << 8) | ((BJ_UINT16)pBuffer[offset+1]))
+#define PF_GET_UINT32(pBuffer,offset) ((pBuffer[offset] << 24) | (pBuffer[offset+1] << 16) | (pBuffer[offset+2] << 8) | (pBuffer[offset+3]))
+
+
+inline void endian_swap(BJ_UINT8& x)
+{
+ x = (x>>8) |(x<<8);
+}
+
+inline void endian_swap(BJ_UINT32& x)
+{
+ x = (x>>24) |
+ ((x<<8) & 0x00FF0000) |
+ ((x>>8) & 0x0000FF00) |
+ (x<<24);
+}
+
+
+inline void endian_swap(BJ_UINT64& x)
+{
+ x = (x>>56) |
+ ((x<<40) & 0x00FF000000000000) |
+ ((x<<24) & 0x0000FF0000000000) |
+ ((x<<8) & 0x000000FF00000000) |
+ ((x>>8) & 0x00000000FF000000) |
+ ((x>>24) & 0x0000000000FF0000) |
+ ((x>>40) & 0x000000000000FF00) |
+ (x<<56);
+}
+
+#endif
diff --git a/mDNSResponder/mDNSMacOSX/BonjourTop/source/main.cpp b/mDNSResponder/mDNSMacOSX/BonjourTop/source/main.cpp
new file mode 100644
index 00000000..52107bbe
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/BonjourTop/source/main.cpp
@@ -0,0 +1,179 @@
+//
+// main.cpp
+// BonjourTop
+//
+// Created by Terrin Eager on 4/24/13.
+// Copyright (c) 2013-2014 Apple Inc. All rights reserved.
+//
+
+#include <stdio.h>
+#include <curses.h>
+
+#include "bjtypes.h"
+#include "BonjourTop.h"
+
+#include <signal.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+
+#define BJ_VERSION_MAJOR 0
+#define BJ_VERSION_MINOR 23
+CBonjourTop BjTop;
+
+static void
+usage()
+{
+ printf("bonjourtop usage: bonjourTop (Version: %d.%d)\n",BJ_VERSION_MAJOR,BJ_VERSION_MINOR);
+ printf("\t\t\t [-t tcptrace_filename ]\n");
+ printf("\t\t\t [-i interfaceName]\n");
+ printf("\t\t\t [-m ipaddress/subnetmask] ie 17.255.45.12/17\n");
+ printf("\t\t\t [-e export_filename] \n");
+ printf("\t\t\t [-x seconds] 'Snapshot export every x seconds'\n");
+ printf("\t\t\t [-s] 'service information'\n");
+ printf("\t\t\t [-v] 'report the version number' \n");
+ printf("\t\t\t [-d] filename 'export device map. Adds timestamp and csv extension to the filename' \n");
+ printf("\t\t\t [-f application] 'filter application for device map (only available with -t -d options)' \n");
+ printf("While running the follow keys may be used:\n");
+ printf("\t b - sort by Bytes\n");
+ printf("\t p - sort by Packets (default)\n");
+ printf("\t n - sort by Name\n");
+ printf("\t a - Display Application Names (default) \n");
+ printf("\t s - Display Services Names \n");
+ printf("\t t - Display 24 hour packet per min \n");
+
+ printf("\t o - flip sort order\n");
+ printf("\t e - export to BonjourTop.csv\n");
+ printf("\t q - quit\n\n");
+}
+
+static void
+handle_window_change(int signal) {
+ switch (signal) {
+ case SIGWINCH:
+ BjTop.WindowSizeChanged();
+ break;
+ default:
+ break;
+ }
+}
+
+int main(int argc, char * const *argv)
+{
+
+ sigset_t sset, oldsset;
+ int c;
+
+ static struct option longopts[] = {
+ { "trace", required_argument, NULL, 't' },
+ { "interface", required_argument, NULL, 'i' },
+ { "ipaddr_subnet", required_argument, NULL, 'm' },
+ { "export", required_argument, NULL, 'e' },
+ { "snapshot", required_argument, NULL, 'x' },
+ { "service", no_argument, NULL, 's' },
+ { "version", no_argument, NULL, 'v' },
+ { "devicemap", required_argument, NULL, 'd' },
+ { "filter", required_argument, NULL, 'f' },
+ { NULL, 0, NULL, 0 }
+ };
+
+ sigemptyset(&sset);
+
+ /* Block SIGWINCH signals while we are in a relayout. */
+ if(-1 == sigprocmask(SIG_BLOCK, &sset, &oldsset)) {
+ perror("sigprocmask");
+ exit(EXIT_FAILURE);
+ }
+
+ BJ_COLLECTBY_TYPE TypeList[] = {CBT_SERVICE,CBT_REQUEST_RESPONDS,CBT_SAME_DIFF_SUBNET,CBT_IP_ADDRESS_TYPE,CBT_PACKET};
+ BJString sTemp;
+
+ bool bLiveCapture = true;
+ bool bExport = false;
+
+ while ((c = getopt_long(argc, argv, "t:i:m:e:x:svd:f:phb", longopts, NULL)) != -1) {
+ switch (c) {
+ case 't':
+ BjTop.m_pTcpDumpFileName = optarg; // TCP Dump Filename
+ bLiveCapture = false;
+ BjTop.m_bCursers = false;
+ break;
+ case 'p':
+ BjTop.m_bCursers = false;
+ break;
+ case 'e':
+ bExport = true;
+ BjTop.m_pExportFileName = optarg; // Export filename
+ break;
+ case 'i':
+ BjTop.interfaceName = optarg; // Interface name
+ break;
+ case 'm':
+ BjTop.SetIPAddr(optarg); // TODO: verify that the argument is an ip address
+ break;
+ case 'x':
+ sTemp = optarg; // time in seconds for snapshots
+ BjTop.m_SnapshotSeconds = sTemp.GetUINT32();
+ break;
+ case 'd':
+ BjTop.m_bImportExportDeviceMap = true;
+ BjTop.m_DeviceFileName = optarg;
+ break;
+ case 'f':
+ BjTop.filterApplicationName = optarg;
+ break;
+ case 's':
+ BjTop.m_CurrentDisplay = CBonjourTop::BJ_DISPLAY_SERVICE;
+ break;
+ case 'v':
+ printf("\nbonjourtop Version: %d.%d\n\n",BJ_VERSION_MAJOR,BJ_VERSION_MINOR);
+ exit(0);
+ break;
+ case 'b':
+ BjTop.m_Collection.Init(TypeList);
+ bExport = true;
+ break;
+ case 'h':
+ usage();
+ exit(0);
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (BjTop.m_bCursers)
+ {
+ signal(SIGWINCH, handle_window_change);
+ initscr();
+ timeout(0);
+ BjTop.PrintResults(1,false);
+ }
+
+ if (bLiveCapture)
+ BjTop.LiveCapture();
+ else
+ BjTop.CaptureFile();
+
+
+ if (bExport)
+ {
+ BjTop.ExportResults();
+ return 0;
+ }
+
+ if (BjTop.m_bCursers)
+ endwin();
+
+ if (BjTop.m_bImportExportDeviceMap)
+ {
+ BjTop.WriteDeviceFile();
+ BjTop.WriteVendorFile();
+ }
+
+ return 0;
+}
+
+
diff --git a/mDNSResponder/mDNSMacOSX/D2D.c b/mDNSResponder/mDNSMacOSX/D2D.c
new file mode 100644
index 00000000..2848cdab
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/D2D.c
@@ -0,0 +1,995 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2002-2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "D2D.h"
+#include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
+#include "DNSCommon.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_internal.h"
+#include "uds_daemon.h"
+#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));
+
+#pragma mark - D2D Support
+
+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(const mDNSu8 * const lhs, const mDNSu16 lhs_len, const mDNSu8 * const rhs, const mDNSu16 rhs_len, D2DRecordListElem **D2DListp)
+{
+ mDNS *const m = &mDNSStorage;
+
+ // 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(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
+{
+ mDNS *const m = &mDNSStorage;
+ 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((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 ENABLE_BLE_TRIGGERED_BONJOUR
+ // 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;
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
+
+ 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(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((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(&mDNSStorage, &arptr->ar));
+ mDNSPlatformMemFree(arptr);
+ return ptr;
+}
+
+mDNSexport void xD2DRemoveFromCache(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(key, keySize, value, valueSize);
+ if (ptr)
+ {
+ LogInfo("xD2DRemoveFromCache: Remove from cache: %s", ARDisplayString(&mDNSStorage, &ptr->ar));
+ mDNS_Deregister(&mDNSStorage, &ptr->ar);
+ }
+ }
+ else
+ LogMsg("xD2DRemoveFromCache: Unexpected result %d", result);
+}
+
+mDNSlocal void xD2DServiceResolved(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
+{
+ (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(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
+{
+ (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(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize)
+{
+ (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)
+{
+ const char *eventString = "unknown";
+
+ KQueueLock();
+
+ 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(result, instanceHandle, transportType, key, keySize, value, valueSize);
+ break;
+ case D2DServiceLost:
+ xD2DRemoveFromCache(result, instanceHandle, transportType, key, keySize, value, valueSize);
+ break;
+ case D2DServiceResolved:
+ xD2DServiceResolved(result, instanceHandle, transportType, key, keySize, value, valueSize);
+ break;
+ case D2DServiceRetained:
+ xD2DRetainHappened(result, instanceHandle, transportType, key, keySize, value, valueSize);
+ break;
+ case D2DServiceReleased:
+ xD2DReleaseHappened(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("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(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;
+}
+
+mDNSexport void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags)
+{
+#if ENABLE_BLE_TRIGGERED_BONJOUR
+ // 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(InterfaceID, &lower, qtype, flags, compression_lhs, end - compression_lhs);
+ }
+ else
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
+ 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)
+{
+#if ENABLE_BLE_TRIGGERED_BONJOUR
+ // 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(InterfaceID, &lower, qtype, flags))
+ xD2DClearCache(&lower, qtype);
+ }
+ else
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
+ 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)
+{
+#if ENABLE_BLE_TRIGGERED_BONJOUR
+ if (applyToBLE(resourceRecord->InterfaceID, flags))
+ {
+ domainname lower;
+
+ DomainnameToLower(resourceRecord->name, &lower);
+ start_BLE_advertise(resourceRecord, &lower, resourceRecord->rrtype, flags);
+ }
+ else
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
+ 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)
+{
+#if ENABLE_BLE_TRIGGERED_BONJOUR
+ // 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);
+ }
+ else
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
+ 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);
+ external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_SRV, 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);
+ }
+}
+
+void initializeD2DPlugins(mDNS *const m)
+{
+ // 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");
+ }
+}
+
+void terminateD2DPlugins(void)
+{
+ if (D2DTerminate)
+ {
+ D2DStatus ds = D2DTerminate();
+ if (ds != kD2DSuccess)
+ LogMsg("D2DTerminate failed: %d", ds);
+ else
+ LogMsg("D2DTerminate succeeded");
+ }
+}
+
+#ifdef UNIT_TEST
+#pragma mark - Unit test support routines
+
+// These unit test support routines are called from unittests/ framework
+// and are not compiled for the mDNSResponder runtime code paths.
+
+void D2D_unitTest(void)
+{
+}
+
+#endif // UNIT_TEST
diff --git a/mDNSResponder/mDNSMacOSX/D2D.h b/mDNSResponder/mDNSMacOSX/D2D.h
new file mode 100644
index 00000000..a9850728
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/D2D.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2015-2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _D2D_H_
+#define _D2D_H_
+
+#include "mDNSEmbeddedAPI.h" // Defines the interface provided to the client layer above
+#include "dnssd_ipc.h"
+#include <DeviceToDeviceManager/DeviceToDeviceManager.h>
+
+extern void internal_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags);
+extern void internal_stop_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const type, DNS_TypeValues qtype, DNSServiceFlags flags);
+extern void internal_start_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags);
+extern void internal_stop_advertising_service(const ResourceRecord *const resourceRecord, DNSServiceFlags flags);
+
+void xD2DAddToCache(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize);
+void xD2DRemoveFromCache(D2DStatus result, D2DServiceInstance instanceHandle, D2DTransportType transportType, const Byte *key, size_t keySize, const Byte *value, size_t valueSize);
+
+#if ENABLE_BLE_TRIGGERED_BONJOUR
+// Just define as the current max value for now for BLE.c prototype.
+// TODO: Will need to define in DeviceToDeviceManager.framework if we convert the
+// BLE discovery code to a D2D plugin.
+#define D2DBLETransport D2DTransportMax
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
+
+#ifdef UNIT_TEST
+#pragma mark - Unit test declarations
+
+// Unit test entry points, which are not used in the mDNSResponder runtime code paths.
+void D2D_unitTest(void);
+
+#endif // UNIT_TEST
+
+#endif /* _D2D_H_ */
diff --git a/mDNSResponder/mDNSMacOSX/DNS64.c b/mDNSResponder/mDNSMacOSX/DNS64.c
new file mode 100644
index 00000000..1f4e0ec2
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DNS64.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright (c) 2017 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <TargetConditionals.h>
+
+// DNS64 code is only for iOS, which is currently the only Apple OS that supports DNS proxy network extensions.
+
+#if TARGET_OS_IOS
+#include "DNS64.h"
+
+#include <AssertMacros.h>
+#include <network/nat64.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dns_sd.h"
+#include "dns_sd_internal.h"
+#include "uDNS.h"
+
+//===========================================================================================================================
+// Constants
+//===========================================================================================================================
+
+#define kDNS64IPv4OnlyFQDNString "\x8" "ipv4only" "\x4" "arpa"
+#define kDNS64IPv4OnlyFQDN ((const domainname *) kDNS64IPv4OnlyFQDNString)
+#define kDNS64IPv4OnlyFQDNLength 15 // 9 bytes for first label, 5 bytes for second label, and 1 byte for the root label.
+
+#define sizeof_field(TYPE, FIELD) sizeof(((TYPE *)0)->FIELD) // From CoreUtils.h
+
+check_compile_time(sizeof(kDNS64IPv4OnlyFQDNString) == kDNS64IPv4OnlyFQDNLength);
+check_compile_time(sizeof_field(DNSQuestion, qname) >= kDNS64IPv4OnlyFQDNLength);
+check_compile_time(sizeof_field(DNS64, qnameStash) == kDNS64IPv4OnlyFQDNLength);
+
+//===========================================================================================================================
+// Local Prototypes
+//===========================================================================================================================
+
+mDNSlocal mStatus DNS64GetIPv6Addrs(mDNS *m, mDNSu16 inResGroupID, struct in6_addr **outAddrs, uint32_t *outAddrCount);
+mDNSlocal mStatus DNS64GetPrefixes(mDNS *m, mDNSu16 inResGroupID, nw_nat64_prefix_t **outPrefixes, uint32_t *outPrefixCount);
+mDNSlocal mDNSBool DNS64GetReverseIPv6Addr(const domainname *inQName, struct in6_addr *outAddr);
+mDNSlocal mDNSu32 DNS64IPv4OnlyFQDNHash(void);
+mDNSlocal void DNS64RestartQuestion(mDNS *m, DNSQuestion *q, DNS64State newState);
+mDNSlocal mDNSBool DNS64TestIPv6Synthesis(mDNS *m, mDNSu16 inResGroupID, const mDNSv4Addr *inV4Addr);
+
+//===========================================================================================================================
+// DNS64StateMachine
+//===========================================================================================================================
+
+mDNSexport mDNSBool DNS64StateMachine(mDNS *m, DNSQuestion *inQ, const ResourceRecord *inRR, QC_result inResult)
+{
+ // If this is an mDNS question, then exit early. DNS64 is only for unicast DNS questions.
+
+ if (mDNSOpaque16IsZero(inQ->TargetQID)) return (mDNSfalse);
+
+ switch (inQ->dns64.state)
+ {
+ // If this question is going to be answered with a negative AAAA record and the question is not for "ipv4only.arpa." and
+ // the question's DNS server's interface supports NAT64, then restart the question as an "ipv4only.arpa." AAAA question.
+ // Otherwise, do nothing.
+
+ case kDNS64State_Initial:
+ if ((inRR->RecordType == kDNSRecordTypePacketNegative) && (inResult == QC_add))
+ {
+ if ((inQ->qtype == kDNSType_AAAA) &&
+ (inRR->rrtype == kDNSType_AAAA) &&
+ (inRR->rrclass == kDNSClass_IN) &&
+ ((inQ->qnamehash != DNS64IPv4OnlyFQDNHash()) || !SameDomainName(&inQ->qname, kDNS64IPv4OnlyFQDN)) &&
+ inQ->qDNSServer &&
+ nw_nat64_does_interface_index_support_nat64((uint32_t)(uintptr_t)inQ->qDNSServer->interface))
+ {
+ DNS64RestartQuestion(m, inQ, kDNS64State_PrefixDiscovery);
+ return (mDNStrue);
+ }
+ else if ((inQ->qtype == kDNSType_PTR) &&
+ (inRR->rrtype == kDNSType_PTR) &&
+ (inRR->rrclass == kDNSClass_IN) &&
+ inQ->qDNSServer &&
+ nw_nat64_does_interface_index_support_nat64((uint32_t)(uintptr_t)inQ->qDNSServer->interface) &&
+ DNS64GetReverseIPv6Addr(&inQ->qname, NULL))
+ {
+ DNS64RestartQuestion(m, inQ, kDNS64State_PrefixDiscoveryPTR);
+ return (mDNStrue);
+ }
+ }
+ break;
+
+ // If the "ipv4only.arpa." question is going to be answered with a positive AAAA record, then restart it as a question
+ // for an A record with the original AAAA qname.
+ // Otherwise, restart the question for the original AAAA record.
+
+ case kDNS64State_PrefixDiscovery:
+ if ((inRR->RecordType != kDNSRecordTypePacketNegative) &&
+ (inResult == QC_add) &&
+ (inRR->rrtype == kDNSType_AAAA) &&
+ (inRR->rrclass == kDNSClass_IN))
+ {
+ DNS64RestartQuestion(m, inQ, kDNS64State_QueryA);
+ return (mDNStrue);
+ }
+ else
+ {
+ DNS64RestartQuestion(m, inQ, kDNS64State_QueryAAAA);
+ return (mDNStrue);
+ }
+ break;
+
+ // The "ipv4only.arpa." question is going to be answered. Restart the question now. DNS64HandleNewQuestion() will decide
+ // whether or not to change it to a reverse IPv4 question.
+
+ case kDNS64State_PrefixDiscoveryPTR:
+ DNS64RestartQuestion(m, inQ, kDNS64State_QueryPTR);
+ return (mDNStrue);
+ break;
+
+ // If this question is going to be answered with a CNAME, then do nothing.
+ // If this question is going to be answered with a positive A record that's synthesizable, then set the state to
+ // QueryARecord2.
+ // Otherwise, restart the question for the original AAAA record.
+
+ case kDNS64State_QueryA:
+ if (inRR->rrtype != kDNSType_CNAME)
+ {
+ if ((inRR->RecordType != kDNSRecordTypePacketNegative) &&
+ (inResult == QC_add) &&
+ (inRR->rrtype == kDNSType_A) &&
+ (inRR->rrclass == kDNSClass_IN) &&
+ inQ->qDNSServer &&
+ DNS64TestIPv6Synthesis(m, inQ->qDNSServer->resGroupID, &inRR->rdata->u.ipv4))
+ {
+ inQ->dns64.state = kDNS64State_QueryA2;
+ }
+ else
+ {
+ DNS64RestartQuestion(m, inQ, kDNS64State_QueryAAAA);
+ return (mDNStrue);
+ }
+ }
+ break;
+
+ // For all other states, do nothing.
+
+ case kDNS64State_QueryA2:
+ case kDNS64State_QueryAAAA:
+ case kDNS64State_QueryPTR:
+ case kDNS64State_ReverseIPv4:
+ case kDNS64State_ReverseIPv6:
+ break;
+
+ default:
+ LogMsg("DNS64StateMachine: unrecognized DNS64 state %d", inQ->dns64.state);
+ break;
+ }
+
+ return (mDNSfalse);
+}
+
+//===========================================================================================================================
+// DNS64AnswerQuestion
+//===========================================================================================================================
+
+mDNSexport mStatus DNS64AnswerQuestion(mDNS *m, DNSQuestion *inQ, const ResourceRecord *inRR, QC_result inResult)
+{
+ mStatus err;
+ ResourceRecord newRR;
+ RData rdata;
+ nw_nat64_prefix_t * prefixes = NULL;
+ uint32_t prefixCount;
+ uint32_t i;
+ struct in_addr v4Addr;
+ struct in6_addr synthV6;
+
+ require_action_quiet(inQ->qDNSServer, exit, err = mStatus_BadParamErr);
+
+ err = DNS64GetPrefixes(m, inQ->qDNSServer->resGroupID, &prefixes, &prefixCount);
+ require_noerr_quiet(err, exit);
+
+ newRR = *inRR;
+ newRR.rrtype = kDNSType_AAAA;
+ newRR.rdlength = 16;
+ rdata.MaxRDLength = newRR.rdlength;
+ newRR.rdata = &rdata;
+
+ memcpy(&v4Addr.s_addr, inRR->rdata->u.ipv4.b, 4);
+ for (i = 0; i < prefixCount; i++)
+ {
+ if (nw_nat64_synthesize_v6(&prefixes[i], &v4Addr, &synthV6))
+ {
+ memcpy(rdata.u.ipv6.b, synthV6.s6_addr, 16);
+ inQ->QuestionCallback(m, inQ, &newRR, inResult);
+ }
+ }
+ err = mStatus_NoError;
+
+exit:
+ if (prefixes) free(prefixes);
+ return (err);
+}
+
+//===========================================================================================================================
+// DNS64HandleNewQuestion
+//===========================================================================================================================
+
+mDNSexport void DNS64HandleNewQuestion(mDNS *m, DNSQuestion *inQ)
+{
+ if (inQ->dns64.state == kDNS64State_QueryPTR)
+ {
+ struct in6_addr v6Addr;
+
+ inQ->dns64.state = kDNS64State_ReverseIPv6;
+ if (inQ->qDNSServer && DNS64GetReverseIPv6Addr(&inQ->qname, &v6Addr))
+ {
+ mStatus err;
+ nw_nat64_prefix_t * prefixes;
+ uint32_t prefixCount;
+ uint32_t i;
+ struct in_addr v4Addr;
+ char qnameStr[MAX_REVERSE_MAPPING_NAME_V4];
+
+ err = DNS64GetPrefixes(m, inQ->qDNSServer->resGroupID, &prefixes, &prefixCount);
+ require_noerr_quiet(err, exit);
+
+ for (i = 0; i < prefixCount; i++)
+ {
+ if (nw_nat64_extract_v4(&prefixes[i], &v6Addr, &v4Addr))
+ {
+ const mDNSu8 * const a = (const mDNSu8 *)&v4Addr.s_addr;
+
+ snprintf(qnameStr, sizeof(qnameStr), "%u.%u.%u.%u.in-addr.arpa.", a[3], a[2], a[1], a[0]);
+ MakeDomainNameFromDNSNameString(&inQ->qname, qnameStr);
+ inQ->qnamehash = DomainNameHashValue(&inQ->qname);
+ inQ->dns64.state = kDNS64State_ReverseIPv4;
+ break;
+ }
+ }
+ free(prefixes);
+ }
+ }
+
+exit:
+ return;
+}
+
+//===========================================================================================================================
+// DNS64ResetState
+//===========================================================================================================================
+
+// Called from mDNS_StopQuery_internal().
+
+mDNSexport void DNS64ResetState(DNSQuestion *inQ)
+{
+ switch (inQ->dns64.state)
+ {
+ case kDNS64State_PrefixDiscoveryPTR:
+ inQ->qtype = kDNSType_PTR; // Restore qtype to PTR and fall through.
+
+ case kDNS64State_PrefixDiscovery:
+ memcpy(&inQ->qname, inQ->dns64.qnameStash, sizeof(inQ->dns64.qnameStash)); // Restore the previous qname.
+ inQ->qnamehash = DomainNameHashValue(&inQ->qname);
+ break;
+
+ case kDNS64State_QueryA:
+ case kDNS64State_QueryA2:
+ inQ->qtype = kDNSType_AAAA; // Restore qtype to AAAA.
+ break;
+
+ // Do nothing for the other states.
+
+ case kDNS64State_Initial:
+ case kDNS64State_QueryAAAA:
+ case kDNS64State_QueryPTR:
+ case kDNS64State_ReverseIPv4:
+ case kDNS64State_ReverseIPv6:
+ break;
+
+ default:
+ LogMsg("DNS64ResetState: unrecognized DNS64 state %d", inQ->dns64.state);
+ break;
+ }
+ inQ->dns64.state = kDNS64State_Initial;
+}
+
+//===========================================================================================================================
+// DNS64RestartQuestions
+//===========================================================================================================================
+
+mDNSexport void DNS64RestartQuestions(mDNS *m)
+{
+ DNSQuestion * q;
+ DNSQuestion * restartList = NULL;
+ DNSServer * newServer;
+
+ m->RestartQuestion = m->Questions;
+ while (m->RestartQuestion)
+ {
+ q = m->RestartQuestion;
+ m->RestartQuestion = q->next;
+ if (q->dns64.state != kDNS64State_Initial)
+ {
+ SetValidDNSServers(m, q);
+ q->triedAllServersOnce = 0;
+ newServer = GetServerForQuestion(m, q);
+ if (q->qDNSServer != newServer)
+ {
+ if (!CacheRecordRmvEventsForQuestion(m, q))
+ {
+ LogInfo("DNS64RestartQuestions: Question deleted while delivering RMV events from cache");
+ }
+ else
+ {
+ LogInfo("DNS64RestartQuestions: Stop question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
+ mDNS_StopQuery_internal(m, q);
+ q->next = restartList;
+ restartList = q;
+ }
+ }
+ }
+ }
+ while ((q = restartList) != NULL)
+ {
+ restartList = restartList->next;
+ q->next = NULL;
+ LogInfo("DNS64RestartQuestions: Start question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
+ mDNS_StartQuery_internal(m, q);
+ }
+}
+
+//===========================================================================================================================
+// DNS64GetIPv6Addrs
+//===========================================================================================================================
+
+#define IsPositiveAAAAFromResGroup(RR, RES_GROUP_ID) \
+ ((RR)->rDNSServer && \
+ ((RR)->rDNSServer->resGroupID == RES_GROUP_ID) && \
+ ((RR)->rrtype == kDNSType_AAAA) && \
+ ((RR)->RecordType != kDNSRecordTypePacketNegative) && \
+ !(RR)->InterfaceID)
+
+mDNSlocal mStatus DNS64GetIPv6Addrs(mDNS *m, const mDNSu16 inResGroupID, struct in6_addr **outAddrs, uint32_t *outAddrCount)
+{
+ mStatus err;
+ const CacheGroup * cg;
+ const CacheRecord * cr;
+ struct in6_addr * addrs = NULL;
+ uint32_t addrCount;
+ uint32_t recordCount;
+
+ cg = CacheGroupForName(m, DNS64IPv4OnlyFQDNHash(), kDNS64IPv4OnlyFQDN);
+ require_action_quiet(cg, exit, err = mStatus_NoSuchRecord);
+
+ recordCount = 0;
+ for (cr = cg->members; cr; cr = cr->next)
+ {
+ if (IsPositiveAAAAFromResGroup(&cr->resrec, inResGroupID))
+ {
+ recordCount++;
+ }
+ }
+ require_action_quiet(recordCount > 0, exit, err = mStatus_NoSuchRecord);
+
+ addrs = (struct in6_addr *)calloc(recordCount, sizeof(*addrs));
+ require_action_quiet(addrs, exit, err = mStatus_NoMemoryErr);
+
+ addrCount = 0;
+ for (cr = cg->members; cr && (addrCount < recordCount); cr = cr->next)
+ {
+ if (IsPositiveAAAAFromResGroup(&cr->resrec, inResGroupID))
+ {
+ memcpy(addrs[addrCount].s6_addr, cr->resrec.rdata->u.ipv6.b, 16);
+ addrCount++;
+ }
+ }
+
+ *outAddrs = addrs;
+ addrs = NULL;
+ *outAddrCount = addrCount;
+ err = mStatus_NoError;
+
+exit:
+ if (addrs) free(addrs);
+ return (err);
+}
+
+//===========================================================================================================================
+// DNS64GetPrefixes
+//===========================================================================================================================
+
+mDNSlocal mStatus DNS64GetPrefixes(mDNS *m, mDNSu16 inResGroupID, nw_nat64_prefix_t **outPrefixes, uint32_t *outPrefixCount)
+{
+ mStatus err;
+ struct in6_addr * v6Addrs;
+ uint32_t v6AddrCount;
+ nw_nat64_prefix_t * prefixes;
+ int32_t prefixCount;
+
+ err = DNS64GetIPv6Addrs(m, inResGroupID, &v6Addrs, &v6AddrCount);
+ require_noerr_quiet(err, exit);
+
+ prefixCount = nw_nat64_copy_prefixes_from_ipv4only_records(v6Addrs, v6AddrCount, &prefixes);
+ free(v6Addrs);
+ require_action_quiet(prefixCount > 0, exit, err = mStatus_UnknownErr);
+
+ *outPrefixes = prefixes;
+ *outPrefixCount = prefixCount;
+
+exit:
+ return (err);
+}
+
+//===========================================================================================================================
+// DNS64GetReverseIPv6Addr
+//===========================================================================================================================
+
+#define kReverseIPv6Domain ((const domainname *) "\x3" "ip6" "\x4" "arpa")
+
+mDNSlocal mDNSBool DNS64GetReverseIPv6Addr(const domainname *inQName, struct in6_addr *outAddr)
+{
+ const mDNSu8 * ptr;
+ int i;
+ unsigned int c;
+ unsigned int nl;
+ unsigned int nu;
+
+ // If the name is of the form "x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.ip6.arpa.", where each x
+ // is a hex digit, then the sequence of 32 hex digit labels represents the nibbles of an IPv6 address in reverse order.
+ // See <https://tools.ietf.org/html/rfc3596#section-2.5>.
+
+ ptr = (const mDNSu8 *)inQName;
+ for (i = 0; i < 16; i++)
+ {
+ if (*ptr++ != 1) return (mDNSfalse); // If this label's length is not 1, then fail.
+ c = *ptr++; // Get label byte.
+ if ( (c >= '0') && (c <= '9')) nl = c - '0'; // If it's a hex digit, get its numeric value.
+ else if ((c >= 'a') && (c <= 'f')) nl = (c - 'a') + 10;
+ else if ((c >= 'A') && (c <= 'F')) nl = (c - 'A') + 10;
+ else return (mDNSfalse); // Otherwise, fail.
+
+ if (*ptr++ != 1) return (mDNSfalse); // If this label's length is not 1, then fail.
+ c = *ptr++; // Get label byte.
+ if ( (c >= '0') && (c <= '9')) nu = c - '0'; // If it's a hex digit, get its numeric value.
+ else if ((c >= 'a') && (c <= 'f')) nu = (c - 'a') + 10;
+ else if ((c >= 'A') && (c <= 'F')) nu = (c - 'A') + 10;
+ else return (mDNSfalse); // Otherwise, fail.
+
+ if (outAddr) outAddr->s6_addr[15 - i] = (mDNSu8)((nu << 4) | nl);
+ }
+
+ // The rest of the name needs to be "ip6.arpa.". If it isn't, fail.
+
+ if (!SameDomainName((const domainname *)ptr, kReverseIPv6Domain)) return (mDNSfalse);
+
+ return (mDNStrue);
+}
+
+//===========================================================================================================================
+// DNS64IPv4OnlyFQDNHash
+//===========================================================================================================================
+
+mDNSlocal mDNSu32 DNS64IPv4OnlyFQDNHash(void)
+{
+ static dispatch_once_t sHashOnce;
+ static mDNSu32 sHash;
+
+ dispatch_once(&sHashOnce, ^{ sHash = DomainNameHashValue(kDNS64IPv4OnlyFQDN); });
+
+ return (sHash);
+}
+
+//===========================================================================================================================
+// DNS64RestartQuestion
+//===========================================================================================================================
+
+mDNSlocal void DNS64RestartQuestion(mDNS *const m, DNSQuestion *inQ, DNS64State inNewState)
+{
+ mDNS_StopQuery_internal(m, inQ);
+
+ inQ->dns64.state = inNewState;
+ switch (inQ->dns64.state)
+ {
+ case kDNS64State_Initial:
+ break;
+
+ case kDNS64State_PrefixDiscovery:
+ case kDNS64State_PrefixDiscoveryPTR:
+ // Save the first 15 bytes from the original qname that are displaced by setting qname to "ipv4only.arpa.".
+
+ memcpy(inQ->dns64.qnameStash, &inQ->qname, sizeof(inQ->dns64.qnameStash));
+ AssignDomainName(&inQ->qname, kDNS64IPv4OnlyFQDN);
+ inQ->qnamehash = DNS64IPv4OnlyFQDNHash();
+ inQ->qtype = kDNSType_AAAA;
+ break;
+
+ case kDNS64State_QueryA:
+ case kDNS64State_QueryA2:
+ inQ->qtype = kDNSType_A;
+ break;
+
+ case kDNS64State_QueryPTR:
+ case kDNS64State_ReverseIPv4:
+ case kDNS64State_ReverseIPv6:
+ inQ->qtype = kDNSType_PTR;
+ break;
+
+ case kDNS64State_QueryAAAA:
+ inQ->qtype = kDNSType_AAAA;
+ break;
+
+ default:
+ LogMsg("DNS64RestartQuestion: unrecognized DNS64 state %d", inQ->dns64.state);
+ break;
+ }
+
+ mDNS_StartQuery_internal(m, inQ);
+}
+
+//===========================================================================================================================
+// DNS64TestIPv6Synthesis
+//===========================================================================================================================
+
+mDNSlocal mDNSBool DNS64TestIPv6Synthesis(mDNS *m, mDNSu16 inResGroupID, const mDNSv4Addr *inV4Addr)
+{
+ mStatus err;
+ nw_nat64_prefix_t * prefixes = NULL;
+ uint32_t prefixCount;
+ uint32_t i;
+ struct in_addr v4Addr;
+ struct in6_addr synthV6;
+ mDNSBool result = mDNSfalse;
+
+ err = DNS64GetPrefixes(m, inResGroupID, &prefixes, &prefixCount);
+ require_noerr_quiet(err, exit);
+
+ memcpy(&v4Addr.s_addr, inV4Addr->b, 4);
+ for (i = 0; i < prefixCount; i++)
+ {
+ if (nw_nat64_synthesize_v6(&prefixes[i], &v4Addr, &synthV6))
+ {
+ result = mDNStrue;
+ break;
+ }
+ }
+
+exit:
+ if (prefixes) free(prefixes);
+ return (result);
+}
+#endif // TARGET_OS_IOS
diff --git a/mDNSResponder/mDNSMacOSX/DNS64.h b/mDNSResponder/mDNSMacOSX/DNS64.h
new file mode 100644
index 00000000..80eb7feb
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DNS64.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DNS64_h
+#define __DNS64_h
+
+#include "mDNSEmbeddedAPI.h"
+
+#define DNS64IsQueryingARecord(STATE) (((STATE) == kDNS64State_QueryA) || ((STATE) == kDNS64State_QueryA2))
+#define DNS64ShouldAnswerQuestion(Q, RR) (DNS64IsQueryingARecord((Q)->dns64.state) && ((RR)->rrtype == kDNSType_A))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+mDNSexport mDNSBool DNS64StateMachine(mDNS *m, DNSQuestion *inQ, const ResourceRecord *inRR, QC_result inResult);
+mDNSexport mStatus DNS64AnswerQuestion(mDNS *m, DNSQuestion *inQ, const ResourceRecord *inRR, QC_result inResult);
+mDNSexport void DNS64HandleNewQuestion(mDNS *m, DNSQuestion *inQ);
+mDNSexport void DNS64ResetState(DNSQuestion *inQ);
+mDNSexport void DNS64RestartQuestions(mDNS *m);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __DNS64_h
diff --git a/mDNSResponder/mDNSMacOSX/DNS64State.h b/mDNSResponder/mDNSMacOSX/DNS64State.h
new file mode 100644
index 00000000..1a847900
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DNS64State.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DNS64State_h
+#define __DNS64State_h
+
+typedef enum
+{
+ kDNS64State_Initial = 0, // Initial state.
+ kDNS64State_PrefixDiscovery = 1, // Querying for "ipv4only.arpa." AAAA records to discover NAT64 IPv6 prefix(es).
+ kDNS64State_PrefixDiscoveryPTR = 2, // Same as PrefixDiscovery, but discoverying for "ip6.arpa." PTR record queries.
+ kDNS64State_QueryA = 3, // Querying for A record with same QNAME as AAAA record query.
+ kDNS64State_QueryA2 = 4, // Continuing A record query after being answered with a synthesizable A record.
+ kDNS64State_QueryAAAA = 5, // Querying for original AAAA record.
+ kDNS64State_QueryPTR = 6, // Determining whether to query for reverse IPV4 or reverse IPv6 PTR record.
+ kDNS64State_ReverseIPv4 = 7, // Querying for reverse IPV4 (in-addr.arpa.) PTR record.
+ kDNS64State_ReverseIPv6 = 8 // Querying for the original reverse IPv6 (ip6.arpa.) PTR record.
+
+} DNS64State;
+
+typedef struct
+{
+ DNS64State state; // Current state.
+ mDNSu8 qnameStash[15]; // Temporary space to hold the up to 15 bytes that are displaced in a DNSQuestion's qname
+ // when it's set to "ipv4only.arpa." during prefix discovery.
+} DNS64;
+
+#endif // __DNS64State_h
diff --git a/mDNSResponder/mDNSMacOSX/DNSProxySupport.c b/mDNSResponder/mDNSMacOSX/DNSProxySupport.c
index 7666cbc4..8a2e70b9 100644
--- a/mDNSResponder/mDNSMacOSX/DNSProxySupport.c
+++ b/mDNSResponder/mDNSMacOSX/DNSProxySupport.c
@@ -23,6 +23,8 @@
#include <sys/event.h>
#include <netinet/tcp.h>
+mDNSexport mDNS mDNSStorage;
+
#define ValidSocket(s) ((s) >= 0)
// Global to store the 4 DNS Proxy Listeners (UDPv4/6, TCPv4/6)
@@ -92,7 +94,7 @@ mDNSlocal int ProxyTCPRead(ProxyTCPInfo_t *tcpInfo)
return 1;
}
-mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context)
+mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context, __unused mDNSBool encounteredEOF)
{
int ret;
struct sockaddr_storage from;
@@ -185,11 +187,11 @@ mDNSlocal void ProxyTCPSocketCallBack(int s1, short filter, void *context)
// We pass sock for the TCPSocket and the "ti" for context as that's what we want to free at the end.
// In the UDP case, there is just a single socket and nothing to free. Hence, the context (last argument)
// would be NULL.
- kq->m->p->TCPProxyCallback(kq->m, sock, ti->reply, (mDNSu8 *)ti->reply + ti->replyLen, &senderAddr, senderPort, &destAddr,
+ kq->m->p->TCPProxyCallback(sock, ti->reply, (mDNSu8 *)ti->reply + ti->replyLen, &senderAddr, senderPort, &destAddr,
UnicastDNSPort, (mDNSInterfaceID)(uintptr_t)intf_id, ti);
}
-mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context)
+mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context, __unused mDNSBool encounteredEOF)
{
int newfd;
struct sockaddr_storage ss;
@@ -271,14 +273,14 @@ mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context)
}
}
-mDNSlocal mStatus SetupUDPProxySocket(mDNS *const m, int skt, KQSocketSet *cp, u_short sa_family, mDNSBool useBackgroundTrafficClass)
+mDNSlocal mStatus SetupUDPProxySocket(int skt, KQSocketSet *cp, u_short sa_family, mDNSBool useBackgroundTrafficClass)
{
int *s = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
KQueueEntry *k = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
const int on = 1;
mStatus err = mStatus_NoError;
- cp->m = m;
+ cp->m = &mDNSStorage;
cp->closeFlag = mDNSNULL;
// set default traffic class
@@ -348,13 +350,13 @@ mDNSlocal mStatus SetupUDPProxySocket(mDNS *const m, int skt, KQSocketSet *cp, u
return(err);
}
-mDNSlocal mStatus SetupTCPProxySocket(mDNS *const m, int skt, KQSocketSet *cp, u_short sa_family, mDNSBool useBackgroundTrafficClass)
+mDNSlocal mStatus SetupTCPProxySocket(int skt, KQSocketSet *cp, u_short sa_family, mDNSBool useBackgroundTrafficClass)
{
int *s = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
KQueueEntry *k = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
mStatus err;
- cp->m = m;
+ cp->m = &mDNSStorage;
// XXX may not be used by the TCP codepath
cp->closeFlag = mDNSNULL;
@@ -438,9 +440,10 @@ mDNSlocal void BindDPSocket(int fd, int sa_family)
}
// Setup DNS Proxy Skts in main kevent loop and set the skt options
-mDNSlocal void SetupDNSProxySkts(mDNS *const m, int fd[4])
+mDNSlocal void SetupDNSProxySkts(int fd[4])
{
- int i;
+ mDNS *const m = &mDNSStorage;
+ int i;
mStatus err;
KQSocketSet *udpSS;
KQSocketSet *tcpSS;
@@ -454,19 +457,19 @@ mDNSlocal void SetupDNSProxySkts(mDNS *const m, int fd[4])
// myKQSocketCallBack checks for proxy and calls the m->p->ProxyCallback instead of mDNSCoreReceive
udpSS->proxy = mDNStrue;
- err = SetupUDPProxySocket(m, fd[0], udpSS, AF_INET, mDNSfalse);
+ err = SetupUDPProxySocket(fd[0], udpSS, AF_INET, mDNSfalse);
if (err)
LogMsg("SetupDNSProxySkts: ERROR!! UDPv4 Socket");
- err = SetupUDPProxySocket(m, fd[1], udpSS, AF_INET6, mDNSfalse);
+ err = SetupUDPProxySocket(fd[1], udpSS, AF_INET6, mDNSfalse);
if (err)
LogMsg("SetupDNSProxySkts: ERROR!! UDPv6 Socket");
- err = SetupTCPProxySocket(m, fd[2], tcpSS, AF_INET, mDNSfalse);
+ err = SetupTCPProxySocket(fd[2], tcpSS, AF_INET, mDNSfalse);
if (err)
LogMsg("SetupDNSProxySkts: ERROR!! TCPv4 Socket");
- err = SetupTCPProxySocket(m, fd[3], tcpSS, AF_INET6, mDNSfalse);
+ err = SetupTCPProxySocket(fd[3], tcpSS, AF_INET6, mDNSfalse);
if (err)
LogMsg("SetupDNSProxySkts: ERROR!! TCPv6 Socket");
@@ -475,7 +478,7 @@ mDNSlocal void SetupDNSProxySkts(mDNS *const m, int fd[4])
}
// Create and bind the DNS Proxy Skts for use
-mDNSexport void mDNSPlatformInitDNSProxySkts(mDNS *const m, ProxyCallback UDPCallback, ProxyCallback TCPCallback)
+mDNSexport void mDNSPlatformInitDNSProxySkts(ProxyCallback UDPCallback, ProxyCallback TCPCallback)
{
int dpskt[4];
@@ -506,10 +509,10 @@ mDNSexport void mDNSPlatformInitDNSProxySkts(mDNS *const m, ProxyCallback UDPCal
LogInfo("mDNSPlatformInitDNSProxySkts: Opened Listener Sockets for DNS Proxy : %d, %d, %d, %d",
dpskt[0], dpskt[1], dpskt[2], dpskt[3]);
- m->p->UDPProxyCallback = UDPCallback;
- m->p->TCPProxyCallback = TCPCallback;
+ mDNSStorage.p->UDPProxyCallback = UDPCallback;
+ mDNSStorage.p->TCPProxyCallback = TCPCallback;
- SetupDNSProxySkts(m, dpskt);
+ SetupDNSProxySkts(dpskt);
}
mDNSexport void mDNSPlatformCloseDNSProxySkts(mDNS *const m)
diff --git a/mDNSResponder/mDNSMacOSX/DNSSECSupport.c b/mDNSResponder/mDNSMacOSX/DNSSECSupport.c
index b87f0d44..6db54b1c 100644
--- a/mDNSResponder/mDNSMacOSX/DNSSECSupport.c
+++ b/mDNSResponder/mDNSMacOSX/DNSSECSupport.c
@@ -561,7 +561,7 @@ mDNSexport void DNSSECProbe(mDNS *const m)
if (DNSSECProbeQuestion.ThisQInterval != -1)
return;
- rand = mDNSRandom(0x3FFFFFFF) % 100;
+ rand = mDNSRandom(FutureTime) % 100;
// Probe 1% of the time
if (rand >= DNSSECProbePercentage)
return;
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/CNDomainBrowserPathUtils.h b/mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/CNDomainBrowserPathUtils.h
new file mode 100644
index 00000000..682b9721
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/CNDomainBrowserPathUtils.h
@@ -0,0 +1,22 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+NSString * DomainPathToDNSDomain(NSArray * domainPath);
+NSArray * DNSDomainToDomainPath(NSString * domain);
+NSString * TrimCharactersFromDNSDomain(NSString * domain);
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/CNDomainBrowserPathUtils.m b/mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/CNDomainBrowserPathUtils.m
new file mode 100644
index 00000000..baa7702e
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/CNDomainBrowserPathUtils.m
@@ -0,0 +1,114 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "CNDomainBrowserPathUtils.h"
+#import <CFNetwork/CFHostPriv.h>
+#include "../../../Clients/ClientCommon.h"
+
+static const char *EscapeLabel(const char *cstr, char label[64])
+{
+ // Based on code on clownfish from: DNSName::GetEscapedDNSName
+ char *ptr = label;
+ while (*cstr) // While we have characters in the label...
+ {
+ char c = *cstr++;
+ if (c == '\\' || c == '.') // escape '\' and '.'
+ {
+ if (ptr >= label+64-2) return(NULL);
+ *ptr++ = '\\';
+ *ptr++ = c;
+ }
+ else if (c <= ' ') // escape ' ' and lower
+ {
+ if (ptr >= label+64-4) return(NULL);
+ *ptr++ = '\\';
+ *ptr++ = '0' + (c / 100);
+ *ptr++ = '0' + ((c / 10) % 10);
+ *ptr++ = '0' + (c % 10);
+ }
+ else
+ {
+ if (ptr >= label+64-1) return(NULL);
+ *ptr++ = c;
+ }
+ }
+ *ptr = 0;
+ return(label);
+}
+
+NSString * DomainPathToDNSDomain(NSArray * domainPath)
+{
+ NSMutableString * dnsStr = [NSMutableString string];
+
+ char label[64];
+ for (NSString * next in domainPath)
+ {
+ NSString * nextLabel;
+ if (dnsStr.length) nextLabel = [NSString stringWithUTF8String: EscapeLabel([next UTF8String], label)];
+ else nextLabel = next;
+ [dnsStr insertString: [NSString stringWithFormat: @"%@.", nextLabel] atIndex: 0];
+ }
+
+ return(dnsStr);
+}
+
+NSArray * DNSDomainToDomainPath(NSString * domain)
+{
+ int labels = 0, depth = 0;
+ char text[64];
+ const char * domainStr = domain.UTF8String;
+ const char *label[128];
+ NSString * undottedStr;
+ NSMutableArray *a = [NSMutableArray array];
+
+ while (*domainStr)
+ {
+ label[labels] = domainStr;
+ domainStr = GetNextLabel(domainStr, text);
+
+ undottedStr = [[NSString stringWithUTF8String: label[labels]]
+ stringByTrimmingCharactersInSet: [NSCharacterSet punctuationCharacterSet]];
+ if (!*domainStr || _CFHostIsDomainTopLevel((__bridge CFStringRef)undottedStr))
+ {
+ if (labels)
+ {
+ labels--; // If not first level then back up one level
+ undottedStr = [[NSString stringWithUTF8String: label[labels]]
+ stringByTrimmingCharactersInSet: [NSCharacterSet punctuationCharacterSet]];
+ }
+ [a addObject: undottedStr];
+ break;
+ }
+ labels++;
+ }
+
+ // Process the remainder of the hierarchy
+ for (depth = 0 ; depth < labels ; depth++)
+ {
+ GetNextLabel(label[labels-1-depth], text);
+ [a addObject: [NSString stringWithUTF8String: text]];
+ }
+
+ return(a);
+}
+
+NSString * TrimCharactersFromDNSDomain(NSString * domain)
+{
+ NSMutableCharacterSet * trimSet = [NSMutableCharacterSet whitespaceCharacterSet];
+ [trimSet formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]];
+ return([domain stringByTrimmingCharactersInSet:trimSet]);
+}
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/_CNDomainBrowser.h b/mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/_CNDomainBrowser.h
new file mode 100644
index 00000000..b80c2bf2
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/_CNDomainBrowser.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import <dispatch/queue.h>
+
+extern const NSString * _CNSubDomainKey_defaultFlag;
+extern const NSString * _CNSubDomainKey_subPath;
+
+@protocol _CNDomainBrowserDelegate;
+
+@interface _CNDomainBrowser : NSObject
+
+@property (nonatomic) BOOL browseRegistration;
+@property (nonatomic) BOOL ignoreLocal;
+@property (nonatomic) BOOL ignoreBTMM;
+@property (strong) dispatch_queue_t callbackQueue;
+@property (readonly) BOOL isBrowsing;
+
+- (instancetype)initWithDelegate:(id<_CNDomainBrowserDelegate>)delegate;
+- (void)startBrowser;
+- (void)stopBrowser;
+
+@property (readonly) NSArray * defaultDomainPath;
+@property (readonly) NSArray * flattenedDNSDomains;
+
+- (NSArray *)subDomainsAtDomainPath:(NSArray *)domainPath;
+
+@end
+
+@protocol _CNDomainBrowserDelegate <NSObject>
+
+- (void)bonjourBrowserDomainUpdate:(NSArray *)defaultDomainPath;
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/_CNDomainBrowser.m b/mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/_CNDomainBrowser.m
new file mode 100644
index 00000000..37983772
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/Shared/_CNDomainBrowser.m
@@ -0,0 +1,190 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "_CNDomainBrowser.h"
+#import "CNDomainBrowserPathUtils.h"
+#include <dns_sd.h>
+
+const NSString * _CNSubDomainKey_defaultFlag = @"defaultFlag";
+const NSString * _CNSubDomainKey_subPath = @"subPath";
+const NSString * _CNSubDomainKey_reverseDomainPath = @"reverseDomainPath";
+
+@interface _CNDomainBrowser ()
+
+@property (assign) DNSServiceRef browseDomainR;
+@property (strong) NSMutableDictionary * browseDomainD;
+
+@property (weak) id<_CNDomainBrowserDelegate> delegate;
+
+@end
+
+@implementation _CNDomainBrowser
+
+void enumReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *replyDomain, void *context);
+
+- (instancetype)initWithDelegate:(id<_CNDomainBrowserDelegate>)delegate
+{
+ if (self = [super init])
+ {
+ _delegate = delegate;
+ [self _commonInit];
+ }
+ return(self);
+}
+
+- (void)_commonInit
+{
+ self.browseDomainD = [NSMutableDictionary dictionary];
+ self.callbackQueue = dispatch_get_main_queue();
+}
+
+- (void)dealloc
+{
+ [self stopBrowser];
+}
+
+- (void)startBrowser
+{
+ if (!_browseDomainR)
+ {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ dispatch_queue_t queue = dispatch_queue_create("DNSServiceEnumerateDomains", DISPATCH_QUEUE_PRIORITY_DEFAULT);
+ dispatch_set_context(queue, (void *)CFBridgingRetain(self));
+ dispatch_set_finalizer_f(queue, finalizer);
+
+ DNSServiceRef ref;
+ if (DNSServiceEnumerateDomains(&ref, _browseRegistration ? kDNSServiceFlagsRegistrationDomains : kDNSServiceFlagsBrowseDomains, 0, enumReply, (__bridge void *)self))
+ NSLog(@"DNSServiceEnumerateDomains failed");
+ else
+ {
+ _browseDomainR = ref;
+ (void)DNSServiceSetDispatchQueue(_browseDomainR, queue);
+ }
+ });
+ }
+}
+
+- (void)stopBrowser
+{
+ if (_browseDomainR)
+ {
+ DNSServiceRefDeallocate(_browseDomainR);
+ _browseDomainR = nil;
+ }
+}
+
+- (NSArray *)defaultDomainPath
+{
+ NSArray * revDomainArray = nil;
+
+ NSArray *defaults = [[self.browseDomainD allValues] filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"(%K == %@)", _CNSubDomainKey_defaultFlag, @YES]];
+ if (defaults.count) revDomainArray = defaults[0][_CNSubDomainKey_reverseDomainPath];
+ if (!revDomainArray) revDomainArray = [NSArray arrayWithObject: @"local"]; // If no defaults found
+
+ return(revDomainArray);
+}
+
+- (NSArray *)flattenedDNSDomains
+{
+ return([self.browseDomainD allKeys]);
+}
+
+- (NSArray *)subDomainsAtDomainPath:(NSArray *)domainPath
+{
+ NSMutableDictionary * subs = [NSMutableDictionary dictionary];
+ for (NSDictionary * next in [self.browseDomainD allValues])
+ {
+ NSArray * bdomain = next[_CNSubDomainKey_reverseDomainPath];
+ if (bdomain.count > domainPath.count)
+ {
+ BOOL match = YES;
+ for (NSUInteger i = 0 ; i < domainPath.count ; i++)
+ {
+ if (![bdomain[i] isEqualToString: domainPath[i]]) { match = NO; break; }
+ }
+ if (match)
+ {
+ NSString * key = bdomain[domainPath.count];
+ [subs setObject: @{ _CNSubDomainKey_subPath: key, _CNSubDomainKey_defaultFlag: next[_CNSubDomainKey_defaultFlag] } forKey: key];
+ }
+ }
+ }
+ return([subs allValues]);
+}
+
+- (void) reloadBrowser
+{
+ if ([_delegate respondsToSelector: @selector(bonjourBrowserDomainUpdate:)])
+ {
+ dispatch_async(self.callbackQueue, ^{
+ [_delegate bonjourBrowserDomainUpdate: [self defaultDomainPath]];
+ });
+ }
+}
+
+- (BOOL)isBrowsing
+{
+ return(_browseDomainR != nil);
+}
+
+#pragma mark - Dispatch
+
+static void finalizer(void * context)
+{
+ _CNDomainBrowser *self = (__bridge _CNDomainBrowser *)context;
+ NSLog(@"finalizer: %@", self);
+ (void)CFBridgingRelease((__bridge void *)self);
+}
+
+#pragma mark - Commands
+
+#pragma mark - Static Callbacks
+
+void enumReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
+ const char *replyDomain, void *context)
+{
+ (void)sdRef;
+ (void)interfaceIndex;
+ (void)errorCode;
+
+ if (!*replyDomain) return;
+
+ _CNDomainBrowser *self = (__bridge _CNDomainBrowser *)context;
+ NSString *key = [NSString stringWithUTF8String: replyDomain];
+
+ if (self.ignoreLocal && [key isEqualToString: @"local."]) return;
+ if (self.ignoreBTMM && [key hasSuffix: @".members.btmm.icloud.com."]) return;
+
+ if (!(flags & kDNSServiceFlagsAdd))
+ {
+ [self.browseDomainD removeObjectForKey:key];
+ }
+ else
+ {
+ NSArray * pathArray = DNSDomainToDomainPath(key);
+ [self.browseDomainD setObject: @{ _CNSubDomainKey_reverseDomainPath: pathArray,
+ _CNSubDomainKey_defaultFlag: (flags & kDNSServiceFlagsDefault) ? @YES : @NO }
+ forKey: key];
+ }
+
+ if (!(flags & kDNSServiceFlagsMoreComing))
+ {
+ [self reloadBrowser];
+ }
+}
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/CNDomainBrowserViewController.h b/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/CNDomainBrowserViewController.h
new file mode 100644
index 00000000..bf70f88c
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/CNDomainBrowserViewController.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+IB_DESIGNABLE
+
+@protocol CNDomainBrowserViewControllerDelegate;
+
+@interface CNTableViewController : UITableViewController
+@end
+
+@interface CNDomainBrowserViewController : CNTableViewController
+
+@property (nonatomic) IBInspectable BOOL browseRegistration;
+@property (nonatomic) IBInspectable BOOL ignoreLocal;
+@property (weak) IBOutlet id<CNDomainBrowserViewControllerDelegate> delegate;
+
+@property (readonly) NSString * selectedDNSDomain;
+@property (readonly) NSString * defaultDNSDomain;
+@property (readonly) NSArray * flattenedDNSDomains;
+
+@property (readonly) BOOL isBrowsing;
+
+- (void)startBrowse;
+- (void)stopBrowse;
+
+@end
+
+@protocol CNDomainBrowserViewControllerDelegate <NSObject>
+
+@optional
+
+- (void)domainBrowserDomainSelected:(NSString *)domain;
+- (void)bonjourBrowserDomainUpdate:(NSString *)defaultDomain;
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/CNDomainBrowserViewController.m b/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/CNDomainBrowserViewController.m
new file mode 100644
index 00000000..b8c9e65c
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/CNDomainBrowserViewController.m
@@ -0,0 +1,350 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "CNDomainBrowserViewController.h"
+#import "_CNDomainBrowser.h"
+#import "CNDomainBrowserPathUtils.h"
+#import <AssertMacros.h>
+
+#define LocalizedStringFromTableInMyBundle(key, table, comment) \
+ NSLocalizedStringFromTableInBundle(key, table, [NSBundle bundleForClass: [self class]], comment)
+
+
+@interface CNTableViewController()
+@property (copy) NSArray * pathArray;
+@property (assign) NSInteger selectionIndex;
+@end
+
+@implementation CNTableViewController
+
+- (instancetype)initWithStyle:(UITableViewStyle)style
+{
+ if (self = [super initWithStyle: style])
+ {
+ _selectionIndex = NSNotFound;
+ _pathArray = [NSArray array];
+ }
+ return self;
+}
+
+@end
+
+@interface CNDomainBrowserViewController ()
+
+@property _CNDomainBrowser * bonjour;
+
+@property (strong) NSMutableDictionary * instanceInfoStrings;
+@property (strong) NSMutableDictionary * instanceStatusViews;
+
+@end
+
+@implementation CNDomainBrowserViewController
+
+- (instancetype)initWithStyle:(UITableViewStyle)style
+{
+ if (self = [super initWithStyle: style])
+ {
+ [self commonInit];
+ }
+ return(self);
+}
+
+- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ if (self = [super initWithNibName: nibNameOrNil bundle: nibBundleOrNil])
+ {
+ [self commonInit];
+ }
+ return(self);
+}
+
+- (nullable instancetype)initWithCoder:(NSCoder *)coder
+{
+ if (self = [super initWithCoder: coder])
+ {
+ [self commonInit];
+ }
+ return(self);
+}
+
+- (void)commonInit
+{
+ self.bonjour = [[_CNDomainBrowser alloc] initWithDelegate: (id<_CNDomainBrowserDelegate>)self];
+ self.bonjour.browseRegistration = _browseRegistration;
+ self.bonjour.ignoreLocal = _ignoreLocal;
+ self.instanceInfoStrings = [NSMutableDictionary dictionary];
+ self.instanceStatusViews = [NSMutableDictionary dictionary];
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+ [super viewWillAppear: animated];
+ NSArray * pathArray = DNSDomainToDomainPath(_selectedDNSDomain);
+ if ((self.isMovingToParentViewController || self.isBeingPresented) && (pathArray.count > 1))
+ {
+ [self updateUIToDomainPathArray: pathArray];
+ }
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+
+ self.tableView.allowsMultipleSelectionDuringEditing = NO;
+ self.tableView.dataSource = (id<UITableViewDataSource>)self;
+ self.tableView.delegate = (id<UITableViewDelegate>)self;
+
+ self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: LocalizedStringFromTableInMyBundle(@"_dnsBrowser.browsedomains.cancel", @"DomainBrowser", nil)
+ style: UIBarButtonItemStylePlain
+ target: self
+ action: @selector(cancelAction:)];
+
+}
+
+- (void)updateUIToDomainPathArray:(NSArray *)newPathArray
+{
+ if (newPathArray.count > 1)
+ {
+ CNTableViewController * controller = nil;
+ NSMutableArray * newSubPathArray = [NSMutableArray array];
+ for (NSString * nextPathComponent in newPathArray)
+ {
+ BOOL animate = NO;//(newPathArray.count == ++count);
+ controller = [self pushNewBrowseController: newSubPathArray.lastObject animated: animate];
+ controller.pathArray = newSubPathArray;
+ [newSubPathArray addObject: nextPathComponent];
+ }
+ }
+}
+
+- (IBAction)cancelAction:(id)sender
+{
+ (void)sender; // Unused
+ [self.navigationController dismissViewControllerAnimated: YES completion: nil];
+}
+
+- (CNTableViewController *)pushNewBrowseController:(NSString *)title animated:(BOOL)animated
+{
+ CNTableViewController *tvc = [[CNTableViewController alloc] initWithStyle: self.tableView.style];
+ tvc.title = title;
+ tvc.clearsSelectionOnViewWillAppear = NO;
+ tvc.tableView.dataSource = (id<UITableViewDataSource>)self;
+ tvc.tableView.delegate = (id<UITableViewDelegate>)self;
+ [self.navigationController pushViewController: tvc animated: animated];
+ return(tvc);
+}
+
+- (CNTableViewController *)controllerForTableView:(UITableView *)tableView
+{
+ CNTableViewController * result = nil;
+
+ for (CNTableViewController * next in self.navigationController.viewControllers)
+ {
+ if ([next isKindOfClass: [CNTableViewController class]] && next.tableView == tableView)
+ {
+ result = next;
+ break;
+ }
+ }
+
+ return(result);
+}
+
+- (NSArray *)selectedPathArrayForTableView:(UITableView *)tableView includeSelectedRow:(BOOL)includeSelection
+{
+ NSMutableArray * pathArray = [NSMutableArray array];
+ CNTableViewController * controller = [self controllerForTableView: tableView];
+
+ [pathArray addObjectsFromArray: controller.pathArray];
+
+ if (includeSelection && controller.selectionIndex != NSNotFound)
+ {
+ NSArray * rowArray = [[self.bonjour subDomainsAtDomainPath: pathArray] sortedArrayUsingComparator: ^(id obj1, id obj2) {
+ return (NSComparisonResult)[ obj1[_CNSubDomainKey_subPath] compare: obj2[_CNSubDomainKey_subPath]];
+ }];
+ if (controller.selectionIndex < (NSInteger)rowArray.count)
+ {
+ [pathArray addObject: rowArray[controller.selectionIndex][_CNSubDomainKey_subPath]];
+ }
+ }
+
+ return(pathArray);
+}
+
+- (void)plusButtonPressed:(UIControl *)button withEvent:(UIEvent *)event
+{
+ UITableView * tableView = ((UITableViewController *)self.navigationController.topViewController).tableView;
+ NSIndexPath * indexPath = [tableView indexPathForRowAtPoint: [[[event touchesForView: button] anyObject] locationInView: tableView]];
+ if (indexPath != nil && self.delegate)
+ {
+ [self controllerForTableView: tableView].selectionIndex = indexPath.row;
+ NSArray * pathArray = [self selectedPathArrayForTableView: ((CNTableViewController *)self.navigationController.topViewController).tableView includeSelectedRow: YES];
+ _selectedDNSDomain = DomainPathToDNSDomain(pathArray);
+ [self.navigationController dismissViewControllerAnimated: YES completion: ^{
+ if ([self.delegate respondsToSelector: @selector(domainBrowserDomainSelected:)])
+ {
+ [self.delegate domainBrowserDomainSelected: _selectedDNSDomain];
+ }
+ }];
+ }
+}
+
+#pragma mark - Public Methods
+
+- (void)setIgnoreLocal:(BOOL)ignoreLocal
+{
+ _ignoreLocal = ignoreLocal;
+ self.bonjour.ignoreLocal = _ignoreLocal;
+}
+
+- (void)setBrowseRegistration:(BOOL)browseRegistration
+{
+ _browseRegistration = browseRegistration;
+ self.bonjour.browseRegistration = _browseRegistration;
+}
+
+- (NSString *)defaultDNSDomain
+{
+ return(DomainPathToDNSDomain(self.bonjour.defaultDomainPath));
+}
+
+- (NSArray *)flattenedDNSDomains
+{
+ return(self.bonjour.flattenedDNSDomains);
+}
+
+- (void)startBrowse
+{
+ [self.bonjour startBrowser];
+}
+
+- (void)stopBrowse
+{
+ [self.bonjour stopBrowser];
+}
+
+- (BOOL)isBrowsing
+{
+ return(self.bonjour.isBrowsing);
+}
+
+#pragma mark - TableView Delegates
+
+- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ (void)tableView; // Unused
+ (void)indexPath; // Unused
+ return UITableViewAutomaticDimension;
+}
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
+{
+ (void)tableView; // Unused
+ return(1);
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+ (void)section; // Unused
+ return([self.bonjour subDomainsAtDomainPath: [self selectedPathArrayForTableView: tableView includeSelectedRow: NO]].count);
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ UITableViewCell *cell = nil;
+
+ static NSString *MyIdentifier = @"browse_cell_id";
+ cell = [tableView dequeueReusableCellWithIdentifier: MyIdentifier];
+ if (!cell)
+ {
+ cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: MyIdentifier];
+ }
+
+ // Get the name
+ NSMutableArray * pathArray = [NSMutableArray arrayWithArray: [self selectedPathArrayForTableView: tableView includeSelectedRow: NO]];
+ NSArray * rowArray = [[self.bonjour subDomainsAtDomainPath: pathArray] sortedArrayUsingComparator: ^(id obj1, id obj2) {
+ return (NSComparisonResult)[ obj1[_CNSubDomainKey_subPath] compare: obj2[_CNSubDomainKey_subPath]];
+ }];
+ if (indexPath.row < (NSInteger)rowArray.count)
+ {
+ NSDictionary * item = [rowArray objectAtIndex: indexPath.row];
+ NSString *val = item[_CNSubDomainKey_subPath];
+ cell.textLabel.text = val;
+
+ // Set selection
+ BOOL selected = ([self controllerForTableView: tableView].selectionIndex == indexPath.row);
+ if (selected) [tableView selectRowAtIndexPath: indexPath animated: NO scrollPosition: UITableViewScrollPositionNone];
+
+ // Make Default domain bold
+ if ([item[_CNSubDomainKey_defaultFlag] boolValue]) cell.textLabel.font = [UIFont boldSystemFontOfSize: [UIFont labelFontSize]];
+ else cell.textLabel.font = nil;
+
+ // See if it's a leaf
+ [pathArray addObject: val];
+ cell.accessoryType = [self.bonjour subDomainsAtDomainPath: pathArray].count ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
+
+ // Add the "+" button
+ UIButton * plus = [UIButton buttonWithType: UIButtonTypeContactAdd];
+ [plus addTarget: self action: @selector(plusButtonPressed:withEvent:) forControlEvents: UIControlEventTouchUpInside];
+ plus.userInteractionEnabled = YES;
+ [cell.contentView addSubview: plus];
+
+ plus.translatesAutoresizingMaskIntoConstraints = NO;
+ [plus.widthAnchor constraintEqualToConstant: plus.frame.size.width].active = YES;
+ [plus.heightAnchor constraintEqualToConstant: plus.frame.size.height].active = YES;
+ [plus.centerYAnchor constraintEqualToAnchor: cell.layoutMarginsGuide.centerYAnchor].active = YES;
+ [plus.trailingAnchor constraintEqualToAnchor: cell.layoutMarginsGuide.trailingAnchor constant: -20].active = YES;
+ }
+
+ return(cell);
+}
+
+- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ UITableViewCell * cell = [tableView cellForRowAtIndexPath: indexPath];
+ return((cell.accessoryType == UITableViewCellAccessoryNone) ? nil : indexPath);
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ UITableViewCell * cell = [tableView cellForRowAtIndexPath: indexPath];
+ if (cell.accessoryType != UITableViewCellAccessoryNone)
+ {
+ // Push next
+ CNTableViewController * controller = [self controllerForTableView: tableView];
+ NSArray * lastpathArray = controller.pathArray;
+ controller.selectionIndex = indexPath.row;
+ NSString * title = cell.textLabel.text;
+ controller = [self pushNewBrowseController: title animated: YES];
+ controller.pathArray = [lastpathArray arrayByAddingObject: title];
+ }
+ [tableView deselectRowAtIndexPath: indexPath animated: YES];
+}
+
+#pragma mark - _CNDomainBrowser Delegates
+
+- (void)bonjourBrowserDomainUpdate:(NSArray *)defaultDomainPath
+{
+ _selectedDNSDomain = DomainPathToDNSDomain(defaultDomainPath);
+ [((UITableViewController *)self.navigationController.topViewController).tableView reloadData];
+ if ([self.delegate respondsToSelector: @selector(bonjourBrowserDomainUpdate:)])
+ {
+ [self.delegate bonjourBrowserDomainUpdate: _selectedDNSDomain];
+ }
+}
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/DomainBrowser.h b/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/DomainBrowser.h
new file mode 100644
index 00000000..4a740bfe
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/DomainBrowser.h
@@ -0,0 +1,30 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+//! Project version number for DomainBrowser.
+FOUNDATION_EXPORT double DomainBrowserVersionNumber;
+
+//! Project version string for DomainBrowser.
+FOUNDATION_EXPORT const unsigned char DomainBrowserVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import <DomainBrowser/PublicHeader.h>
+
+
+#import <DomainBrowser/CNDomainBrowserViewController.h>
+#import <DomainBrowser/CNDomainBrowserPathUtils.h>
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/DomainBrowser.strings b/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/DomainBrowser.strings
new file mode 100644
index 00000000..27956d73
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/DomainBrowser.strings
@@ -0,0 +1,18 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+"_dnsBrowser.browsedomains.cancel" = "Cancel";
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/Info.plist b/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/Info.plist
new file mode 100644
index 00000000..d3de8eef
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/iOS/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>$(CURRENT_PROJECT_VERSION)</string>
+ <key>NSPrincipalClass</key>
+ <string></string>
+</dict>
+</plist>
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/CNDomainBrowserView.h b/mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/CNDomainBrowserView.h
new file mode 100644
index 00000000..ccc381b3
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/CNDomainBrowserView.h
@@ -0,0 +1,58 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+@protocol CNDomainBrowserViewDelegate;
+
+IB_DESIGNABLE
+
+@interface CNDomainBrowserView : NSView
+
+@property (nonatomic) IBInspectable BOOL browseRegistration;
+@property (nonatomic) IBInspectable BOOL ignoreLocal;
+@property (nonatomic) IBInspectable BOOL ignoreBTMM;
+@property (weak) IBOutlet id<CNDomainBrowserViewDelegate> delegate;
+
+@property (readonly) NSString * selectedDNSDomain;
+@property (readonly) NSString * defaultDNSDomain;
+@property (readonly) NSArray * flattenedDNSDomains;
+
+@property (readonly) BOOL isBrowsing;
+
+- (void)startBrowse;
+- (void)stopBrowse;
+
+@end
+
+@protocol CNDomainBrowserViewDelegate <NSObject>
+
+@optional
+
+- (void)bonjourBrowserDomainSelected:(NSString *)domain;
+- (void)bonjourBrowserDomainUpdate:(NSString *)defaultDomain;
+
+@end
+
+@interface CNBonjourDomainCell : NSCell
+@end
+
+@interface CNBonjourDomainView : NSView
+
+@property(strong, nonatomic) NSString * domain;
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/CNDomainBrowserView.m b/mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/CNDomainBrowserView.m
new file mode 100644
index 00000000..1bb52602
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/CNDomainBrowserView.m
@@ -0,0 +1,474 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "CNDomainBrowserView.h"
+#import "_CNDomainBrowser.h"
+#import "CNDomainBrowserPathUtils.h"
+
+#define DEBUG_POPUP_CELLS 0
+#define SHOW_SERVICETYPE_IF_SEARCH_COUNT 0
+#define TEST_LEGACYBROWSE 0
+
+#define BROWSER_CELL_SPACING 4
+
+@protocol CNServiceTypeLocalizerDelegate <NSObject>
+@property (strong) NSDictionary * localizedServiceTypesDictionary;
+@end
+
+@interface CNServiceTypeLocalizer : NSValueTransformer
+{
+ id<CNServiceTypeLocalizerDelegate> _delegate;
+}
+- (instancetype)initWithDelegate:(id<CNServiceTypeLocalizerDelegate>)delegate;
+
+@end
+
+@implementation CNServiceTypeLocalizer
+
+- (instancetype)initWithDelegate:(id<CNServiceTypeLocalizerDelegate>)delegate
+{
+ if (self = [super init])
+ {
+ _delegate = delegate;
+ }
+ return(self);
+}
+
++ (Class)transformedValueClass
+{
+ return [NSString class];
+}
+
++ (BOOL)allowsReverseTransformation
+{
+ return NO;
+}
+
+- (nullable id)transformedValue:(nullable id)value
+{
+ id result = value;
+
+ if (value && _delegate && [_delegate respondsToSelector: @selector(localizedServiceTypesDictionary)])
+ {
+ NSString * localizedValue = [_delegate.localizedServiceTypesDictionary objectForKey: value];
+ if (localizedValue) result = localizedValue;
+ }
+
+ return(result);
+}
+
+@end
+
+@implementation NSBrowser(PathArray)
+
+- (NSArray *)pathArrayToColumn:(NSInteger)column includeSelectedRow:(BOOL)includeSelection
+{
+ NSMutableArray * pathArray = [NSMutableArray array];
+ if (!includeSelection) column--;
+ for (NSInteger c = 0 ; c <= column ; c++)
+ {
+ NSBrowserCell *cell = [self selectedCellInColumn: c];
+ if (cell) [pathArray addObject: [cell stringValue]];
+ }
+
+ return(pathArray);
+}
+
+@end
+
+@interface CNDomainBrowserView ()
+
+@property (strong) _CNDomainBrowser * bonjour;
+@property (strong) NSSplitView * mainSplitView;
+
+@property (strong) NSTableView * instanceTable;
+@property (strong) NSArrayController * instanceC;
+@property (strong) NSTableColumn * instanceNameColumn;
+@property (strong) NSTableColumn * instanceServiceTypeColumn;
+@property (strong) NSTableColumn * instancePathPopupColumn;
+
+@property (strong) NSBrowser * browser;
+
+@property (strong) CNServiceTypeLocalizer * serviceTypeLocalizer;
+
+@end
+
+@implementation CNDomainBrowserView
+
+- (instancetype)initWithFrame:(NSRect)frameRect
+{
+ if (self = [super initWithFrame: frameRect])
+ {
+ [self commonInit];
+ }
+ return(self);
+}
+
+- (nullable instancetype)initWithCoder:(NSCoder *)coder
+{
+ if (self = [super initWithCoder: coder])
+ {
+ [self commonInit];
+ }
+ return(self);
+}
+
+- (void)awakeFromNib
+{
+ [super awakeFromNib];
+
+ self.bonjour = [[_CNDomainBrowser alloc] initWithDelegate:(id<_CNDomainBrowserDelegate>)self];
+ _bonjour.browseRegistration = _browseRegistration;
+ _bonjour.ignoreLocal = _ignoreLocal;
+ _bonjour.ignoreBTMM = _ignoreBTMM;
+}
+
+
+- (void)contentViewsInit
+{
+ NSRect frame = self.frame;
+ self.instanceC = [[NSArrayController alloc] init];
+ self.serviceTypeLocalizer = [[CNServiceTypeLocalizer alloc] initWithDelegate: (id<CNServiceTypeLocalizerDelegate>)self];
+
+ // Bottom browser
+ frame.origin.x = frame.origin.y = 0;
+ NSBrowser * browserView = [[NSBrowser alloc] initWithFrame: frame];
+ browserView.delegate = (id<NSBrowserDelegate>)self;
+ browserView.action = @selector(clickAction:);
+ browserView.titled = NO;
+ browserView.separatesColumns = NO;
+ browserView.allowsEmptySelection = YES;
+ browserView.allowsMultipleSelection = NO;
+ browserView.takesTitleFromPreviousColumn = NO;
+ browserView.hasHorizontalScroller = YES;
+ browserView.columnResizingType = NSBrowserNoColumnResizing;
+ browserView.minColumnWidth = 50;
+ self.browser = browserView;
+
+ [self addSubview: browserView];
+}
+
+- (void)commonInit
+{
+ [self contentViewsInit];
+}
+
+- (void)viewWillMoveToWindow:(NSWindow *)newWindow
+{
+ [super viewWillMoveToWindow: newWindow];
+ if (newWindow)
+ {
+ [self.mainSplitView adjustSubviews];
+ }
+}
+
+- (void)setDomainSelectionToPathArray:(NSArray *)pathArray
+{
+ NSInteger column = 0;
+ for (NSString * nextPathComponent in pathArray)
+ {
+ NSArray * subPath = [self.browser pathArrayToColumn: column includeSelectedRow: NO];
+ NSArray * rowArray = [[self.bonjour subDomainsAtDomainPath: subPath] sortedArrayUsingComparator: ^(id obj1, id obj2) {
+ return (NSComparisonResult)[ obj1[_CNSubDomainKey_subPath] compare: obj2[_CNSubDomainKey_subPath]];
+ }];
+ NSInteger nextRow = [rowArray indexOfObjectPassingTest: ^BOOL(id obj, NSUInteger index, BOOL *stop) {
+ (void)index;
+ (void)stop;
+ return [obj[_CNSubDomainKey_subPath] isEqualToString: nextPathComponent];
+ }];
+ [self.browser selectRow: nextRow inColumn: column++];
+ }
+}
+
+- (NSInteger)maxNumberOfVisibleSubDomainRows
+{
+ NSInteger result = 0;
+
+ for (NSInteger i = self.browser.firstVisibleColumn ; i <= self.browser.lastVisibleColumn ; i++)
+ {
+ NSInteger rows = [self browser: self.browser numberOfRowsInColumn: i];
+ result = MAX(rows, result);
+ }
+
+ return(result);
+}
+
+#pragma mark - Public Methods
+
+- (void)setIgnoreLocal:(BOOL)ignoreLocal
+{
+ _ignoreLocal = ignoreLocal;
+ self.bonjour.ignoreLocal = _ignoreLocal;
+}
+
+- (void)setBrowseRegistration:(BOOL)browseRegistration
+{
+ _browseRegistration = browseRegistration;
+ self.bonjour.browseRegistration = _browseRegistration;
+}
+
+- (NSString *)selectedDNSDomain
+{
+ NSArray * pathArray = [self.browser pathArrayToColumn: self.browser.selectedColumn includeSelectedRow: YES];
+ return(DomainPathToDNSDomain(pathArray));
+}
+
+- (NSString *)defaultDNSDomain
+{
+ return(DomainPathToDNSDomain(self.bonjour.defaultDomainPath));
+}
+
+- (NSArray *)flattenedDNSDomains
+{
+ return(self.bonjour.flattenedDNSDomains);
+}
+
+
+- (void)startBrowse
+{
+ [self.bonjour startBrowser];
+}
+
+- (void)stopBrowse
+{
+ [self.bonjour stopBrowser];
+}
+
+- (BOOL)isBrowsing
+{
+ return(self.bonjour.isBrowsing);
+}
+
+#pragma mark - Notifications
+
+- (void)browser:(NSBrowser *)sender selectionDidChange:(NSArray *)pathArray
+{
+ if (_delegate && [_delegate respondsToSelector: @selector(bonjourBrowserDomainSelected:)] &&
+ sender == self.browser)
+ {
+ [_delegate bonjourBrowserDomainSelected: pathArray ? DomainPathToDNSDomain(pathArray) : nil];
+ }
+}
+
+#pragma mark - NSBrowserDelegate
+
+- (NSInteger)browser:(NSBrowser *)sender numberOfRowsInColumn:(NSInteger)column
+{
+ return ([self.bonjour subDomainsAtDomainPath: [sender pathArrayToColumn: column includeSelectedRow: NO]].count);
+}
+
+- (void)browser:(NSBrowser *)sender willDisplayCell:(id)cell atRow:(NSUInteger)row column:(NSInteger)column
+{
+ // Get the name
+ NSMutableArray * pathArray = [NSMutableArray arrayWithArray: [sender pathArrayToColumn: column includeSelectedRow: NO]];
+ NSArray * rowArray = [[self.bonjour subDomainsAtDomainPath: pathArray] sortedArrayUsingComparator: ^(id obj1, id obj2) {
+ return (NSComparisonResult)[ obj1[_CNSubDomainKey_subPath] compare: obj2[_CNSubDomainKey_subPath]];
+ }];
+ if (row < rowArray.count)
+ {
+ NSDictionary * item = [rowArray objectAtIndex: row];
+ NSString *val = item[_CNSubDomainKey_subPath];
+ [cell setStringValue: val];
+
+ // See if it's a leaf
+ [pathArray addObject: val];
+ ((NSBrowserCell*)cell).leaf = (![self.bonjour subDomainsAtDomainPath: pathArray].count);
+
+ // Make Default domain bold
+ if ([item[_CNSubDomainKey_defaultFlag] boolValue]) ((NSBrowserCell*)cell).font = [NSFont boldSystemFontOfSize: [NSFont systemFontSizeForControlSize: sender.controlSize]];
+ else ((NSBrowserCell*)cell).font = [NSFont controlContentFontOfSize: [NSFont systemFontSizeForControlSize: sender.controlSize]];
+ }
+}
+
+- (CGFloat)browser:(NSBrowser *)sender shouldSizeColumn:(NSInteger)column forUserResize:(BOOL)forUserResize toWidth:(CGFloat)suggestedWidth
+{
+ (void)forUserResize;
+ CGFloat newSize = 0;
+
+ NSArray * pathArray = [NSArray arrayWithArray: [sender pathArrayToColumn: column includeSelectedRow: NO]];
+ NSArray * rowArray = [[self.bonjour subDomainsAtDomainPath: pathArray] sortedArrayUsingComparator: ^(id obj1, id obj2) {
+ return (NSComparisonResult)[ obj1[_CNSubDomainKey_subPath] compare: obj2[_CNSubDomainKey_subPath]];
+ }];
+
+ for (NSDictionary * next in rowArray)
+ {
+ NSFont * font = [next[_CNSubDomainKey_defaultFlag] boolValue] ?
+ [NSFont boldSystemFontOfSize: [NSFont systemFontSizeForControlSize: sender.controlSize]]:
+ [NSFont controlContentFontOfSize: [NSFont systemFontSizeForControlSize: sender.controlSize]];
+ NSArray * itemArray = [pathArray arrayByAddingObjectsFromArray: [NSArray arrayWithObject: next[_CNSubDomainKey_subPath]]];
+ NSBrowserCell * cell = [[NSBrowserCell alloc] initTextCell: next[_CNSubDomainKey_subPath]];
+ cell.font = font;
+ cell.leaf = ([self.bonjour subDomainsAtDomainPath: itemArray].count == 0);
+ newSize = MAX(newSize, cell.cellSize.width + BROWSER_CELL_SPACING);
+ }
+
+ if (!newSize) newSize = suggestedWidth;
+ newSize = (NSInteger)(newSize + 0.5);
+
+ return(newSize);
+}
+
+#pragma mark - _CNDomainBrowser Delegates
+
+- (void)bonjourBrowserDomainUpdate:(NSArray *)defaultDomainPath
+{
+ (void)defaultDomainPath;
+ [self.browser loadColumnZero];
+ [self setDomainSelectionToPathArray: self.bonjour.defaultDomainPath];
+}
+
+#pragma mark - Commands
+
+- (IBAction)clickAction:(id)sender
+{
+ (void)sender;
+ NSArray * pathArray = [self.browser pathArrayToColumn: self.browser.selectedColumn includeSelectedRow: YES];
+ if (!pathArray.count) pathArray = self.bonjour.defaultDomainPath;
+ [self setDomainSelectionToPathArray: pathArray];
+ [self browser: self.browser selectionDidChange: pathArray];
+}
+
+@end
+
+@interface CNBonjourDomainCell()
+
+@property(strong) NSMutableArray * browserCells;
+
+@end
+
+@implementation CNBonjourDomainCell
+
+- (instancetype)init
+{
+ self = [super init];
+ if (self)
+ {
+ self.browserCells = [NSMutableArray array];
+ }
+ return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)coder
+{
+ self = [super initWithCoder:coder];
+ if (self)
+ {
+ self.browserCells = [NSMutableArray array];
+ }
+ return self;
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+ CNBonjourDomainCell *cell = [super copyWithZone: zone];
+ if (cell)
+ {
+ cell.browserCells = [NSMutableArray arrayWithArray: self.browserCells];
+ }
+ return cell;
+}
+
+- (void) setObjectValue:(id)objectValue
+{
+ [super setObjectValue: objectValue];
+
+ [self.browserCells removeAllObjects];
+ if ([objectValue isKindOfClass: [NSString class]])
+ {
+ NSUInteger count = 0;
+ NSArray * subPaths = DNSDomainToDomainPath(objectValue);
+ for (NSString * nextPath in subPaths)
+ {
+ NSBrowserCell * nextCell = [[NSBrowserCell alloc] initTextCell: nextPath];
+ nextCell.leaf = (++count == subPaths.count);
+ [self.browserCells addObject: nextCell];
+ }
+ }
+}
+
+- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
+{
+ CGFloat usedWidth = BROWSER_CELL_SPACING / 2;
+ for (NSBrowserCell * nextCell in self.browserCells)
+ {
+ NSRect nextRect = cellFrame;
+ nextRect.size.width = cellFrame.size.width - usedWidth;
+ nextRect.origin.x += usedWidth;
+
+ NSSize cellSize = [nextCell cellSizeForBounds: nextRect];
+ CGFloat yOffset = (nextRect.size.height - cellSize.height) / 2;
+ nextRect.size.width = cellSize.width;
+ nextRect.size.height = cellSize.height;
+ nextRect.origin.y += yOffset;
+
+ [nextCell drawInteriorWithFrame: nextRect
+ inView: controlView];
+ usedWidth += nextRect.size.width + BROWSER_CELL_SPACING;
+ }
+}
+
+@end
+
+@interface CNBonjourDomainView()
+
+@property(strong) CNBonjourDomainCell * cell;
+
+@end
+
+@implementation CNBonjourDomainView
+
+- (instancetype)initWithFrame:(NSRect)frameRect
+{
+ self = [super initWithFrame:frameRect];
+ if (self)
+ {
+ self.cell = [[CNBonjourDomainCell alloc] init];
+ }
+ return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)coder
+{
+ self = [super initWithCoder:coder];
+ if (self)
+ {
+ self.cell = [[CNBonjourDomainCell alloc] init];
+ }
+ return self;
+}
+
+- (void) setDomain:(NSString *)domain
+{
+ if (![domain isEqualToString: self.cell.stringValue])
+ {
+ self.cell.stringValue = domain;
+ self.needsDisplay = YES;
+ }
+}
+
+- (NSString *)domain
+{
+ return self.cell.stringValue;
+}
+
+- (void) drawRect:(NSRect)dirtyRect
+{
+ (void)dirtyRect; // Unused
+ [self.cell drawInteriorWithFrame: self.bounds inView: self];
+}
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/DomainBrowser.h b/mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/DomainBrowser.h
new file mode 100644
index 00000000..bdc9a877
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/DomainBrowser.h
@@ -0,0 +1,30 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+//! Project version number for DomainBrowser.
+FOUNDATION_EXPORT double DomainBrowserVersionNumber;
+
+//! Project version string for DomainBrowser.
+FOUNDATION_EXPORT const unsigned char DomainBrowserVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import <DomainBrowser/PublicHeader.h>
+
+
+#import <DomainBrowser/CNDomainBrowserView.h>
+#import <DomainBrowser/CNDomainBrowserPathUtils.h>
diff --git a/mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/Info.plist b/mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/Info.plist
new file mode 100644
index 00000000..d3de8eef
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/DomainBrowser/macOS/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>$(CURRENT_PROJECT_VERSION)</string>
+ <key>NSPrincipalClass</key>
+ <string></string>
+</dict>
+</plist>
diff --git a/mDNSResponder/mDNSMacOSX/LegacyNATTraversal.c b/mDNSResponder/mDNSMacOSX/LegacyNATTraversal.c
index acfb3dca..2c90d929 100644
--- a/mDNSResponder/mDNSMacOSX/LegacyNATTraversal.c
+++ b/mDNSResponder/mDNSMacOSX/LegacyNATTraversal.c
@@ -27,7 +27,6 @@
# include <ws2tcpip.h>
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
-# define mDNSASLLog( UUID, SUBDOMAIN, RESULT, SIGNATURE, FORMAT, ... ) ;
static int
inet_pton( int family, const char * addr, void * dst )
@@ -80,7 +79,7 @@ mDNSlocal mStatus SendPortMapRequest(mDNS *m, NATTraversalInfo *n);
#define RequestedPortNum(n) (mDNSVal16(mDNSIPPortIsZero((n)->RequestedPort) ? (n)->IntPort : (n)->RequestedPort) + (mDNSu16)(n)->tcpInfo.retries)
// Note that this function assumes src is already NULL terminated
-mDNSlocal void AllocAndCopy(mDNSu8 **const dst, const mDNSu8 *const src)
+mDNSlocal void AllocAndCopy(char **const dst, const char *const src)
{
if (src == mDNSNULL) return;
if ((strlen((char*)src)) >= UINT32_MAX || (*dst = mDNSPlatformMemAllocate((mDNSu32)strlen((char*)src) + 1)) == mDNSNULL)
@@ -93,7 +92,7 @@ mDNSlocal void AllocAndCopy(mDNSu8 **const dst, const mDNSu8 *const src)
// This function does a simple parse of an HTTP URL that may include a hostname, port, and path
// If found in the URL, addressAndPort and path out params will point to newly allocated space (and will leak if they were previously pointing at allocated space)
-mDNSlocal mStatus ParseHttpUrl(const mDNSu8 *ptr, const mDNSu8 *const end, mDNSu8 **const addressAndPort, mDNSIPPort *const port, mDNSu8 **const path)
+mDNSlocal mStatus ParseHttpUrl(const mDNSu8 *ptr, const mDNSu8 *const end, char **const addressAndPort, mDNSIPPort *const port, char **const path)
{
// if the data begins with "http://", we assume there is a hostname and possibly a port number
if (end - ptr >= 7 && strncasecmp((char*)ptr, "http://", 7) == 0)
@@ -210,7 +209,7 @@ mDNSlocal void handleLNTDeviceDescriptionResponse(tcpLNTInfo *tcpInfo)
if (http_result == HTTPCode_404) LNT_ClearState(m);
if (http_result != HTTPCode_200)
{
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "noop", "HTTP Result", "HTTP code: %d", http_result);
+ LogInfo("handleLNTDeviceDescriptionResponse: HTTP Result code: %d", http_result);
return;
}
@@ -318,7 +317,7 @@ mDNSlocal void handleLNTGetExternalAddressResponse(tcpLNTInfo *tcpInfo)
if (http_result == HTTPCode_404) LNT_ClearState(m);
if (http_result != HTTPCode_200)
{
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.AddressRequest", "noop", "HTTP Result", "HTTP code: %d", http_result);
+ LogInfo("handleLNTGetExternalAddressResponse: HTTP Result code: %d", http_result);
return;
}
@@ -336,7 +335,6 @@ mDNSlocal void handleLNTGetExternalAddressResponse(tcpLNTInfo *tcpInfo)
if (inet_pton(AF_INET, (char*)ptr, &ExtAddr) <= 0)
{
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.AddressRequest", "noop", "inet_pton", "");
LogMsg("handleLNTGetExternalAddressResponse: Router returned bad address %s", ptr);
err = NATErr_NetFail;
ExtAddr = zerov4Addr;
@@ -380,12 +378,11 @@ mDNSlocal void handleLNTPortMappingResponse(tcpLNTInfo *tcpInfo)
if (tcpInfo->retries < 100)
{
tcpInfo->retries++; SendPortMapRequest(tcpInfo->m, natInfo);
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", "noop", "Conflict", "Retry %d", tcpInfo->retries);
+ LogInfo("handleLNTPortMappingResponse: Conflict retry %d", tcpInfo->retries);
}
else
{
LogMsg("handleLNTPortMappingResponse too many conflict retries %d %d", mDNSVal16(natInfo->IntPort), mDNSVal16(natInfo->RequestedPort));
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", "noop", "Conflict - too many retries", "Retries: %d", tcpInfo->retries);
natTraversalHandlePortMapReply(m, natInfo, m->UPnPInterfaceID, NATErr_Res, zeroIPPort, 0, NATTProtocolUPNPIGD);
}
return;
@@ -397,7 +394,7 @@ mDNSlocal void handleLNTPortMappingResponse(tcpLNTInfo *tcpInfo)
else if (http_result == HTTPCode_Other) LogMsg("handleLNTPortMappingResponse got unexpected response code");
else if (http_result == HTTPCode_404) LNT_ClearState(m);
if (http_result != HTTPCode_200 && http_result != HTTPCode_500)
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", "noop", "HTTP Result", "HTTP code: %d", http_result);
+ LogInfo("handleLNTPortMappingResponse: HTTP Result code: %d", http_result);
}
mDNSlocal void DisposeInfoFromUnmapList(mDNS *m, tcpLNTInfo *tcpInfo)
@@ -479,20 +476,17 @@ exit:
switch (tcpInfo->op)
{
- case LNTDiscoveryOp: if (m->UPnPSOAPAddressString == mDNSNULL)
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "failure", "SOAP Address", "");
- if (m->UPnPSOAPURL == mDNSNULL)
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "failure", "SOAP path", "");
- if (m->UPnPSOAPAddressString && m->UPnPSOAPURL)
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.DeviceDescription", "success", "success", "");
+ case LNTDiscoveryOp:
+ LogInfo("tcpConnectionCallback: DeviceDescription SOAP address %s SOAP path %s",
+ m->UPnPSOAPAddressString ? m->UPnPSOAPAddressString : "NULL", m->UPnPSOAPURL ? m->UPnPSOAPURL : "NULL");
break;
- case LNTExternalAddrOp: mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.AddressRequest",
- mDNSIPv4AddressIsZero(m->ExtAddress) ? "failure" : "success",
- mDNSIPv4AddressIsZero(m->ExtAddress) ? "failure" : "success", "");
+ case LNTExternalAddrOp:
+ LogInfo("tcpConnectionCallback: AddressRequest %s", mDNSIPv4AddressIsZero(m->ExtAddress) ? "failure" : "success");
break;
- case LNTPortMapOp: if (tcpInfo->parentNATInfo)
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.PortMapRequest", (tcpInfo->parentNATInfo->Result) ? "failure" : "success",
- (tcpInfo->parentNATInfo->Result) ? "failure" : "success", "Result: %d", tcpInfo->parentNATInfo->Result);
+ case LNTPortMapOp:
+ if (tcpInfo->parentNATInfo)
+ LogInfo("tcpConnectionCallback: PortMapRequest %s result %d",
+ (tcpInfo->parentNATInfo->Result) ? "failure" : "success", tcpInfo->parentNATInfo->Result);
break;
case LNTPortMapDeleteOp: break;
default: break;
@@ -530,7 +524,7 @@ mDNSlocal mStatus MakeTCPConnection(mDNS *const m, tcpLNTInfo *info, const mDNSA
else if ((info->Reply = mDNSPlatformMemAllocate(LNT_MAXBUFSIZE)) == mDNSNULL) { LogInfo("can't allocate reply buffer"); return (mStatus_NoMemoryErr); }
if (info->sock) { LogInfo("MakeTCPConnection: closing previous open connection"); mDNSPlatformTCPCloseConnection(info->sock); info->sock = mDNSNULL; }
- info->sock = mDNSPlatformTCPSocket(m, kTCPSocketFlags_Zero, &srcport, mDNSfalse);
+ info->sock = mDNSPlatformTCPSocket(kTCPSocketFlags_Zero, &srcport, mDNSfalse);
if (!info->sock) { LogMsg("LNT MakeTCPConnection: unable to create TCP socket"); mDNSPlatformMemFree(info->Reply); info->Reply = mDNSNULL; return(mStatus_NoMemoryErr); }
LogInfo("MakeTCPConnection: connecting to %#a:%d", &info->Address, mDNSVal16(info->Port));
err = mDNSPlatformTCPConnect(info->sock, Addr, Port, mDNSNULL, 0, tcpConnectionCallback, info);
@@ -828,7 +822,7 @@ mDNSexport void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID Interface
}
if (ptr == mDNSNULL || ptr == end)
{
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "failure", "Location", "");
+ LogInfo("LNT_ConfigureRouterInfo: Location field not found");
return; // not a message we care about
}
ptr += 9; //Skip over 'Location:'
@@ -856,7 +850,7 @@ mDNSexport void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID Interface
// the Router URL should look something like "/dyndev/uuid:0013-108c-4b3f0000f3dc"
if (ParseHttpUrl(ptr, end, &m->UPnPRouterAddressString, &m->UPnPRouterPort, &m->UPnPRouterURL) != mStatus_NoError)
{
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "failure", "Parse URL", "");
+ LogInfo("LNT_ConfigureRouterInfo: Failed to parse URL");
return;
}
@@ -864,14 +858,12 @@ mDNSexport void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID Interface
if (m->UPnPRouterAddressString == mDNSNULL)
{
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "failure", "Router address", "");
LogMsg("LNT_ConfigureRouterInfo: UPnPRouterAddressString is NULL");
}
else LogInfo("LNT_ConfigureRouterInfo: Router address string [%s]", m->UPnPRouterAddressString);
if (m->UPnPRouterURL == mDNSNULL)
{
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "failure", "Router path", "");
LogMsg("LNT_ConfigureRouterInfo: UPnPRouterURL is NULL");
}
else LogInfo("LNT_ConfigureRouterInfo: Router URL [%s]", m->UPnPRouterURL);
@@ -882,7 +874,6 @@ mDNSexport void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID Interface
// Don't need the SSDP socket anymore
if (m->SSDPSocket) { debugf("LNT_ConfigureRouterInfo destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
- mDNSASLLog((uuid_t *)&m->asl_uuid, "natt.legacy.ssdp", "success", "success", "");
// now send message to get the device description
GetDeviceDescription(m, &m->tcpDeviceInfo);
}
@@ -917,7 +908,7 @@ mDNSexport void LNT_SendDiscoveryMsg(mDNS *m)
if (!mDNSIPv4AddressIsZero(m->Router.ip.v4))
{
- if (!m->SSDPSocket) { m->SSDPSocket = mDNSPlatformUDPSocket(m, zeroIPPort); debugf("LNT_SendDiscoveryMsg created SSDPSocket %p", &m->SSDPSocket); }
+ if (!m->SSDPSocket) { m->SSDPSocket = mDNSPlatformUDPSocket(zeroIPPort); debugf("LNT_SendDiscoveryMsg created SSDPSocket %p", &m->SSDPSocket); }
mDNSPlatformSendUDP(m, buf, buf + bufLen, 0, m->SSDPSocket, &m->Router, SSDPPort, mDNSfalse);
mDNSPlatformSendUDP(m, buf, buf + bufLen, 0, m->SSDPSocket, &multicastDest, SSDPPort, mDNSfalse);
}
diff --git a/mDNSResponder/mDNSMacOSX/Metrics.m b/mDNSResponder/mDNSMacOSX/Metrics.m
index bfff58e4..f8a3ae73 100644
--- a/mDNSResponder/mDNSMacOSX/Metrics.m
+++ b/mDNSResponder/mDNSMacOSX/Metrics.m
@@ -294,8 +294,6 @@ typedef struct
// Globals
//===========================================================================================================================
-extern mDNS mDNSStorage;
-
static DNSDomainStats * gDomainStatsList = NULL;
static ResolveStatsDomain * gResolveStatsList = NULL;
static ResolveStatsDNSServer * gResolveStatsServerList = NULL;
@@ -1487,10 +1485,10 @@ mDNSlocal mStatus SubmitAWDMetric(UInt32 inMetricID)
case AWDMetricId_MDNSResponder_ServicesStats:
[AWDMetricManagerSoft postMetricWithId:AWDMetricId_MDNSResponder_ServicesStats unsignedIntegerValue:max_num_regservices];
- KQueueLock(&mDNSStorage);
+ KQueueLock();
// reset the no of max services since we want to collect the max no of services registered per AWD submission period
max_num_regservices = curr_num_regservices;
- KQueueUnlock(&mDNSStorage, "SubmitAWDSimpleMetricServiceStats");
+ KQueueUnlock("SubmitAWDSimpleMetricServiceStats");
err = mStatus_NoError;
break;
@@ -1520,10 +1518,10 @@ mDNSlocal mStatus SubmitAWDMetricQueryStats(void)
err = CreateDomainStatsList(&newDomainStatsList);
require_noerr_quiet(err, exit);
- KQueueLock(&mDNSStorage);
+ KQueueLock();
domainStatsList = gDomainStatsList;
gDomainStatsList = newDomainStatsList;
- KQueueUnlock(&mDNSStorage, "SubmitAWDMetricQueryStats");
+ KQueueUnlock("SubmitAWDMetricQueryStats");
container = [gAWDServerConnection newMetricContainerWithIdentifier:AWDMetricId_MDNSResponder_DNSStatistics];
require_action_quiet(container, exit, err = mStatus_UnknownErr);
@@ -1578,14 +1576,14 @@ mDNSlocal mStatus SubmitAWDMetricResolveStats(void)
err = CreateResolveStatsList(&newResolveStatsList);
require_noerr_quiet(err, exit);
- KQueueLock(&mDNSStorage);
+ KQueueLock();
domainList = gResolveStatsList;
serverList = gResolveStatsServerList;
gResolveStatsList = newResolveStatsList;
gResolveStatsServerList = NULL;
gResolveStatsNextServerID = 0;
gResolveStatsObjCount = 0;
- KQueueUnlock(&mDNSStorage, "SubmitAWDMetricResolveStats");
+ KQueueUnlock("SubmitAWDMetricResolveStats");
container = [gAWDServerConnection newMetricContainerWithIdentifier:AWDMetricId_MDNSResponder_ResolveStats];
require_action_quiet(container, exit, err = mStatus_UnknownErr);
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/add_idle.tiff b/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/add_idle.tiff
deleted file mode 100644
index b78b0c2a..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/add_idle.tiff
+++ /dev/null
Binary files differ
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/add_pressed.tiff b/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/add_pressed.tiff
deleted file mode 100644
index b842e20c..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/add_pressed.tiff
+++ /dev/null
Binary files differ
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/remove_disabled.tiff b/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/remove_disabled.tiff
deleted file mode 100644
index 70d3dd9c..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/remove_disabled.tiff
+++ /dev/null
Binary files differ
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/remove_idle.tiff b/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/remove_idle.tiff
deleted file mode 100644
index dacc97c3..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/remove_idle.tiff
+++ /dev/null
Binary files differ
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/remove_pressed.tiff b/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/remove_pressed.tiff
deleted file mode 100644
index de3f8779..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/Artwork/remove_pressed.tiff
+++ /dev/null
Binary files differ
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/Base.lproj/DNSServiceDiscoveryPref.nib/designable.nib b/mDNSResponder/mDNSMacOSX/PreferencePane/Base.lproj/DNSServiceDiscoveryPref.nib/designable.nib
new file mode 100644
index 00000000..187ac388
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/Base.lproj/DNSServiceDiscoveryPref.nib/designable.nib
@@ -0,0 +1,821 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="12118" systemVersion="17A210a" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+ <dependencies>
+ <deployment identifier="macosx"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <objects>
+ <customObject id="-2" userLabel="File's Owner" customClass="DNSServiceDiscoveryPref">
+ <connections>
+ <outlet property="_initialKeyView" destination="107" id="235"/>
+ <outlet property="_lastKeyView" destination="107" id="183"/>
+ <outlet property="_window" destination="12" id="142"/>
+ <outlet property="addBrowseDomainButton" destination="381" id="384"/>
+ <outlet property="addBrowseDomainManualWindow" destination="NFb-eI-atL" id="0AN-Mr-e84"/>
+ <outlet property="addBrowseDomainWindow" destination="333" id="363"/>
+ <outlet property="applyButton" destination="208" id="238"/>
+ <outlet property="bonjourBrowserView" destination="200327" id="200328"/>
+ <outlet property="browseCancelButton" destination="341" id="375"/>
+ <outlet property="browseDomainList" destination="327" id="349"/>
+ <outlet property="browseDomainTextField" destination="W2d-Us-Cpm" id="kOZ-wG-OPp"/>
+ <outlet property="browseOKButton" destination="340" id="376"/>
+ <outlet property="comboAuthButton" destination="137" id="201"/>
+ <outlet property="hostName" destination="107" id="224"/>
+ <outlet property="hostNameSharedSecretButton" destination="263" id="270"/>
+ <outlet property="regDomainTextField" destination="OEh-fL-Ol6" id="Dv0-aj-gah"/>
+ <outlet property="regDomainView" destination="Reu-VC-MNz" id="4I2-zS-sdq"/>
+ <outlet property="registrationBrowserView" destination="agb-WV-smo" id="j7U-ZK-LIb"/>
+ <outlet property="registrationSelectButton" destination="KqE-pc-8z0" id="CJS-ml-2CA"/>
+ <outlet property="registrationSharedSecretButton" destination="267" id="268"/>
+ <outlet property="removeBrowseDomainButton" destination="383" id="385"/>
+ <outlet property="revertButton" destination="290" id="292"/>
+ <outlet property="secretCancelButton" destination="341" id="373"/>
+ <outlet property="secretOKButton" destination="260" id="377"/>
+ <outlet property="selectRegistrationDomainManualWindow" destination="he2-0K-CWy" id="eXD-7o-XQU"/>
+ <outlet property="selectRegistrationDomainWindow" destination="ail-If-2Xp" id="34V-c7-D3b"/>
+ <outlet property="sharedSecretName" destination="256" id="275"/>
+ <outlet property="sharedSecretValue" destination="257" id="276"/>
+ <outlet property="sharedSecretWindow" destination="255" id="274"/>
+ <outlet property="statusImageView" destination="320" id="321"/>
+ <outlet property="tabView" destination="100" id="380"/>
+ <outlet property="wideAreaCheckBox" destination="179" id="240"/>
+ </connections>
+ </customObject>
+ <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+ <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+ <window title="Bonjour" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" deferred="NO" oneShot="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="12" userLabel="PrefPane">
+ <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
+ <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+ <rect key="contentRect" x="51" y="335" width="596" height="343"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
+ <value key="minSize" type="size" width="213.66399999999999" height="10"/>
+ <view key="contentView" id="6">
+ <rect key="frame" x="0.0" y="0.0" width="596" height="343"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <tabView translatesAutoresizingMaskIntoConstraints="NO" id="100">
+ <rect key="frame" x="13" y="52" width="570" height="285"/>
+ <font key="font" metaFont="system"/>
+ <tabViewItems>
+ <tabViewItem label="Hostname" identifier="1" id="102">
+ <view key="view" id="101">
+ <rect key="frame" x="10" y="33" width="550" height="239"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="107">
+ <rect key="frame" x="119" y="155" width="383" height="22"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="left" placeholderString="steve.example.com" drawsBackground="YES" id="100107">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ <connections>
+ <outlet property="delegate" destination="-2" id="227"/>
+ </connections>
+ </textField>
+ <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="108">
+ <rect key="frame" x="43" y="158" width="70" height="17"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Hostname:" id="100108">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="117">
+ <rect key="frame" x="18" y="185" width="514" height="34"/>
+ <constraints>
+ <constraint firstAttribute="width" priority="499" constant="510" id="TMz-kS-KCv"/>
+ </constraints>
+ <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="Enter a hostname for this computer. Other computers on the Internet will be able to reach your computer using this hostname." id="100117">
+ <font key="font" metaFont="systemBold"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="263">
+ <rect key="frame" x="113" y="119" width="109" height="32"/>
+ <buttonCell key="cell" type="push" title="Password…" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="100263">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <action selector="changeButtonPressed:" target="-2" id="272"/>
+ </connections>
+ </button>
+ <imageView translatesAutoresizingMaskIntoConstraints="NO" id="320">
+ <rect key="frame" x="510" y="156" width="20" height="20"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="20" id="7Qf-g0-5SV"/>
+ <constraint firstAttribute="height" constant="20" id="bfL-QJ-KFw"/>
+ </constraints>
+ <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageAlignment="left" imageScaling="proportionallyDown" id="100320"/>
+ </imageView>
+ </subviews>
+ <constraints>
+ <constraint firstItem="263" firstAttribute="leading" secondItem="107" secondAttribute="leading" id="4Dv-gf-Cjr"/>
+ <constraint firstAttribute="trailing" secondItem="117" secondAttribute="trailing" constant="20" symbolic="YES" id="5zc-LQ-OC8"/>
+ <constraint firstItem="320" firstAttribute="leading" secondItem="107" secondAttribute="trailing" constant="8" symbolic="YES" id="BIu-YL-Fr2"/>
+ <constraint firstItem="263" firstAttribute="top" secondItem="107" secondAttribute="bottom" constant="8" symbolic="YES" id="K1w-WG-3KW"/>
+ <constraint firstItem="107" firstAttribute="centerY" secondItem="320" secondAttribute="centerY" id="LlU-Oy-3va"/>
+ <constraint firstItem="107" firstAttribute="top" secondItem="117" secondAttribute="bottom" constant="8" symbolic="YES" id="V8c-G1-gsR"/>
+ <constraint firstItem="117" firstAttribute="top" secondItem="101" secondAttribute="top" constant="20" symbolic="YES" id="Xnz-bz-ahU"/>
+ <constraint firstItem="117" firstAttribute="leading" secondItem="101" secondAttribute="leading" constant="20" symbolic="YES" id="ZIG-S4-cst"/>
+ <constraint firstItem="107" firstAttribute="leading" secondItem="108" secondAttribute="trailing" constant="8" symbolic="YES" id="cQG-zv-Ozo"/>
+ <constraint firstItem="108" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="101" secondAttribute="leading" constant="20" symbolic="YES" id="foH-DQ-yvJ"/>
+ <constraint firstItem="107" firstAttribute="leading" secondItem="101" secondAttribute="leading" priority="499" constant="119" id="qGZ-fm-Wgf"/>
+ <constraint firstAttribute="trailing" secondItem="320" secondAttribute="trailing" constant="20" symbolic="YES" id="w2R-Kc-Tj3"/>
+ <constraint firstItem="108" firstAttribute="baseline" secondItem="107" secondAttribute="baseline" id="xcr-32-mbs"/>
+ </constraints>
+ </view>
+ </tabViewItem>
+ <tabViewItem label="Registration" identifier="2" id="98">
+ <view key="view" id="99">
+ <rect key="frame" x="10" y="33" width="550" height="239"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <button translatesAutoresizingMaskIntoConstraints="NO" id="179">
+ <rect key="frame" x="41" y="157" width="72" height="18"/>
+ <buttonCell key="cell" type="check" title="Domain:" bezelStyle="regularSquare" imagePosition="left" alignment="right" inset="2" id="100179">
+ <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <action selector="wideAreaCheckBoxChanged:" target="-2" id="317"/>
+ </connections>
+ </button>
+ <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="267">
+ <rect key="frame" x="222" y="119" width="109" height="32"/>
+ <buttonCell key="cell" type="push" title="Password…" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="100267">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <action selector="changeButtonPressed:" target="-2" id="273"/>
+ </connections>
+ </button>
+ <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="348">
+ <rect key="frame" x="18" y="185" width="514" height="34"/>
+ <constraints>
+ <constraint firstAttribute="width" priority="499" constant="510" id="lUQ-CZ-AzC"/>
+ </constraints>
+ <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Check the box and select a registration domain to enable Bonjour advertising beyond the local subnet." id="100348">
+ <font key="font" metaFont="systemBold"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="KqE-pc-8z0">
+ <rect key="frame" x="113" y="119" width="109" height="32"/>
+ <buttonCell key="cell" type="push" title="Select…" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="TjV-QO-BW7">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <action selector="selectWideAreaDomainButtonPressed:" target="-2" id="d4S-la-iyw"/>
+ </connections>
+ </button>
+ <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cxI-8W-6HI">
+ <rect key="frame" x="119" y="155" width="411" height="22"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" enabled="NO" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="Oao-6x-0X9">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <customView translatesAutoresizingMaskIntoConstraints="NO" id="Reu-VC-MNz" customClass="CNBonjourDomainView">
+ <rect key="frame" x="119" y="155" width="411" height="22"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="22" id="l7c-m9-GcE"/>
+ </constraints>
+ </customView>
+ </subviews>
+ <constraints>
+ <constraint firstItem="267" firstAttribute="leading" secondItem="KqE-pc-8z0" secondAttribute="trailing" constant="12" symbolic="YES" id="2kZ-P9-l60"/>
+ <constraint firstItem="Reu-VC-MNz" firstAttribute="centerY" secondItem="cxI-8W-6HI" secondAttribute="centerY" id="984-4H-aIz"/>
+ <constraint firstItem="179" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="99" secondAttribute="leading" constant="20" symbolic="YES" id="D3d-wd-QYX"/>
+ <constraint firstItem="Reu-VC-MNz" firstAttribute="top" secondItem="348" secondAttribute="bottom" constant="8" symbolic="YES" id="GcL-zf-7HQ"/>
+ <constraint firstItem="348" firstAttribute="top" secondItem="99" secondAttribute="top" constant="20" symbolic="YES" id="HDQ-fd-PwR"/>
+ <constraint firstItem="Reu-VC-MNz" firstAttribute="height" secondItem="cxI-8W-6HI" secondAttribute="height" id="HUo-M5-tyi"/>
+ <constraint firstItem="Reu-VC-MNz" firstAttribute="width" secondItem="cxI-8W-6HI" secondAttribute="width" id="JML-71-xrY"/>
+ <constraint firstItem="cxI-8W-6HI" firstAttribute="baseline" secondItem="179" secondAttribute="baseline" id="NX1-5X-UZI"/>
+ <constraint firstItem="348" firstAttribute="leading" secondItem="99" secondAttribute="leading" constant="20" symbolic="YES" id="P0u-7u-LJv"/>
+ <constraint firstItem="KqE-pc-8z0" firstAttribute="leading" secondItem="cxI-8W-6HI" secondAttribute="leading" id="RDS-Bc-KYd"/>
+ <constraint firstItem="Reu-VC-MNz" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="99" secondAttribute="leading" constant="20" symbolic="YES" id="d8L-Kb-W49"/>
+ <constraint firstItem="Reu-VC-MNz" firstAttribute="centerX" secondItem="cxI-8W-6HI" secondAttribute="centerX" id="dfu-qB-Ezj"/>
+ <constraint firstItem="Reu-VC-MNz" firstAttribute="leading" secondItem="179" secondAttribute="trailing" constant="8" symbolic="YES" id="rUC-3C-r32"/>
+ <constraint firstItem="KqE-pc-8z0" firstAttribute="top" secondItem="cxI-8W-6HI" secondAttribute="bottom" constant="8" symbolic="YES" id="skb-cf-d2E"/>
+ <constraint firstAttribute="trailing" secondItem="Reu-VC-MNz" secondAttribute="trailing" constant="20" symbolic="YES" id="ta5-1S-y3v"/>
+ <constraint firstAttribute="trailing" secondItem="348" secondAttribute="trailing" constant="20" symbolic="YES" id="tr3-Ed-I8w"/>
+ <constraint firstItem="267" firstAttribute="baseline" secondItem="KqE-pc-8z0" secondAttribute="baseline" id="vt0-3i-y05"/>
+ <constraint firstItem="267" firstAttribute="width" secondItem="KqE-pc-8z0" secondAttribute="width" id="vxX-jt-NDx"/>
+ <constraint firstItem="Reu-VC-MNz" firstAttribute="leading" secondItem="99" secondAttribute="leading" priority="499" constant="119" id="xdT-xB-bam"/>
+ </constraints>
+ </view>
+ </tabViewItem>
+ <tabViewItem label="Browsing" identifier="" id="322">
+ <view key="view" id="323">
+ <rect key="frame" x="10" y="33" width="550" height="239"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <scrollView horizontalLineScroll="24" horizontalPageScroll="10" verticalLineScroll="24" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="326">
+ <rect key="frame" x="20" y="82" width="510" height="112"/>
+ <clipView key="contentView" id="r8V-oO-qTS">
+ <rect key="frame" x="1" y="1" width="508" height="110"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" alternatingRowBackgroundColors="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="22" id="327">
+ <rect key="frame" x="0.0" y="0.0" width="508" height="110"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <size key="intercellSpacing" width="3" height="2"/>
+ <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+ <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
+ <tableColumns>
+ <tableColumn identifier="Enabled" width="35" minWidth="30" maxWidth="1000" id="328">
+ <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
+ <font key="font" metaFont="smallSystem"/>
+ <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" white="0.33333299" alpha="1" colorSpace="calibratedWhite"/>
+ </tableHeaderCell>
+ <buttonCell key="dataCell" type="check" bezelStyle="regularSquare" imagePosition="above" alignment="center" inset="2" id="358">
+ <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
+ <font key="font" metaFont="cellTitle"/>
+ <connections>
+ <action selector="enableBrowseDomainClicked:" target="-2" id="360"/>
+ </connections>
+ </buttonCell>
+ </tableColumn>
+ <tableColumn identifier="Domain" editable="NO" width="451.9541015625" minWidth="49.3466796875" maxWidth="1000" id="329">
+ <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Domain">
+ <font key="font" metaFont="smallSystem"/>
+ <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" white="0.33333299" alpha="1" colorSpace="calibratedWhite"/>
+ </tableHeaderCell>
+ <customCell key="dataCell" alignment="left" id="LhH-Yh-n33" customClass="CNBonjourDomainCell"/>
+ </tableColumn>
+ </tableColumns>
+ <connections>
+ <outlet property="dataSource" destination="-2" id="350"/>
+ <outlet property="delegate" destination="-2" id="351"/>
+ </connections>
+ </tableView>
+ </subviews>
+ </clipView>
+ <constraints>
+ <constraint firstAttribute="height" constant="112" id="Pf1-34-QXp"/>
+ </constraints>
+ <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="100326">
+ <rect key="frame" x="-100" y="-100" width="493" height="15"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </scroller>
+ <scroller key="verticalScroller" verticalHuggingPriority="750" horizontal="NO" id="200326">
+ <rect key="frame" x="493" y="1" width="16" height="110"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </scroller>
+ </scrollView>
+ <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="330">
+ <rect key="frame" x="18" y="202" width="514" height="17"/>
+ <constraints>
+ <constraint firstAttribute="width" priority="499" constant="510" id="xXz-Xx-cVE"/>
+ </constraints>
+ <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Choose which domains to browse using Wide-Area Bonjour." id="100330">
+ <font key="font" metaFont="systemBold"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <button toolTip="Click to define shortcuts within applications." verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="381">
+ <rect key="frame" x="20" y="49" width="24" height="26"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="24" id="llU-4M-pcI"/>
+ <constraint firstAttribute="height" constant="24" id="qD8-y4-ZkW"/>
+ </constraints>
+ <buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSAddTemplate" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" id="100381">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <action selector="addBrowseDomainClicked:" target="-2" id="386"/>
+ </connections>
+ </button>
+ <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="383">
+ <rect key="frame" x="43" y="49" width="24" height="26"/>
+ <buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSRemoveTemplate" imagePosition="overlaps" alignment="center" controlSize="small" state="on" borderStyle="border" id="100383">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="smallSystem"/>
+ <string key="keyEquivalent"></string>
+ </buttonCell>
+ <connections>
+ <action selector="removeBrowseDomainClicked:" target="-2" id="387"/>
+ </connections>
+ </button>
+ </subviews>
+ <constraints>
+ <constraint firstItem="326" firstAttribute="leading" secondItem="323" secondAttribute="leading" constant="20" symbolic="YES" id="BHw-zP-zzH"/>
+ <constraint firstItem="381" firstAttribute="centerY" secondItem="383" secondAttribute="centerY" id="Cae-WW-gYH"/>
+ <constraint firstItem="326" firstAttribute="leading" secondItem="381" secondAttribute="leading" id="GCR-nb-Kbp"/>
+ <constraint firstItem="381" firstAttribute="height" secondItem="383" secondAttribute="height" id="GYW-Vr-6c8"/>
+ <constraint firstAttribute="trailing" secondItem="326" secondAttribute="trailing" constant="20" symbolic="YES" id="HGK-Ej-oKA"/>
+ <constraint firstItem="383" firstAttribute="leading" secondItem="381" secondAttribute="trailing" constant="-1" id="KYa-XM-Qrh"/>
+ <constraint firstAttribute="trailing" secondItem="330" secondAttribute="trailing" constant="20" symbolic="YES" id="Lkk-cy-gcf"/>
+ <constraint firstItem="326" firstAttribute="top" secondItem="330" secondAttribute="bottom" constant="8" symbolic="YES" id="Pna-sQ-Iom"/>
+ <constraint firstItem="381" firstAttribute="top" secondItem="326" secondAttribute="bottom" constant="8" symbolic="YES" id="YmF-BH-VOk"/>
+ <constraint firstItem="381" firstAttribute="width" secondItem="383" secondAttribute="width" id="kJf-PK-P0M"/>
+ <constraint firstItem="330" firstAttribute="leading" secondItem="323" secondAttribute="leading" constant="20" symbolic="YES" id="luC-Nv-ec5"/>
+ <constraint firstItem="330" firstAttribute="top" secondItem="323" secondAttribute="top" constant="20" symbolic="YES" id="yVJ-PT-T31"/>
+ </constraints>
+ </view>
+ </tabViewItem>
+ </tabViewItems>
+ </tabView>
+ <customView translatesAutoresizingMaskIntoConstraints="NO" id="137" customClass="SFAuthorizationView">
+ <rect key="frame" x="20" y="20" width="356" height="34"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="34" id="T24-JY-FUW"/>
+ <constraint firstAttribute="width" constant="356" id="hHs-jB-Xz8"/>
+ </constraints>
+ </customView>
+ <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="208">
+ <rect key="frame" x="502" y="13" width="80" height="32"/>
+ <buttonCell key="cell" type="push" title="Apply" bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" inset="2" id="100208">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <action selector="applyClicked:" target="-2" id="209"/>
+ </connections>
+ </button>
+ <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="290">
+ <rect key="frame" x="422" y="13" width="80" height="32"/>
+ <buttonCell key="cell" type="push" title="Revert" bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" inset="2" id="100290">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <action selector="revertClicked:" target="-2" id="293"/>
+ </connections>
+ </button>
+ </subviews>
+ <constraints>
+ <constraint firstAttribute="trailing" secondItem="100" secondAttribute="trailing" constant="20" symbolic="YES" id="DEs-Vk-n3D"/>
+ <constraint firstItem="208" firstAttribute="width" secondItem="290" secondAttribute="width" id="GMB-MK-qPS"/>
+ <constraint firstAttribute="bottom" secondItem="137" secondAttribute="bottom" constant="20" symbolic="YES" id="M0C-li-Dr1"/>
+ <constraint firstItem="100" firstAttribute="leading" secondItem="6" secondAttribute="leading" constant="20" symbolic="YES" id="Ozi-Cv-NdV"/>
+ <constraint firstAttribute="bottom" secondItem="208" secondAttribute="bottom" constant="20" symbolic="YES" id="PGr-uI-dUi"/>
+ <constraint firstItem="290" firstAttribute="baseline" secondItem="208" secondAttribute="baseline" id="Rcf-kj-OQp"/>
+ <constraint firstItem="137" firstAttribute="leading" secondItem="6" secondAttribute="leading" constant="20" symbolic="YES" id="dWc-kl-h8o"/>
+ <constraint firstItem="208" firstAttribute="leading" secondItem="290" secondAttribute="trailing" constant="12" symbolic="YES" id="g3l-gL-wIw"/>
+ <constraint firstItem="137" firstAttribute="top" secondItem="100" secondAttribute="bottom" constant="8" symbolic="YES" id="jDb-sm-pFt"/>
+ <constraint firstItem="100" firstAttribute="top" secondItem="6" secondAttribute="top" constant="12" symbolic="YES" id="nWn-mH-iEl"/>
+ <constraint firstAttribute="trailing" secondItem="208" secondAttribute="trailing" constant="20" symbolic="YES" id="xIc-XH-CzB"/>
+ </constraints>
+ </view>
+ <point key="canvasLocation" x="6" y="454"/>
+ </window>
+ <window title="Shared Secret" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="255" userLabel="SharedSecret">
+ <windowStyleMask key="styleMask" titled="YES"/>
+ <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+ <rect key="contentRect" x="591" y="108" width="496" height="148"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
+ <value key="minSize" type="size" width="213" height="107"/>
+ <view key="contentView" id="254">
+ <rect key="frame" x="0.0" y="0.0" width="496" height="148"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="256">
+ <rect key="frame" x="96" y="81" width="380" height="22"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="left" drawsBackground="YES" id="100256">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ <connections>
+ <outlet property="delegate" destination="-2" id="283"/>
+ <outlet property="nextKeyView" destination="257" id="288"/>
+ </connections>
+ </textField>
+ <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="257" customClass="NSSecureTextField">
+ <rect key="frame" x="96" y="49" width="380" height="22"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="left" drawsBackground="YES" id="100257">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ <connections>
+ <outlet property="delegate" destination="-2" id="284"/>
+ <outlet property="nextKeyView" destination="256" id="289"/>
+ </connections>
+ </textField>
+ <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="258">
+ <rect key="frame" x="46" y="84" width="44" height="17"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Name:" id="100258">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="259">
+ <rect key="frame" x="24" y="52" width="66" height="17"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Password:" id="100259">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <button verticalHuggingPriority="750" tag="1" translatesAutoresizingMaskIntoConstraints="NO" id="260">
+ <rect key="frame" x="400" y="13" width="82" height="32"/>
+ <buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="100260">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ <string key="keyEquivalent" base64-UTF8="YES">
+DQ
+</string>
+ </buttonCell>
+ <connections>
+ <action selector="closeMyCustomSheet:" target="-2" id="279"/>
+ </connections>
+ </button>
+ <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="261">
+ <rect key="frame" x="318" y="13" width="82" height="32"/>
+ <buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="100261">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ <string key="keyEquivalent" base64-UTF8="YES">
+Gw
+</string>
+ </buttonCell>
+ <connections>
+ <action selector="closeMyCustomSheet:" target="-2" id="280"/>
+ </connections>
+ </button>
+ <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="262">
+ <rect key="frame" x="18" y="111" width="460" height="17"/>
+ <constraints>
+ <constraint firstAttribute="width" priority="499" constant="456" id="Mua-9c-7eO"/>
+ </constraints>
+ <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="Enter a password if your DNS server requires authentication." id="100262">
+ <font key="font" metaFont="systemBold"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ </subviews>
+ <constraints>
+ <constraint firstAttribute="trailing" secondItem="256" secondAttribute="trailing" constant="20" symbolic="YES" id="3mf-gO-3d5"/>
+ <constraint firstAttribute="trailing" secondItem="262" secondAttribute="trailing" constant="20" symbolic="YES" id="7wb-gt-2py"/>
+ <constraint firstItem="261" firstAttribute="baseline" secondItem="260" secondAttribute="baseline" id="9Qx-ne-W5G"/>
+ <constraint firstItem="258" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="254" secondAttribute="leading" constant="20" symbolic="YES" id="9jU-dY-JqX"/>
+ <constraint firstItem="260" firstAttribute="top" secondItem="257" secondAttribute="bottom" constant="8" symbolic="YES" id="Dt1-uv-H2r"/>
+ <constraint firstItem="262" firstAttribute="leading" secondItem="254" secondAttribute="leading" constant="20" symbolic="YES" id="El6-is-b6l"/>
+ <constraint firstItem="256" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="254" secondAttribute="leading" constant="20" symbolic="YES" id="IAp-Sj-ojh"/>
+ <constraint firstItem="262" firstAttribute="top" secondItem="254" secondAttribute="top" constant="20" symbolic="YES" id="IKv-MA-MaG"/>
+ <constraint firstItem="260" firstAttribute="leading" secondItem="261" secondAttribute="trailing" constant="12" symbolic="YES" id="Jih-R5-3WX"/>
+ <constraint firstAttribute="trailing" secondItem="260" secondAttribute="trailing" constant="20" symbolic="YES" id="L7K-Si-lMS"/>
+ <constraint firstItem="256" firstAttribute="leading" secondItem="254" secondAttribute="leading" priority="499" constant="96" id="MGe-DK-IsJ"/>
+ <constraint firstItem="257" firstAttribute="leading" secondItem="256" secondAttribute="leading" id="XiH-SB-ew9"/>
+ <constraint firstItem="261" firstAttribute="width" secondItem="260" secondAttribute="width" id="ZBv-82-oHI"/>
+ <constraint firstItem="257" firstAttribute="leading" secondItem="254" secondAttribute="leading" priority="499" constant="96" id="ZSQ-Eu-kfv"/>
+ <constraint firstItem="257" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="254" secondAttribute="leading" constant="20" symbolic="YES" id="awk-Ih-h6t"/>
+ <constraint firstAttribute="trailing" secondItem="257" secondAttribute="trailing" constant="20" symbolic="YES" id="b4B-N1-Kkw"/>
+ <constraint firstItem="256" firstAttribute="top" secondItem="262" secondAttribute="bottom" constant="8" symbolic="YES" id="bMU-Gr-KAT"/>
+ <constraint firstItem="259" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="254" secondAttribute="leading" constant="20" symbolic="YES" id="djz-PT-u6u"/>
+ <constraint firstItem="259" firstAttribute="baseline" secondItem="257" secondAttribute="baseline" id="eqD-gu-QY7"/>
+ <constraint firstItem="256" firstAttribute="leading" secondItem="258" secondAttribute="trailing" constant="8" symbolic="YES" id="g6K-nY-Pnf"/>
+ <constraint firstAttribute="bottom" secondItem="260" secondAttribute="bottom" constant="20" symbolic="YES" id="qad-Pr-uFC"/>
+ <constraint firstItem="257" firstAttribute="top" secondItem="256" secondAttribute="bottom" constant="10" symbolic="YES" id="qyJ-gm-15K"/>
+ <constraint firstItem="257" firstAttribute="leading" secondItem="259" secondAttribute="trailing" constant="8" symbolic="YES" id="sAe-2s-bxV"/>
+ <constraint firstItem="258" firstAttribute="baseline" secondItem="256" secondAttribute="baseline" id="xZU-Nd-Q5f"/>
+ </constraints>
+ </view>
+ <point key="canvasLocation" x="148" y="69"/>
+ </window>
+ <window title="Add Browse Domains" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="333" userLabel="AddDomain">
+ <windowStyleMask key="styleMask" titled="YES"/>
+ <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+ <rect key="contentRect" x="634" y="377" width="496" height="220"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
+ <value key="minSize" type="size" width="213" height="107"/>
+ <view key="contentView" id="334">
+ <rect key="frame" x="0.0" y="0.0" width="496" height="220"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="336">
+ <rect key="frame" x="18" y="183" width="460" height="17"/>
+ <constraints>
+ <constraint firstAttribute="width" priority="499" constant="456" id="qTJ-tL-p1s"/>
+ </constraints>
+ <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="Choose a domain to add to your list of Bonjour browse domains." id="100336">
+ <font key="font" metaFont="systemBold"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <customView translatesAutoresizingMaskIntoConstraints="NO" id="200327" customClass="CNDomainBrowserView">
+ <rect key="frame" x="20" y="61" width="456" height="114"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="114" id="ey8-36-A8G"/>
+ </constraints>
+ <userDefinedRuntimeAttributes>
+ <userDefinedRuntimeAttribute type="boolean" keyPath="registrationDomains" value="NO"/>
+ <userDefinedRuntimeAttribute type="boolean" keyPath="ignoreLocal" value="YES"/>
+ <userDefinedRuntimeAttribute type="boolean" keyPath="ignoreBTMM" value="NO"/>
+ <userDefinedRuntimeAttribute type="boolean" keyPath="browseRegistration" value="NO"/>
+ </userDefinedRuntimeAttributes>
+ </customView>
+ <button verticalHuggingPriority="750" tag="1" translatesAutoresizingMaskIntoConstraints="NO" id="340">
+ <rect key="frame" x="400" y="13" width="82" height="32"/>
+ <buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="100340">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ <string key="keyEquivalent" base64-UTF8="YES">
+DQ
+</string>
+ </buttonCell>
+ <connections>
+ <action selector="closeMyCustomSheet:" target="-2" id="365"/>
+ </connections>
+ </button>
+ <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="341">
+ <rect key="frame" x="318" y="13" width="82" height="32"/>
+ <buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="100341">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ <string key="keyEquivalent" base64-UTF8="YES">
+Gw
+</string>
+ </buttonCell>
+ <connections>
+ <action selector="closeMyCustomSheet:" target="-2" id="364"/>
+ </connections>
+ </button>
+ </subviews>
+ <constraints>
+ <constraint firstItem="341" firstAttribute="width" secondItem="340" secondAttribute="width" id="1kP-hH-4fg"/>
+ <constraint firstItem="336" firstAttribute="leading" secondItem="334" secondAttribute="leading" constant="20" symbolic="YES" id="6p2-FN-dgI"/>
+ <constraint firstItem="200327" firstAttribute="leading" secondItem="334" secondAttribute="leading" constant="20" symbolic="YES" id="BFf-ab-vji"/>
+ <constraint firstItem="341" firstAttribute="baseline" secondItem="340" secondAttribute="baseline" id="DdL-N2-sRf"/>
+ <constraint firstItem="336" firstAttribute="top" secondItem="334" secondAttribute="top" constant="20" symbolic="YES" id="Iei-fi-sMQ"/>
+ <constraint firstItem="340" firstAttribute="top" secondItem="200327" secondAttribute="bottom" constant="20" symbolic="YES" id="Ouj-CX-0R3"/>
+ <constraint firstAttribute="trailing" secondItem="200327" secondAttribute="trailing" constant="20" symbolic="YES" id="QWi-nn-fZb"/>
+ <constraint firstItem="200327" firstAttribute="top" secondItem="336" secondAttribute="bottom" constant="8" symbolic="YES" id="f1Y-2w-Xl7"/>
+ <constraint firstAttribute="trailing" secondItem="336" secondAttribute="trailing" constant="20" symbolic="YES" id="gOk-i6-e6u"/>
+ <constraint firstAttribute="trailing" secondItem="340" secondAttribute="trailing" constant="20" symbolic="YES" id="gvy-DL-dCw"/>
+ <constraint firstAttribute="bottom" secondItem="340" secondAttribute="bottom" constant="20" symbolic="YES" id="i1j-hc-gtt"/>
+ <constraint firstItem="340" firstAttribute="leading" secondItem="341" secondAttribute="trailing" constant="12" symbolic="YES" id="yRJ-0k-a3r"/>
+ </constraints>
+ </view>
+ <point key="canvasLocation" x="-27" y="-234"/>
+ </window>
+ <window title="Add Browse Domains" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="NFb-eI-atL" userLabel="AddDomainManual">
+ <windowStyleMask key="styleMask" titled="YES"/>
+ <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+ <rect key="contentRect" x="634" y="377" width="496" height="133"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
+ <value key="minSize" type="size" width="213" height="107"/>
+ <view key="contentView" id="gUJ-3k-BQQ">
+ <rect key="frame" x="0.0" y="0.0" width="496" height="133"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <button verticalHuggingPriority="750" tag="1" translatesAutoresizingMaskIntoConstraints="NO" id="aoV-3v-A7q">
+ <rect key="frame" x="400" y="13" width="82" height="32"/>
+ <buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="Jo3-6e-vxc">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ <string key="keyEquivalent" base64-UTF8="YES">
+DQ
+</string>
+ </buttonCell>
+ <connections>
+ <action selector="closeMyCustomSheet:" target="-2" id="hMi-BR-qQY"/>
+ </connections>
+ </button>
+ <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="a0y-0s-TTY">
+ <rect key="frame" x="318" y="13" width="82" height="32"/>
+ <buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="qne-aW-QHl">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ <string key="keyEquivalent" base64-UTF8="YES">
+Gw
+</string>
+ </buttonCell>
+ <connections>
+ <action selector="closeMyCustomSheet:" target="-2" id="eUl-Y1-c5S"/>
+ </connections>
+ </button>
+ <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Sfp-nO-NP2">
+ <rect key="frame" x="36" y="52" width="54" height="17"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Domain:" id="b6L-KA-Dqu">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Myg-XJ-ngM">
+ <rect key="frame" x="18" y="79" width="460" height="34"/>
+ <constraints>
+ <constraint firstAttribute="width" priority="499" constant="456" id="nwj-Vn-nBx"/>
+ </constraints>
+ <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="The following domain will be added to your list of Bonjour browse domains." id="m5w-3d-gfR">
+ <font key="font" metaFont="systemBold"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="W2d-Us-Cpm">
+ <rect key="frame" x="96" y="49" width="380" height="22"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="kJz-0i-YUX">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ </subviews>
+ <constraints>
+ <constraint firstAttribute="trailing" secondItem="W2d-Us-Cpm" secondAttribute="trailing" constant="20" symbolic="YES" id="08z-5S-y1p"/>
+ <constraint firstAttribute="trailing" secondItem="Myg-XJ-ngM" secondAttribute="trailing" constant="20" symbolic="YES" id="2qd-6o-hRs"/>
+ <constraint firstAttribute="trailing" secondItem="aoV-3v-A7q" secondAttribute="trailing" constant="20" symbolic="YES" id="5WH-eg-Ibw"/>
+ <constraint firstItem="W2d-Us-Cpm" firstAttribute="leading" secondItem="gUJ-3k-BQQ" secondAttribute="leading" priority="499" constant="96" id="KBy-nt-u24"/>
+ <constraint firstItem="aoV-3v-A7q" firstAttribute="baseline" secondItem="a0y-0s-TTY" secondAttribute="baseline" id="L8X-K0-cNZ"/>
+ <constraint firstItem="W2d-Us-Cpm" firstAttribute="leading" secondItem="Sfp-nO-NP2" secondAttribute="trailing" constant="8" symbolic="YES" id="Pw7-gK-pJO"/>
+ <constraint firstItem="Myg-XJ-ngM" firstAttribute="top" secondItem="gUJ-3k-BQQ" secondAttribute="top" constant="20" symbolic="YES" id="Vkn-zN-QmY"/>
+ <constraint firstAttribute="bottom" secondItem="aoV-3v-A7q" secondAttribute="bottom" constant="20" symbolic="YES" id="aJb-Dk-Ofa"/>
+ <constraint firstItem="aoV-3v-A7q" firstAttribute="top" secondItem="W2d-Us-Cpm" secondAttribute="bottom" constant="8" symbolic="YES" id="bbw-LB-NG3"/>
+ <constraint firstItem="Myg-XJ-ngM" firstAttribute="leading" secondItem="gUJ-3k-BQQ" secondAttribute="leading" constant="20" symbolic="YES" id="cab-6m-9M7"/>
+ <constraint firstItem="W2d-Us-Cpm" firstAttribute="top" secondItem="Myg-XJ-ngM" secondAttribute="bottom" constant="8" symbolic="YES" id="ewM-hb-zj3"/>
+ <constraint firstItem="W2d-Us-Cpm" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="gUJ-3k-BQQ" secondAttribute="leading" constant="20" symbolic="YES" id="jsT-pp-iwi"/>
+ <constraint firstItem="Sfp-nO-NP2" firstAttribute="baseline" secondItem="W2d-Us-Cpm" secondAttribute="baseline" id="qPo-ba-jjr"/>
+ <constraint firstItem="aoV-3v-A7q" firstAttribute="leading" secondItem="a0y-0s-TTY" secondAttribute="trailing" constant="12" symbolic="YES" id="tzd-P2-c6b"/>
+ <constraint firstItem="Sfp-nO-NP2" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="gUJ-3k-BQQ" secondAttribute="leading" constant="20" symbolic="YES" id="vVs-34-dSS"/>
+ <constraint firstItem="aoV-3v-A7q" firstAttribute="width" secondItem="a0y-0s-TTY" secondAttribute="width" id="xg1-eb-4Pj"/>
+ </constraints>
+ </view>
+ <point key="canvasLocation" x="-27" y="-524"/>
+ </window>
+ <window title="Add Registration Domain" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="ail-If-2Xp" userLabel="SelectRegDomain">
+ <windowStyleMask key="styleMask" titled="YES"/>
+ <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+ <rect key="contentRect" x="634" y="377" width="496" height="220"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
+ <value key="minSize" type="size" width="213" height="107"/>
+ <view key="contentView" id="W37-VK-yC5">
+ <rect key="frame" x="0.0" y="0.0" width="496" height="220"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="q4Y-tT-1h7">
+ <rect key="frame" x="18" y="183" width="460" height="17"/>
+ <constraints>
+ <constraint firstAttribute="width" priority="499" constant="456" id="zF0-CN-3xD"/>
+ </constraints>
+ <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="Choose a domain to use as your Bonjour registration domain." id="EDB-Ul-M1P">
+ <font key="font" metaFont="systemBold"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <customView translatesAutoresizingMaskIntoConstraints="NO" id="agb-WV-smo" customClass="CNDomainBrowserView">
+ <rect key="frame" x="20" y="61" width="456" height="114"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="114" id="3JN-68-aTf"/>
+ </constraints>
+ <userDefinedRuntimeAttributes>
+ <userDefinedRuntimeAttribute type="boolean" keyPath="registrationDomains" value="YES"/>
+ <userDefinedRuntimeAttribute type="boolean" keyPath="ignoreLocal" value="YES"/>
+ <userDefinedRuntimeAttribute type="boolean" keyPath="ignoreBTMM" value="NO"/>
+ <userDefinedRuntimeAttribute type="boolean" keyPath="browseRegistration" value="YES"/>
+ </userDefinedRuntimeAttributes>
+ </customView>
+ <button verticalHuggingPriority="750" tag="1" translatesAutoresizingMaskIntoConstraints="NO" id="8fZ-4V-xd6">
+ <rect key="frame" x="400" y="13" width="82" height="32"/>
+ <buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="eLF-AD-BgY">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ <string key="keyEquivalent" base64-UTF8="YES">
+DQ
+</string>
+ </buttonCell>
+ <connections>
+ <action selector="closeMyCustomSheet:" target="-2" id="HFg-iF-1qy"/>
+ </connections>
+ </button>
+ <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="I6S-g0-R0G">
+ <rect key="frame" x="318" y="13" width="82" height="32"/>
+ <buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="a1o-he-Kv7">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ <string key="keyEquivalent" base64-UTF8="YES">
+Gw
+</string>
+ </buttonCell>
+ <connections>
+ <action selector="closeMyCustomSheet:" target="-2" id="SQP-5g-qGG"/>
+ </connections>
+ </button>
+ </subviews>
+ <constraints>
+ <constraint firstItem="8fZ-4V-xd6" firstAttribute="top" secondItem="agb-WV-smo" secondAttribute="bottom" constant="20" symbolic="YES" id="4cD-Af-ApJ"/>
+ <constraint firstItem="q4Y-tT-1h7" firstAttribute="leading" secondItem="W37-VK-yC5" secondAttribute="leading" constant="20" symbolic="YES" id="8fj-II-NeF"/>
+ <constraint firstItem="q4Y-tT-1h7" firstAttribute="top" secondItem="W37-VK-yC5" secondAttribute="top" constant="20" symbolic="YES" id="Bq5-8Z-4eY"/>
+ <constraint firstItem="agb-WV-smo" firstAttribute="leading" secondItem="W37-VK-yC5" secondAttribute="leading" constant="20" symbolic="YES" id="Kex-pV-3tR"/>
+ <constraint firstAttribute="trailing" secondItem="q4Y-tT-1h7" secondAttribute="trailing" constant="20" symbolic="YES" id="Piu-PE-SEc"/>
+ <constraint firstItem="agb-WV-smo" firstAttribute="top" secondItem="q4Y-tT-1h7" secondAttribute="bottom" constant="8" symbolic="YES" id="Spl-BU-U7l"/>
+ <constraint firstItem="8fZ-4V-xd6" firstAttribute="width" secondItem="I6S-g0-R0G" secondAttribute="width" id="Xx2-3v-4H5"/>
+ <constraint firstItem="8fZ-4V-xd6" firstAttribute="leading" secondItem="I6S-g0-R0G" secondAttribute="trailing" constant="12" symbolic="YES" id="aly-0r-bvb"/>
+ <constraint firstAttribute="bottom" secondItem="8fZ-4V-xd6" secondAttribute="bottom" constant="20" symbolic="YES" id="eqT-TT-gxE"/>
+ <constraint firstItem="8fZ-4V-xd6" firstAttribute="baseline" secondItem="I6S-g0-R0G" secondAttribute="baseline" id="h1B-xs-zFp"/>
+ <constraint firstAttribute="trailing" secondItem="agb-WV-smo" secondAttribute="trailing" constant="20" symbolic="YES" id="xLH-br-4Uh"/>
+ <constraint firstAttribute="trailing" secondItem="8fZ-4V-xd6" secondAttribute="trailing" constant="20" symbolic="YES" id="xiF-Cr-13M"/>
+ </constraints>
+ </view>
+ <point key="canvasLocation" x="538" y="-234"/>
+ </window>
+ <window title="Add Registration Domain" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="he2-0K-CWy" userLabel="SelectRegDomainManual">
+ <windowStyleMask key="styleMask" titled="YES"/>
+ <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+ <rect key="contentRect" x="634" y="377" width="496" height="133"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
+ <value key="minSize" type="size" width="213" height="107"/>
+ <view key="contentView" id="FYv-ly-yOd">
+ <rect key="frame" x="0.0" y="0.0" width="496" height="133"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <button verticalHuggingPriority="750" tag="1" translatesAutoresizingMaskIntoConstraints="NO" id="sau-gD-LVt">
+ <rect key="frame" x="400" y="13" width="82" height="32"/>
+ <buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="jAh-nT-Qwg">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ <string key="keyEquivalent" base64-UTF8="YES">
+DQ
+</string>
+ </buttonCell>
+ <connections>
+ <action selector="closeMyCustomSheet:" target="-2" id="ySI-9p-3tZ"/>
+ </connections>
+ </button>
+ <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Ypd-8h-xfJ">
+ <rect key="frame" x="318" y="13" width="82" height="32"/>
+ <buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" inset="2" id="Nd2-rR-DtX">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ <string key="keyEquivalent" base64-UTF8="YES">
+Gw
+</string>
+ </buttonCell>
+ <connections>
+ <action selector="closeMyCustomSheet:" target="-2" id="YM3-jW-TNM"/>
+ </connections>
+ </button>
+ <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="die-Uf-Bn9">
+ <rect key="frame" x="36" y="52" width="54" height="17"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Domain:" id="ZIy-WQ-OIZ">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="06e-WM-3MP">
+ <rect key="frame" x="18" y="79" width="460" height="34"/>
+ <constraints>
+ <constraint firstAttribute="width" priority="499" constant="456" id="ilh-EM-DG1"/>
+ </constraints>
+ <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="The following registration domain will be used by Bonjour to advertise beyond the local subnet." id="SLP-nX-Q2C">
+ <font key="font" metaFont="systemBold"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OEh-fL-Ol6">
+ <rect key="frame" x="96" y="49" width="380" height="22"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="aIe-CQ-mQ3">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ </subviews>
+ <constraints>
+ <constraint firstItem="OEh-fL-Ol6" firstAttribute="leading" secondItem="FYv-ly-yOd" secondAttribute="leading" priority="499" constant="96" id="1Nc-CQ-lXd"/>
+ <constraint firstItem="06e-WM-3MP" firstAttribute="top" secondItem="FYv-ly-yOd" secondAttribute="top" constant="20" symbolic="YES" id="5wy-Ji-7tZ"/>
+ <constraint firstItem="OEh-fL-Ol6" firstAttribute="top" secondItem="06e-WM-3MP" secondAttribute="bottom" constant="8" symbolic="YES" id="7BD-rk-RTl"/>
+ <constraint firstItem="sau-gD-LVt" firstAttribute="leading" secondItem="Ypd-8h-xfJ" secondAttribute="trailing" constant="12" symbolic="YES" id="7oo-eg-nGA"/>
+ <constraint firstItem="die-Uf-Bn9" firstAttribute="baseline" secondItem="OEh-fL-Ol6" secondAttribute="baseline" id="DbC-UI-YFz"/>
+ <constraint firstItem="die-Uf-Bn9" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="FYv-ly-yOd" secondAttribute="leading" constant="20" symbolic="YES" id="Ip2-Q3-r3l"/>
+ <constraint firstAttribute="trailing" secondItem="sau-gD-LVt" secondAttribute="trailing" constant="20" symbolic="YES" id="Jce-ky-wTf"/>
+ <constraint firstItem="sau-gD-LVt" firstAttribute="width" secondItem="Ypd-8h-xfJ" secondAttribute="width" id="NkV-L2-e4p"/>
+ <constraint firstItem="sau-gD-LVt" firstAttribute="top" secondItem="OEh-fL-Ol6" secondAttribute="bottom" constant="8" symbolic="YES" id="Omq-c5-SZQ"/>
+ <constraint firstAttribute="trailing" secondItem="06e-WM-3MP" secondAttribute="trailing" constant="20" symbolic="YES" id="U0T-5s-Jip"/>
+ <constraint firstAttribute="bottom" secondItem="sau-gD-LVt" secondAttribute="bottom" constant="20" symbolic="YES" id="cWG-NL-TzC"/>
+ <constraint firstAttribute="trailing" secondItem="OEh-fL-Ol6" secondAttribute="trailing" constant="20" symbolic="YES" id="igv-0W-kuw"/>
+ <constraint firstItem="OEh-fL-Ol6" firstAttribute="leading" secondItem="die-Uf-Bn9" secondAttribute="trailing" constant="8" symbolic="YES" id="j71-MK-aiv"/>
+ <constraint firstItem="sau-gD-LVt" firstAttribute="baseline" secondItem="Ypd-8h-xfJ" secondAttribute="baseline" id="t9l-JC-Ab2"/>
+ <constraint firstItem="06e-WM-3MP" firstAttribute="leading" secondItem="FYv-ly-yOd" secondAttribute="leading" constant="20" symbolic="YES" id="wIW-Ja-ih6"/>
+ <constraint firstItem="OEh-fL-Ol6" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="FYv-ly-yOd" secondAttribute="leading" constant="20" symbolic="YES" id="wia-Av-Bte"/>
+ </constraints>
+ </view>
+ <point key="canvasLocation" x="538" y="-525"/>
+ </window>
+ </objects>
+ <resources>
+ <image name="NSAddTemplate" width="11" height="11"/>
+ <image name="NSRemoveTemplate" width="11" height="11"/>
+ </resources>
+</document>
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/Base.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib b/mDNSResponder/mDNSMacOSX/PreferencePane/Base.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib
new file mode 100644
index 00000000..33cf8f83
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/Base.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib
Binary files differ
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool-Info.plist b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool-Info.plist
new file mode 100644
index 00000000..3e9f22e6
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool-Info.plist
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>BonjourPrefTool</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>XPC!</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright © 2017 Apple Inc. All rights reserved.</string>
+ <key>XPCService</key>
+ <dict>
+ <key>ServiceType</key>
+ <string>Application</string>
+ <key>_AllowedClients</key>
+ <array>
+ <string>identifier = com.apple.preference.bonjour.remoteservice and (anchor apple or (anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9]))</string>
+ </array>
+ <key>_RoleAccount</key>
+ <string>root</string>
+ </dict>
+</dict>
+</plist>
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.h b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.h
new file mode 100644
index 00000000..02d97711
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "BonjourPrefToolProtocol.h"
+
+// This object implements the protocol which we have defined. It provides the actual behavior for the service.
+// It is 'exported' by the service to make it available to the process hosting the service over an NSXPCConnection.
+@interface BonjourPrefTool : NSObject <BonjourPrefToolProtocol>
+@end
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.m b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.m
new file mode 100644
index 00000000..c0d7bb9e
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefTool.m
@@ -0,0 +1,158 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "BonjourPrefTool.h"
+#import "BonjourSCStore.h"
+#import <Security/Security.h>
+#import <dns_sd.h>
+
+#define DYNDNS_KEYCHAIN_DESCRIPTION "Dynamic DNS Key"
+
+#pragma mark - Keychain Funcs
+
+static SecAccessRef
+MyMakeUidAccess(uid_t uid)
+{
+ // make the "uid/gid" ACL subject
+ // this is a CSSM_LIST_ELEMENT chain
+ CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = {
+ CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION, // selector version
+ CSSM_ACL_MATCH_UID, // set mask: match uids (only)
+ uid, // uid to match
+ 0 // gid (not matched here)
+ };
+ CSSM_LIST_ELEMENT subject2 = { NULL, 0, 0, {{0,0,0}} };
+ subject2.Element.Word.Data = (UInt8 *)&selector;
+ subject2.Element.Word.Length = sizeof(selector);
+ CSSM_LIST_ELEMENT subject1 = { &subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID, {{0,0,0}} };
+
+
+ // rights granted (replace with individual list if desired)
+ CSSM_ACL_AUTHORIZATION_TAG rights[] = {
+ CSSM_ACL_AUTHORIZATION_ANY // everything
+ };
+ // owner component (right to change ACL)
+ CSSM_ACL_OWNER_PROTOTYPE owner = {
+ // TypedSubject
+ { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
+ // Delegate
+ false
+ };
+ // ACL entries (any number, just one here)
+ CSSM_ACL_ENTRY_INFO acls =
+ {
+ // CSSM_ACL_ENTRY_PROTOTYPE
+ {
+ { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, // TypedSubject
+ false, // Delegate
+ { sizeof(rights) / sizeof(rights[0]), rights }, // Authorization rights for this entry
+ { { 0, 0 }, { 0, 0 } }, // CSSM_ACL_VALIDITY_PERIOD
+ "" // CSSM_STRING EntryTag
+ },
+ // CSSM_ACL_HANDLE
+ 0
+ };
+
+ SecAccessRef a = NULL;
+ (void) SecAccessCreateFromOwnerAndACL(&owner, 1, &acls, &a);
+ return a;
+}
+
+static OSStatus
+MyAddDynamicDNSPassword(SecKeychainRef keychain, SecAccessRef a, UInt32 serviceNameLength, const char *serviceName,
+ UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData)
+{
+ char * description = DYNDNS_KEYCHAIN_DESCRIPTION;
+ UInt32 descriptionLength = strlen(DYNDNS_KEYCHAIN_DESCRIPTION);
+ UInt32 type = 'ddns';
+ UInt32 creator = 'ddns';
+ UInt32 typeLength = sizeof(type);
+ UInt32 creatorLength = sizeof(creator);
+ OSStatus err;
+
+ // set up attribute vector (each attribute consists of {tag, length, pointer})
+ SecKeychainAttribute attrs[] = { { kSecLabelItemAttr, serviceNameLength, (char *)serviceName },
+ { kSecAccountItemAttr, accountNameLength, (char *)accountName },
+ { kSecServiceItemAttr, serviceNameLength, (char *)serviceName },
+ { kSecDescriptionItemAttr, descriptionLength, (char *)description },
+ { kSecTypeItemAttr, typeLength, (UInt32 *)&type },
+ { kSecCreatorItemAttr, creatorLength, (UInt32 *)&creator } };
+ SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
+
+ err = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &attributes, passwordLength, passwordData, keychain, a, NULL);
+ return err;
+}
+
+static int
+SetKeychainEntry(NSDictionary * secretDictionary)
+// Create a new entry in system keychain, or replace existing
+{
+ CFStringRef keyNameString;
+ CFStringRef domainString;
+ CFStringRef secretString;
+ SecKeychainItemRef item = NULL;
+ int result = 0;
+ char keyname[kDNSServiceMaxDomainName];
+ char domain[kDNSServiceMaxDomainName];
+ char secret[kDNSServiceMaxDomainName];
+
+ keyNameString = (__bridge CFStringRef)[secretDictionary objectForKey:(NSString *)SC_DYNDNS_KEYNAME_KEY];
+ require(keyNameString != NULL, exit);
+
+ domainString = (__bridge CFStringRef)[secretDictionary objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
+ require(domainString != NULL, exit);
+
+ secretString = (__bridge CFStringRef)[secretDictionary objectForKey:(NSString *)SC_DYNDNS_SECRET_KEY];
+ require(secretString != NULL, exit);
+
+ CFStringGetCString(keyNameString, keyname, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
+ CFStringGetCString(domainString, domain, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
+ CFStringGetCString(secretString, secret, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
+
+ result = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
+ if (result == noErr)
+ {
+ result = SecKeychainFindGenericPassword(NULL, strlen(domain), domain, 0, NULL, 0, NULL, &item);
+ if (result == noErr)
+ {
+ result = SecKeychainItemDelete(item);
+ if (result != noErr) fprintf(stderr, "SecKeychainItemDelete returned %d\n", result);
+ }
+
+ result = MyAddDynamicDNSPassword(NULL, MyMakeUidAccess(0), strlen(domain), domain, strlen(keyname)+1, keyname, strlen(secret)+1, secret);
+ if (result != noErr) fprintf(stderr, "MyAddDynamicDNSPassword returned %d\n", result);
+ if (item) CFRelease(item);
+ }
+
+exit:
+ return result;
+}
+
+
+@implementation BonjourPrefTool
+
+- (void) setKeychainEntry:(NSDictionary *_Nonnull)secretDictionary withStatus:(void (^ _Nonnull)(OSStatus))status
+{
+ OSStatus result;
+
+ result = SetKeychainEntry (secretDictionary);
+// NSLog(@"setKeychainEntry: %@ result: %d", secretDictionary, result);
+
+ status (result);
+}
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefToolProtocol.h b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefToolProtocol.h
new file mode 100644
index 00000000..e82bfdf6
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/BonjourPrefToolProtocol.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+// The protocol that this service will vend as its API. This header file will
+// also need to be visible to the process hosting the service.
+@protocol BonjourPrefToolProtocol
+
+- (void) setKeychainEntry:(NSDictionary *_Nonnull)secretDictionary withStatus:(void (^ _Nonnull)(OSStatus))status;
+
+@end
+
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/entitlements.plist b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/entitlements.plist
new file mode 100644
index 00000000..a3088cce
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/entitlements.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.private.xpc.role-account</key>
+ <true/>
+</dict>
+</plist>
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/main.m b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/main.m
new file mode 100644
index 00000000..3ed65fc5
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/BonjourPrefTool/main.m
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "BonjourPrefTool.h"
+
+@interface ServiceDelegate : NSObject <NSXPCListenerDelegate>
+@end
+
+@implementation ServiceDelegate
+
+- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {
+ // This method is where the NSXPCListener configures, accepts, and resumes a new incoming NSXPCConnection.
+ (void)listener; // Unused
+
+ // Configure the connection.
+ // First, set the interface that the exported object implements.
+ newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(BonjourPrefToolProtocol)];
+
+ // Next, set the object that the connection exports. All messages sent on the connection to this service will be sent to the exported object to handle. The connection retains the exported object.
+ BonjourPrefTool *exportedObject = [BonjourPrefTool new];
+ newConnection.exportedObject = exportedObject;
+
+ // Resuming the connection allows the system to deliver more incoming messages.
+ [newConnection resume];
+
+ // Returning YES from this method tells the system that you have accepted this connection. If you want to reject the connection for some reason, call -invalidate on the connection and return NO.
+ return YES;
+}
+
+@end
+
+int main(int argc, const char *argv[])
+{
+ (void)argc; // Unused
+ (void)argv; // Unused
+
+ // Create the delegate for the service.
+ ServiceDelegate *delegate = [ServiceDelegate new];
+
+ // Set up the one NSXPCListener for this service. It will handle all incoming connections.
+ NSXPCListener *listener = [NSXPCListener serviceListener];
+ listener.delegate = delegate;
+
+ // Resuming the serviceListener starts this service. This method does not return.
+ [listener resume];
+ return 0;
+}
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c b/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c
deleted file mode 100644
index 43da5025..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- File: ConfigurationAuthority.c
-
- Abstract: Interface to system security framework that manages access
- to protected resources like system configuration preferences.
-
- Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
-
- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms. If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under Apple's
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software. Neither the name, trademarks, service marks or logos of
- Apple Computer, Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "ConfigurationAuthority.h"
-#include "ConfigurationRights.h"
-
-#include <AssertMacros.h>
-
-
-static AuthorizationRef gAuthRef = 0;
-
-static AuthorizationItem gAuthorizations[] = { { UPDATE_SC_RIGHT, 0, NULL, 0 },
- { EDIT_SYS_KEYCHAIN_RIGHT, 0, NULL, 0 }};
-static AuthorizationRights gAuthSet = { sizeof gAuthorizations / sizeof gAuthorizations[0], gAuthorizations };
-
-static CFDictionaryRef CreateRightsDict( CFStringRef prompt)
-/* Create a CFDictionary decribing an auth right. See /etc/authorization for examples. */
-/* Specifies that the right requires admin authentication, which persists for 5 minutes. */
-{
- CFMutableDictionaryRef dict = NULL, tmpDict;
- CFMutableArrayRef mechanisms;
- CFNumberRef timeout;
- int val;
-
- tmpDict = CFDictionaryCreateMutable( (CFAllocatorRef) NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- require( tmpDict != NULL, MakeDictFailed);
-
- CFDictionaryAddValue(tmpDict, CFSTR("class"), CFSTR("user"));
- CFDictionaryAddValue(tmpDict, CFSTR("comment"), prompt);
- CFDictionaryAddValue(tmpDict, CFSTR("group"), CFSTR("admin"));
-
- mechanisms = CFArrayCreateMutable((CFAllocatorRef) NULL, 1, &kCFTypeArrayCallBacks);
- require( mechanisms != NULL, MakeArrayFailed);
- CFArrayAppendValue( mechanisms, CFSTR("builtin:authenticate"));
- CFDictionaryAddValue( tmpDict, CFSTR("mechanisms"), mechanisms);
-
- val = 300; // seconds
- timeout = CFNumberCreate((CFAllocatorRef) NULL, kCFNumberIntType, &val);
- require( timeout != NULL, MakeIntFailed);
- CFDictionaryAddValue( tmpDict, CFSTR("timeout"), timeout);
- CFDictionaryAddValue( tmpDict, CFSTR("shared"), kCFBooleanTrue);
-
- dict = tmpDict;
- tmpDict = NULL;
-
- CFRelease( timeout);
-MakeIntFailed:
- CFRelease( mechanisms);
-MakeArrayFailed:
- if ( tmpDict)
- CFRelease( tmpDict);
-MakeDictFailed:
- return dict;
-}
-
-OSStatus InitConfigAuthority(void)
-/* Initialize the authorization record-keeping */
-{
- OSStatus err;
- CFDictionaryRef dict;
- CFStringRef rightInfo;
-
- err = AuthorizationCreate((AuthorizationRights*) NULL, (AuthorizationEnvironment*) NULL,
- (AuthorizationFlags) 0, &gAuthRef);
- require_noerr( err, NewAuthFailed);
-
- err = AuthorizationRightGet( UPDATE_SC_RIGHT, (CFDictionaryRef*) NULL);
- if (err == errAuthorizationDenied)
- {
- rightInfo = CFCopyLocalizedString(CFSTR("Authentication required to set Dynamic DNS preferences."),
- CFSTR("Describes operation that requires user authorization"));
- require_action( rightInfo != NULL, GetStrFailed, err=coreFoundationUnknownErr;);
- dict = CreateRightsDict(rightInfo);
- require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr; CFRelease(rightInfo));
-
- err = AuthorizationRightSet(gAuthRef, UPDATE_SC_RIGHT, dict, (CFStringRef) NULL,
- (CFBundleRef) NULL, (CFStringRef) NULL);
- CFRelease(rightInfo);
- CFRelease(dict);
- }
- require_noerr( err, AuthSetFailed);
-
- err = AuthorizationRightGet( EDIT_SYS_KEYCHAIN_RIGHT, (CFDictionaryRef*) NULL);
- if (err == errAuthorizationDenied)
- {
- rightInfo = CFCopyLocalizedString( CFSTR("Authentication required to edit System Keychain."),
- CFSTR("Describes operation that requires user authorization"));
- require_action( rightInfo != NULL, GetStrFailed, err=coreFoundationUnknownErr;);
- dict = CreateRightsDict( rightInfo);
- require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr; CFRelease(rightInfo));
-
- err = AuthorizationRightSet(gAuthRef, EDIT_SYS_KEYCHAIN_RIGHT, dict, (CFStringRef) NULL,
- (CFBundleRef) NULL, (CFStringRef) NULL);
- CFRelease( rightInfo);
- CFRelease( dict);
- }
- require_noerr( err, AuthSetFailed);
-
-AuthSetFailed:
-GetStrFailed:
-NewAuthFailed:
- return err;
-}
-
-OSStatus AttemptAcquireAuthority( Boolean allowUI)
-/* Try to get permission for privileged ops, either implicitly or by asking the user for */
-/* authority to perform operations (if necessary) */
-{
- AuthorizationFlags allowFlag = allowUI ? kAuthorizationFlagInteractionAllowed : 0;
- OSStatus err;
-
- err = AuthorizationCopyRights( gAuthRef, &gAuthSet, (AuthorizationEnvironment*) NULL,
- kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize |
- allowFlag,
- (AuthorizationRights**) NULL);
- return err;
-}
-
-OSStatus ReleaseAuthority(void)
-/* Discard authority to perform operations */
-{
- (void) AuthorizationFree( gAuthRef, kAuthorizationFlagDefaults);
- gAuthRef = 0;
- return AuthorizationCreate( (AuthorizationRights*) NULL, (AuthorizationEnvironment*) NULL,
- (AuthorizationFlags) 0, &gAuthRef);
-}
-
-Boolean CurrentlyAuthorized(void)
-{
- OSStatus err = AttemptAcquireAuthority(true);
- return err == noErr;
-}
-
-
-OSStatus ExternalizeAuthority(AuthorizationExternalForm *pAuth)
-/* Package up current authorizations for transfer to another process */
-{
- return AuthorizationMakeExternalForm(gAuthRef, pAuth);
-}
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.h b/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.h
deleted file mode 100644
index 49da93d0..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/ConfigurationAuthority.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- File: ConfigurationAuthority.h
-
- Abstract: Interface to system security framework that manages access
- to protected resources like system configuration preferences.
-
- Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
-
- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms. If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under Apple's
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software. Neither the name, trademarks, service marks or logos of
- Apple Computer, Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <CoreServices/CoreServices.h>
-#include <Security/Security.h>
-
-OSStatus InitConfigAuthority(void);
-Boolean CurrentlyAuthorized(void);
-OSStatus AttemptAcquireAuthority(Boolean allowUI);
-OSStatus ReleaseAuthority(void);
-OSStatus ExternalizeAuthority(AuthorizationExternalForm *pAuth);
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h b/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h
index f0586591..36bfee81 100644
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.h
@@ -41,70 +41,62 @@
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#import <Cocoa/Cocoa.h>
#import <PreferencePanes/PreferencePanes.h>
-#import <CoreFoundation/CoreFoundation.h>
#import <SecurityInterface/SFAuthorizationView.h>
-#import <SystemConfiguration/SystemConfiguration.h>
#import <dns_sd.h>
-typedef struct MyDNSServiceState {
- DNSServiceRef service;
- CFRunLoopSourceRef source;
- CFSocketRef socket;
-} MyDNSServiceState;
-
+@class CNBonjourDomainView;
+@class CNDomainBrowserView;
@interface DNSServiceDiscoveryPref : NSPreferencePane
{
- IBOutlet NSTextField *hostName;
- IBOutlet NSTextField *sharedSecretName;
- IBOutlet NSSecureTextField *sharedSecretValue;
- IBOutlet NSComboBox *browseDomainsComboBox;
- IBOutlet NSComboBox *regDomainsComboBox;
- IBOutlet NSButton *wideAreaCheckBox;
- IBOutlet NSButton *hostNameSharedSecretButton;
- IBOutlet NSButton *registrationSharedSecretButton;
- IBOutlet NSButton *applyButton;
- IBOutlet NSButton *revertButton;
- IBOutlet NSWindow *sharedSecretWindow;
- IBOutlet NSWindow *addBrowseDomainWindow;
- IBOutlet NSButton *addBrowseDomainButton;
- IBOutlet NSButton *removeBrowseDomainButton;
- IBOutlet NSButton *browseOKButton;
- IBOutlet NSButton *browseCancelButton;
- IBOutlet NSButton *secretOKButton;
- IBOutlet NSButton *secretCancelButton;
- IBOutlet NSImageView *statusImageView;
- IBOutlet NSTabView *tabView;
- IBOutlet NSTableView *browseDomainList;
- IBOutlet SFAuthorizationView *comboAuthButton;
-
- NSWindow *mainWindow;
- NSString *currentHostName;
- NSString *currentRegDomain;
- NSArray *currentBrowseDomainsArray;
- NSMutableArray *browseDomainsArray;
- NSMutableArray *defaultBrowseDomainsArray;
- NSString *defaultRegDomain;
-
- NSString *hostNameSharedSecretName;
- NSString *hostNameSharedSecretValue;
- NSString *regSharedSecretName;
- NSString *regSharedSecretValue;
- BOOL currentWideAreaState;
- BOOL prefsNeedUpdating;
- BOOL toolInstalled;
- BOOL browseDomainListEnabled;
- BOOL justStartedEditing;
- NSImage *successImage;
- NSImage *inprogressImage;
- NSImage *failureImage;
-
- MyDNSServiceState regQuery;
- MyDNSServiceState browseQuery;
- NSMutableArray *browseDataSource;
- NSMutableArray *registrationDataSource;
+ IBOutlet NSTextField *hostName;
+ IBOutlet NSTextField *sharedSecretName;
+ IBOutlet NSSecureTextField *sharedSecretValue;
+ IBOutlet NSTextField *browseDomainTextField;
+ IBOutlet NSTextField *regDomainTextField;
+ IBOutlet CNBonjourDomainView *regDomainView;
+ IBOutlet NSButton *wideAreaCheckBox;
+ IBOutlet NSButton *hostNameSharedSecretButton;
+ IBOutlet NSButton *registrationSelectButton;
+ IBOutlet NSButton *registrationSharedSecretButton;
+ IBOutlet NSButton *applyButton;
+ IBOutlet NSButton *revertButton;
+ IBOutlet NSWindow *sharedSecretWindow;
+ IBOutlet NSWindow *addBrowseDomainWindow;
+ IBOutlet NSWindow *addBrowseDomainManualWindow;
+ IBOutlet NSWindow *selectRegistrationDomainWindow;
+ IBOutlet NSWindow *selectRegistrationDomainManualWindow;
+ IBOutlet NSButton *addBrowseDomainButton;
+ IBOutlet NSButton *removeBrowseDomainButton;
+ IBOutlet NSButton *secretOKButton;
+ IBOutlet NSButton *secretCancelButton;
+ IBOutlet NSImageView *statusImageView;
+ IBOutlet NSTabView *tabView;
+ IBOutlet NSTableView *browseDomainList;
+ IBOutlet CNDomainBrowserView *bonjourBrowserView;
+ IBOutlet CNDomainBrowserView *registrationBrowserView;
+ IBOutlet SFAuthorizationView *comboAuthButton;
+
+ NSWindow *mainWindow;
+ NSString *currentHostName;
+ NSString *currentRegDomain;
+ NSArray *currentBrowseDomainsArray;
+ NSMutableArray *browseDomainsArray;
+ NSString *defaultRegDomain;
+
+ NSString *hostNameSharedSecretName;
+ NSString *hostNameSharedSecretValue;
+ NSString *regSharedSecretName;
+ NSString *regSharedSecretValue;
+ BOOL currentWideAreaState;
+ BOOL prefsNeedUpdating;
+ BOOL browseDomainListEnabled;
+ NSImage *successImage;
+ NSImage *inprogressImage;
+ NSImage *failureImage;
+
+ NSMutableArray *registrationDataSource;
}
-(IBAction)applyClicked : (id)sender;
@@ -114,29 +106,21 @@ typedef struct MyDNSServiceState {
-(IBAction)revertClicked : (id)sender;
-(IBAction)changeButtonPressed : (id)sender;
-(IBAction)closeMyCustomSheet : (id)sender;
--(IBAction)comboAction : (id)sender;
-(IBAction)wideAreaCheckBoxChanged : (id)sender;
--(NSMutableArray *)browseDataSource;
-(NSMutableArray *)registrationDataSource;
--(NSComboBox *)browseDomainsComboBox;
--(NSComboBox *)regDomainsComboBox;
-(NSString *)currentRegDomain;
--(NSMutableArray *)defaultBrowseDomainsArray;
-(NSArray *)currentBrowseDomainsArray;
-(NSString *)currentHostName;
-(NSString *)defaultRegDomain;
-(void)setDefaultRegDomain : (NSString *)domain;
-
-(void)enableApplyButton;
-(void)disableApplyButton;
-(void)applyCurrentState;
--(void)setBrowseDomainsComboBox;
-(void)setupInitialValues;
--(void)startDomainBrowsing;
-(void)toggleWideAreaBonjour : (BOOL)state;
-(void)updateApplyButtonState;
-(void)enableControls;
@@ -154,7 +138,7 @@ typedef struct MyDNSServiceState {
-(int)statusForHostName : (NSString * )domain;
-(NSData *)dataForDomainArray : (NSArray *)domainArray;
-(NSData *)dataForDomain : (NSString *)domainName isEnabled : (BOOL)enabled;
--(NSData *)dataForSharedSecret : (NSString *)secret domain : (NSString *)domainName key : (NSString *)keyName;
+-(NSDictionary *)dictionaryForSharedSecret : (NSString *)secret domain : (NSString *)domainName key : (NSString *)keyName;
-(BOOL)domainAlreadyInList : (NSString *)domainString;
-(NSString *)trimCharactersFromDomain : (NSString *)domain;
@@ -163,8 +147,6 @@ typedef struct MyDNSServiceState {
-(void)authorizationViewDidAuthorize : (SFAuthorizationView *)view;
-(void)authorizationViewDidDeauthorize : (SFAuthorizationView *)view;
-(void)mainViewDidLoad;
--(int)numberOfItemsInComboBox : (NSComboBox *)aComboBox;
--(id)comboBox : (NSComboBox *)aComboBox objectValueForItemAtIndex : (int)index;
-(void)controlTextDidChange : (NSNotification *) notification;
@end
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m b/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m
index ba5f64bf..f58f3013 100644
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m
@@ -42,15 +42,46 @@
*/
#import "DNSServiceDiscoveryPref.h"
-#import "ConfigurationAuthority.h"
-#import "PrivilegedOperations.h"
-#import <unistd.h>
+#import "CNDomainBrowserView.h"
+#import "BonjourSCStore.h"
+#import "BonjourPrefTool.h"
+#import <Foundation/NSXPCConnection_Private.h>
#include "../../Clients/ClientCommon.h"
-#ifndef NSINTEGER_DEFINED
-#define NSInteger int
+#pragma mark - BonjourPrefTool
+
+static OSStatus
+DNSPrefTool_SetKeychainEntry(NSDictionary * secretDictionary)
+{
+ __block OSStatus result;
+ BonjourPrefTool * prefTool;
+
+ NSXPCConnection * _connectionToTool = [[NSXPCConnection alloc] initWithServiceName:@"com.apple.preference.bonjour.tool"];
+ _connectionToTool.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(BonjourPrefToolProtocol)];
+ [_connectionToTool resume];
+
+#if 0
+ prefTool = [_connectionToTool remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) {
+ NSLog( @"Cannot connect to BonjourPrefTool: %@.", error);
+ result = error.code;
+ }];
+#else
+ prefTool = [_connectionToTool synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) {
+ NSLog( @"Cannot connect to BonjourPrefTool: %@.", error);
+ result = error.code;
+ }];
#endif
+ [prefTool setKeychainEntry: secretDictionary withStatus: ^(OSStatus status){
+ result = status;
+ }];
+
+ [_connectionToTool invalidate];
+
+ return (result);
+}
+
+#pragma mark -
@implementation DNSServiceDiscoveryPref
@@ -75,162 +106,13 @@ static void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void
{
(void)store; // Unused
(void)changedKeys; // Unused
- DNSServiceDiscoveryPref * me = (DNSServiceDiscoveryPref *)context;
+ DNSServiceDiscoveryPref * me = (__bridge DNSServiceDiscoveryPref *)context;
assert(me != NULL);
[me setupInitialValues];
}
-static void ServiceDomainEnumReply( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
- DNSServiceErrorType errorCode, const char *replyDomain, void *context, DNSServiceFlags enumType)
-{
- (void)sdRef; // Unused
- (void)interfaceIndex; // Unused
- (void)errorCode; // Unused
- if (strcmp(replyDomain, "local.") == 0) return; // local domain is not interesting
-
- DNSServiceDiscoveryPref * me = (DNSServiceDiscoveryPref *)context;
- BOOL moreComing = (BOOL)(flags & kDNSServiceFlagsMoreComing);
- NSMutableArray * domainArray;
- NSMutableArray * defaultBrowseDomainsArray = nil;
- NSComboBox * domainComboBox;
- NSString * domainString;
- char decodedDomainString[kDNSServiceMaxDomainName] = "\0";
- char nextLabel[256] = "\0";
- char * buffer = (char *)replyDomain;
-
- while (*buffer) {
- buffer = (char *)GetNextLabel(buffer, nextLabel);
- strcat(decodedDomainString, nextLabel);
- strcat(decodedDomainString, ".");
- }
-
- // Remove trailing dot from domain name.
- decodedDomainString[strlen(decodedDomainString)-1] = '\0';
-
- domainString = [[[NSString alloc] initWithUTF8String:(const char *)decodedDomainString] autorelease];
-
- if (enumType & kDNSServiceFlagsRegistrationDomains) {
- domainArray = [me registrationDataSource];
- domainComboBox = [me regDomainsComboBox];
- } else {
- domainArray = [me browseDataSource];
- domainComboBox = [me browseDomainsComboBox];
- defaultBrowseDomainsArray = [me defaultBrowseDomainsArray];
- }
-
- if (flags & kDNSServiceFlagsAdd) {
- [domainArray removeObject:domainString]; // How can I check if an object is in the array?
- [domainArray addObject:domainString];
- if ((flags & kDNSServiceFlagsDefault) && (enumType & kDNSServiceFlagsRegistrationDomains)) {
- [me setDefaultRegDomain:domainString];
- if ([[domainComboBox stringValue] length] == 0) [domainComboBox setStringValue:domainString];
- } else if ((flags & kDNSServiceFlagsDefault) && !(enumType & kDNSServiceFlagsRegistrationDomains)) {
- [defaultBrowseDomainsArray removeObject:domainString];
- [defaultBrowseDomainsArray addObject:domainString];
- }
- }
-
- if (moreComing == NO) {
- [domainArray sortUsingFunction:MyArrayCompareFunction context:nil];
- [domainComboBox reloadData];
- }
-}
-
-
-static void
-browseDomainReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
- DNSServiceErrorType errorCode, const char *replyDomain, void *context)
-{
- ServiceDomainEnumReply(sdRef, flags, interfaceIndex, errorCode, replyDomain, context, kDNSServiceFlagsBrowseDomains);
-}
-
-
-static void
-registrationDomainReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
- DNSServiceErrorType errorCode, const char *replyDomain, void *context)
-{
- ServiceDomainEnumReply(sdRef, flags, interfaceIndex, errorCode, replyDomain, context, kDNSServiceFlagsRegistrationDomains);
-}
-
-
-
-static void
-MyDNSServiceCleanUp(MyDNSServiceState * query)
-{
- /* Remove the CFRunLoopSource from the current run loop. */
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), query->source, kCFRunLoopCommonModes);
- CFRelease(query->source);
-
- /* Invalidate the CFSocket. */
- CFSocketInvalidate(query->socket);
- CFRelease(query->socket);
-
- /* Workaround that gives time to CFSocket's select thread so it can remove the socket from its FD set
- before we close the socket by calling DNSServiceRefDeallocate. <rdar://problem/3585273> */
- usleep(1000);
-
- /* Terminate the connection with the mDNSResponder daemon, which cancels the query. */
- DNSServiceRefDeallocate(query->service);
-}
-
-
-
-static void
-MySocketReadCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void * data, void * info)
-{
- #pragma unused(s)
- #pragma unused(type)
- #pragma unused(address)
- #pragma unused(data)
-
- DNSServiceErrorType err;
-
- MyDNSServiceState * query = (MyDNSServiceState *)info; // context passed in to CFSocketCreateWithNative().
- assert(query != NULL);
-
- /* Read a reply from the mDNSResponder. */
- err= DNSServiceProcessResult(query->service);
- if (err != kDNSServiceErr_NoError) {
- fprintf(stderr, "DNSServiceProcessResult returned %d\n", err);
-
- /* Terminate the query operation and release the CFRunLoopSource and CFSocket. */
- MyDNSServiceCleanUp(query);
- }
-}
-
-
-
-static void
-MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
-{
- CFSocketNativeHandle sock;
- CFOptionFlags sockFlags;
- CFSocketContext context = { 0, query, NULL, NULL, NULL }; // Use MyDNSServiceState as context data.
-
- /* Access the underlying Unix domain socket to communicate with the mDNSResponder daemon. */
- sock = DNSServiceRefSockFD(query->service);
- assert(sock != -1);
-
- /* Create a CFSocket using the Unix domain socket. */
- query->socket = CFSocketCreateWithNative(NULL, sock, kCFSocketReadCallBack, MySocketReadCallback, &context);
- assert(query->socket != NULL);
-
- /* Prevent CFSocketInvalidate from closing DNSServiceRef's socket. */
- sockFlags = CFSocketGetSocketFlags(query->socket);
- CFSocketSetSocketFlags(query->socket, sockFlags & (~kCFSocketCloseOnInvalidate));
-
- /* Create a CFRunLoopSource from the CFSocket. */
- query->source = CFSocketCreateRunLoopSource(NULL, query->socket, 0);
- assert(query->source != NULL);
-
- /* Add the CFRunLoopSource to the current run loop. */
- CFRunLoopAddSource(CFRunLoopGetCurrent(), query->source, kCFRunLoopCommonModes);
-}
-
-
-
-(void)updateStatusImageView
{
int value = [self statusForHostName:currentHostName];
@@ -242,7 +124,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
- (void)watchForPreferenceChanges
{
- SCDynamicStoreContext context = { 0, self, NULL, NULL, NULL };
+ SCDynamicStoreContext context = { 0, (__bridge void * _Nullable)(self), NULL, NULL, NULL };
SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("watchForPreferenceChanges"), NetworkChanged, &context);
CFMutableArrayRef keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
CFRunLoopSourceRef rls;
@@ -274,12 +156,11 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
assert(store != NULL);
- NSDictionary *dynamicDNS = (NSDictionary *)SCDynamicStoreCopyValue(store, SC_DYNDNS_STATE_KEY);
+ NSDictionary *dynamicDNS = (NSDictionary *)CFBridgingRelease(SCDynamicStoreCopyValue(store, SC_DYNDNS_STATE_KEY));
if (dynamicDNS) {
NSDictionary *hostNames = [dynamicDNS objectForKey:(NSString *)SC_DYNDNS_HOSTNAMES_KEY];
NSDictionary *infoDict = [hostNames objectForKey:lowercaseDomain];
if (infoDict) status = [[infoDict objectForKey:(NSString*)SC_DYNDNS_STATUS_KEY] intValue];
- CFRelease(dynamicDNS);
}
CFRelease(store);
@@ -287,53 +168,37 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
}
-- (void)startDomainBrowsing
-{
- DNSServiceFlags flags;
- OSStatus err = noErr;
-
- flags = kDNSServiceFlagsRegistrationDomains;
- err = DNSServiceEnumerateDomains(&regQuery.service, flags, 0, registrationDomainReply, (void *)self);
- if (err == kDNSServiceErr_NoError) MyDNSServiceAddServiceToRunLoop(&regQuery);
-
- flags = kDNSServiceFlagsBrowseDomains;
- err = DNSServiceEnumerateDomains(&browseQuery.service, flags, 0, browseDomainReply, (void *)self);
- if (err == kDNSServiceErr_NoError) MyDNSServiceAddServiceToRunLoop(&browseQuery);
-}
-
-
-(void)readPreferences
{
NSDictionary *origDict;
NSArray *regDomainArray;
NSArray *hostArray;
- if (currentRegDomain) [currentRegDomain release];
- if (currentBrowseDomainsArray) [currentBrowseDomainsArray release];
- if (currentHostName) [currentHostName release];
+ if (currentRegDomain) currentRegDomain = nil;
+ if (currentBrowseDomainsArray) currentBrowseDomainsArray = nil;
+ if (currentHostName) currentHostName = nil;
SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("com.apple.preference.bonjour"), NULL, NULL);
- origDict = (NSDictionary *)SCDynamicStoreCopyValue(store, SC_DYNDNS_SETUP_KEY);
+ origDict = (NSDictionary *)CFBridgingRelease(SCDynamicStoreCopyValue(store, SC_DYNDNS_SETUP_KEY));
regDomainArray = [origDict objectForKey:(NSString *)SC_DYNDNS_REGDOMAINS_KEY];
if (regDomainArray && [regDomainArray count] > 0) {
currentRegDomain = [[[regDomainArray objectAtIndex:0] objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY] copy];
currentWideAreaState = [[[regDomainArray objectAtIndex:0] objectForKey:(NSString *)SC_DYNDNS_ENABLED_KEY] intValue];
} else {
- currentRegDomain = [[NSString alloc] initWithString:@""];
+ currentRegDomain = @"";
currentWideAreaState = NO;
}
- currentBrowseDomainsArray = [[origDict objectForKey:(NSString *)SC_DYNDNS_BROWSEDOMAINS_KEY] retain];
+ currentBrowseDomainsArray = [origDict objectForKey:(NSString *)SC_DYNDNS_BROWSEDOMAINS_KEY];
hostArray = [origDict objectForKey:(NSString *)SC_DYNDNS_HOSTNAMES_KEY];
if (hostArray && [hostArray count] > 0) {
currentHostName = [[[hostArray objectAtIndex:0] objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY] copy];
} else {
- currentHostName = [[NSString alloc] initWithString:@""];
+ currentHostName = @"";
}
- if (origDict) CFRelease((CFDictionaryRef)origDict);
if (store) CFRelease(store);
}
@@ -344,27 +209,14 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
}
-- (void)setBrowseDomainsComboBox
-{
- NSString * domain = nil;
-
- if ([defaultBrowseDomainsArray count] > 0) {
- NSEnumerator * arrayEnumerator = [defaultBrowseDomainsArray objectEnumerator];
- while ((domain = [arrayEnumerator nextObject]) != NULL) {
- if ([self domainAlreadyInList:domain] == NO) break;
- }
- }
- if (domain) [browseDomainsComboBox setStringValue:domain];
- else [browseDomainsComboBox setStringValue:@""];
-}
-
-
- (IBAction)addBrowseDomainClicked:(id)sender
{
- [self setBrowseDomainsComboBox];
+ NSWindow * window = (([NSEvent modifierFlags] & NSAlternateKeyMask) == NSAlternateKeyMask) ? addBrowseDomainManualWindow : addBrowseDomainWindow;
+ [browseDomainTextField setStringValue: [NSString string]];
- [NSApp beginSheet:addBrowseDomainWindow modalForWindow:mainWindow modalDelegate:self
- didEndSelector:@selector(addBrowseDomainSheetDidEnd:returnCode:contextInfo:) contextInfo:sender];
+ [self disableControls];
+ [NSApp beginSheet:window modalForWindow:mainWindow modalDelegate:self
+ didEndSelector:@selector(addBrowseDomainSheetDidEnd:returnCode:contextInfo:) contextInfo:(__bridge void * _Null_unspecified)(sender)];
[browseDomainList deselectAll:sender];
[self updateApplyButtonState];
@@ -385,15 +237,14 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
{
NSTableView *tableView = sender;
NSMutableDictionary *browseDomainDict;
- int value;
+ NSInteger value;
browseDomainDict = [[browseDomainsArray objectAtIndex:[tableView clickedRow]] mutableCopy];
value = [[browseDomainDict objectForKey:(NSString *)SC_DYNDNS_ENABLED_KEY] intValue];
- [browseDomainDict setObject:[[[NSNumber alloc] initWithInt:(!value)] autorelease] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY];
+ [browseDomainDict setObject:[NSNumber numberWithInt:(!value)] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY];
[browseDomainsArray replaceObjectAtIndex:[tableView clickedRow] withObject:browseDomainDict];
[tableView reloadData];
[self updateApplyButtonState];
- [browseDomainDict release];
}
@@ -431,7 +282,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
if ([[tableColumn identifier] isEqualTo:(NSString *)SC_DYNDNS_ENABLED_KEY]) {
value = [browseDomainDict objectForKey:(NSString *)SC_DYNDNS_ENABLED_KEY];
} else if ([[tableColumn identifier] isEqualTo:(NSString *)SC_DYNDNS_DOMAIN_KEY]) {
- value = [browseDomainDict objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
+ value = [browseDomainDict objectForKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
}
}
}
@@ -449,7 +300,6 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
}
if (browseDomainsArray) {
- [browseDomainsArray release];
browseDomainsArray = nil;
}
@@ -458,9 +308,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
if (browseDomainsArray) {
[browseDomainsArray sortUsingFunction:MyDomainArrayCompareFunction context:nil];
if ([browseDomainsArray isEqualToArray:currentBrowseDomainsArray] == NO) {
- OSStatus err = WriteBrowseDomain((CFDataRef)[self dataForDomainArray:browseDomainsArray]);
- if (err != noErr) NSLog(@"WriteBrowseDomain returned %d\n", (int32_t)err);
- [currentBrowseDomainsArray release];
+ [BonjourSCStore setObject: browseDomainsArray forKey: (NSString *)SC_DYNDNS_BROWSEDOMAINS_KEY];
currentBrowseDomainsArray = [browseDomainsArray copy];
}
}
@@ -470,11 +318,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
[browseDomainList reloadData];
if (currentRegDomain && ([currentRegDomain length] > 0)) {
- [regDomainsComboBox setStringValue:currentRegDomain];
- [registrationDataSource removeObject:currentRegDomain];
- [registrationDataSource addObject:currentRegDomain];
- [registrationDataSource sortUsingFunction:MyArrayCompareFunction context:nil];
- [regDomainsComboBox reloadData];
+ regDomainView.domain = currentRegDomain;
}
if (currentWideAreaState) {
@@ -484,12 +328,10 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
}
if (hostNameSharedSecretValue) {
- [hostNameSharedSecretValue release];
hostNameSharedSecretValue = nil;
}
if (regSharedSecretValue) {
- [regSharedSecretValue release];
regSharedSecretValue = nil;
}
@@ -502,11 +344,8 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
- (void)awakeFromNib
-{
- OSStatus err;
-
+{
prefsNeedUpdating = NO;
- toolInstalled = NO;
browseDomainListEnabled = NO;
defaultRegDomain = nil;
currentRegDomain = nil;
@@ -515,35 +354,40 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
hostNameSharedSecretValue = nil;
regSharedSecretValue = nil;
browseDomainsArray = nil;
- justStartedEditing = YES;
currentWideAreaState = NO;
NSString *successPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"success" ofType:@"tiff"];
NSString *inprogressPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"inprogress" ofType:@"tiff"];
NSString *failurePath = [[NSBundle bundleForClass:[self class]] pathForResource:@"failure" ofType:@"tiff"];
registrationDataSource = [[NSMutableArray alloc] init];
- browseDataSource = [[NSMutableArray alloc] init];
- defaultBrowseDomainsArray = [[NSMutableArray alloc] init];
successImage = [[NSImage alloc] initWithContentsOfFile:successPath];
inprogressImage = [[NSImage alloc] initWithContentsOfFile:inprogressPath];
failureImage = [[NSImage alloc] initWithContentsOfFile:failurePath];
[tabView selectFirstTabViewItem:self];
[self setupInitialValues];
- [self startDomainBrowsing];
[self watchForPreferenceChanges];
-
- InitConfigAuthority();
- err = EnsureToolInstalled();
- if (err == noErr) toolInstalled = YES;
- else { long int tmp = err; fprintf(stderr, "EnsureToolInstalled returned %ld\n", tmp); }
}
+- (void)willSelect
+{
+ [super willSelect];
+ [bonjourBrowserView startBrowse];
+ [registrationBrowserView startBrowse];
+
+}
+
+- (void)willUnselect
+{
+ [super willUnselect];
+ [bonjourBrowserView stopBrowse];
+ [registrationBrowserView stopBrowse];
+}
- (IBAction)closeMyCustomSheet:(id)sender
{
- BOOL result = [sender isEqualTo:browseOKButton] || [sender isEqualTo:secretOKButton];
+ BOOL result = [sender tag];
if (result) [NSApp endSheet:[sender window] returnCode:NSOKButton];
else [NSApp endSheet:[sender window] returnCode:NSCancelButton];
@@ -552,7 +396,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
- (void)sharedSecretSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
- NSButton * button = (NSButton *)contextInfo;
+ NSButton * button = (__bridge NSButton *)contextInfo;
[sheet orderOut:self];
[self enableControls];
@@ -587,7 +431,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
- (NSString *)trimCharactersFromDomain:(NSString *)domain
{
- NSMutableCharacterSet * trimSet = [[[NSCharacterSet whitespaceCharacterSet] mutableCopy] autorelease];
+ NSMutableCharacterSet * trimSet = [NSMutableCharacterSet whitespaceCharacterSet];
[trimSet formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]];
return [domain stringByTrimmingCharactersInSet:trimSet];
}
@@ -600,15 +444,16 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
[self enableControls];
if (returnCode == NSOKButton) {
- NSString * newBrowseDomainString = [self trimCharactersFromDomain:[browseDomainsComboBox stringValue]];
+ NSString * newBrowseDomainString;
+ if(sheet == addBrowseDomainManualWindow) newBrowseDomainString = [self trimCharactersFromDomain:[browseDomainTextField stringValue]];
+ else newBrowseDomainString = [self trimCharactersFromDomain:bonjourBrowserView.selectedDNSDomain];
NSMutableDictionary *newBrowseDomainDict;
-
if (browseDomainsArray == nil) browseDomainsArray = [[NSMutableArray alloc] initWithCapacity:0];
if ([self domainAlreadyInList:newBrowseDomainString] == NO) {
- newBrowseDomainDict = [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease];
+ newBrowseDomainDict = [[NSMutableDictionary alloc] initWithCapacity:2];
[newBrowseDomainDict setObject:newBrowseDomainString forKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
- [newBrowseDomainDict setObject:[[[NSNumber alloc] initWithBool:YES] autorelease] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY];
+ [newBrowseDomainDict setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY];
[browseDomainsArray addObject:newBrowseDomainDict];
[browseDomainsArray sortUsingFunction:MyDomainArrayCompareFunction context:nil];
@@ -618,12 +463,10 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
}
}
-
-(void)validateTextFields
{
[hostName validateEditing];
- [browseDomainsComboBox validateEditing];
- [regDomainsComboBox validateEditing];
+ [browseDomainTextField validateEditing];
}
@@ -650,11 +493,11 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
} else {
if (regSharedSecretValue) {
[sharedSecretValue setStringValue:regSharedSecretValue];
- } else if ((keyName = [self sharedSecretKeyName:[regDomainsComboBox stringValue]]) != NULL) {
+ } else if ((keyName = [self sharedSecretKeyName:regDomainView.domain]) != NULL) {
[sharedSecretName setStringValue:keyName];
[sharedSecretValue setStringValue:@"****************"];
} else {
- [sharedSecretName setStringValue:[regDomainsComboBox stringValue]];
+ [sharedSecretName setStringValue:regDomainView.domain];
[sharedSecretValue setStringValue:@""];
}
}
@@ -665,9 +508,36 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
else [sharedSecretWindow makeFirstResponder:sharedSecretName];
[NSApp beginSheet:sharedSecretWindow modalForWindow:mainWindow modalDelegate:self
- didEndSelector:@selector(sharedSecretSheetDidEnd:returnCode:contextInfo:) contextInfo:sender];
+ didEndSelector:@selector(sharedSecretSheetDidEnd:returnCode:contextInfo:) contextInfo:(__bridge void * _Null_unspecified)(sender)];
+}
+
+
+- (IBAction)selectWideAreaDomainButtonPressed:(id)sender
+{
+ NSWindow * window = (([NSEvent modifierFlags] & NSAlternateKeyMask) == NSAlternateKeyMask) ? selectRegistrationDomainManualWindow : selectRegistrationDomainWindow;
+ regDomainTextField.stringValue = regDomainView.domain;
+
+ [self disableControls];
+ [NSApp beginSheet:window modalForWindow:mainWindow modalDelegate:self
+ didEndSelector:@selector(selectWideAreaDomainSheetDidEnd:returnCode:contextInfo:) contextInfo:(__bridge void * _Null_unspecified)(sender)];
+
+ [self updateApplyButtonState];
}
+- (void)selectWideAreaDomainSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
+{
+ (void)contextInfo; // Unused
+ [sheet orderOut:self];
+ [self enableControls];
+
+ if (returnCode == NSOKButton) {
+ NSString * newRegDomainString;
+ if(sheet == selectRegistrationDomainManualWindow) newRegDomainString = [self trimCharactersFromDomain:[regDomainTextField stringValue]];
+ else newRegDomainString = [self trimCharactersFromDomain:registrationBrowserView.selectedDNSDomain];
+ regDomainView.domain = newRegDomainString;
+ [self updateApplyButtonState];
+ }
+}
- (IBAction)wideAreaCheckBoxChanged:(id)sender
{
@@ -677,10 +547,11 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
}
+
- (void)updateApplyButtonState
{
NSString *hostNameString = [hostName stringValue];
- NSString *regDomainString = [regDomainsComboBox stringValue];
+ NSString *regDomainString = regDomainView.domain;
if ((currentHostName && ([hostNameString compare:currentHostName] != NSOrderedSame)) ||
(currentRegDomain && ([regDomainString compare:currentRegDomain] != NSOrderedSame) && ([wideAreaCheckBox state])) ||
(currentHostName == nil && ([hostNameString length]) > 0) ||
@@ -697,7 +568,6 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
}
-
- (void)controlTextDidChange:(NSNotification *)notification
{
(void)notification; // Unused
@@ -705,69 +575,18 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
}
-
-- (IBAction)comboAction:(id)sender
-{
- (void)sender; // Unused
- [self updateApplyButtonState];
-}
-
-
-- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)ind
-{
- NSString *domain = nil;
- if ([aComboBox isEqualTo:browseDomainsComboBox]) domain = [browseDataSource objectAtIndex:ind];
- else if ([aComboBox isEqualTo:regDomainsComboBox]) domain = [registrationDataSource objectAtIndex:ind];
- return domain;
-}
-
-
-
-- (int)numberOfItemsInComboBox:(NSComboBox *)aComboBox
-{
- int count = 0;
- if ([aComboBox isEqualTo:browseDomainsComboBox]) count = [browseDataSource count];
- else if ([aComboBox isEqualTo:regDomainsComboBox]) count = [registrationDataSource count];
- return count;
-}
-
-
-- (NSMutableArray *)browseDataSource
-{
- return browseDataSource;
-}
-
-
- (NSMutableArray *)registrationDataSource
{
return registrationDataSource;
}
-- (NSComboBox *)browseDomainsComboBox
-{
- return browseDomainsComboBox;
-}
-
-
-- (NSComboBox *)regDomainsComboBox
-{
- return regDomainsComboBox;
-}
-
-
- (NSString *)currentRegDomain
{
return currentRegDomain;
}
-- (NSMutableArray *)defaultBrowseDomainsArray
-{
- return defaultBrowseDomainsArray;
-}
-
-
- (NSArray *)currentBrowseDomainsArray
{
return currentBrowseDomainsArray;
@@ -788,9 +607,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
- (void)setDefaultRegDomain:(NSString *)domain
{
- [defaultRegDomain release];
defaultRegDomain = domain;
- [defaultRegDomain retain];
}
@@ -800,13 +617,12 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
mainWindow = [[self mainView] window];
}
-
- (void)mainViewDidLoad
-{
+{
[comboAuthButton setString:"system.preferences"];
[comboAuthButton setDelegate:self];
- [comboAuthButton updateStatus:nil];
[comboAuthButton setAutoupdate:YES];
+ [super mainViewDidLoad];
}
@@ -821,12 +637,9 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
- (void)applyCurrentState
{
[self validateTextFields];
-
- if (toolInstalled == YES) {
- [self savePreferences];
- [self disableApplyButton];
- [mainWindow makeFirstResponder:nil];
- }
+ [self savePreferences];
+ [self disableApplyButton];
+ [mainWindow makeFirstResponder:nil];
}
@@ -849,7 +662,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
- (void)toggleWideAreaBonjour:(BOOL)state
{
[wideAreaCheckBox setState:state];
- [regDomainsComboBox setEnabled:state];
+ [registrationSelectButton setEnabled:state];
[registrationSharedSecretButton setEnabled:state];
}
@@ -871,7 +684,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
- (void)savePanelWillClose:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
(void)sheet; // Unused
- DNSServiceDiscoveryPref * me = (DNSServiceDiscoveryPref *)contextInfo;
+ DNSServiceDiscoveryPref * me = (__bridge DNSServiceDiscoveryPref *)contextInfo;
if (returnCode == NSAlertDefaultReturn) {
[me applyCurrentState];
@@ -942,7 +755,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
}
CFRelease(itemRef);
}
- return [keyName autorelease];
+ return keyName;
}
@@ -957,7 +770,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
ptr = (char *)GetNextLabel(ptr, text);
domainName = [[NSString alloc] initWithUTF8String:(const char *)ptr];
}
- return ([domainName autorelease]);
+ return (domainName);
}
@@ -967,11 +780,11 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
NSMutableDictionary *domainDict = nil;
if (domainName && [domainName length] > 0) {
- domainDict= [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease];
+ domainDict= [NSMutableDictionary dictionaryWithCapacity:2];
[domainDict setObject:domainName forKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
- [domainDict setObject:[[[NSNumber alloc] initWithBool:enabled] autorelease] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY];
+ [domainDict setObject:[NSNumber numberWithBool:enabled] forKey:(NSString *)SC_DYNDNS_ENABLED_KEY];
}
- domainsArray = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];
+ domainsArray = [NSMutableArray arrayWithCapacity:1];
if (domainDict) [domainsArray addObject:domainDict];
return [NSArchiver archivedDataWithRootObject:domainsArray];
}
@@ -983,26 +796,25 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
}
-- (NSData *)dataForSharedSecret:(NSString *)secret domain:(NSString *)domainName key:(NSString *)keyName
+- (NSDictionary *)dictionaryForSharedSecret:(NSString *)secret domain:(NSString *)domainName key:(NSString *)keyName
{
- NSMutableDictionary *sharedSecretDict = [[[NSMutableDictionary alloc] initWithCapacity:3] autorelease];
+ NSMutableDictionary *sharedSecretDict = [NSMutableDictionary dictionaryWithCapacity:3];
[sharedSecretDict setObject:secret forKey:(NSString *)SC_DYNDNS_SECRET_KEY];
[sharedSecretDict setObject:[domainName lowercaseString] forKey:(NSString *)SC_DYNDNS_DOMAIN_KEY];
[sharedSecretDict setObject:keyName forKey:(NSString *)SC_DYNDNS_KEYNAME_KEY];
- return [NSArchiver archivedDataWithRootObject:sharedSecretDict];
+ return sharedSecretDict;
}
-(void)savePreferences
{
NSString *hostNameString = [hostName stringValue];
- NSString *regDomainString = [regDomainsComboBox stringValue];
+ NSString *regDomainString = regDomainView.domain;
NSString *tempHostNameSharedSecretName = hostNameSharedSecretName;
NSString *tempRegSharedSecretName = regSharedSecretName;
- NSData *browseDomainData = nil;
BOOL regSecretWasSet = NO;
BOOL hostSecretWasSet = NO;
- OSStatus err = noErr;
+ BOOL updateHostname = NO;
hostNameString = [self trimCharactersFromDomain:hostNameString];
regDomainString = [self trimCharactersFromDomain:regDomainString];
@@ -1010,7 +822,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
tempRegSharedSecretName = [self trimCharactersFromDomain:tempRegSharedSecretName];
[hostName setStringValue:hostNameString];
- [regDomainsComboBox setStringValue:regDomainString];
+ regDomainView.domain = regDomainString;
// Convert Shared Secret account names to lowercase.
tempHostNameSharedSecretName = [tempHostNameSharedSecretName lowercaseString];
@@ -1018,46 +830,48 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
// Save hostname shared secret.
if ([hostNameSharedSecretName length] > 0 && ([hostNameSharedSecretValue length] > 0)) {
- SetKeyForDomain((CFDataRef)[self dataForSharedSecret:hostNameSharedSecretValue domain:hostNameString key:tempHostNameSharedSecretName]);
- [hostNameSharedSecretValue release];
+ DNSPrefTool_SetKeychainEntry([self dictionaryForSharedSecret:hostNameSharedSecretValue domain:hostNameString key:tempHostNameSharedSecretName]);
hostNameSharedSecretValue = nil;
hostSecretWasSet = YES;
}
// Save registration domain shared secret.
if (([regSharedSecretName length] > 0) && ([regSharedSecretValue length] > 0)) {
- SetKeyForDomain((CFDataRef)[self dataForSharedSecret:regSharedSecretValue domain:regDomainString key:tempRegSharedSecretName]);
- [regSharedSecretValue release];
+ DNSPrefTool_SetKeychainEntry([self dictionaryForSharedSecret:regSharedSecretValue domain:regDomainString key:tempRegSharedSecretName]);
regSharedSecretValue = nil;
regSecretWasSet = YES;
}
// Save hostname.
if ((currentHostName == NULL) || [currentHostName compare:hostNameString] != NSOrderedSame) {
- err = WriteHostname((CFDataRef)[self dataForDomain:hostNameString isEnabled:YES]);
- if (err != noErr) NSLog(@"WriteHostname returned %d\n", (int32_t)err);
currentHostName = [hostNameString copy];
+ updateHostname = YES;
} else if (hostSecretWasSet) {
- WriteHostname((CFDataRef)[self dataForDomain:@"" isEnabled:NO]);
- usleep(200000); // Temporary hack
- if ([currentHostName length] > 0) WriteHostname((CFDataRef)[self dataForDomain:(NSString *)currentHostName isEnabled:YES]);
+ currentHostName = @"";
+ updateHostname = YES;
+ }
+
+ if (updateHostname) {
+ [BonjourSCStore setObject: currentHostName.length ? @[@{
+ (NSString *)SC_DYNDNS_DOMAIN_KEY : currentHostName,
+ (NSString *)SC_DYNDNS_ENABLED_KEY : @YES
+ }] : nil
+ forKey: (NSString *)SC_DYNDNS_HOSTNAMES_KEY];
}
// Save browse domain.
if (browseDomainsArray && [browseDomainsArray isEqualToArray:currentBrowseDomainsArray] == NO) {
- browseDomainData = [self dataForDomainArray:browseDomainsArray];
- err = WriteBrowseDomain((CFDataRef)browseDomainData);
- if (err != noErr) NSLog(@"WriteBrowseDomain returned %d\n", (int32_t)err);
+ [BonjourSCStore setObject: browseDomainsArray forKey: (NSString *)SC_DYNDNS_BROWSEDOMAINS_KEY];
currentBrowseDomainsArray = [browseDomainsArray copy];
}
// Save registration domain.
if ((currentRegDomain == NULL) || ([currentRegDomain compare:regDomainString] != NSOrderedSame) || (currentWideAreaState != [wideAreaCheckBox state])) {
-
- err = WriteRegistrationDomain((CFDataRef)[self dataForDomain:regDomainString isEnabled:[wideAreaCheckBox state]]);
- if (err != noErr) NSLog(@"WriteRegistrationDomain returned %d\n", (int32_t)err);
-
- if (currentRegDomain) CFRelease(currentRegDomain);
+ [BonjourSCStore setObject: @[@{
+ (NSString *)SC_DYNDNS_DOMAIN_KEY : regDomainString,
+ (NSString *)SC_DYNDNS_ENABLED_KEY : [wideAreaCheckBox state] ? @YES : @NO
+ }]
+ forKey: (NSString *)SC_DYNDNS_REGDOMAINS_KEY];
currentRegDomain = [regDomainString copy];
if ([currentRegDomain length] > 0) {
@@ -1065,16 +879,25 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
[registrationDataSource removeObject:regDomainString];
[registrationDataSource addObject:currentRegDomain];
[registrationDataSource sortUsingFunction:MyArrayCompareFunction context:nil];
- [regDomainsComboBox reloadData];
+ // [regDomainsComboBox reloadData];
} else {
currentWideAreaState = NO;
[self toggleWideAreaBonjour:NO];
- if (defaultRegDomain != nil) [regDomainsComboBox setStringValue:defaultRegDomain];
+ if (defaultRegDomain != nil) regDomainView.domain = defaultRegDomain;
}
} else if (regSecretWasSet) {
- WriteRegistrationDomain((CFDataRef)[self dataForDomain:@"" isEnabled:NO]);
- usleep(200000); // Temporary hack
- if ([currentRegDomain length] > 0) WriteRegistrationDomain((CFDataRef)[self dataForDomain:currentRegDomain isEnabled:currentWideAreaState]);
+ [BonjourSCStore setObject: @[@{
+ (NSString *)SC_DYNDNS_DOMAIN_KEY : @"",
+ (NSString *)SC_DYNDNS_ENABLED_KEY : @NO
+ }]
+ forKey: (NSString *)SC_DYNDNS_REGDOMAINS_KEY];
+ if ([currentRegDomain length] > 0) {
+ [BonjourSCStore setObject: @[@{
+ (NSString *)SC_DYNDNS_DOMAIN_KEY : currentRegDomain,
+ (NSString *)SC_DYNDNS_ENABLED_KEY : currentWideAreaState ? @YES : @NO
+ }]
+ forKey: (NSString *)SC_DYNDNS_REGDOMAINS_KEY];
+ }
}
}
@@ -1095,7 +918,7 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
self,
@selector( savePanelWillClose:returnCode:contextInfo: ),
NULL,
- (void *) self, // sender,
+ (__bridge void *) self, // sender,
@"" );
return NSUnselectLater;
}
@@ -1109,11 +932,10 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
{
[hostName setEnabled:NO];
[hostNameSharedSecretButton setEnabled:NO];
- [browseDomainsComboBox setEnabled:NO];
[applyButton setEnabled:NO];
[revertButton setEnabled:NO];
[wideAreaCheckBox setEnabled:NO];
- [regDomainsComboBox setEnabled:NO];
+ [registrationSelectButton setEnabled: NO];
[registrationSharedSecretButton setEnabled:NO];
[statusImageView setEnabled:NO];
@@ -1138,8 +960,8 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
{
[hostName setEnabled:YES];
[hostNameSharedSecretButton setEnabled:YES];
- [browseDomainsComboBox setEnabled:YES];
[wideAreaCheckBox setEnabled:YES];
+ [registrationSelectButton setEnabled: YES];
[registrationSharedSecretButton setEnabled:YES];
[self toggleWideAreaBonjour:[wideAreaCheckBox state]];
[statusImageView setEnabled:YES];
@@ -1157,14 +979,14 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
- (void)authorizationViewDidAuthorize:(SFAuthorizationView *)view
{
- (void)view; // Unused
+ (void)view; // unused
[self enableControls];
}
- (void)authorizationViewDidDeauthorize:(SFAuthorizationView *)view
{
- (void)view; // Unused
+ (void)view; // unused
[self disableControls];
}
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/classes.nib b/mDNSResponder/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/classes.nib
deleted file mode 100644
index 58c1f3e5..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/classes.nib
+++ /dev/null
@@ -1,59 +0,0 @@
-{
- IBClasses = (
- {
- ACTIONS = {
- addBrowseDomainClicked = id;
- applyClicked = id;
- changeButtonPressed = id;
- closeMyCustomSheet = id;
- comboAction = id;
- enableBrowseDomainClicked = id;
- removeBrowseDomainClicked = id;
- revertClicked = id;
- wideAreaCheckBoxChanged = id;
- };
- CLASS = DNSServiceDiscoveryPref;
- LANGUAGE = ObjC;
- OUTLETS = {
- addBrowseDomainButton = NSButton;
- addBrowseDomainWindow = NSWindow;
- applyButton = NSButton;
- browseCancelButton = NSButton;
- browseDomainList = NSTableView;
- browseDomainsComboBox = NSComboBox;
- browseOKButton = NSButton;
- comboAuthButton = SFAuthorizationView;
- hostName = NSTextField;
- hostNameSharedSecretButton = NSButton;
- regDomainsComboBox = NSComboBox;
- registrationSharedSecretButton = NSButton;
- removeBrowseDomainButton = NSButton;
- revertButton = NSButton;
- secretCancelButton = NSButton;
- secretOKButton = NSButton;
- sharedSecretName = NSTextField;
- sharedSecretValue = NSSecureTextField;
- sharedSecretWindow = NSWindow;
- statusImageView = NSImageView;
- tabView = NSTabView;
- wideAreaCheckBox = NSButton;
- };
- SUPERCLASS = NSPreferencePane;
- },
- {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
- {
- CLASS = NSPreferencePane;
- LANGUAGE = ObjC;
- OUTLETS = {
- "_firstKeyView" = id;
- "_initialKeyView" = id;
- "_lastKeyView" = id;
- "_window" = id;
- };
- SUPERCLASS = NSObject;
- },
- {CLASS = NSSegmentedControl; LANGUAGE = ObjC; SUPERCLASS = NSControl; },
- {CLASS = SFAuthorizationView; LANGUAGE = ObjC; SUPERCLASS = NSView; }
- );
- IBVersion = 1;
-} \ No newline at end of file
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/info.nib b/mDNSResponder/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/info.nib
deleted file mode 100644
index e8dbd926..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/info.nib
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>IBDocumentLocation</key>
- <string>32 63 547 281 0 0 1024 746 </string>
- <key>IBFramework Version</key>
- <string>439.0</string>
- <key>IBOpenObjects</key>
- <array>
- <integer>255</integer>
- <integer>333</integer>
- <integer>12</integer>
- </array>
- <key>IBSystem Version</key>
- <string>8F23</string>
-</dict>
-</plist>
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib b/mDNSResponder/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib
deleted file mode 100644
index eec01ee4..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib/keyedobjects.nib
+++ /dev/null
Binary files differ
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/Info-PreferencePane.plist b/mDNSResponder/mDNSMacOSX/PreferencePane/Info-PreferencePane.plist
index e5cdb9f2..134a7647 100644
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/Info-PreferencePane.plist
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/Info-PreferencePane.plist
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
@@ -32,5 +32,7 @@
<string>Bonjour</string>
<key>NSPrincipalClass</key>
<string>DNSServiceDiscoveryPref</string>
+ <key>NSPrefPaneRemoteViewClass</key>
+ <string>BonjourPrefRemoteViewService</string>
</dict>
</plist>
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c b/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c
deleted file mode 100644
index a279c983..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- File: PrivilegedOperations.c
-
- Abstract: Interface to "ddnswriteconfig" setuid root tool.
-
- Copyright: (c) Copyright 2005-2015 Apple Inc. All rights reserved.
-
- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms. If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under Apple's
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software. Neither the name, trademarks, service marks or logos of
- Apple Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "PrivilegedOperations.h"
-#include "ConfigurationAuthority.h"
-#include <CoreFoundation/CoreFoundation.h>
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <spawn.h>
-#include <sys/wait.h>
-#include <AssertMacros.h>
-#include <Security/Security.h>
-
-extern char **environ;
-Boolean gToolApproved = false;
-
-static pid_t execTool(const char *args[])
-{
- pid_t child;
-
- int err = posix_spawn(&child, args[0], NULL, NULL, (char *const *)args, environ);
- if (err)
- {
- printf("exec of %s failed; err = %d\n", args[0], err);
- return -1;
- }
- else
- return child;
-}
-
-OSStatus EnsureToolInstalled(void)
-// Make sure that the tool is installed in the right place, with the right privs, and the right version.
-{
- CFURLRef bundleURL;
- pid_t toolPID;
- int status = 0;
- OSStatus err = noErr;
- const char *args[] = { kToolPath, "0", "V", NULL };
- char toolSourcePath[PATH_MAX] = {};
- char toolInstallerPath[PATH_MAX] = {};
-
- if (gToolApproved)
- return noErr;
-
- // Check version of installed tool
- toolPID = execTool(args);
- if (toolPID > 0)
- {
- waitpid(toolPID, &status, 0);
- if (WIFEXITED(status) && WEXITSTATUS(status) == PRIV_OP_TOOL_VERS)
- return noErr;
- }
-
- // Locate our in-bundle copy of privop tool
- bundleURL = CFBundleCopyBundleURL(CFBundleGetBundleWithIdentifier(CFSTR("com.apple.preference.bonjour")) );
- if (bundleURL != NULL)
- {
- CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolSourcePath, sizeof toolSourcePath);
- CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolInstallerPath, sizeof toolInstallerPath);
- CFRelease(bundleURL);
-
- if (strlcat(toolSourcePath, "/Contents/Resources/" kToolName, sizeof toolSourcePath ) >= sizeof toolSourcePath ) return(-1);
- if (strlcat(toolInstallerPath, "/Contents/Resources/" kToolInstaller, sizeof toolInstallerPath) >= sizeof toolInstallerPath) return(-1);
- }
- else
- return coreFoundationUnknownErr;
-
- // Obtain authorization and run in-bundle copy as root to install it
- {
- AuthorizationItem aewpRight = { kAuthorizationRightExecute, strlen(toolInstallerPath), toolInstallerPath, 0 };
- AuthorizationItemSet rights = { 1, &aewpRight };
- AuthorizationRef authRef;
-
- err = AuthorizationCreate(&rights, (AuthorizationEnvironment*) NULL,
- kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights |
- kAuthorizationFlagPreAuthorize, &authRef);
- if (err == noErr)
- {
- char *installerargs[] = { toolSourcePath, NULL };
- err = AuthorizationExecuteWithPrivileges(authRef, toolInstallerPath, 0, installerargs, (FILE**) NULL);
- if (err == noErr)
- {
- int pid = wait(&status);
- if (pid > 0 && WIFEXITED(status))
- {
- err = WEXITSTATUS(status);
- if (err == noErr)
- {
- gToolApproved = true;
- }
- } else {
- err = -1;
- }
- }
- (void) AuthorizationFree(authRef, kAuthorizationFlagDefaults);
- }
- }
-
- return err;
-}
-
-
-static OSStatus ExecWithCmdAndParam(const char *subCmd, CFDataRef paramData)
-// Execute our privop tool with the supplied subCmd and parameter
-{
- OSStatus err = noErr;
- int commFD, dataLen;
- u_int32_t len;
- pid_t child;
- char fileNum[16];
- UInt8 *buff;
- const char *args[] = { kToolPath, NULL, "A", NULL, NULL };
- AuthorizationExternalForm authExt;
-
- err = ExternalizeAuthority(&authExt);
- require_noerr(err, AuthFailed);
-
- dataLen = CFDataGetLength(paramData);
- buff = (UInt8*) malloc(dataLen * sizeof(UInt8));
- require_action(buff != NULL, AllocBuffFailed, err=memFullErr;);
- {
- CFRange all = { 0, dataLen };
- CFDataGetBytes(paramData, all, buff);
- }
-
- commFD = fileno(tmpfile());
- snprintf(fileNum, sizeof(fileNum), "%d", commFD);
- args[1] = fileNum;
- args[3] = subCmd;
-
- // write authority to pipe
- len = 0; // tag, unused
- write(commFD, &len, sizeof len);
- len = sizeof authExt; // len
- write(commFD, &len, sizeof len);
- write(commFD, &authExt, len);
-
- // write parameter to pipe
- len = 0; // tag, unused
- write(commFD, &len, sizeof len);
- len = dataLen; // len
- write(commFD, &len, sizeof len);
- write(commFD, buff, len);
-
- child = execTool(args);
- if (child > 0)
- {
- int status = 0;
- waitpid(child, &status, 0);
- if (WIFEXITED(status))
- err = WEXITSTATUS(status);
- //fprintf(stderr, "child exited; status = %d (%ld)\n", status, err);
- }
-
- close(commFD);
-
- free(buff);
-AllocBuffFailed:
-AuthFailed:
- return err;
-}
-
-OSStatus
-WriteBrowseDomain(CFDataRef domainArrayData)
-{
- if (!CurrentlyAuthorized())
- return authFailErr;
- return ExecWithCmdAndParam("Wb", domainArrayData);
-}
-
-OSStatus
-WriteRegistrationDomain(CFDataRef domainArrayData)
-{
- if (!CurrentlyAuthorized())
- return authFailErr;
- return ExecWithCmdAndParam("Wd", domainArrayData);
-}
-
-OSStatus
-WriteHostname(CFDataRef domainArrayData)
-{
- if (!CurrentlyAuthorized())
- return authFailErr;
- return ExecWithCmdAndParam("Wh", domainArrayData);
-}
-
-OSStatus
-SetKeyForDomain(CFDataRef secretData)
-{
- if (!CurrentlyAuthorized())
- return authFailErr;
- return ExecWithCmdAndParam("Wk", secretData);
-}
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.h b/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.h
deleted file mode 100644
index 91a60daf..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/PrivilegedOperations.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- File: PrivilegedOperations.h
-
- Abstract: Interface to "ddnswriteconfig" setuid root tool.
-
- Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
-
- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms. If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under Apple's
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software. Neither the name, trademarks, service marks or logos of
- Apple Computer, Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <CoreServices/CoreServices.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-#define PRIV_OP_TOOL_VERS 4
-
-#define kToolName "ddnswriteconfig"
-#define kToolPath "/Library/Application Support/Bonjour/" kToolName
-#define kToolInstaller "installtool"
-
-#define SC_DYNDNS_SETUP_KEY CFSTR("Setup:/Network/DynamicDNS")
-#define SC_DYNDNS_STATE_KEY CFSTR("State:/Network/DynamicDNS")
-#define SC_DYNDNS_REGDOMAINS_KEY CFSTR("RegistrationDomains")
-#define SC_DYNDNS_BROWSEDOMAINS_KEY CFSTR("BrowseDomains")
-#define SC_DYNDNS_HOSTNAMES_KEY CFSTR("HostNames")
-#define SC_DYNDNS_DOMAIN_KEY CFSTR("Domain")
-#define SC_DYNDNS_KEYNAME_KEY CFSTR("KeyName")
-#define SC_DYNDNS_SECRET_KEY CFSTR("Secret")
-#define SC_DYNDNS_ENABLED_KEY CFSTR("Enabled")
-#define SC_DYNDNS_STATUS_KEY CFSTR("Status")
-#define DYNDNS_KEYCHAIN_DESCRIPTION "Dynamic DNS Key"
-
-
-OSStatus EnsureToolInstalled(void);
-OSStatus WriteRegistrationDomain(CFDataRef domainArrayData);
-OSStatus WriteBrowseDomain(CFDataRef domainArrayData);
-OSStatus WriteHostname(CFDataRef domainArrayData);
-OSStatus SetKeyForDomain(CFDataRef secretData);
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService-Info.plist b/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService-Info.plist
new file mode 100644
index 00000000..0e72660a
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService-Info.plist
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>XPC!</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>CFBundleVisibleComponentName</key>
+ <string>$(CFBundleVisibleComponentName)</string>
+ <key>LSBackgroundOnly</key>
+ <true/>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright © 2015 Apple Inc. All rights reserved.</string>
+ <key>NSPreferencePaneBundle</key>
+ <string>Bonjour</string>
+ <key>NSPrincipalClass</key>
+ <string>NSViewServiceApplication</string>
+ <key>XPCService</key>
+ <dict>
+ <key>JoinExistingSession</key>
+ <true/>
+ <key>RunLoopType</key>
+ <string>_NSApplicationMain</string>
+ </dict>
+</dict>
+</plist>
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService.h b/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService.h
new file mode 100644
index 00000000..3f063e36
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService.h
@@ -0,0 +1,22 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <ViewBridge/NSViewService.h>
+#import <PreferencePanes/NSPrefRemoteViewService.h>
+
+@interface BonjourPrefRemoteViewService : NSPrefRemoteViewService
+@end
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService.m b/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService.m
new file mode 100644
index 00000000..821c6617
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService.m
@@ -0,0 +1,21 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "BonjourPrefRemoteViewService.h"
+
+@implementation BonjourPrefRemoteViewService
+@end
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/InfoPlist.strings b/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/InfoPlist.strings
new file mode 100644
index 00000000..d9d85419
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/InfoPlist.strings
@@ -0,0 +1,3 @@
+/* Localized versions of Info.plist keys */
+
+CFBundleVisibleComponentName = "System Preferences";
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/entitlements.plist b/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/entitlements.plist
new file mode 100644
index 00000000..7017a781
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/entitlements.plist
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.SystemConfiguration.SCPreferences-write-access</key>
+ <array>
+ <string>preferences.plist</string>
+ </array>
+</dict>
+</plist>
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/main.m b/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/main.m
new file mode 100644
index 00000000..e503647a
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/PreferencePane/RemoteViewService/main.m
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import <PreferencePanes/PreferencePaneXPCMain.h>
+
+int
+main(int inArgc, const char *inArgv[])
+{
+ int result = 0;
+
+ @autoreleasepool
+ {
+ @try
+ {
+ result = PreferencePaneMain(inArgc, inArgv);
+ }
+ @catch(NSException * e)
+ {
+ NSLog(@"%s caught %@: '%@' with user dictionary %@ and call stack %@", __func__, [e name], [e reason], [e userInfo], [e callStackSymbols]);
+ result = 1;
+ }
+ }
+
+ return result;
+}
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/ddnswriteconfig.m b/mDNSResponder/mDNSMacOSX/PreferencePane/ddnswriteconfig.m
deleted file mode 100644
index 8e64fc46..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/ddnswriteconfig.m
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- File: ddnswriteconfig.m
-
- Abstract: Setuid root tool invoked by Preference Pane to perform
- privileged accesses to system configuration preferences and the system keychain.
- Invoked by PrivilegedOperations.c.
-
- Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
-
- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms. If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under Apple's
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software. Neither the name, trademarks, service marks or logos of
- Apple Computer, Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#import "PrivilegedOperations.h"
-#import "ConfigurationRights.h"
-
-#import <stdio.h>
-#import <stdint.h>
-#import <stdlib.h>
-#import <unistd.h>
-#import <fcntl.h>
-#import <errno.h>
-#import <sys/types.h>
-#import <sys/stat.h>
-#import <sys/mman.h>
-#import <mach-o/dyld.h>
-#import <dns_sd.h>
-#import <AssertMacros.h>
-#import <Security/Security.h>
-#import <CoreServices/CoreServices.h>
-#import <CoreFoundation/CoreFoundation.h>
-#import <SystemConfiguration/SystemConfiguration.h>
-#import <Foundation/Foundation.h>
-
-
-static AuthorizationRef gAuthRef = 0;
-
-static OSStatus
-WriteArrayToDynDNS(CFStringRef arrayKey, CFArrayRef domainArray)
-{
- SCPreferencesRef store;
- OSStatus err = noErr;
- CFDictionaryRef origDict;
- CFMutableDictionaryRef dict = NULL;
- Boolean result;
- CFStringRef scKey = CFSTR("/System/Network/DynamicDNS");
-
-
- // Add domain to the array member ("arrayKey") of the DynamicDNS dictionary
- // Will replace duplicate, at head of list
- // At this point, we only support a single-item list
- store = SCPreferencesCreate(NULL, CFSTR("com.apple.preference.bonjour"), NULL);
- require_action(store != NULL, SysConfigErr, err=paramErr;);
- require_action(true == SCPreferencesLock( store, true), LockFailed, err=coreFoundationUnknownErr;);
-
- origDict = SCPreferencesPathGetValue(store, scKey);
- if (origDict)
- {
- dict = CFDictionaryCreateMutableCopy(NULL, 0, origDict);
- }
-
- if (!dict)
- {
- dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- }
- require_action( dict != NULL, NoDict, err=memFullErr;);
-
- if (CFArrayGetCount(domainArray) > 0)
- {
- CFDictionarySetValue(dict, arrayKey, domainArray);
- }
- else
- {
- CFDictionaryRemoveValue(dict, arrayKey);
- }
-
- result = SCPreferencesPathSetValue(store, scKey, dict);
- require_action(result, SCError, err=kernelPrivilegeErr;);
-
- result = SCPreferencesCommitChanges(store);
- require_action(result, SCError, err=kernelPrivilegeErr;);
- result = SCPreferencesApplyChanges(store);
- require_action(result, SCError, err=kernelPrivilegeErr;);
-
-SCError:
- CFRelease(dict);
-NoDict:
- SCPreferencesUnlock(store);
-LockFailed:
- CFRelease(store);
-SysConfigErr:
- return err;
-}
-
-
-static int
-readTaggedBlock(int fd, u_int32_t *pTag, u_int32_t *pLen, char **ppBuff)
-// Read tag, block len and block data from stream and return. Dealloc *ppBuff via free().
-{
- ssize_t num;
- u_int32_t tag, len; // Don't use ssize_t because that's different on 32- vs. 64-bit
- int result = 0;
-
- num = read(fd, &tag, sizeof tag);
- require_action(num == sizeof tag, GetTagFailed, result = -1;);
- num = read(fd, &len, sizeof len);
- require_action(num == sizeof len, GetLenFailed, result = -1;);
-
- *ppBuff = (char*) malloc( len);
- require_action(*ppBuff != NULL, AllocFailed, result = -1;);
-
- num = read(fd, *ppBuff, len);
- if (num == (ssize_t)len)
- {
- *pTag = tag;
- *pLen = len;
- }
- else
- {
- free(*ppBuff);
- result = -1;
- }
-
-AllocFailed:
-GetLenFailed:
-GetTagFailed:
- return result;
-}
-
-
-
-static int
-SetAuthInfo( int fd)
-{
- int result = 0;
- u_int32_t tag, len;
- char *p;
-
- result = readTaggedBlock( fd, &tag, &len, &p);
- require( result == 0, ReadParamsFailed);
- require( len == sizeof(AuthorizationExternalForm), ReadParamsFailed);
- require( len == kAuthorizationExternalFormLength, ReadParamsFailed);
-
- if (gAuthRef != 0)
- {
- (void) AuthorizationFree(gAuthRef, kAuthorizationFlagDefaults);
- gAuthRef = 0;
- }
-
- result = AuthorizationCreateFromExternalForm((AuthorizationExternalForm*) p, &gAuthRef);
-
- free( p);
-ReadParamsFailed:
- return result;
-}
-
-
-static int
-HandleWriteDomain(int fd, int domainType)
-{
- CFArrayRef domainArray;
- CFDataRef domainData;
- int result = 0;
- u_int32_t tag, len;
- char *p;
-
- AuthorizationItem scAuth = { UPDATE_SC_RIGHT, 0, NULL, 0 };
- AuthorizationRights authSet = { 1, &scAuth };
-
- if (noErr != (result = AuthorizationCopyRights(gAuthRef, &authSet, NULL, (AuthorizationFlags)0, NULL)))
- return result;
-
- result = readTaggedBlock(fd, &tag, &len, &p);
- require(result == 0, ReadParamsFailed);
-
- domainData = CFDataCreate(NULL, (UInt8 *)p, len);
- domainArray = (CFArrayRef)[NSUnarchiver unarchiveObjectWithData:(NSData *)domainData];
- CFRelease(domainData);
- free(p);
-
- if (domainType)
- {
- result = WriteArrayToDynDNS(SC_DYNDNS_REGDOMAINS_KEY, domainArray);
- }
- else
- {
- result = WriteArrayToDynDNS(SC_DYNDNS_BROWSEDOMAINS_KEY, domainArray);
- }
-
-ReadParamsFailed:
- return result;
-}
-
-
-static int
-HandleWriteHostname(int fd)
-{
- CFArrayRef domainArray;
- CFDataRef domainData;
- int result = 0;
- u_int32_t tag, len;
- char *p;
-
- AuthorizationItem scAuth = { UPDATE_SC_RIGHT, 0, NULL, 0 };
- AuthorizationRights authSet = { 1, &scAuth };
-
- if (noErr != (result = AuthorizationCopyRights(gAuthRef, &authSet, NULL, (AuthorizationFlags) 0, NULL)))
- return result;
-
- result = readTaggedBlock(fd, &tag, &len, &p);
- require(result == 0, ReadParamsFailed);
-
- domainData = CFDataCreate(NULL, (const UInt8 *)p, len);
- domainArray = (CFArrayRef)[NSUnarchiver unarchiveObjectWithData:(NSData *)domainData];
- result = WriteArrayToDynDNS(SC_DYNDNS_HOSTNAMES_KEY, domainArray);
- CFRelease(domainData);
- free(p);
-
-ReadParamsFailed:
- return result;
-}
-
-
-static SecAccessRef
-MyMakeUidAccess(uid_t uid)
-{
- // make the "uid/gid" ACL subject
- // this is a CSSM_LIST_ELEMENT chain
- CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = {
- CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION, // selector version
- CSSM_ACL_MATCH_UID, // set mask: match uids (only)
- uid, // uid to match
- 0 // gid (not matched here)
- };
- CSSM_LIST_ELEMENT subject2 = { NULL, 0, 0, {{0,0,0}} };
- subject2.Element.Word.Data = (UInt8 *)&selector;
- subject2.Element.Word.Length = sizeof(selector);
- CSSM_LIST_ELEMENT subject1 = { &subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID, {{0,0,0}} };
-
-
- // rights granted (replace with individual list if desired)
- CSSM_ACL_AUTHORIZATION_TAG rights[] = {
- CSSM_ACL_AUTHORIZATION_ANY // everything
- };
- // owner component (right to change ACL)
- CSSM_ACL_OWNER_PROTOTYPE owner = {
- // TypedSubject
- { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
- // Delegate
- false
- };
- // ACL entries (any number, just one here)
- CSSM_ACL_ENTRY_INFO acls =
- {
- // CSSM_ACL_ENTRY_PROTOTYPE
- {
- { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, // TypedSubject
- false, // Delegate
- { sizeof(rights) / sizeof(rights[0]), rights }, // Authorization rights for this entry
- { { 0, 0 }, { 0, 0 } }, // CSSM_ACL_VALIDITY_PERIOD
- "" // CSSM_STRING EntryTag
- },
- // CSSM_ACL_HANDLE
- 0
- };
-
- SecAccessRef a = NULL;
- (void) SecAccessCreateFromOwnerAndACL(&owner, 1, &acls, &a);
- return a;
-}
-
-
-static OSStatus
-MyAddDynamicDNSPassword(SecKeychainRef keychain, SecAccessRef a, UInt32 serviceNameLength, const char *serviceName,
- UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData)
-{
- char * description = DYNDNS_KEYCHAIN_DESCRIPTION;
- UInt32 descriptionLength = strlen(DYNDNS_KEYCHAIN_DESCRIPTION);
- UInt32 type = 'ddns';
- UInt32 creator = 'ddns';
- UInt32 typeLength = sizeof(type);
- UInt32 creatorLength = sizeof(creator);
- OSStatus err;
-
- // set up attribute vector (each attribute consists of {tag, length, pointer})
- SecKeychainAttribute attrs[] = { { kSecLabelItemAttr, serviceNameLength, (char *)serviceName },
- { kSecAccountItemAttr, accountNameLength, (char *)accountName },
- { kSecServiceItemAttr, serviceNameLength, (char *)serviceName },
- { kSecDescriptionItemAttr, descriptionLength, (char *)description },
- { kSecTypeItemAttr, typeLength, (UInt32 *)&type },
- { kSecCreatorItemAttr, creatorLength, (UInt32 *)&creator } };
- SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
-
- err = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &attributes, passwordLength, passwordData, keychain, a, NULL);
- return err;
-}
-
-
-static int
-SetKeychainEntry(int fd)
-// Create a new entry in system keychain, or replace existing
-{
- CFDataRef secretData;
- CFDictionaryRef secretDictionary;
- CFStringRef keyNameString;
- CFStringRef domainString;
- CFStringRef secretString;
- SecKeychainItemRef item = NULL;
- int result = 0;
- u_int32_t tag, len;
- char *p;
- char keyname[kDNSServiceMaxDomainName];
- char domain[kDNSServiceMaxDomainName];
- char secret[kDNSServiceMaxDomainName];
-
- AuthorizationItem kcAuth = { EDIT_SYS_KEYCHAIN_RIGHT, 0, NULL, 0 };
- AuthorizationRights authSet = { 1, &kcAuth };
-
- if (noErr != (result = AuthorizationCopyRights(gAuthRef, &authSet, NULL, (AuthorizationFlags)0, NULL)))
- return result;
-
- result = readTaggedBlock(fd, &tag, &len, &p);
- require_noerr(result, ReadParamsFailed);
-
- secretData = CFDataCreate(NULL, (UInt8 *)p, len);
- secretDictionary = (CFDictionaryRef)[NSUnarchiver unarchiveObjectWithData:(NSData *)secretData];
- CFRelease(secretData);
- free(p);
-
- keyNameString = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_KEYNAME_KEY);
- assert(keyNameString != NULL);
-
- domainString = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_DOMAIN_KEY);
- assert(domainString != NULL);
-
- secretString = (CFStringRef)CFDictionaryGetValue(secretDictionary, SC_DYNDNS_SECRET_KEY);
- assert(secretString != NULL);
-
- CFStringGetCString(keyNameString, keyname, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
- CFStringGetCString(domainString, domain, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
- CFStringGetCString(secretString, secret, kDNSServiceMaxDomainName, kCFStringEncodingUTF8);
-
- result = SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
- if (result == noErr)
- {
- result = SecKeychainFindGenericPassword(NULL, strlen(domain), domain, 0, NULL, 0, NULL, &item);
- if (result == noErr)
- {
- result = SecKeychainItemDelete(item);
- if (result != noErr) fprintf(stderr, "SecKeychainItemDelete returned %d\n", result);
- }
-
- result = MyAddDynamicDNSPassword(NULL, MyMakeUidAccess(0), strlen(domain), domain, strlen(keyname)+1, keyname, strlen(secret)+1, secret);
- if (result != noErr) fprintf(stderr, "MyAddDynamicDNSPassword returned %d\n", result);
- if (item) CFRelease(item);
- }
-
-ReadParamsFailed:
- return result;
-}
-
-
-int main( int argc, char **argv)
-/* argv[0] is the exec path; argv[1] is a fd for input data; argv[2]... are operation codes.
- The tool supports the following operations:
- V -- exit with status PRIV_OP_TOOL_VERS
- A -- read AuthInfo from input pipe
- Wd -- write registration domain to dynamic store
- Wb -- write browse domain to dynamic store
- Wh -- write hostname to dynamic store
- Wk -- write keychain entry for given account name
-*/
-{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- int commFD = -1, iArg, result = 0;
-
- if ( 0 != seteuid( 0))
- return -1;
-
- if ( argc == 3 && 0 == strcmp( argv[2], "V"))
- return PRIV_OP_TOOL_VERS;
-
- if ( argc > 1)
- {
- commFD = strtol( argv[1], NULL, 0);
- lseek( commFD, 0, SEEK_SET);
- }
- for ( iArg = 2; iArg < argc && result == 0; iArg++)
- {
- if ( 0 == strcmp( "A", argv[ iArg])) // get auth info
- {
- result = SetAuthInfo( commFD);
- }
- else if ( 0 == strcmp( "Wd", argv[ iArg])) // Write registration domain
- {
- result = HandleWriteDomain( commFD, 1);
- }
- else if ( 0 == strcmp( "Wb", argv[ iArg])) // Write browse domain
- {
- result = HandleWriteDomain( commFD, 0);
- }
- else if ( 0 == strcmp( "Wh", argv[ iArg])) // Write hostname
- {
- result = HandleWriteHostname( commFD);
- }
- else if ( 0 == strcmp( "Wk", argv[ iArg])) // Write keychain entry
- {
- result = SetKeychainEntry( commFD);
- }
- }
- [pool release];
- return result;
-}
-
-// Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion
-// e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4"
-// To expand "version" to its value before making the string, use STRINGIFY(version) instead
-#define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) #s
-#define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s)
-
-// NOT static -- otherwise the compiler may optimize it out
-// The "@(#) " pattern is a special prefix the "what" command looks for
-const char VersionString_SCCS[] = "@(#) ddnswriteconfig " STRINGIFY(mDNSResponderVersion) " (" __DATE__ " " __TIME__ ")";
-
-#if _BUILDING_XCODE_PROJECT_
-// If the process crashes, then this string will be magically included in the automatically-generated crash log
-const char *__crashreporter_info__ = VersionString_SCCS + 5;
-asm(".desc ___crashreporter_info__, 0x10");
-#endif
diff --git a/mDNSResponder/mDNSMacOSX/PreferencePane/installtool b/mDNSResponder/mDNSMacOSX/PreferencePane/installtool
deleted file mode 100755
index ce341c87..00000000
--- a/mDNSResponder/mDNSMacOSX/PreferencePane/installtool
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/perl
-# Emacs settings: -*- tab-width: 4 -*-
-#
-# File: installtool
-#
-# Abstract: Copy "ddnswriteconfig" to Application Support and make it setuid root.
-#
-# Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved.
-#
-# Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
-# ("Apple") in consideration of your agreement to the following terms, and your
-# use, installation, modification or redistribution of this Apple software
-# constitutes acceptance of these terms. If you do not agree with these terms,
-# please do not use, install, modify or redistribute this Apple software.
-#
-# In consideration of your agreement to abide by the following terms, and subject
-# to these terms, Apple grants you a personal, non-exclusive license, under Apple's
-# copyrights in this original Apple software (the "Apple Software"), to use,
-# reproduce, modify and redistribute the Apple Software, with or without
-# modifications, in source and/or binary forms; provided that if you redistribute
-# the Apple Software in its entirety and without modifications, you must retain
-# this notice and the following text and disclaimers in all such redistributions of
-# the Apple Software. Neither the name, trademarks, service marks or logos of
-# Apple Computer, Inc. may be used to endorse or promote products derived from the
-# Apple Software without specific prior written permission from Apple. Except as
-# expressly stated in this notice, no other rights or licenses, express or implied,
-# are granted by Apple herein, including but not limited to any patent rights that
-# may be infringed by your derivative works or by other works in which the Apple
-# Software may be incorporated.
-#
-# The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
-# WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
-# WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-# COMBINATION WITH YOUR PRODUCTS.
-#
-# IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-# OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
-# (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
-# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Create the Bonjour subdirectory.
-# Copy ARGV[0] to $dest and set owner and suid permissions.
-#
-# This script will be run as root by the AEWP trampoline.
-#
-
-use File::Temp qw/ :mktemp /;
-
-$dest_dir = "/Library/Application Support/Bonjour";
-$dest = $dest_dir . "/ddnswriteconfig";
-
-$template = ".XXXXXX";
-
-# Perl seems to think this code is running setuid root, so it applies its security checks.
-# See <http://www.monster-submit.com/resources/docs/pod/perlsec.html>.
-# In fact this is NOT a setuid script. It is a normal unprivileged user-level script --
-# but it is run as root when properly authorized by a user with an admin password,
-# via the AuthorizationExecuteWithPrivileges() call.
-# We therefore have to do this trick pattern match to 'untaint' the source file specified in $ARGV[0].
-if ($ARGV[0] =~ /^(.+)$/) { $src = $1; }
-
-# Also clear $ENV{PATH} so we don't get "Insecure $ENV{PATH}" fatal errors
-$ENV{PATH} = "";
-
-if (! -d $dest_dir) {
- $dest_tmp_dir = mkdtemp ($dest_dir . $template);
- (chown 0, 80, $dest_tmp_dir) or cleanup_dir();
- (chmod 0755, $dest_tmp_dir) or cleanup_dir();
- (rename $dest_tmp_dir, $dest_dir) or cleanup_dir();
-}
-
-$dest_tmp = mktemp ($dest . $template);
-
-if ($src ne '') {
- system ('/bin/cp', '-f', $src, $dest_tmp) and cleanup();
- (chown 0, 80, $dest_tmp) or cleanup();
- (chmod 04555, $dest_tmp) or cleanup();
- (rename $dest_tmp, $dest) or cleanup();
-}
-exit (0);
-
-sub cleanup {
- unlink $dest_tmp;
- exit (1);
-}
-
-sub cleanup_dir {
- unlink $dest_tmp_dir;
- exit (1);
-}
diff --git a/mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h b/mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h
deleted file mode 100644
index f3b480ea..00000000
--- a/mDNSResponder/mDNSMacOSX/Private/dns_sd_private.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2015 Apple Inc. All rights reserved.
- */
-
-#ifndef _DNS_SD_PRIVATE_H
-#define _DNS_SD_PRIVATE_H
-
-/* DNSServiceCreateDelegateConnection()
- *
- * Parameters:
- *
- * sdRef: A pointer to an uninitialized DNSServiceRef. Deallocating
- * the reference (via DNSServiceRefDeallocate()) severs the
- * connection and deregisters all records registered on this connection.
- *
- * pid : Process ID of the delegate
- *
- * uuid: UUID of the delegate
- *
- * Note that only one of the two arguments (pid or uuid) can be specified. If pid
- * is zero, uuid will be assumed to be a valid value; otherwise pid will be used.
- *
- * return value: Returns kDNSServiceErr_NoError on success, otherwise returns
- * an error code indicating the specific failure that occurred (in which
- * case the DNSServiceRef is not initialized). kDNSServiceErr_NotAuth is
- * returned to indicate that the calling process does not have entitlements
- * to use this API.
- */
-DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid);
-
-// Map the source port of the local UDP socket that was opened for sending the DNS query
-// to the process ID of the application that triggered the DNS resolution.
-//
-/* DNSServiceGetPID() Parameters:
- *
- * srcport: Source port (in network byte order) of the UDP socket that was created by
- * the daemon to send the DNS query on the wire.
- *
- * pid: Process ID of the application that started the name resolution which triggered
- * the daemon to send the query on the wire. The value can be -1 if the srcport
- * cannot be mapped.
- *
- * return value: Returns kDNSServiceErr_NoError on success, or kDNSServiceErr_ServiceNotRunning
- * if the daemon is not running. The value of the pid is undefined if the return
- * value has error.
- */
-DNSServiceErrorType DNSSD_API DNSServiceGetPID
-(
- uint16_t srcport,
- int32_t *pid
-);
-
-#define kDNSServiceCompPrivateDNS "PrivateDNS"
-#define kDNSServiceCompMulticastDNS "MulticastDNS"
-
-#endif
diff --git a/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c b/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c
index 9b3885e6..ad5136df 100644
--- a/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c
+++ b/mDNSResponder/mDNSMacOSX/Private/dnsctl_server.c
@@ -23,7 +23,7 @@ static dispatch_queue_t dnsctlserver_queue = NULL;
mDNSlocal void handle_logging(mDNSu32 log_level)
{
- KQueueLock(&mDNSStorage);
+ KQueueLock();
switch (log_level)
{
@@ -55,12 +55,12 @@ mDNSlocal void handle_logging(mDNSu32 log_level)
}
UpdateDebugState();
- KQueueUnlock(&mDNSStorage, "LogLevel changed");
+ KQueueUnlock("LogLevel changed");
}
mDNSlocal void handle_stateinfo(mDNSu32 state_level)
{
- KQueueLock(&mDNSStorage);
+ KQueueLock();
switch (state_level)
{
@@ -73,13 +73,13 @@ mDNSlocal void handle_stateinfo(mDNSu32 state_level)
break;
}
- KQueueUnlock(&mDNSStorage, "StateInfo dumped");
+ KQueueUnlock("StateInfo dumped");
}
mDNSlocal void handle_test_mode(mDNSu32 test_mode)
{
- KQueueLock(&mDNSStorage);
+ KQueueLock();
switch (test_mode)
{
@@ -99,7 +99,7 @@ mDNSlocal void handle_test_mode(mDNSu32 test_mode)
break;
}
- KQueueUnlock(&mDNSStorage, "Test Msg to mDNSResponderHelper");
+ KQueueUnlock("Test Msg to mDNSResponderHelper");
}
mDNSlocal void handle_terminate()
diff --git a/mDNSResponder/mDNSMacOSX/Private/xpc_services.c b/mDNSResponder/mDNSMacOSX/Private/xpc_services.c
index 4cad6ba0..8bf45a4b 100644
--- a/mDNSResponder/mDNSMacOSX/Private/xpc_services.c
+++ b/mDNSResponder/mDNSMacOSX/Private/xpc_services.c
@@ -41,11 +41,11 @@ mDNSlocal void ActivateDNSProxy(mDNSu32 IpIfArr[MaxIp], mDNSu32 OpIf, mDNSBool p
LogInfo("ActivateDNSProxy: InterfaceIndex List by Client: Input[%d, %d, %d, %d, %d] Output[%d] ", IpIfArr[0], IpIfArr[1],
IpIfArr[2], IpIfArr[3], IpIfArr[4], OpIf);
- KQueueLock(&mDNSStorage);
- DNSProxyInit(&mDNSStorage, IpIfArr, OpIf);
+ KQueueLock();
+ DNSProxyInit(IpIfArr, OpIf);
if (proxy_off) // Open skts only if proxy was OFF else we may end up opening extra skts
- mDNSPlatformInitDNSProxySkts(&mDNSStorage, ProxyUDPCallback, ProxyTCPCallback);
- KQueueUnlock(&mDNSStorage, "DNSProxy Activated");
+ mDNSPlatformInitDNSProxySkts(ProxyUDPCallback, ProxyTCPCallback);
+ KQueueUnlock("DNSProxy Activated");
}
mDNSlocal void handle_dps_terminate()
@@ -55,11 +55,11 @@ mDNSlocal void handle_dps_terminate()
// Clear the Client's PID, so that we can now accept new DPS requests
dps_client_pid = 0;
- KQueueLock(&mDNSStorage);
+ KQueueLock();
mDNSPlatformCloseDNSProxySkts(&mDNSStorage);
// TBD: Close TCP Sockets
- DNSProxyTerminate(&mDNSStorage);
- KQueueUnlock(&mDNSStorage, "DNSProxy Deactivated");
+ DNSProxyTerminate();
+ KQueueUnlock("DNSProxy Deactivated");
}
mDNSlocal void handle_dps_request(xpc_object_t req)
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/Contents.json b/mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/Contents.json
new file mode 100644
index 00000000..da4a164c
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/UIPreferencesBlueCheck.imageset/Contents.json b/mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/UIPreferencesBlueCheck.imageset/Contents.json
new file mode 100644
index 00000000..6bfae10b
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/UIPreferencesBlueCheck.imageset/Contents.json
@@ -0,0 +1,22 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "UIPreferencesBlueCheck.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "UIPreferencesBlueCheck@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/UIPreferencesBlueCheck.imageset/UIPreferencesBlueCheck.png b/mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/UIPreferencesBlueCheck.imageset/UIPreferencesBlueCheck.png
new file mode 100644
index 00000000..44a1cc53
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/UIPreferencesBlueCheck.imageset/UIPreferencesBlueCheck.png
Binary files differ
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/UIPreferencesBlueCheck.imageset/UIPreferencesBlueCheck@2x.png b/mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/UIPreferencesBlueCheck.imageset/UIPreferencesBlueCheck@2x.png
new file mode 100644
index 00000000..ce094512
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/Assets.xcassets/UIPreferencesBlueCheck.imageset/UIPreferencesBlueCheck@2x.png
Binary files differ
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourConstants.h b/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourConstants.h
new file mode 100644
index 00000000..189b58de
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourConstants.h
@@ -0,0 +1,15 @@
+//
+// BonjourSettingsController.m
+// mDNSResponder
+//
+// Created by Phil on 7/28/16.
+//
+//
+
+#import <Preferences/Preferences.h>
+
+@interface BonjourSettingsController: PSListItemsController {
+
+}
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSCStore.h b/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSCStore.h
new file mode 100644
index 00000000..15b12a6e
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSCStore.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <SystemConfiguration/SystemConfiguration.h>
+#import <Security/Security.h>
+
+#define SC_DYNDNS_PREFS_KEY CFSTR("com.apple.preference.bonjour")
+#define SC_DYNDNS_SYSTEM_KEY CFSTR("/System/Network/DynamicDNS")
+#define SC_DYNDNS_REGDOMAINS_KEY CFSTR("RegistrationDomains")
+#define SC_DYNDNS_BROWSEDOMAINS_KEY CFSTR("BrowseDomains")
+#define SC_DYNDNS_HOSTNAMES_KEY CFSTR("HostNames")
+#define SC_DYNDNS_DOMAIN_KEY CFSTR("Domain")
+#define SC_DYNDNS_KEYNAME_KEY CFSTR("KeyName")
+#define SC_DYNDNS_SECRET_KEY CFSTR("Secret")
+#define SC_DYNDNS_ENABLED_KEY CFSTR("Enabled")
+#define SC_DYNDNS_STATUS_KEY CFSTR("Status")
+
+#define SC_DYNDNS_SETUP_KEY CFSTR("Setup:/Network/DynamicDNS")
+#define SC_DYNDNS_STATE_KEY CFSTR("State:/Network/DynamicDNS")
+
+@interface BonjourSCStore : NSObject
+
++ (NSArray *_Nullable)objectForKey:(NSString *_Nonnull)key;
++ (void)setObject:(NSArray *_Nullable)value forKey:(NSString *_Nonnull)key;
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSCStore.m b/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSCStore.m
new file mode 100644
index 00000000..e4f9b0d5
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSCStore.m
@@ -0,0 +1,84 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "BonjourSCStore.h"
+#import <Foundation/Foundation.h>
+#import <AssertMacros.h>
+
+@implementation BonjourSCStore
+
++ (NSArray * _Nullable)objectForKey:(NSString * _Nonnull)key
+{
+ NSArray * result = nil;
+ SCPreferencesRef store;
+ OSStatus err;
+ NSDictionary * origDict;
+
+ store = SCPreferencesCreateWithAuthorization(kCFAllocatorDefault, SC_DYNDNS_PREFS_KEY, NULL, NULL);
+ require_action(store != NULL, SysConfigErr, err = SCError());
+ require_action(true == SCPreferencesLock(store, true), LockFailed, err = SCError());
+
+ origDict = (__bridge NSDictionary *)SCPreferencesPathGetValue(store, SC_DYNDNS_SYSTEM_KEY);
+ if (origDict) origDict = [NSDictionary dictionaryWithDictionary: origDict];
+
+ result = [origDict objectForKey: key];
+
+ SCPreferencesUnlock(store);
+
+LockFailed:
+ CFRelease(store);
+SysConfigErr:
+ return(result);
+}
+
++ (void)setObject:(NSArray * _Nullable)value forKey:(NSString * _Nonnull)key
+{
+ SCPreferencesRef store;
+ OSStatus err;
+ NSMutableDictionary * origDict;
+ Boolean success;
+
+ store = SCPreferencesCreateWithAuthorization(kCFAllocatorDefault, SC_DYNDNS_PREFS_KEY, NULL, NULL);
+ require_action(store != NULL, SysConfigErr, err = SCError());
+ require_action(true == SCPreferencesLock(store, true), LockFailed, err = SCError());
+
+ origDict = (__bridge NSMutableDictionary *)SCPreferencesPathGetValue(store, SC_DYNDNS_SYSTEM_KEY);
+ if (!origDict) origDict = [NSMutableDictionary dictionary];
+ else origDict = [NSMutableDictionary dictionaryWithDictionary: origDict];
+
+ if (value.count) [origDict setObject: value forKey: key];
+ else [origDict removeObjectForKey: key];
+
+ success = SCPreferencesPathSetValue(store, SC_DYNDNS_SYSTEM_KEY, (__bridge CFDictionaryRef)origDict);
+ require_action(success, SCError, err = SCError(););
+
+ success = SCPreferencesCommitChanges(store);
+ require_action(success, SCError, err = SCError());
+ success = SCPreferencesApplyChanges(store);
+ require_action(success, SCError, err = SCError());
+
+SCError:
+ SCPreferencesUnlock(store);
+LockFailed:
+ CFRelease(store);
+SysConfigErr:
+ return;
+}
+
+
+@end
+
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSettingsController.h b/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSettingsController.h
new file mode 100644
index 00000000..0f3d95b3
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSettingsController.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Preferences/Preferences.h>
+
+@interface BonjourSettingsController: PSListItemsController {
+
+}
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSettingsController.m b/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSettingsController.m
new file mode 100644
index 00000000..86e4ae7a
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/BonjourSettingsController.m
@@ -0,0 +1,143 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "BonjourSettingsController.h"
+#import "HostnameController.h"
+#import "BonjourSCStore.h"
+#import "CNBrowseDomainsController.h"
+#import <AssertMacros.h>
+
+#define LocalizedStringFromMyBundle(key, comment) \
+ NSLocalizedStringFromTableInBundle(key, @"Localizable", [NSBundle bundleForClass: [self class]], comment)
+
+@interface BonjourSettingsController ()
+
+@property (strong) NSString * bonjourHostname;
+@property (strong) NSArray * browseDomainsA;
+
+@end
+
+@implementation BonjourSettingsController
+
+- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ if (self = [super initWithNibName: nibNameOrNil bundle: nibBundleOrNil])
+ {
+ [self commonInit];
+ }
+ return(self);
+}
+
+- (void)commonInit
+{
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+ [super viewWillAppear: animated];
+ [self readPreferences];
+ [self reloadSpecifiers];
+}
+
+- (id) getDomainCount:(PSSpecifier *)specifier
+{
+ (void)specifier; // Unused
+ return [NSNumber numberWithInteger: [_browseDomainsA filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"(%K == %@)", (NSString *)SC_DYNDNS_ENABLED_KEY, @YES]].count].stringValue;
+}
+
+- (id) getHostname:(PSSpecifier *)specifier
+{
+ (void)specifier; // Unused
+ return _bonjourHostname.length ? _bonjourHostname : LocalizedStringFromMyBundle(@"_bonjour.hostname.unset", nil);
+}
+
+- (NSArray *)specifiers
+{
+ if (!_specifiers) {
+ PSSpecifier * specifier;
+ NSMutableArray * specifiers = [NSMutableArray array];
+
+ specifier = [PSSpecifier groupSpecifierWithName: LocalizedStringFromMyBundle(@"_bonjour.hostname.groupname", nil)];
+ [specifiers addObject: specifier];
+ specifier = [PSSpecifier preferenceSpecifierNamed: LocalizedStringFromMyBundle(@"_bonjour.hostname.name", nil)
+ target: self
+ set: nil
+ get: @selector(getHostname:)
+ detail: [HostnameController class]
+ cell: PSLinkListCell
+ edit: nil];
+ [specifier setProperty: @"hostnameID"
+ forKey: PSIDKey];
+ [specifiers addObject: specifier];
+
+ specifier = [PSSpecifier groupSpecifierWithName: LocalizedStringFromMyBundle(@"_bonjour.browse.groupname", nil)];
+ [specifiers addObject: specifier];
+ specifier = [PSSpecifier preferenceSpecifierNamed: LocalizedStringFromMyBundle(@"_bonjour.browse.name", nil)
+ target: self
+ set: nil
+ get: @selector(getDomainCount:)
+ detail: [CNBrowseDomainsController class]
+ cell: PSLinkListCell
+ edit: nil];
+ [specifier setProperty: @"browseID"
+ forKey: PSIDKey];
+ [specifiers addObject: specifier];
+
+ _specifiers = specifiers;
+ }
+ return _specifiers;
+}
+
+-(void)readPreferences
+{
+ self.browseDomainsA = [BonjourSCStore objectForKey: (NSString *)SC_DYNDNS_BROWSEDOMAINS_KEY];
+
+ NSArray * hostArray;
+ hostArray = [BonjourSCStore objectForKey: (NSString *)SC_DYNDNS_HOSTNAMES_KEY];
+ if (hostArray && [hostArray count] > 0)
+ {
+ self.bonjourHostname = hostArray[0][(NSString *)SC_DYNDNS_DOMAIN_KEY];
+ }
+ else self.bonjourHostname = nil;
+
+ if (!_browseDomainsA) self.browseDomainsA = [NSMutableArray array];
+ if (!_bonjourHostname) self.bonjourHostname = [NSString string];
+}
+
+#pragma mark - TableView Delegates
+
+- (void)listItemSelected:(NSIndexPath *)indexPath //sender is NSIndexPath of selection
+{
+ if (indexPath.section == 0)
+ {
+ HostnameController * c = [[HostnameController alloc] initWithStyle: UITableViewStyleGrouped];
+ c.bonjourHostname = _bonjourHostname;
+ c.title = LocalizedStringFromMyBundle(@"_bonjour.hostname.name", nil);
+ [self.navigationController pushViewController: c animated: YES];
+ }
+ else if (indexPath.section == 1)
+ {
+ CNBrowseDomainsController * c = [[CNBrowseDomainsController alloc] initWithStyle: UITableViewStyleGrouped];
+ c.browseDomainsA = _browseDomainsA;
+ c.title = LocalizedStringFromMyBundle(@"_bonjour.browse.name", nil);
+ [self.navigationController pushViewController: c animated: YES];
+ }
+
+ [_table deselectRowAtIndexPath: indexPath animated: YES];
+}
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/CNBrowseDomainsController.h b/mDNSResponder/mDNSMacOSX/SettingsBundle/CNBrowseDomainsController.h
new file mode 100644
index 00000000..da6813ef
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/CNBrowseDomainsController.h
@@ -0,0 +1,37 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol CNBrowseDomainsDelegate;
+
+@interface CNBrowseDomainsController : UITableViewController
+
+@property (weak) IBOutlet id<CNBrowseDomainsDelegate> delegate;
+@property (strong) NSArray * browseDomainsA;
+
+- (void)addBrowseDomain:(NSString *)fullPath;
+
+@end
+
+@protocol CNBrowseDomainsDelegate <NSObject>
+
+@optional
+
+- (void)domainBrowserDomainSelected:(NSString *)domain;
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/CNBrowseDomainsController.m b/mDNSResponder/mDNSMacOSX/SettingsBundle/CNBrowseDomainsController.m
new file mode 100644
index 00000000..f729eb7d
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/CNBrowseDomainsController.m
@@ -0,0 +1,710 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "CNBrowseDomainsController.h"
+#import "CNDomainBrowserViewController.h"
+#import "CNDomainBrowserPathUtils.h"
+#import "BonjourSCStore.h"
+#import <AssertMacros.h>
+
+#define kTag_AddBrowse 100
+#define kTag_AddManual 101
+
+const NSString * _CNBrowseDomainKey_fullname = (NSString *)SC_DYNDNS_DOMAIN_KEY;
+const NSString * _CNBrowseDomainKey_enabled = (NSString *)SC_DYNDNS_ENABLED_KEY;
+
+#define LocalizedStringFromMyBundle(key, comment ) \
+ NSLocalizedStringFromTableInBundle(key, @"Localizable", [NSBundle bundleForClass: [self class]], comment )
+
+@interface CNPathPopoverViewController : UIViewController
+
+@property (strong) UILabel * label;
+@property (copy) NSArray * pathArray;
+@property (assign) CGPoint offset;
+
+@end
+
+@implementation CNPathPopoverViewController
+
+- (instancetype)initWithPathArray:(NSArray *)pathArray
+{
+ if (self = [self initWithNibName: nil bundle: nil] )
+ {
+ _pathArray = pathArray;
+ NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
+ [paragraphStyle setLineSpacing: [UIFont labelFontSize] * 0.3];
+
+ NSMutableAttributedString * itemStr = [[NSMutableAttributedString alloc] init];
+ NSUInteger count = 0;
+ for (NSString * next in _pathArray )
+ {
+ NSString * nextLine = [NSString stringWithFormat: @"%@%@", itemStr.length ? @"\n" : @"", next];
+ UIColor * nextColor = ((count++ == 0) || (count == _pathArray.count)) ? [UIColor grayColor] : [UIColor blackColor];
+ [itemStr appendAttributedString:
+ [[NSMutableAttributedString alloc] initWithString: nextLine
+ attributes: @{ NSForegroundColorAttributeName: nextColor,
+ NSParagraphStyleAttributeName: paragraphStyle
+ }]];
+ }
+
+ _label = [[UILabel alloc] initWithFrame: CGRectZero];
+ _label.numberOfLines = 0;
+ _label.attributedText = itemStr;
+ [_label sizeToFit];
+
+ _offset = CGPointMake(25, 15 );
+ CGRect rect = _label.frame;
+ rect.origin.x += _offset.x;
+ rect.origin.y += _offset.y;
+ [_label setFrame: rect];
+ }
+ return(self );
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ [self.view addSubview: _label];
+}
+
+- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
+{
+ [super willTransitionToTraitCollection: newCollection withTransitionCoordinator: coordinator];
+ [self.presentingViewController dismissViewControllerAnimated: NO completion: nil];
+}
+
+@end
+
+@interface CNPathAccessoryView : UIView
+
+@property (strong, readonly) UIButton * elipsisButton;
+@property (strong, readonly) UIButton * pathLabel;
+@property (weak) UITableView * tableView;
+@property (weak) UITableViewCell * cell;
+@property (strong, readonly) NSArray * pathArray;
+
+@end
+
+@implementation CNPathAccessoryView
+
+- (instancetype) initWithFrame:(CGRect)frame pathArray:(NSArray *)pathArray
+{
+ self = [super initWithFrame:frame];
+ if (self) {
+ _pathArray = pathArray;
+ if (_pathArray )
+ {
+ _pathLabel = [UIButton buttonWithType: UIButtonTypeCustom];
+ [_pathLabel setTitle: _pathArray[_pathArray.count-1] forState: UIControlStateNormal];
+ [_pathLabel setTitleColor: [UIColor blackColor] forState: UIControlStateNormal];
+ _pathLabel.titleLabel.font = [UIFont systemFontOfSize: [UIFont labelFontSize]];
+ [self addSubview: _pathLabel];
+
+ _pathLabel.translatesAutoresizingMaskIntoConstraints = NO;
+ [_pathLabel sizeToFit];
+ [_pathLabel.widthAnchor constraintEqualToConstant: _pathLabel.frame.size.width].active = YES;
+ [_pathLabel.trailingAnchor constraintEqualToAnchor: self.trailingAnchor].active = YES;
+ [_pathLabel.topAnchor constraintEqualToAnchor: self.topAnchor].active = YES;
+ [_pathLabel.bottomAnchor constraintEqualToAnchor: self.bottomAnchor].active = YES;
+ }
+ if (_pathArray.count > 2 )
+ {
+ _elipsisButton = [UIButton buttonWithType: UIButtonTypeCustom];
+ [_elipsisButton setTitle: @"…" forState: UIControlStateNormal];
+ [_elipsisButton setTitleColor: _elipsisButton.tintColor forState: UIControlStateNormal];
+ [_elipsisButton setTitleColor: [UIColor grayColor] forState: UIControlStateHighlighted];
+ _elipsisButton.titleLabel.font = [UIFont boldSystemFontOfSize: [UIFont labelFontSize]];
+ [_elipsisButton addTarget: self action: @selector(pathButtonPressed:withEvent:) forControlEvents: UIControlEventTouchUpInside];
+ _elipsisButton.userInteractionEnabled = YES;
+ [self addSubview: _elipsisButton];
+
+ _elipsisButton.translatesAutoresizingMaskIntoConstraints = NO;
+ [_elipsisButton sizeToFit];
+ [_elipsisButton.widthAnchor constraintEqualToConstant: _elipsisButton.frame.size.width].active = YES;
+ [_elipsisButton.trailingAnchor constraintEqualToAnchor: _pathLabel.leadingAnchor].active = YES;
+ [_elipsisButton.topAnchor constraintGreaterThanOrEqualToAnchor: self.topAnchor].active = YES;
+ [_elipsisButton.bottomAnchor constraintLessThanOrEqualToAnchor: self.bottomAnchor].active = YES;
+ }
+ }
+ return self;
+}
+
+- (BOOL) canBecomeFirstResponder
+{
+ return YES;
+}
+
+- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection
+{
+ (void)controller; // Unused
+ (void)traitCollection; // Unused
+ return UIModalPresentationNone;
+}
+
+- (void) pathButtonPressed:(UIControl *)button withEvent:(UIEvent *)event
+{
+ (void)button; // Unused
+
+ if (!self.cell.showingDeleteConfirmation )
+ {
+ [self becomeFirstResponder];
+
+ UIView *buttonView = [[event.allTouches anyObject] view];
+ CGRect buttonFrame = [buttonView convertRect: buttonView.frame toView: self];
+
+ CNPathPopoverViewController * controller = [[CNPathPopoverViewController alloc] initWithPathArray: self.pathArray];
+ controller.modalPresentationStyle = UIModalPresentationPopover;
+ controller.preferredContentSize = CGSizeMake(controller.label.frame.size.width + controller.offset.x * 2, controller.label.frame.size.height + controller.offset.y * 2 );
+
+ UIPopoverPresentationController *popover = controller.popoverPresentationController;
+ popover.delegate = (id<UIPopoverPresentationControllerDelegate>)self;
+ popover.sourceView = buttonView;
+ popover.sourceRect = buttonFrame;
+ popover.permittedArrowDirections = UIPopoverArrowDirectionLeft | UIPopoverArrowDirectionRight;
+
+ [(UIViewController *)self.tableView.delegate presentViewController: controller
+ animated: YES
+ completion: nil];
+ }
+}
+
+- (CGSize) sizeThatFits:(CGSize)size
+{
+ (void)size; // Unused
+ CGSize ret = CGSizeZero;
+ CGFloat maxX = 0.0;
+ CGFloat maxHeight = 0.0;
+ for (UIView *view in [self subviews] )
+ {
+ CGRect frame = view.frame;
+ CGFloat frameMaxX = CGRectGetMaxX(frame);
+ CGFloat frameHeight = CGRectGetHeight(frame);
+ maxX += frameMaxX;
+ if (frameHeight > maxHeight )
+ {
+ maxHeight = frameHeight;
+ }
+ }
+ ret.width = maxX;
+ ret.height = maxHeight;
+ return ret;
+}
+
+@end
+
+@interface CNManualDomainViewController : UITableViewController
+
+@property (weak) CNBrowseDomainsController * delegate;
+@property (weak) UITextField * textField;
+
+@end
+
+#define kTag_EditTextField 103
+
+@implementation CNManualDomainViewController
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+
+ self.tableView.dataSource = (id<UITableViewDataSource>)self;
+ self.tableView.delegate = (id<UITableViewDelegate>)self;
+
+ self.title = LocalizedStringFromMyBundle(@"_dnsBrowser.manualdomain.title", nil );
+ self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: LocalizedStringFromMyBundle(@"_dnsBrowser.manualdomain.cancel", nil )
+ style: UIBarButtonItemStylePlain
+ target: self
+ action: @selector(cancelAction:)];
+
+ self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: LocalizedStringFromMyBundle(@"_dnsBrowser.manualdomain.add", nil )
+ style: UIBarButtonItemStylePlain
+ target: self
+ action: @selector(addAction:)];
+ self.navigationItem.rightBarButtonItem.enabled = NO;
+}
+
+- (void)viewWillDisappear:(BOOL)animated
+{
+ [super viewWillDisappear: animated];
+ if (self.isMovingFromParentViewController )
+ {
+ [[NSNotificationCenter defaultCenter] removeObserver: self];
+ }
+}
+
+- (void)viewDidAppear:(BOOL)animated
+{
+ [super viewDidAppear: animated];
+ if (self.isMovingToParentViewController )
+ {
+ [self.textField becomeFirstResponder];
+ }
+}
+
+- (IBAction)addAction:(id)sender
+{
+ (void)sender; // Unused
+ [self.navigationController dismissViewControllerAnimated: YES completion: ^{
+ [self.delegate addBrowseDomain: self.textField.text];
+ }];
+}
+
+- (IBAction)cancelAction:(id)sender
+{
+ (void)sender; // Unused
+ [self.navigationController dismissViewControllerAnimated: YES completion: nil];
+}
+
+#pragma mark - Notifications
+
+- (void)textFieldDidChange:(NSNotification *)notification
+{
+ UITextField * textField = (UITextField *)notification.object;
+ self.navigationItem.rightBarButtonItem.enabled = (textField.text.length > 0);
+}
+
+#pragma mark - TableView Delegates
+
+- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ (void)tableView; // Unused
+ (void)indexPath; // Unused
+ return UITableViewAutomaticDimension;
+}
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
+{
+ (void)tableView; // Unused
+ NSInteger result = 0;
+
+ if (tableView == self.tableView ) result = 1;
+
+ return(result );
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+ (void)section; // Unused
+ NSInteger result = 0;
+
+ if (tableView == self.tableView && section == 0 ) result = 1;
+
+ return(result );
+}
+
+- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
+{
+ NSString * result = nil;
+
+ if (tableView == self.tableView && section == 0 )
+ {
+ result = LocalizedStringFromMyBundle(@"_dnsBrowser.manualdomain.footer", nil );
+ }
+
+ return(result );
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ UITableViewCell *cell = nil;
+
+ if (tableView == self.tableView )
+ {
+ if (indexPath.section == 0 && indexPath.row == 0 )
+ {
+ static NSString *MyIdentifier = @"manual_domain_cell_id";
+ cell = [tableView dequeueReusableCellWithIdentifier: MyIdentifier];
+ if (!cell )
+ {
+ cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleValue1 reuseIdentifier: MyIdentifier];
+ }
+
+ cell.textLabel.hidden = YES;
+ cell.detailTextLabel.hidden = YES;
+
+ [[cell viewWithTag: kTag_EditTextField] removeFromSuperview];
+ UITextField * textField = [[UITextField alloc] initWithFrame:CGRectZero];
+ textField.tag = kTag_EditTextField;
+ textField.adjustsFontSizeToFitWidth = YES;
+ textField.placeholder = LocalizedStringFromMyBundle(@"_dnsBrowser.manualdomain.defaultValue", nil );
+ textField.keyboardType = UIKeyboardTypeURL;
+ textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
+ textField.autocorrectionType = UITextAutocorrectionTypeNo;
+ textField.enablesReturnKeyAutomatically = YES;
+ textField.clearButtonMode = UITextFieldViewModeAlways;
+ [cell.contentView addSubview: textField];
+
+ textField.translatesAutoresizingMaskIntoConstraints = NO;
+ [textField.leadingAnchor constraintEqualToAnchor: cell.layoutMarginsGuide.leadingAnchor].active = YES;
+ [textField.trailingAnchor constraintEqualToAnchor: cell.layoutMarginsGuide.trailingAnchor].active = YES;
+ [textField.topAnchor constraintEqualToAnchor: cell.layoutMarginsGuide.topAnchor].active = YES;
+ [textField.bottomAnchor constraintEqualToAnchor: cell.layoutMarginsGuide.bottomAnchor].active = YES;
+
+ [[NSNotificationCenter defaultCenter] addObserver: self
+ selector: @selector(textFieldDidChange:)
+ name: UITextFieldTextDidChangeNotification
+ object: textField];
+ self.textField = textField;
+ }
+ }
+
+ return(cell );
+}
+
+- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ (void)tableView; // Unused
+ (void)indexPath; // Unused
+ return(nil );
+}
+
+@end
+
+@interface CNBrowseDomainsController ()
+
+@property (strong) NSDictionary * selectedInstance;
+@property (strong) NSMutableDictionary * instanceInfoStrings;
+@property (strong) NSMutableDictionary * instanceStatusViews;
+
+@property (strong) CNDomainBrowserViewController * browseController;
+
+@end
+
+@implementation CNBrowseDomainsController
+
+- (instancetype)initWithStyle:(UITableViewStyle)style
+{
+ if (self = [super initWithStyle: style] )
+ {
+ [self commonInit];
+ }
+ return(self );
+}
+
+- (void)contentViewsInit
+{
+ self.tableView.allowsMultipleSelectionDuringEditing = NO;
+}
+
+- (void)commonInit
+{
+ self.instanceInfoStrings = [NSMutableDictionary dictionary];
+ self.instanceStatusViews = [NSMutableDictionary dictionary];
+ self.browseController = [[CNDomainBrowserViewController alloc] initWithStyle: UITableViewStylePlain];
+ _browseController.delegate = (id<CNDomainBrowserViewControllerDelegate>)self;
+ _browseController.ignoreLocal = YES;
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ [self contentViewsInit];
+
+ self.tableView.dataSource = (id<UITableViewDataSource>)self;
+ self.tableView.delegate = (id<UITableViewDelegate>)self;
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+ [super viewWillAppear: animated];
+ if (self.isMovingToParentViewController)
+ {
+ [_browseController startBrowse];
+ }
+}
+
+- (void)viewWillDisappear:(BOOL)animated
+{
+ [super viewWillDisappear: animated];
+ if (self.isMovingFromParentViewController )
+ {
+ [self savePreferences];
+ [_browseController stopBrowse];
+ }
+}
+
+-(void)savePreferences
+{
+ [BonjourSCStore setObject: _browseDomainsA.count ? _browseDomainsA : nil forKey: (NSString *)SC_DYNDNS_BROWSEDOMAINS_KEY];
+}
+
+- (NSDictionary *)browseDomainForRow:(NSInteger)row
+{
+ NSDictionary * result = nil;
+ NSInteger curRow = 0;
+
+ for (NSDictionary * nextDomain in self.browseDomainsA )
+ {
+ if (curRow == row )
+ {
+ result = nextDomain;
+ break;
+ }
+ curRow++;
+ }
+
+ return(result );
+}
+
+- (NSInteger)indexOfDomainInList:(NSString *)domainString
+{
+ NSInteger index = 0;
+ if (_browseDomainsA ) {
+ NSDictionary *domainDict;
+ NSString *domainName;
+ NSEnumerator *arrayEnumerator = [_browseDomainsA objectEnumerator];
+ while ((domainDict = [arrayEnumerator nextObject]) != NULL)
+ {
+ domainName = [domainDict objectForKey:_CNBrowseDomainKey_fullname];
+ if ([domainString caseInsensitiveCompare:domainName] == NSOrderedSame) return index;
+ index++;
+ }
+ }
+ return NSNotFound;
+}
+
+- (void)addBrowseDomain:(NSString *)fullPath
+{
+ NSString * trimmedPath = TrimCharactersFromDNSDomain(fullPath );
+ NSInteger index = [self indexOfDomainInList: trimmedPath];
+ NSMutableArray * domains = [NSMutableArray arrayWithArray: self.browseDomainsA];
+
+ if (index == NSNotFound )
+ {
+ [domains addObject: @{
+ _CNBrowseDomainKey_fullname: trimmedPath,
+ _CNBrowseDomainKey_enabled: @YES
+ }];
+
+ self.browseDomainsA = [NSArray arrayWithArray: domains];
+ [self.tableView insertRowsAtIndexPaths: @[[NSIndexPath indexPathForRow: domains.count-1 inSection: 0]] withRowAnimation: UITableViewRowAnimationAutomatic];
+ }
+ else
+ {
+ NSDictionary * domain = domains[index];
+ domains[index] = @{
+ _CNBrowseDomainKey_fullname: domain[_CNBrowseDomainKey_fullname],
+ _CNBrowseDomainKey_enabled: @YES
+ };
+ self.browseDomainsA = [NSArray arrayWithArray: domains];
+ NSIndexPath * indexPath = [NSIndexPath indexPathForRow: index inSection: 0];
+ [CATransaction begin];
+ [CATransaction setCompletionBlock:^{
+ [self.tableView deselectRowAtIndexPath: indexPath animated: YES];
+ }];
+ [self.tableView reloadRowsAtIndexPaths: @[indexPath] withRowAnimation: UITableViewRowAnimationAutomatic];
+ [self.tableView selectRowAtIndexPath: indexPath animated: YES scrollPosition: UITableViewScrollPositionMiddle];
+ [CATransaction commit];
+
+ }
+}
+
+#pragma mark - CNDomainBrowserViewControllerDelegate
+
+- (void)domainBrowserDomainSelected:(NSString *)domain
+{
+ [self newPathSelected: domain];
+}
+
+- (void)bonjourBrowserDomainUpdate:(NSString *)defaultDomain
+{
+ (void)defaultDomain; // Unused
+ [self.tableView reloadData];
+}
+
+#pragma mark - TableView Delegates
+
+- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ (void)tableView; // Unused
+ (void)indexPath; // Unused
+ return UITableViewAutomaticDimension;
+}
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
+{
+ (void)tableView; // Unused
+ NSInteger result = 0;
+
+ if (tableView == self.tableView ) result = (self.browseController.flattenedDNSDomains.count > 0) ? 3 : 2;
+ else result = 1;
+
+ return(result );
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+ (void)section; // Unused
+ NSInteger result = 0;
+
+ if (tableView == self.tableView )
+ {
+ if (section == 0 )
+ {
+ result = self.browseDomainsA.count;
+ }
+ else
+ {
+ result = 1;
+ }
+ }
+
+ return(result );
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ UITableViewCell *cell = nil;
+
+ if (tableView == self.tableView )
+ {
+ if (indexPath.section == 0 )
+ {
+ NSDictionary * record = [self browseDomainForRow: indexPath.row];
+ if (record )
+ {
+ static NSString *MyIdentifier = @"browse_cell_id";
+ cell = [tableView dequeueReusableCellWithIdentifier: MyIdentifier];
+ if (!cell )
+ {
+ cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: MyIdentifier];
+ }
+ NSArray * pathArray = DNSDomainToDomainPath(record[_CNBrowseDomainKey_fullname] );
+ cell.textLabel.text = pathArray[pathArray.count-1];
+ cell.textLabel.textColor = nil;
+ cell.textLabel.numberOfLines = 0;
+ cell.accessoryType = UITableViewCellAccessoryNone;
+ cell.accessoryView = nil;
+ cell.imageView.image = [[UIImage imageNamed: @"UIPreferencesBlueCheck.png"
+ inBundle: [NSBundle bundleForClass: [self class]]
+ compatibleWithTraitCollection: nil] imageWithRenderingMode: UIImageRenderingModeAlwaysTemplate];
+ cell.imageView.hidden = ![record[_CNBrowseDomainKey_enabled] boolValue];
+
+ NSArray * accPathArray = (pathArray.count > 2) ?
+ [[pathArray reverseObjectEnumerator] allObjects] :
+ ((pathArray.count > 1) ? @[pathArray[0]] : nil);
+ if (accPathArray )
+ {
+ CNPathAccessoryView * accView = [[CNPathAccessoryView alloc] initWithFrame: CGRectZero
+ pathArray: accPathArray];
+ accView.tableView = tableView;
+ accView.cell = cell;
+ [accView sizeToFit];
+ cell.accessoryView = accView;
+ }
+ }
+ }
+ else
+ {
+ static NSString *MyIdentifier = @"button_cell_id";
+ cell = [tableView dequeueReusableCellWithIdentifier: MyIdentifier];
+ if (!cell )
+ {
+ cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: MyIdentifier];
+ }
+
+ if (self.browseController.flattenedDNSDomains.count > 0 && indexPath.section == 1 )
+ {
+ cell.textLabel.textColor = self.view.tintColor;
+ cell.textLabel.text = LocalizedStringFromMyBundle(@"_dnsBrowser.domains.selectdomain", nil );
+ cell.accessoryType = UITableViewCellAccessoryNone;
+ cell.tag = kTag_AddBrowse;
+ }
+ else
+ {
+ cell.textLabel.textColor = self.view.tintColor;
+ cell.textLabel.text = LocalizedStringFromMyBundle(@"_dnsBrowser.domains.selectmanual", nil );
+ cell.accessoryType = UITableViewCellAccessoryNone;
+ cell.tag = kTag_AddManual;
+ }
+ }
+ }
+
+ return(cell );
+}
+
+- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ BOOL result = NO;
+
+ if (tableView == self.tableView && indexPath.section == 0 ) result = YES;
+
+ return(result );
+}
+
+- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ if (editingStyle == UITableViewCellEditingStyleDelete )
+ {
+ NSMutableArray * domains = [NSMutableArray arrayWithArray: self.browseDomainsA];
+ [domains removeObjectAtIndex: indexPath.row];
+ self.browseDomainsA = [NSArray arrayWithArray: domains];
+ [tableView deleteRowsAtIndexPaths: @[indexPath] withRowAnimation: UITableViewRowAnimationAutomatic];
+ }
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ UITableViewCell * cell = [tableView cellForRowAtIndexPath: indexPath];
+ if (tableView == self.tableView )
+ {
+ if (indexPath.section == 0 )
+ { // Toggle check and enable bit
+ NSMutableArray * domains = [NSMutableArray arrayWithArray: self.browseDomainsA];
+ NSMutableDictionary * selection = [NSMutableDictionary dictionaryWithDictionary: domains[indexPath.row]];
+ selection[_CNBrowseDomainKey_enabled] = [NSNumber numberWithBool: ![selection[_CNBrowseDomainKey_enabled] boolValue]];
+ domains[indexPath.row] = selection;
+ self.browseDomainsA = [NSArray arrayWithArray: domains];
+ [tableView reloadRowsAtIndexPaths: @[indexPath] withRowAnimation: UITableViewRowAnimationAutomatic];
+ }
+ else
+ {
+ if (cell.tag == kTag_AddBrowse )
+ {
+ CNDomainBrowserViewController *c = _browseController;
+ c.title = LocalizedStringFromMyBundle(@"_bonjour.browse.name", nil);
+ c.clearsSelectionOnViewWillAppear = NO;
+ c.modalPresentationStyle = UIModalPresentationFormSheet;
+ UINavigationController * nv = [[UINavigationController alloc] initWithRootViewController: c];
+ [self presentViewController: nv animated: YES completion: nil];
+ }
+ else if (cell.tag == kTag_AddManual )
+ {
+ CNManualDomainViewController * c = [[CNManualDomainViewController alloc] initWithStyle: UITableViewStyleGrouped];
+ c.delegate = self;
+ c.modalPresentationStyle = UIModalPresentationFormSheet;
+ UINavigationController * nv = [[UINavigationController alloc] initWithRootViewController: c];
+ [self presentViewController: nv animated: YES completion: nil];
+ }
+ }
+ }
+ [tableView deselectRowAtIndexPath: indexPath animated: YES];
+}
+
+#pragma mark - Commands
+
+- (void)newPathSelected:(NSString *)fullPath
+{
+ [CATransaction begin];
+ [CATransaction setCompletionBlock:^{
+ [self addBrowseDomain: fullPath];
+ }];
+ [self.navigationController popToViewController: self animated: YES];
+ [CATransaction commit];
+ }
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/HostnameController.h b/mDNSResponder/mDNSMacOSX/SettingsBundle/HostnameController.h
new file mode 100644
index 00000000..f6835463
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/HostnameController.h
@@ -0,0 +1,25 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface HostnameController : UITableViewController {
+
+}
+@property (strong) NSString * bonjourHostname;
+
+@end
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/HostnameController.m b/mDNSResponder/mDNSMacOSX/SettingsBundle/HostnameController.m
new file mode 100644
index 00000000..94edc369
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/HostnameController.m
@@ -0,0 +1,125 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "HostnameController.h"
+#import "BonjourSCStore.h"
+#import <AssertMacros.h>
+#import <Preferences/Preferences.h>
+
+#define LocalizedStringFromMyBundle(key, comment) \
+ NSLocalizedStringFromTableInBundle(key, @"Localizable", [NSBundle bundleForClass: [self class]], comment)
+
+@interface HostnameController ()
+
+@property (strong) UITextField * textField;
+
+@end
+
+@implementation HostnameController
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+
+ self.tableView.dataSource = (id<UITableViewDataSource>)self;
+ self.tableView.delegate = (id<UITableViewDelegate>)self;
+}
+
+- (void)viewWillDisappear:(BOOL)animated
+{
+ [super viewWillDisappear: animated];
+ if (self.isMovingFromParentViewController)
+ {
+ [[self firstResponder] resignFirstResponder]; // Ends any outstanding edits
+ self.bonjourHostname = _textField.attributedText.string;
+ [self savePreferences]; }
+}
+
+-(void)savePreferences
+{
+ [BonjourSCStore setObject: _bonjourHostname.length ? @[@{
+ (NSString *)SC_DYNDNS_DOMAIN_KEY : _bonjourHostname,
+ (NSString *)SC_DYNDNS_ENABLED_KEY : @YES
+ }] : nil
+ forKey: (NSString *)SC_DYNDNS_HOSTNAMES_KEY];
+}
+
+- (void)_setHostname:(NSString *)value
+{
+ self.bonjourHostname = value;
+}
+
+#pragma mark - TableView Delegates
+
+- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ (void)tableView; // Unused
+ (void)indexPath; // Unused
+ return UITableViewAutomaticDimension;
+}
+
+- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
+{
+ (void)tableView; // Unused
+ (void)section; // Unused
+ return(LocalizedStringFromMyBundle(@"_bonjour.hostname.desc", nil));
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+ (void)tableView; // Unused
+ (void)section; // Unused
+ return(1);
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ PSEditableTableCell *cell = nil;
+
+ if (tableView == self.tableView && indexPath.section == 0)
+ {
+ static NSString *MyIdentifier = @"hostname_cell_id";
+ cell = (PSEditableTableCell *)[tableView dequeueReusableCellWithIdentifier: MyIdentifier];
+ if (!cell)
+ {
+ cell = [[PSEditableTableCell alloc] initWithStyle: [PSEditableTableCell cellStyle] reuseIdentifier: MyIdentifier];
+ }
+ cell.placeholderText = LocalizedStringFromMyBundle(@"_bonjour.hostname.placeholder", nil);
+ cell.textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
+ cell.textField.clearButtonMode = UITextFieldViewModeAlways;
+ cell.textField.autocorrectionType = UITextAutocorrectionTypeNo;
+ cell.textField.keyboardType = UIKeyboardTypeURL;
+ cell.title = @"";
+ cell.value = _bonjourHostname;
+ self.textField = cell.textField;
+ }
+
+ return(cell);
+}
+
+- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ (void)tableView; // Unused
+ BOOL result = YES;
+
+ if (indexPath.section == 0 && indexPath.row == 0) result = NO;
+
+ return(result);
+}
+
+@end
+
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/Info.plist b/mDNSResponder/mDNSMacOSX/SettingsBundle/Info.plist
new file mode 100644
index 00000000..9fe8b991
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>NSPrincipalClass</key>
+ <string>BonjourSettingsController</string>
+ <key>CFBundleDisplayName</key>
+ <string>Bonjour</string>
+</dict>
+</plist>
diff --git a/mDNSResponder/mDNSMacOSX/SettingsBundle/Localizable.strings b/mDNSResponder/mDNSMacOSX/SettingsBundle/Localizable.strings
new file mode 100644
index 00000000..94ee788d
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/SettingsBundle/Localizable.strings
@@ -0,0 +1,34 @@
+/*
+ *
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+"_bonjour.hostname.groupname" = "Hostname";
+"_bonjour.hostname.name" = "Hostname";
+"_bonjour.hostname.unset" = "Not set";
+"_bonjour.hostname.desc" = "Enter a hostname for this device. Other computers on the Internet will be able to reach your device using this hostname.";
+"_bonjour.hostname.placeholder" = "steve.example.com";
+
+"_bonjour.browse.groupname" = "Browsing";
+"_bonjour.browse.name" = "Browse Domains";
+
+"_dnsBrowser.domains.selectdomain" = "Browse For Domain…";
+"_dnsBrowser.domains.selectmanual" = "Manually Enter Domain…";
+
+"_dnsBrowser.manualdomain.title" = "Manual Domain";
+"_dnsBrowser.manualdomain.add" = "Add";
+"_dnsBrowser.manualdomain.cancel" = "Cancel";
+"_dnsBrowser.manualdomain.defaultValue" = "example.com";
+"_dnsBrowser.manualdomain.footer" = "The domain will be added to your list of Bonjour browse domains.";
diff --git a/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist b/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist
index 91ed1da3..002e322e 100644
--- a/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist
+++ b/mDNSResponder/mDNSMacOSX/com.apple.mDNSResponderHelper.plist
@@ -1,21 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>Label</key>
- <string>com.apple.mDNSResponderHelper.reloaded</string>
- <key>OnDemand</key>
- <true/>
- <key>ProgramArguments</key>
- <array>
- <string>/usr/sbin/mDNSResponderHelper</string>
- </array>
- <key>MachServices</key>
- <dict>
- <key>com.apple.mDNSResponder_Helper</key>
- <true/>
- </dict>
- <key>POSIXSpawnType</key>
- <string>Interactive</string>
+ <key>Label</key>
+ <string>com.apple.mDNSResponderHelper.reloaded</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/usr/sbin/mDNSResponderHelper</string>
+ </array>
+ <key>MachServices</key>
+ <dict>
+ <key>com.apple.mDNSResponder_Helper</key>
+ <true/>
+ </dict>
+ <key>POSIXSpawnType</key>
+ <string>Interactive</string>
</dict>
</plist>
diff --git a/mDNSResponder/mDNSMacOSX/coreBLE.h b/mDNSResponder/mDNSMacOSX/coreBLE.h
index cc00923a..29a0a17d 100644
--- a/mDNSResponder/mDNSMacOSX/coreBLE.h
+++ b/mDNSResponder/mDNSMacOSX/coreBLE.h
@@ -18,15 +18,22 @@
#ifndef _coreBLE_H_
#define _coreBLE_H_
+#if ENABLE_BLE_TRIGGERED_BONJOUR
+
#include "BLE.h"
@interface coreBLE : NSObject <CBCentralManagerDelegate, CBPeripheralManagerDelegate, CBPeripheralDelegate>
- (id)init;
-- (void) advertiseBrowses:(serviceHash_t) browseHash andRegistrations:(serviceHash_t) registeredHash;
+- (void) updateBeacon:(serviceHash_t) bloomFilter;
+- (void) startBeacon;
+- (bool) isBeaconing;
- (void) stopBeacon;
-- (void) updateScan:(bool) start;
+- (void) startScan;
+- (void) stopScan;
@end
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
+
#endif /* _coreBLE_H_ */
diff --git a/mDNSResponder/mDNSMacOSX/coreBLE.m b/mDNSResponder/mDNSMacOSX/coreBLE.m
index e764169a..8af8422c 100644
--- a/mDNSResponder/mDNSMacOSX/coreBLE.m
+++ b/mDNSResponder/mDNSMacOSX/coreBLE.m
@@ -15,6 +15,8 @@
* limitations under the License.
*/
+#if ENABLE_BLE_TRIGGERED_BONJOUR
+
#include "mDNSEmbeddedAPI.h"
#include "DNSCommon.h"
@@ -28,31 +30,51 @@
static coreBLE * coreBLEptr;
// Call Bluetooth subsystem to start/stop the the Bonjour BLE beacon and
-// beacon scanning based on the current browse and registration hashes.
-void updateBLEBeaconAndScan(serviceHash_t browseHash, serviceHash_t registeredHash)
+// beacon scanning based on the current Bloom filter.
+void updateBLEBeacon(serviceHash_t bloomFilter)
{
if (coreBLEptr == 0)
coreBLEptr = [[coreBLE alloc] init];
- LogInfo("updateBLEBeaconAndScan: browseHash = 0x%x, registeredHash = 0x%x", browseHash, registeredHash);
+ LogInfo("updateBLEBeacon: bloomFilter = 0x%lx", bloomFilter);
- [coreBLEptr advertiseBrowses:browseHash andRegistrations: registeredHash];
- [coreBLEptr updateScan:(browseHash || registeredHash)];
+ [coreBLEptr updateBeacon:bloomFilter];
}
// Stop the current BLE beacon.
void stopBLEBeacon(void)
{
if (coreBLEptr == 0)
- {
- LogInfo("stopBLEBeacon called before BLE scan initialized ??");
- return;
- }
+ coreBLEptr = [[coreBLE alloc] init];
- LogInfo("stopBLEBeacon Stopping beacon");
[coreBLEptr stopBeacon];
}
+bool currentlyBeaconing(void)
+{
+ if (coreBLEptr == 0)
+ coreBLEptr = [[coreBLE alloc] init];
+
+ return [coreBLEptr isBeaconing];
+}
+
+// Start the scan.
+void startBLEScan(void)
+{
+ if (coreBLEptr == 0)
+ coreBLEptr = [[coreBLE alloc] init];
+ [coreBLEptr startScan];
+}
+
+// Stop the scan.
+void stopBLEScan(void)
+{
+ if (coreBLEptr == 0)
+ coreBLEptr = [[coreBLE alloc] init];
+
+ [coreBLEptr stopScan];
+}
+
@implementation coreBLE
{
CBCentralManager *_centralManager;
@@ -60,9 +82,11 @@ void stopBLEBeacon(void)
NSData *_currentlyAdvertisedData;
- // [_centralManager isScanning] is only avilable on iOS and not OSX,
+ // [_centralManager isScanning] is only available on iOS and not OSX,
// so track scanning state locally.
BOOL _isScanning;
+ BOOL _centralManagerIsOn;
+ BOOL _peripheralManagerIsOn;
}
- (id)init
@@ -75,6 +99,8 @@ void stopBLEBeacon(void)
_peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
_currentlyAdvertisedData = nil;
_isScanning = NO;
+ _centralManagerIsOn = NO;
+ _peripheralManagerIsOn = NO;
if (_centralManager == nil || _peripheralManager == nil )
{
@@ -82,7 +108,7 @@ void stopBLEBeacon(void)
}
else
{
- LogInfo("coreBLE initialised");
+ LogInfo("coreBLE initialized");
}
}
@@ -92,7 +118,7 @@ void stopBLEBeacon(void)
#define ADVERTISEMENTDATALENGTH 28 // 31 - 3 (3 bytes for flags)
// TODO:
-// DBDeviceTypeBonjour should eventually be added to the DBDeviceType definitions in WirelessProximity
+// Define DBDeviceTypeBonjour for prototyping until we move to the TDS beacon format.
// The Bluetooth team recommended using a value < 32 for prototyping, since 32 is the number of
// beacon types they can track in their duplicate beacon filtering logic.
#define DBDeviceTypeBonjour 26
@@ -106,27 +132,31 @@ extern mDNSInterfaceID AWDLInterfaceID;
// Transmit the last beacon indicating we are no longer advertising or browsing any services for two seconds.
#define LastBeaconTime 2
-- (void) advertiseBrowses:(serviceHash_t) browseHash andRegistrations:(serviceHash_t) registeredHash
+- (void) updateBeacon:(serviceHash_t) bloomFilter
{
uint8_t advertisingData[ADVERTISEMENTDATALENGTH] = {0, 0xff, 0x4c, 0x00 };
uint8_t advertisingLength = 4;
- // TODO: If we have been transmitting a beacon, we probably want to continue transmitting
- // for a few seconds after both hashes are zero so that that any devices scanning
- // can see the beacon indicating we have stopped all browses and advertisements.
-
- // Stop the beacon if there is no data to advertise.
- if (browseHash == 0 && registeredHash == 0)
+ // If no longer browsing or advertising, beacon this state for 'LastBeaconTime' seconds
+ // so that peers have a chance to notice the state change.
+ if (bloomFilter == 0)
{
- LogInfo("advertiseBrowses:andRegistrations Stopping beacon in %d seconds", LastBeaconTime);
- if (mDNSStorage.NextBLEServiceTime)
- LogInfo("advertiseBrowses:andRegistrations: NextBLEServiceTime already set ??");
+ LogInfo("updateBeacon: Stopping beacon in %d seconds", LastBeaconTime);
- mDNSStorage.NextBLEServiceTime = NonZeroTime(mDNS_TimeNow_NoLock(& mDNSStorage) + LastBeaconTime * mDNSPlatformOneSecond);
+ if (mDNSStorage.timenow == 0)
+ {
+ // This should never happen since all calling code paths should have called mDNS_Lock(), which
+ // initializes the mDNSStorage.timenow value.
+ LogMsg("updateBeacon: NOTE, timenow == 0 ??");
+ }
+
+ mDNSStorage.NextBLEServiceTime = NonZeroTime(mDNSStorage.timenow + (LastBeaconTime * mDNSPlatformOneSecond));
+ finalBeacon = true;
}
else
{
- mDNSStorage.NextBLEServiceTime = 0;
+ // Cancel any pending final beacon processing.
+ finalBeacon = false;
}
// The beacon type.
@@ -135,17 +165,14 @@ extern mDNSInterfaceID AWDLInterfaceID;
// Flags and Version field
advertisingData[advertisingLength++] = BonjourBLEVersion;
- memcpy(& advertisingData[advertisingLength], & browseHash, sizeof(serviceHash_t));
+ memcpy(& advertisingData[advertisingLength], & bloomFilter, sizeof(serviceHash_t));
advertisingLength += sizeof(serviceHash_t);
- memcpy(& advertisingData[advertisingLength], & registeredHash, sizeof(serviceHash_t));
- advertisingLength += sizeof(serviceHash_t);
-
// Add the MAC address of the awdl0 interface. Don't cache it since
// it can get updated periodically.
if (AWDLInterfaceID)
{
- NetworkInterfaceInfoOSX *intf = IfindexToInterfaceInfoOSX(& mDNSStorage, AWDLInterfaceID);
+ NetworkInterfaceInfoOSX *intf = IfindexToInterfaceInfoOSX(AWDLInterfaceID);
if (intf)
memcpy(& advertisingData[advertisingLength], & intf->ifinfo.MAC, sizeof(mDNSEthAddr));
else
@@ -153,63 +180,129 @@ extern mDNSInterfaceID AWDLInterfaceID;
}
else
{
- // just use zero if not avaiblable
+ // Just use zero if not avaiblable.
memset( & advertisingData[advertisingLength], 0, sizeof(mDNSEthAddr));
}
advertisingLength += sizeof(mDNSEthAddr);
- // Total length of data advertised, minus this lenght byte.
+ // Total length of data advertised, minus this length byte.
advertisingData[0] = (advertisingLength - 1);
- LogInfo("advertiseBrowses:andRegistrations advertisingLength = %d", advertisingLength);
+ LogInfo("updateBeacon: advertisingLength = %d", advertisingLength);
- NSData* data = [NSData dataWithBytes:advertisingData length:advertisingLength];
+ if (_currentlyAdvertisedData)
+ [_currentlyAdvertisedData release];
+ _currentlyAdvertisedData = [[NSData alloc] initWithBytes:advertisingData length:advertisingLength];
+ [self startBeacon];
+}
- if([_peripheralManager isAdvertising] && [data isEqualToData: _currentlyAdvertisedData])
+- (void) startBeacon
+{
+ if (!_peripheralManagerIsOn)
{
- // No need to restart the advertisement if it is already active with the same data.
- LogInfo("advertiseBrowses:andRegistrations: No change in advertised data");
+ LogInfo("startBeacon: Not starting beacon, CBPeripheralManager not powered on");
+ return;
}
- else
- {
- _currentlyAdvertisedData = data;
- if ([_peripheralManager isAdvertising])
- {
- LogInfo("advertiseBrowses:andRegistrations: Stop current advertisement before restarting");
- [_peripheralManager stopAdvertising];
- }
- LogInfo("advertiseBrowses:andRegistrations: Starting beacon");
+ if (_currentlyAdvertisedData == nil)
+ {
+ LogInfo("startBeacon: Not starting beacon, no data to advertise");
+ return;
+ }
- [_peripheralManager startAdvertising:@{ CBAdvertisementDataAppleMfgData : _currentlyAdvertisedData, CBCentralManagerScanOptionIsPrivilegedDaemonKey : @YES, @"kCBAdvOptionUseFGInterval" : @YES }];
+ if ([_peripheralManager isAdvertising])
+ {
+ LogInfo("startBeacon: Stop current beacon transmission before restarting");
+ [_peripheralManager stopAdvertising];
}
+ LogInfo("startBeacon: Starting beacon");
+
+#if 0 // Move to this code during Fall 2018 develelopment if still using these APIs.
+ [_peripheralManager startAdvertising:@{ CBAdvertisementDataAppleMfgData : _currentlyAdvertisedData, CBManagerIsPrivilegedDaemonKey : @YES, @"kCBAdvOptionUseFGInterval" : @YES }];
+#else
+ // While CBCentralManagerScanOptionIsPrivilegedDaemonKey is deprecated in current MobileBluetooth project, it's still defined in the current and
+ // previous train SDKs. Suppress deprecated warning for now since we intend to move to a different Bluetooth API to manage the BLE Triggered Bonjour
+ // beacons when this code is enabled by default.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ [_peripheralManager startAdvertising:@{ CBAdvertisementDataAppleMfgData : _currentlyAdvertisedData, CBCentralManagerScanOptionIsPrivilegedDaemonKey : @YES, @"kCBAdvOptionUseFGInterval" : @YES }];
+#pragma GCC diagnostic pop
+#endif
+}
+
+- (bool) isBeaconing
+{
+ return (_currentlyAdvertisedData != nil);
}
- (void) stopBeacon
{
- [_peripheralManager stopAdvertising];
+ if (!_peripheralManagerIsOn)
+ {
+ LogInfo("stopBeacon: CBPeripheralManager is not powered on");
+ return;
+ }
+
+ // Only beaconing if we have advertised data to send.
+ if (_currentlyAdvertisedData)
+ {
+ LogInfo("stoptBeacon: Stopping beacon");
+ [_peripheralManager stopAdvertising];
+ [_currentlyAdvertisedData release];
+ _currentlyAdvertisedData = nil;
+ }
+ else
+ LogInfo("stoptBeacon: Note currently beaconing");
+}
+
+- (void) startScan
+{
+ if (!_centralManagerIsOn)
+ {
+ LogInfo("startScan: Not starting scan, CBCentralManager is not powered on");
+ return;
+ }
+
+ if (_isScanning)
+ {
+ LogInfo("startScan: already scanning, stopping scan before restarting");
+ [_centralManager stopScan];
+ }
+
+ LogInfo("startScan: Starting scan");
+
+ _isScanning = YES;
+
+#if 0 // Move to this code during Fall 2018 develelopment if still using these APIs.
+ [_centralManager scanForPeripheralsWithServices:nil options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES , CBManagerIsPrivilegedDaemonKey : @YES}];
+#else
+ // While CBCentralManagerScanOptionIsPrivilegedDaemonKey is deprecated in current MobileBluetooth project, it's still defined in the current and
+ // previous train SDKs. Suppress deprecated warning for now since we intend to move to a different Bluetooth API to manage the BLE Triggered Bonjour
+ // beacons when this code is enabled by default.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ [_centralManager scanForPeripheralsWithServices:nil options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES , CBCentralManagerScanOptionIsPrivilegedDaemonKey : @YES}];
+#pragma GCC diagnostic pop
+#endif
}
-- (void) updateScan:(bool) start
+- (void) stopScan
{
+ if (!_centralManagerIsOn)
+ {
+ LogInfo("stopScan: Not stopping scan, CBCentralManager is not powered on");
+ return;
+ }
+
if (_isScanning)
{
- if (!start)
- {
- LogInfo("updateScan: stopping scan");
- [_centralManager stopScan];
- _isScanning = NO;
- }
+ LogInfo("stopScan: Stopping scan");
+ [_centralManager stopScan];
+ _isScanning = NO;
}
else
{
- if (start)
- {
- LogInfo("updateScan: starting scan");
-
- _isScanning = YES;
- [_centralManager scanForPeripheralsWithServices:nil options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @NO }];
- }
+ LogInfo("stopScan: Not currently scanning");
}
}
@@ -218,28 +311,40 @@ extern mDNSInterfaceID AWDLInterfaceID;
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch (central.state) {
- case CBCentralManagerStateUnknown:
- LogInfo("centralManagerDidUpdateState: CBCentralManagerStateUnknown");
+ case CBManagerStateUnknown:
+ LogInfo("centralManagerDidUpdateState: CBManagerStateUnknown");
break;
- case CBCentralManagerStateResetting:
- LogInfo("centralManagerDidUpdateState: CBCentralManagerStateResetting");
+ case CBManagerStateResetting:
+ LogInfo("centralManagerDidUpdateState: CBManagerStateResetting");
break;
- case CBCentralManagerStateUnsupported:
- LogInfo("centralManagerDidUpdateState: CBCentralManagerStateUnsupported");
+ case CBManagerStateUnsupported:
+ LogInfo("centralManagerDidUpdateState: CBManagerStateUnsupported");
break;
- case CBCentralManagerStateUnauthorized:
- LogInfo("centralManagerDidUpdateState: CBCentralManagerStateUnauthorized");
+ case CBManagerStateUnauthorized:
+ LogInfo("centralManagerDidUpdateState: CBManagerStateUnauthorized");
break;
- case CBCentralManagerStatePoweredOff:
- LogInfo("centralManagerDidUpdateState: CBCentralManagerStatePoweredOff");
+ case CBManagerStatePoweredOff:
+ LogInfo("centralManagerDidUpdateState: CBManagerStatePoweredOff");
break;
- case CBCentralManagerStatePoweredOn:
- LogInfo("centralManagerDidUpdateState: CBCentralManagerStatePoweredOn");
+ case CBManagerStatePoweredOn:
+ // Hold lock to synchronize with main thread from this callback thread.
+ KQueueLock();
+
+ LogInfo("centralManagerDidUpdateState: CBManagerStatePoweredOn");
+ _centralManagerIsOn = YES;
+ // Only start scan if we have data we will be transmitting or if "suppressBeacons"
+ // is set, indicating we should be scanning, but not beaconing.
+ if (_currentlyAdvertisedData || suppressBeacons)
+ [self startScan];
+ else
+ LogInfo("centralManagerDidUpdateState:: Not starting scan");
+
+ KQueueUnlock("CBManagerStatePoweredOn");
break;
default:
@@ -248,8 +353,8 @@ extern mDNSInterfaceID AWDLInterfaceID;
}
}
-// offset of beacon type in recieved CBAdvertisementDataManufacturerDataKey bytes
-#define beaconTypeByteIndex 2
+#define beaconTypeByteIndex 2 // Offset of beacon type in received CBAdvertisementDataManufacturerDataKey byte array.
+#define beaconDataLength 18 // Total number of bytes in the CBAdvertisementDataManufacturerDataKey.
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI
{
@@ -259,7 +364,9 @@ extern mDNSInterfaceID AWDLInterfaceID;
NSData *data = [advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey];
- if (!data) {
+ // Just return if the beacon data does not match what we are looking for.
+ if (!data || ([data length] != beaconDataLength))
+ {
return;
}
@@ -268,8 +375,8 @@ extern mDNSInterfaceID AWDLInterfaceID;
// Just parse the DBDeviceTypeBonjour beacons.
if (bytes[beaconTypeByteIndex] == DBDeviceTypeBonjour)
{
- serviceHash_t browseHash, registeredHash;
- mDNSEthAddr senderMAC;
+ serviceHash_t peerBloomFilter;
+ mDNSEthAddr peerMAC;
unsigned char flagsAndVersion;
unsigned char *ptr;
@@ -279,41 +386,25 @@ extern mDNSInterfaceID AWDLInterfaceID;
#endif // VERBOSE_BLE_DEBUG
// The DBDeviceTypeBonjour beacon bytes will be:
- // x4C, 0x0, 0x2A, flags_and_version_byte,, browseHash, advertisingServices_hash_bytes,
- // 6_bytes_of_sender_AWDL_MAC_address
+ // 0x4C (1 byte), 0x0 (1 byte), DBDeviceTypeBonjour byte, flags and version byte, 8 byte Bloom filter,
+ // 6 byte sender AWDL MAC address
ptr = & bytes[beaconTypeByteIndex + 1];
flagsAndVersion = *ptr++;
- memcpy(& browseHash, ptr, sizeof(serviceHash_t));
+ memcpy(& peerBloomFilter, ptr, sizeof(serviceHash_t));
ptr += sizeof(serviceHash_t);
- memcpy(& registeredHash, ptr, sizeof(serviceHash_t));
- ptr += sizeof(serviceHash_t);
- memcpy(& senderMAC, ptr, sizeof(senderMAC));
+ memcpy(& peerMAC, ptr, sizeof(peerMAC));
#if VERBOSE_BLE_DEBUG
- LogInfo("didDiscoverPeripheral: version = 0x%x, browseHash = 0x%x, registeredHash = 0x%x",
- flagsAndVersion, browseHash, registeredHash);
+ LogInfo("didDiscoverPeripheral: version = 0x%x, peerBloomFilter = 0x%x",
+ flagsAndVersion, peerBloomFilter);
LogInfo("didDiscoverPeripheral: sender MAC = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
- senderMAC.b[0], senderMAC.b[1], senderMAC.b[2], senderMAC.b[3], senderMAC.b[4], senderMAC.b[5]);
+ peerMAC.b[0], peerMAC.b[1], peerMAC.b[2], peerMAC.b[3], peerMAC.b[4], peerMAC.b[5]);
#else
(void)flagsAndVersion; // Unused
#endif // VERBOSE_BLE_DEBUG
- responseReceived(browseHash, registeredHash, & senderMAC);
-
-#if VERBOSE_BLE_DEBUG
- // Log every 4th package during debug
- static int pkgsIn = 0;
-
- if (((pkgsIn++) & 3) == 0)
- {
- LogInfo("0x%x 0x%x 0x%x 0x%x 0x%x", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]);
-// LogInfo("0x%x 0x%x 0x%x 0x%x 0x%x", bytes[5], bytes[6], bytes[7], bytes[9], bytes[9]);
-// LogInfo("0x%x 0x%x 0x%x 0x%x 0x%x", bytes[10], bytes[11], bytes[12], bytes[13], bytes[14]);
-// LogInfo("0x%x 0x%x 0x%x 0x%x 0x%x", bytes[15], bytes[16], bytes[17], bytes[18], bytes[19]);
- }
-#endif // VERBOSE_BLE_DEBUG
-
+ responseReceived(peerBloomFilter, & peerMAC);
}
}
@@ -323,28 +414,38 @@ extern mDNSInterfaceID AWDLInterfaceID;
{
switch (peripheral.state) {
- case CBPeripheralManagerStateUnknown:
- LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStateUnknown");
+ case CBManagerStateUnknown:
+ LogInfo("peripheralManagerDidUpdateState: CBManagerStateUnknown");
break;
- case CBPeripheralManagerStateResetting:
- LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStateResetting");
+ case CBManagerStateResetting:
+ LogInfo("peripheralManagerDidUpdateState: CBManagerStateResetting");
break;
- case CBPeripheralManagerStateUnsupported:
- LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStateUnsupported");
+ case CBManagerStateUnsupported:
+ LogInfo("peripheralManagerDidUpdateState: CBManagerStateUnsupported");
break;
- case CBPeripheralManagerStateUnauthorized:
- LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStateUnauthorized");
+ case CBManagerStateUnauthorized:
+ LogInfo("peripheralManagerDidUpdateState: CBManagerStateUnauthorized");
break;
- case CBPeripheralManagerStatePoweredOff:
- LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStatePoweredOff");
+ case CBManagerStatePoweredOff:
+ LogInfo("peripheralManagerDidUpdateState: CBManagerStatePoweredOff");
break;
- case CBPeripheralManagerStatePoweredOn:
- LogInfo("peripheralManagerDidUpdateState: CBPeripheralManagerStatePoweredOn");
+ case CBManagerStatePoweredOn:
+ // Hold lock to synchronize with main thread from this callback thread.
+ KQueueLock();
+
+ LogInfo("peripheralManagerDidUpdateState: CBManagerStatePoweredOn");
+ _peripheralManagerIsOn = YES;
+
+ // Start beaconing if we have initialized beacon data to send.
+ if (_currentlyAdvertisedData)
+ [self startBeacon];
+
+ KQueueUnlock("CBManagerStatePoweredOn");
break;
default:
@@ -369,3 +470,4 @@ extern mDNSInterfaceID AWDLInterfaceID;
}
@end
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
diff --git a/mDNSResponder/mDNSMacOSX/daemon.c b/mDNSResponder/mDNSMacOSX/daemon.c
index f3f00ca7..5dece763 100644
--- a/mDNSResponder/mDNSMacOSX/daemon.c
+++ b/mDNSResponder/mDNSMacOSX/daemon.c
@@ -32,7 +32,10 @@
#include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
#include <err.h>
#include <sysexits.h>
-#include <dlfcn.h>
+
+#ifdef UNIT_TEST
+#include "unittest.h"
+#endif
#include "uDNS.h"
#include "DNSCommon.h"
@@ -63,7 +66,15 @@ static os_log_t log_general = NULL;
#define kPreferencesKey_StrictUnicastOrdering CFSTR("StrictUnicastOrdering")
#define kPreferencesKey_OfferSleepProxyService CFSTR("OfferSleepProxyService")
#define kPreferencesKey_UseInternalSleepProxy CFSTR("UseInternalSleepProxy")
+
+#if ENABLE_BLE_TRIGGERED_BONJOUR
#define kPreferencesKey_EnableBLEBasedDiscovery CFSTR("EnableBLEBasedDiscovery")
+#define kPreferencesKey_DefaultToBLETriggered CFSTR("DefaultToBLETriggered")
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
+
+#if TARGET_OS_IPHONE
+#define kPreferencesKey_PreallocateCacheMemory CFSTR("PreallocateCacheMemory")
+#endif
#endif
//*************************************************************************************************************
@@ -75,11 +86,12 @@ static mDNS_PlatformSupport PlatformStorage;
// Start off with a default cache of 32K (141 records of 232 bytes each)
// Each time we grow the cache we add another 141 records
-// 141 * 164 = 32712 bytes.
+// 141 * 232 = 32712 bytes.
// This fits in eight 4kB pages, with 56 bytes spare for memory block headers and similar overhead
#define RR_CACHE_SIZE ((32*1024) / sizeof(CacheRecord))
static CacheEntity rrcachestorage[RR_CACHE_SIZE];
struct CompileTimeAssertionChecks_RR_CACHE_SIZE { char a[(RR_CACHE_SIZE >= 141) ? 1 : -1]; };
+#define kRRCacheGrowSize (sizeof(CacheEntity) * RR_CACHE_SIZE)
#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
@@ -95,7 +107,16 @@ static mDNSBool NoMulticastAdvertisements = mDNSfalse; // By default, advertise
extern mDNSBool StrictUnicastOrdering;
extern mDNSBool AlwaysAppendSearchDomains;
+
+#if ENABLE_BLE_TRIGGERED_BONJOUR
extern mDNSBool EnableBLEBasedDiscovery;
+extern mDNSBool DefaultToBLETriggered;
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
+
+#if TARGET_OS_IPHONE
+static mDNSBool PreallocateCacheMemory = mDNSfalse;
+#define kRRCacheMemoryLimit 1000000 // For now, we limit the cache to at most 1MB on iOS devices.
+#endif
// We keep a list of client-supplied event sources in KQSocketEventSource records
typedef struct KQSocketEventSource
@@ -103,6 +124,8 @@ typedef struct KQSocketEventSource
struct KQSocketEventSource *next;
int fd;
KQueueEntry kqs;
+ udsEventCallback callback;
+ void *context;
} KQSocketEventSource;
static KQSocketEventSource *gEventSources;
@@ -258,13 +281,14 @@ mDNSexport void freeL(char *msg, void *x)
//*************************************************************************************************************
// Registration
-mDNSexport void RecordUpdatedNiceLabel(mDNS *const m, mDNSs32 delay)
+mDNSexport void RecordUpdatedNiceLabel(mDNSs32 delay)
{
- m->p->NotifyUser = NonZeroTime(m->timenow + delay);
+ mDNSStorage.p->NotifyUser = NonZeroTime(mDNSStorage.timenow + delay);
}
-mDNSlocal void mDNSPreferencesSetNames(mDNS *const m, int key, domainlabel *old, domainlabel *new)
+mDNSlocal void mDNSPreferencesSetNames(int key, domainlabel *old, domainlabel *new)
{
+ mDNS *const m = &mDNSStorage;
domainlabel *prevold, *prevnew;
switch (key)
{
@@ -327,13 +351,12 @@ mDNSlocal void mDNSPreferencesSetNames(mDNS *const m, int key, domainlabel *old,
mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
{
- (void)m; // Unused
if (result == mStatus_NoError)
{
if (!SameDomainLabelCS(m->p->userhostlabel.c, m->hostlabel.c))
LogInfo("Local Hostname changed from \"%#s.local\" to \"%#s.local\"", m->p->userhostlabel.c, m->hostlabel.c);
// One second pause in case we get a Computer Name update too -- don't want to alert the user twice
- RecordUpdatedNiceLabel(m, mDNSPlatformOneSecond);
+ RecordUpdatedNiceLabel(mDNSPlatformOneSecond);
}
else if (result == mStatus_NameConflict)
{
@@ -342,7 +365,7 @@ mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
else if (m->timenow - m->p->HostNameConflict > 60 * mDNSPlatformOneSecond)
{
// Tell the helper we've given up
- mDNSPreferencesSetNames(m, kmDNSLocalHostName, &m->p->userhostlabel, NULL);
+ mDNSPreferencesSetNames(kmDNSLocalHostName, &m->p->userhostlabel, NULL);
}
}
else if (result == mStatus_GrowCache)
@@ -350,9 +373,9 @@ mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
// Allocate another chunk of cache storage
static unsigned int allocated = 0;
#if TARGET_OS_IPHONE
- if (allocated >= 1000000) return; // For now we limit the cache to at most 1MB on iOS devices
+ if (allocated >= kRRCacheMemoryLimit) return; // For now we limit the cache to at most 1MB on iOS devices
#endif
- allocated += sizeof(CacheEntity) * RR_CACHE_SIZE;
+ allocated += kRRCacheGrowSize;
// LogMsg("GrowCache %d * %d = %d; total so far %6u", sizeof(CacheEntity), RR_CACHE_SIZE, sizeof(CacheEntity) * RR_CACHE_SIZE, allocated);
CacheEntity *storage = mallocL("mStatus_GrowCache", sizeof(CacheEntity) * RR_CACHE_SIZE);
//LogInfo("GrowCache %d * %d = %d", sizeof(CacheEntity), RR_CACHE_SIZE, sizeof(CacheEntity) * RR_CACHE_SIZE);
@@ -361,8 +384,8 @@ mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result)
else if (result == mStatus_ConfigChanged)
{
// Tell the helper we've seen a change in the labels. It will dismiss the name conflict alert if needed.
- mDNSPreferencesSetNames(m, kmDNSComputerName, &m->p->usernicelabel, &m->nicelabel);
- mDNSPreferencesSetNames(m, kmDNSLocalHostName, &m->p->userhostlabel, &m->hostlabel);
+ mDNSPreferencesSetNames(kmDNSComputerName, &m->p->usernicelabel, &m->nicelabel);
+ mDNSPreferencesSetNames(kmDNSLocalHostName, &m->p->userhostlabel, &m->hostlabel);
// Then we call into the UDS daemon code, to let it do the same
udsserver_handle_configchange(m);
@@ -425,7 +448,7 @@ mDNSexport void INFOCallback(void)
LogMsg("---- BEGIN STATE LOG ---- %s %s %d", mDNSResponderVersionString, OSXVers ? "OSXVers" : "iOSVers", OSXVers ? OSXVers : iOSVers);
- udsserver_info(&mDNSStorage);
+ udsserver_info();
LogMsgNoIdent("----- Platform Timers -----");
LogTimer("m->NextCacheCheck ", mDNSStorage.NextCacheCheck);
@@ -449,33 +472,38 @@ mDNSexport void INFOCallback(void)
if (!mDNSStorage.p->InterfaceList) LogMsgNoIdent("<None>");
else
{
+ LogMsgNoIdent(" Struct addr Registered MAC BSSID Interface Address");
for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
{
// Allow six characters for interface name, for names like "vmnet8"
if (!i->Exists)
- LogMsgNoIdent("%p %2ld, Registered %p, %s %-6s(%lu) %.6a %.6a %#-14a dormant for %d seconds",
+ LogMsgNoIdent("%p %2ld, %p, %s %-6s %.6a %.6a %#-14a dormant for %d seconds",
i, i->ifinfo.InterfaceID, i->Registered,
- i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifinfo.ifname, i->scope_id, &i->ifinfo.MAC, &i->BSSID,
+ i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifinfo.ifname, &i->ifinfo.MAC, &i->BSSID,
&i->ifinfo.ip, utc - i->LastSeen);
else
{
const CacheRecord *sps[3];
FindSPSInCache(&mDNSStorage, &i->ifinfo.NetWakeBrowse, sps);
- LogMsgNoIdent("%p %2ld, Registered %p, %s %-6s(%lu) %.6a %.6a %s %s %-15.4a %s %s %s %s %#a",
+ LogMsgNoIdent("%p %2ld, %p, %s %-6s %.6a %.6a %s %s %s %s %s %s %#a",
i, i->ifinfo.InterfaceID, i->Registered,
- i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifinfo.ifname, i->scope_id, &i->ifinfo.MAC, &i->BSSID,
+ i->sa_family == AF_INET ? "v4" : i->sa_family == AF_INET6 ? "v6" : "??", i->ifinfo.ifname, &i->ifinfo.MAC, &i->BSSID,
i->ifinfo.InterfaceActive ? "Active" : " ",
i->ifinfo.IPv4Available ? "v4" : " ",
- i->ifinfo.IPv4Available ? (mDNSv4Addr*)&i->ifa_v4addr : &zerov4Addr,
i->ifinfo.IPv6Available ? "v6" : " ",
i->ifinfo.Advertise ? "A" : " ",
i->ifinfo.McastTxRx ? "M" : " ",
!(i->ifinfo.InterfaceActive && i->ifinfo.NetWake) ? " " : !sps[0] ? "p" : "P",
&i->ifinfo.ip);
- if (sps[0]) LogMsgNoIdent(" %13d %#s", SPSMetric(sps[0]->resrec.rdata->u.name.c), sps[0]->resrec.rdata->u.name.c);
- if (sps[1]) LogMsgNoIdent(" %13d %#s", SPSMetric(sps[1]->resrec.rdata->u.name.c), sps[1]->resrec.rdata->u.name.c);
- if (sps[2]) LogMsgNoIdent(" %13d %#s", SPSMetric(sps[2]->resrec.rdata->u.name.c), sps[2]->resrec.rdata->u.name.c);
+ // Only print the discovered sleep proxies once for the lead/active interface of an interface set.
+ if (i == i->Registered && (sps[0] || sps[1] || sps[2]))
+ {
+ LogMsgNoIdent(" Sleep Proxy Metric Name");
+ if (sps[0]) LogMsgNoIdent(" %13d %#s", SPSMetric(sps[0]->resrec.rdata->u.name.c), sps[0]->resrec.rdata->u.name.c);
+ if (sps[1]) LogMsgNoIdent(" %13d %#s", SPSMetric(sps[1]->resrec.rdata->u.name.c), sps[1]->resrec.rdata->u.name.c);
+ if (sps[2]) LogMsgNoIdent(" %13d %#s", SPSMetric(sps[2]->resrec.rdata->u.name.c), sps[2]->resrec.rdata->u.name.c);
+ }
}
}
}
@@ -486,14 +514,15 @@ mDNSexport void INFOCallback(void)
{
for (s = mDNSStorage.DNSServers; s; s = s->next)
{
- NetworkInterfaceInfoOSX *ifx = IfindexToInterfaceInfoOSX(&mDNSStorage, s->interface);
- LogMsgNoIdent("DNS Server %##s %s%s%#a:%d %d %s %d %d %s %s %s %s",
+ NetworkInterfaceInfoOSX *ifx = IfindexToInterfaceInfoOSX(s->interface);
+ LogMsgNoIdent("DNS Server %##s %s%s%#a:%d %d %s %d %d %s %s %s %s %s",
s->domain.c, ifx ? ifx->ifinfo.ifname : "", ifx ? " " : "", &s->addr, mDNSVal16(s->port),
s->penaltyTime ? s->penaltyTime - mDNS_TimeNow(&mDNSStorage) : 0, DNSScopeToString(s->scoped),
s->timeout, s->resGroupID,
s->req_A ? "v4" : "!v4",
s->req_AAAA ? "v6" : "!v6",
s->cellIntf ? "cell" : "!cell",
+ s->isExpensive ? "exp" : "!exp",
s->DNSSECAware ? "DNSSECAware" : "!DNSSECAware");
}
}
@@ -612,7 +641,7 @@ mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void
mDNS *const m = &mDNSStorage;
// 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();
switch(msg_header->msgh_id)
{
case SIGHUP: {
@@ -658,7 +687,7 @@ mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void
break;
case SIGPROF: mDNS_McastLoggingEnabled = mDNS_McastLoggingEnabled ? mDNSfalse : mDNStrue;
LogMsg("SIGPROF: Multicast Logging %s", mDNS_McastLoggingEnabled ? "Enabled" : "Disabled");
- LogMcastStateInfo(m, mDNSfalse, mDNStrue, mDNStrue);
+ LogMcastStateInfo(mDNSfalse, mDNStrue, mDNStrue);
mDNS_McastTracingEnabled = (mDNS_PacketLoggingEnabled && mDNS_McastLoggingEnabled) ? mDNStrue : mDNSfalse;
LogMsg("SIGPROF: Multicast Tracing is %s", mDNS_McastTracingEnabled ? "Enabled" : "Disabled");
UpdateDebugState();
@@ -670,7 +699,7 @@ mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void
default: LogMsg("SignalCallback: Unknown signal %d", msg_header->msgh_id); break;
}
- KQueueUnlock(m, "Unix Signal");
+ KQueueUnlock("Unix Signal");
}
// MachServerName is com.apple.mDNSResponder (Supported only till 10.9.x)
@@ -689,6 +718,19 @@ mDNSlocal kern_return_t mDNSDaemonInitialize(void)
return(err);
}
+#if TARGET_OS_IPHONE
+ if (PreallocateCacheMemory)
+ {
+ const int growCount = (kRRCacheMemoryLimit + kRRCacheGrowSize - 1) / kRRCacheGrowSize;
+ int i;
+
+ for (i = 0; i < growCount; ++i)
+ {
+ mDNS_StatusCallback(&mDNSStorage, mStatus_GrowCache);
+ }
+ }
+#endif
+
CFMachPortRef i_port = CFMachPortCreate(NULL, SignalCallback, NULL, NULL);
CFRunLoopSourceRef i_rls = CFMachPortCreateRunLoopSource(NULL, i_port, 0);
signal_port = CFMachPortGetPort(i_port);
@@ -710,7 +752,7 @@ mDNSlocal void SignalDispatch(dispatch_source_t source)
{
int sig = (int)dispatch_source_get_handle(source);
mDNS *const m = &mDNSStorage;
- KQueueLock(m);
+ KQueueLock();
switch(sig)
{
case SIGHUP: {
@@ -741,7 +783,7 @@ mDNSlocal void SignalDispatch(dispatch_source_t source)
break;
default: LogMsg("SignalCallback: Unknown signal %d", sig); break;
}
- KQueueUnlock(m, "Unix Signal");
+ KQueueUnlock("Unix Signal");
}
mDNSlocal void mDNSSetupSignal(dispatch_queue_t queue, int sig)
@@ -834,7 +876,7 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m)
// mDNS_Execute() generates packets, including multicasts that are looped back to ourself.
// If we call mDNS_Execute() first, and generate packets, and then call mDNSMacOSXNetworkChanged() immediately afterwards
// we then systematically lose our own looped-back packets.
- if (m->NetworkChanged && now - m->NetworkChanged >= 0) mDNSMacOSXNetworkChanged(m);
+ if (m->NetworkChanged && now - m->NetworkChanged >= 0) mDNSMacOSXNetworkChanged();
if (m->p->RequestReSleep && now - m->p->RequestReSleep >= 0)
{
@@ -865,13 +907,13 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m)
if (!SameDomainLabelCS(m->p->usernicelabel.c, m->nicelabel.c))
{
LogMsg("Name Conflict: Updated Computer Name from \"%#s\" to \"%#s\"", m->p->usernicelabel.c, m->nicelabel.c);
- mDNSPreferencesSetNames(m, kmDNSComputerName, &m->p->usernicelabel, &m->nicelabel);
+ mDNSPreferencesSetNames(kmDNSComputerName, &m->p->usernicelabel, &m->nicelabel);
m->p->usernicelabel = m->nicelabel;
}
if (!SameDomainLabelCS(m->p->userhostlabel.c, m->hostlabel.c))
{
LogMsg("Name Conflict: Updated Local Hostname from \"%#s.local\" to \"%#s.local\"", m->p->userhostlabel.c, m->hostlabel.c);
- mDNSPreferencesSetNames(m, kmDNSLocalHostName, &m->p->userhostlabel, &m->hostlabel);
+ mDNSPreferencesSetNames(kmDNSLocalHostName, &m->p->userhostlabel, &m->hostlabel);
m->p->HostNameConflict = 0; // Clear our indicator, now name change has been successful
m->p->userhostlabel = m->hostlabel;
}
@@ -964,8 +1006,9 @@ mDNSlocal mDNSu32 DHCPWakeTime(void)
// Scheduling our wakeup for halfway in between -- 90 minutes -- avoids short wakeups while still
// allowing us an adequate safety margin to renew our lease before we lose it.
-mDNSlocal mDNSBool AllowSleepNow(mDNS *const m, mDNSs32 now)
+mDNSlocal mDNSBool AllowSleepNow(mDNSs32 now)
{
+ mDNS *const m = &mDNSStorage;
mDNSBool ready = mDNSCoreReadyForSleep(m, now);
if (m->SleepState && !ready && now - m->SleepLimit < 0) return(mDNSfalse);
@@ -1066,7 +1109,7 @@ mDNSlocal mDNSBool AllowSleepNow(mDNS *const m, mDNSs32 now)
m->SleepState = SleepState_Sleeping;
// Clear our interface list to empty state, ready to go to sleep
// As a side effect of doing this, we'll also cancel any outstanding SPS Resolve calls that didn't complete
- mDNSMacOSXNetworkChanged(m);
+ mDNSMacOSXNetworkChanged();
}
LogSPS("AllowSleepNow: %s(%lX) %s at %ld (%d ticks remaining)",
@@ -1079,15 +1122,6 @@ mDNSlocal mDNSBool AllowSleepNow(mDNS *const m, mDNSs32 now)
m->SleepLimit = 0; // Don't clear m->SleepLimit until after we've logged it above
m->TimeSlept = mDNSPlatformUTC();
- // accumulate total time awake for this statistics gathering interval
- if (m->StatStartTime)
- {
- m->ActiveStatTime += (m->TimeSlept - m->StatStartTime);
-
- // indicate this value is invalid until reinitialzed on wakeup
- m->StatStartTime = 0;
- }
-
#if !TARGET_OS_EMBEDDED && defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements)
if (m->p->IOPMConnection) IOPMConnectionAcknowledgeEventWithOptions(m->p->IOPMConnection, m->p->SleepCookie, opts);
else
@@ -1149,7 +1183,7 @@ mDNSlocal void PrepareForIdle(void *m_param)
}
if (m->SleepLimit)
- if (!AllowSleepNow(m, now))
+ if (!AllowSleepNow(now))
if (nextTimerEvent - m->SleepLimit >= 0)
nextTimerEvent = m->SleepLimit;
@@ -1175,7 +1209,7 @@ mDNSlocal void PrepareForIdle(void *m_param)
#else // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-mDNSlocal void KQWokenFlushBytes(int fd, __unused short filter, __unused void *context)
+mDNSlocal void KQWokenFlushBytes(int fd, __unused short filter, __unused void *context, __unused mDNSBool encounteredEOF)
{
// Read all of the bytes so we won't wake again.
char buffer[100];
@@ -1253,7 +1287,7 @@ mDNSlocal void * KQueueLoop(void *m_param)
}
if (m->SleepLimit)
- if (!AllowSleepNow(m, now))
+ if (!AllowSleepNow(now))
if (nextTimerEvent - m->SleepLimit >= 0)
nextTimerEvent = m->SleepLimit;
@@ -1339,7 +1373,7 @@ mDNSlocal void * KQueueLoop(void *m_param)
const KQueueEntry *const kqentry = new_events[i].udata;
mDNSs32 stime = mDNSPlatformRawTime();
const char *const KQtask = kqentry->KQtask; // Grab a copy in case KQcallback deletes the task
- kqentry->KQcallback(new_events[i].ident, new_events[i].filter, kqentry->KQcontext);
+ kqentry->KQcallback(new_events[i].ident, new_events[i].filter, kqentry->KQcontext, (new_events[i].flags & EV_EOF) != 0);
mDNSs32 etime = mDNSPlatformRawTime();
if (etime - stime >= WatchDogReportingThreshold)
LogInfo("WARNING: %s took %dms to complete", KQtask, etime - stime);
@@ -1441,18 +1475,10 @@ mDNSlocal void init_logging(void)
}
#endif
-#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
-mDNSlocal mDNSBool initialize_networkserviceproxy(void)
-{
- void *NSPImage = dlopen("/System/Library/PrivateFrameworks/NetworkServiceProxy.framework/NetworkServiceProxy", RTLD_LAZY | RTLD_LOCAL);
- if (NSPImage == NULL) {
- os_log_error(OS_LOG_DEFAULT, "dlopen NetworkServiceProxy.framework failed");
- return mDNSfalse;
- }
- return mDNStrue;
-}
-#endif
-
+#ifdef UNIT_TEST
+// Run the unit test main
+UNITTEST_MAIN
+#else
mDNSexport int main(int argc, char **argv)
{
int i;
@@ -1543,7 +1569,15 @@ mDNSexport int main(int argc, char **argv)
AlwaysAppendSearchDomains = PreferencesGetValueBool(kPreferencesKey_AlwaysAppendSearchDomains, AlwaysAppendSearchDomains);
OfferSleepProxyService = PreferencesGetValueInt(kPreferencesKey_OfferSleepProxyService, OfferSleepProxyService);
UseInternalSleepProxy = PreferencesGetValueInt(kPreferencesKey_UseInternalSleepProxy, UseInternalSleepProxy);
+
+#if ENABLE_BLE_TRIGGERED_BONJOUR
EnableBLEBasedDiscovery = PreferencesGetValueBool(kPreferencesKey_EnableBLEBasedDiscovery, EnableBLEBasedDiscovery);
+ DefaultToBLETriggered = PreferencesGetValueBool(kPreferencesKey_DefaultToBLETriggered, DefaultToBLETriggered);
+#endif // ENABLE_BLE_TRIGGERED_BONJOUR
+
+#if TARGET_OS_IPHONE
+ PreallocateCacheMemory = PreferencesGetValueBool(kPreferencesKey_PreallocateCacheMemory, PreallocateCacheMemory);
+#endif
#endif
// Note that mDNSPlatformInit will set DivertMulticastAdvertisements in the mDNS structure
@@ -1621,15 +1655,9 @@ mDNSexport int main(int argc, char **argv)
status = udsserver_init(launchd_fds, launchd_fds_count);
if (status) { LogMsg("Daemon start: udsserver_init failed"); goto exit; }
- mDNSMacOSXNetworkChanged(&mDNSStorage);
+ mDNSMacOSXNetworkChanged();
UpdateDebugState();
-#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
- if (initialize_networkserviceproxy() == mDNSfalse) {
- LogMsg("Failed to initialize NetworkServiceProxy");
- }
-#endif
-
#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
LogInfo("Daemon Start: Using LibDispatch");
// CFRunLoopRun runs both CFRunLoop sources and dispatch sources
@@ -1652,9 +1680,16 @@ mDNSexport int main(int argc, char **argv)
exit:
return(status);
}
+#endif // UNIT_TEST
// uds_daemon.c support routines /////////////////////////////////////////////
+mDNSlocal void kqUDSEventCallback(int fd, short filter, void *context, __unused mDNSBool encounteredEOF)
+{
+ const KQSocketEventSource *const source = context;
+ source->callback(fd, filter, source->context);
+}
+
// Arrange things so that when data appears on fd, callback is called with context
mDNSexport mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback, void *context, void **platform_data)
{
@@ -1668,8 +1703,10 @@ mDNSexport mStatus udsSupportAddFDToEventLoop(int fd, udsEventCallback callback,
newSource->next = mDNSNULL;
newSource->fd = fd;
- newSource->kqs.KQcallback = callback;
- newSource->kqs.KQcontext = context;
+ newSource->callback = callback;
+ newSource->context = context;
+ newSource->kqs.KQcallback = kqUDSEventCallback;
+ newSource->kqs.KQcontext = newSource;
newSource->kqs.KQtask = "UDS client";
#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
newSource->kqs.readSource = mDNSNULL;
@@ -1713,6 +1750,10 @@ mDNSexport mStatus udsSupportRemoveFDFromEventLoop(int fd, void *platform_data)
return mStatus_NoSuchNameErr;
}
+#ifdef UNIT_TEST
+#include "../unittests/daemon_ut.c"
+#endif // UNIT_TEST
+
#if _BUILDING_XCODE_PROJECT_
// If mDNSResponder crashes, then this string will be magically included in the automatically-generated crash log
const char *__crashreporter_info__ = mDNSResponderVersionString;
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
diff --git a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.h b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.h
index 20f7a321..55c74c6c 100644
--- a/mDNSResponder/mDNSMacOSX/mDNSMacOSX.h
+++ b/mDNSResponder/mDNSMacOSX/mDNSMacOSX.h
@@ -62,7 +62,7 @@ enum mDNSDynamicStoreSetConfigKey
typedef struct NetworkInterfaceInfoOSX_struct NetworkInterfaceInfoOSX;
-typedef void (*KQueueEventCallback)(int fd, short filter, void *context);
+typedef void (*KQueueEventCallback)(int fd, short filter, void *context, mDNSBool encounteredEOF);
typedef struct
{
KQueueEventCallback KQcallback;
@@ -86,6 +86,8 @@ typedef struct
KQueueEntry kqsv6;
int *closeFlag;
mDNSBool proxy;
+ mDNSBool sktv4EOF;
+ mDNSBool sktv6EOF;
} KQSocketSet;
struct UDPSocket_struct
@@ -123,6 +125,9 @@ struct TCPSocket_struct
mStatus err;
};
+// Value assiged to 'Exists' to indicate the multicast state of the interface has changed.
+#define MulticastStateChanged 2
+
struct NetworkInterfaceInfoOSX_struct
{
NetworkInterfaceInfo ifinfo; // MUST be the first element in this structure
@@ -147,6 +152,7 @@ struct NetworkInterfaceInfoOSX_struct
int BPF_fd; // -1 uninitialized; -2 requested BPF; -3 failed
int BPF_mcfd; // Socket for our IPv6 ND group membership
u_int BPF_len;
+ mDNSBool isExpensive; // True if this interface has the IFEF_EXPENSIVE flag set.
#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
dispatch_source_t BPF_source;
#else
@@ -216,11 +222,11 @@ extern int KQueueFD;
extern void NotifyOfElusiveBug(const char *title, const char *msg); // Both strings are UTF-8 text
extern void SetDomainSecrets(mDNS *m);
-extern void mDNSMacOSXNetworkChanged(mDNS *const m);
+extern void mDNSMacOSXNetworkChanged(void);
extern void mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring);
-extern NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(const mDNS *const m, mDNSInterfaceID ifindex);
+extern NetworkInterfaceInfoOSX *IfindexToInterfaceInfoOSX(mDNSInterfaceID ifindex);
extern void mDNSUpdatePacketFilter(const ResourceRecord *const excludeRecord);
-extern void myKQSocketCallBack(int s1, short filter, void *context);
+extern void myKQSocketCallBack(int s1, short filter, void *context, mDNSBool encounteredEOF);
extern void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropertyListRef value);
extern void UpdateDebugState(void);
@@ -233,15 +239,14 @@ extern int KQueueSet(int fd, u_short flags, short filter, const KQueueEntry *con
// When events are processed on the non-kqueue thread (i.e. CFRunLoop notifications like Sleep/Wake,
// Interface changes, Keychain changes, etc.) they must use KQueueLock/KQueueUnlock to lock out the kqueue thread
-extern void KQueueLock(mDNS *const m);
-extern void KQueueUnlock(mDNS *const m, const char* task);
+extern void KQueueLock(void);
+extern void KQueueUnlock(const char* task);
extern void mDNSPlatformCloseFD(KQueueEntry *kq, int fd);
extern ssize_t myrecvfrom(const int s, void *const buffer, const size_t max,
struct sockaddr *const from, size_t *const fromlen, mDNSAddr *dstaddr, char *ifname, mDNSu8 *ttl);
extern mDNSBool DictionaryIsEnabled(CFDictionaryRef dict);
-extern void CUPInit(mDNS *const m);
extern const char *DNSScopeToString(mDNSu32 scope);
// If any event takes more than WatchDogReportingThreshold milliseconds to be processed, we log a warning message
@@ -267,14 +272,14 @@ struct CompileTimeAssertionChecks_mDNSMacOSX
// Check our structures are reasonable sizes. Including overly-large buffers, or embedding
// other overly-large structures instead of having a pointer to them, can inadvertently
// cause structure sizes (and therefore memory usage) to balloon unreasonably.
-
- // Checks commented out when sizeof(DNSQuestion) change cascaded into having to change yet another
- // set of hardcoded size values because these structures contain one or more DNSQuestion
- // instances.
-// char sizecheck_NetworkInterfaceInfoOSX[(sizeof(NetworkInterfaceInfoOSX) <= 7084) ? 1 : -1];
+ char sizecheck_NetworkInterfaceInfoOSX[(sizeof(NetworkInterfaceInfoOSX) <= 7464) ? 1 : -1];
char sizecheck_mDNS_PlatformSupport [(sizeof(mDNS_PlatformSupport) <= 1378) ? 1 : -1];
};
+extern mDNSInterfaceID AWDLInterfaceID;
+void initializeD2DPlugins(mDNS *const m);
+void terminateD2DPlugins(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/mDNSResponder/mDNSMacOSX/mDNSNetMonitor/mDNSNetMonitor.8 b/mDNSResponder/mDNSMacOSX/mDNSNetMonitor/mDNSNetMonitor.8
new file mode 100644
index 00000000..455c3009
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/mDNSNetMonitor/mDNSNetMonitor.8
@@ -0,0 +1,40 @@
+.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
+.\"See Also:
+.\"man mdoc.samples for a complete listing of options
+.\"man mdoc for the short list of editing options
+.\"/usr/share/misc/mdoc.template
+.Dd 8/31/16 \" DATE
+.Dt mDNSNetMonitor 8 \" Program name and manual section number
+.Os Darwin
+.Sh NAME \" Section Header - required - don't modify
+.Nm mDNSNetMonitor
+.\" The following lines are read in generating the apropos(man -k) database. Use only key
+.\" words here as the database is built based on the words here and in the .ND line.
+.\" Use .Nm macro to designate other names for the documented program.
+.Nd dumps mDNS traffic on a network
+.Sh SYNOPSIS \" Section Header - required - don't modify
+.Nm
+.Op Fl i Ar interface
+.Op Ar host
+.Sh DESCRIPTION \" Section Header - required - don't modify
+.Nm
+prints out a description of the contents of mDNS packets on a network interface. It is similiar to tcpdump in that it continuously captures packets until it is interrupted by a SIGINT signal (generated, for example, by typing your interrupt character, typically control-C) or a SIGTERM signal (typically generated with the kill(1) command).
+
+When mDNSNetMonitor finishes capturing packets, it will report counts of packets captured per mDNS packet type, service type and source device.
+
+Note that mDNSNetMonitor will not capture unicast mDNS packets.
+.Sh OPTION
+
+-i interface Displays packets on specified interface.
+.Sh Example
+
+To print all packets arriving at or departing from
+.Pa sundown Ns :
+ % mDNSNetMonitor sundown
+.Sh SEE ALSO
+.\" List links in ascending order by section, alphabetically within a section.
+.\" Please do not reference files that do not exist without filing a bug report
+.Xr mDNSResponder 8 ,
+.Xr dns-sd 8
+.\" .Sh BUGS \" Document known, unremedied bugs
+.\" .Sh HISTORY \" Document history if command behaves in a unique manner
diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist b/mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist
index 6d0bd675..a1636401 100644
--- a/mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist
+++ b/mDNSResponder/mDNSMacOSX/mDNSResponder-entitlements.plist
@@ -20,8 +20,6 @@
<true/>
<key>com.apple.private.necp.match</key>
<true/>
- <key>com.apple.private.necp.policies</key>
- <true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.network.client</key>
@@ -34,13 +32,9 @@
<true/>
<key>com.apple.BTServer.appleMfgDataScanner</key>
<true/>
- <key>com.apple.developer.networking.networkextension</key>
- <array>
- <string>app-proxy-provider-system</string>
- </array>
- <key>com.apple.private.neagent</key>
+ <key>com.apple.BTServer.le.att</key>
<true/>
- <key>com.apple.private.nehelper.privileged</key>
+ <key>com.apple.private.network.delegation-whitelist</key>
<true/>
</dict>
</plist>
diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder-xcodeproj-explanation.txt b/mDNSResponder/mDNSMacOSX/mDNSResponder-xcodeproj-explanation.txt
new file mode 100644
index 00000000..e5dfaa3e
--- /dev/null
+++ b/mDNSResponder/mDNSMacOSX/mDNSResponder-xcodeproj-explanation.txt
@@ -0,0 +1,40 @@
+The mDNSResponder project has three umbrella targets:
+Build Some
+Build More
+Build All
+
+The “Build Some” target builds:
+mDNSResponder
+mDNSResponderHelper
+dns-sd tool
+dnsctl
+mDNSNetMonitor
+dns_services
+BonjourEvents
+
+The “Build More” target builds all of “Build Some”, plus
+dnsextd
+ddnswriteconfig
+PreferencePane
+
+The “Build All” target builds all of “Build More” (including “Build Some”) plus
+SystemLibraries
+
+Now, the explanation for this three-layer hierarchy:
+
+The “Build More” is the *first* target in the Xcode project.
+This is what B&I builds by default.
+Why not “Build All”? Because SystemLibraries is special.
+B&I builds the project in two passes. B&I builds SystemLibraries first, to
+make LibSystem. Then B&I builds builds the rest. The default target needs to
+be everything *except* SystemLibraries — i.e. the “Build More” target.
+
+The “Build Some” target builds the subset of “Build More”
+that is useful in routine day-to-day development.
+Since dnsextd, ddnswriteconfig and the PreferencePane aren’t usually
+what we’re working on, it’s quicker not to rebuild them every time.
+
+The “Build All” target is the final one. It builds absolutely everything.
+B&I never builds this (they do the two-pass build) but it’s there so that
+after making changes, but before checking them in, we can quickly and
+easily do a “Build All” and make sure our changes haven’t broken anything.
diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder.sb b/mDNSResponder/mDNSMacOSX/mDNSResponder.sb
index 807217ab..1458815c 100644
--- a/mDNSResponder/mDNSMacOSX/mDNSResponder.sb
+++ b/mDNSResponder/mDNSMacOSX/mDNSResponder.sb
@@ -45,6 +45,7 @@
; Mach communications
; These are needed for things like getpwnam, hostname changes, & keychain
(allow mach-lookup
+ (global-name "com.apple.analyticsd")
(global-name "com.apple.awdd")
(global-name "com.apple.bsd.dirhelper")
(global-name "com.apple.CoreServices.coreservicesd")
@@ -66,15 +67,18 @@
(global-name "com.apple.usymptomsd")
(global-name "com.apple.webcontentfilter.dns")
(global-name "com.apple.server.bluetooth")
+ (global-name "com.apple.server.bluetooth.le.att.xpc")
(global-name "com.apple.awacs")
(global-name "com.apple.networkd")
(global-name "com.apple.securityd")
(global-name "com.apple.wifi.manager")
+ ; "com.apple.blued" is the name used in pre Lobo builds,
+ ; leave it in place while still running roots on pre Lobo targets
(global-name "com.apple.blued")
+ (global-name "com.apple.bluetoothd")
(global-name "com.apple.mobilegestalt.xpc")
- (global-name "com.apple.snhelper")
- (global-name "com.apple.nehelper")
- (global-name "com.apple.networkserviceproxy"))
+ (global-name "com.apple.ReportCrash.SimulateCrash")
+ (global-name "com.apple.snhelper"))
(allow mach-register
(global-name "com.apple.d2d.ipc"))
@@ -100,6 +104,13 @@
; Our socket
(allow file-read* file-write* (literal "/private/var/run/mDNSResponder"))
+; BPF control for sleep proxy server
+(allow file-ioctl (prefix "/dev/bpf"))
+
+; Used by CoreCrypto AES routines.
+(allow file-read* file-write-data file-ioctl
+ (literal "/dev/aes_0"))
+
; System version, settings, and other miscellaneous necessary file system accesses
(allow file-read-data
; Needed for CFCopyVersionDictionary()
@@ -117,6 +128,8 @@
(literal "/private/var/preferences/SystemConfiguration/preferences.plist")
(subpath "/System/Library/Preferences/Logging")
(subpath "/AppleInternal/Library/Preferences/Logging")
+ (subpath "/private/var/preferences/Logging/Subsystems")
+ (subpath "/private/var/db/timezone")
(subpath "/Library/Preferences/Logging"))
@@ -156,3 +169,9 @@
(iokit-user-client-class "wlDNSOffloadUserClient")
(iokit-user-client-class "RootDomainUserClient")
(iokit-user-client-class "AppleMobileFileIntegrityUserClient"))))
+
+; Internal builds only
+(with-filter (system-attribute apple-internal)
+ (allow sysctl-read sysctl-write
+ (sysctl-name "vm.footprint_suspend"))) ; dyld performance reporting
+
diff --git a/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
index 3e6c3fd7..f1a8b1da 100644
--- a/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
+++ b/mDNSResponder/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
@@ -15,8 +15,9 @@
dependencies = (
03067D860C849CC30022BE1F /* PBXTargetDependency */,
D284BF2C0ADD815A0027CCDF /* PBXTargetDependency */,
- D284BF2E0ADD81600027CCDF /* PBXTargetDependency */,
D284BF300ADD81630027CCDF /* PBXTargetDependency */,
+ 0C52E92F1E96AD74006EFE7B /* PBXTargetDependency */,
+ 0C4F36B41E206711005A536B /* PBXTargetDependency */,
);
name = "Build More";
productName = "Build All";
@@ -31,8 +32,10 @@
03067D6E0C83A39C0022BE1F /* PBXTargetDependency */,
03067D6C0C83A3920022BE1F /* PBXTargetDependency */,
BD7833F01ABA5E3500EC51ED /* PBXTargetDependency */,
+ 0C1596C71D7751AD00E09998 /* PBXTargetDependency */,
84C5B3411665544B00C324A8 /* PBXTargetDependency */,
217A4C49138EE14C000A5BA8 /* PBXTargetDependency */,
+ BD9BA7721EAFA3D500658CCF /* PBXTargetDependency */,
);
name = "Build Some";
productName = "Build Some";
@@ -41,6 +44,7 @@
isa = PBXAggregateTarget;
buildConfigurationList = 2141DD08123FFB830086D23E /* Build configuration list for PBXAggregateTarget "SystemLibraries" */;
buildPhases = (
+ B7E2951A1E259AA000C42F6D /* ShellScript */,
);
dependencies = (
2141DD0E123FFC960086D23E /* PBXTargetDependency */,
@@ -62,6 +66,18 @@
name = SystemLibrariesStatic;
productName = SystemLibrariesStatic;
};
+ B7C4B7251E71BD5000136C7A /* Build Some iOS */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = B7C4B7281E71BD5000136C7A /* Build configuration list for PBXAggregateTarget "Build Some iOS" */;
+ buildPhases = (
+ );
+ dependencies = (
+ B7C4B72E1E71BE3500136C7A /* PBXTargetDependency */,
+ B7C4B72C1E71BD6000136C7A /* PBXTargetDependency */,
+ );
+ name = "Build Some iOS";
+ productName = "Build More iOS";
+ };
FFA572650AF190F10055A0F1 /* SystemLibrariesDynamic */ = {
isa = PBXAggregateTarget;
buildConfigurationList = FFA5726E0AF191200055A0F1 /* Build configuration list for PBXAggregateTarget "SystemLibrariesDynamic" */;
@@ -90,6 +106,35 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
+ 0C10EC281DDB956E00D7A0E3 /* LocalOnlyTimeoutTests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C10EC261DDB956000D7A0E3 /* LocalOnlyTimeoutTests.c */; };
+ 0C1596B51D7740B500E09998 /* mDNSPosix.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C1596B31D7740B500E09998 /* mDNSPosix.c */; };
+ 0C1596B61D7740B500E09998 /* NetMonitor.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C1596B41D7740B500E09998 /* NetMonitor.c */; };
+ 0C1596B81D7740C100E09998 /* mDNSUNP.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C1596B71D7740C100E09998 /* mDNSUNP.c */; };
+ 0C1596B91D7740CD00E09998 /* anonymous.c in Sources */ = {isa = PBXBuildFile; fileRef = 21DD8FBD161E9A250033C8F8 /* anonymous.c */; };
+ 0C1596BA1D7740D200E09998 /* CryptoAlg.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F4A145B2AE100939099 /* CryptoAlg.c */; };
+ 0C1596BB1D7740D700E09998 /* DNSDigest.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F461DB5062DBF2900672BF3 /* DNSDigest.c */; };
+ 0C1596BC1D7740DC00E09998 /* DNSCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F60587CEF6001880B3 /* DNSCommon.c */; };
+ 0C1596BD1D7740E300E09998 /* uDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F70587CEF6001880B3 /* uDNS.c */; };
+ 0C1596BE1D7740E900E09998 /* mDNSDebug.c in Sources */ = {isa = PBXBuildFile; fileRef = DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */; };
+ 0C1596BF1D7740EF00E09998 /* PlatformCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FFCB6D73075D539900B8AF62 /* PlatformCommon.c */; };
+ 0C1596C01D77410A00E09998 /* GenLinkedList.c in Sources */ = {isa = PBXBuildFile; fileRef = DBAAFE2C057E8F660085CAD0 /* GenLinkedList.c */; };
+ 0C5674B41DA2BF8600AF3367 /* mDNSCoreReceiveTest.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C5674B21DA2BF6300AF3367 /* mDNSCoreReceiveTest.c */; };
+ 0C635A891E9418D90026C796 /* bjIPAddr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C635A7D1E9418D90026C796 /* bjIPAddr.cpp */; };
+ 0C635A8A1E9418D90026C796 /* bjMACAddr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C635A7E1E9418D90026C796 /* bjMACAddr.cpp */; };
+ 0C635A8B1E9418D90026C796 /* bjsocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C635A7F1E9418D90026C796 /* bjsocket.cpp */; };
+ 0C635A8C1E9418D90026C796 /* bjstring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C635A801E9418D90026C796 /* bjstring.cpp */; };
+ 0C635A8D1E9418D90026C796 /* bjStringtoStringMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C635A811E9418D90026C796 /* bjStringtoStringMap.cpp */; };
+ 0C635A8E1E9418D90026C796 /* BonjourTop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C635A821E9418D90026C796 /* BonjourTop.cpp */; };
+ 0C635A8F1E9418D90026C796 /* CaptureFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C635A831E9418D90026C796 /* CaptureFile.cpp */; };
+ 0C635A901E9418D90026C796 /* CollectBy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C635A841E9418D90026C796 /* CollectBy.cpp */; };
+ 0C635A911E9418D90026C796 /* DNSFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C635A851E9418D90026C796 /* DNSFrame.cpp */; };
+ 0C635A921E9418D90026C796 /* Frame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C635A861E9418D90026C796 /* Frame.cpp */; };
+ 0C635A931E9418D90026C796 /* LLRBTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C635A871E9418D90026C796 /* LLRBTree.cpp */; };
+ 0C635A941E9418D90026C796 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C635A881E9418D90026C796 /* main.cpp */; };
+ 0C6FB90F1D77767300DF6F51 /* mDNSNetMonitor.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0C6FB90E1D775FE900DF6F51 /* mDNSNetMonitor.8 */; };
+ 0C7C00501DD553640078BA89 /* unittest_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C7C00491DD553490078BA89 /* unittest_common.c */; };
+ 0C7C00511DD5536E0078BA89 /* CNameRecordTests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C7C004F1DD553490078BA89 /* CNameRecordTests.c */; };
+ 0CB1C7FC1D9C5C1100A5939F /* D2D.c in Sources */ = {isa = PBXBuildFile; fileRef = 22C7633D1D777B8C0077AFCA /* D2D.c */; };
21070E5F16486B9000A69507 /* DNSSECSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21070E5D16486B9000A69507 /* DNSSECSupport.c */; };
21070E6116486B9000A69507 /* DNSSECSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21070E5E16486B9000A69507 /* DNSSECSupport.h */; };
2124FA2C1471E98C0021D7BB /* nsec.h in Headers */ = {isa = PBXBuildFile; fileRef = 2124FA2B1471E98C0021D7BB /* nsec.h */; };
@@ -117,6 +162,13 @@
21A57F4E145B2AE100939099 /* CryptoAlg.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F4B145B2AE100939099 /* CryptoAlg.h */; };
21A57F53145B2B1400939099 /* CryptoSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F51145B2B1400939099 /* CryptoSupport.c */; };
21A57F55145B2B1400939099 /* CryptoSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F52145B2B1400939099 /* CryptoSupport.h */; };
+ 21B830A21D8A63A300AE2001 /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 219D5541149ED645004464AE /* libxml2.dylib */; };
+ 21B830A31D8A63AE00AE2001 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
+ 21B830A41D8A63BB00AE2001 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
+ 21B830A51D8A63CB00AE2001 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA213D02786FC30CCA2C71 /* IOKit.framework */; };
+ 21B830A61D8A63E400AE2001 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
+ 21B830A71D8A641F00AE2001 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 37538E131D7A43B600226BE4 /* libicucore.dylib */; };
+ 21B830A81D8A642200AE2001 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 37538E131D7A43B600226BE4 /* libicucore.dylib */; };
21DCD05C1461B23700702FC8 /* CryptoAlg.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F4A145B2AE100939099 /* CryptoAlg.c */; };
21DD8FBF161E9A250033C8F8 /* anonymous.c in Sources */ = {isa = PBXBuildFile; fileRef = 21DD8FBD161E9A250033C8F8 /* anonymous.c */; };
21DD8FC1161E9A250033C8F8 /* anonymous.h in Headers */ = {isa = PBXBuildFile; fileRef = 21DD8FBE161E9A250033C8F8 /* anonymous.h */; };
@@ -124,6 +176,7 @@
21F51DC11B3541940070B05C /* com.apple.mDNSResponder.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 21F51DBF1B35412D0070B05C /* com.apple.mDNSResponder.plist */; };
21F51DC31B3541F50070B05C /* com.apple.mDNSResponderHelper.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 21F51DBE1B3541030070B05C /* com.apple.mDNSResponderHelper.plist */; };
21F51DC51B3542210070B05C /* com.apple.dnsextd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 21F51DBD1B3540DB0070B05C /* com.apple.dnsextd.plist */; };
+ 220ABBF21D78F10F008423A7 /* D2D.h in Headers */ = {isa = PBXBuildFile; fileRef = 220ABBF11D78F102008423A7 /* D2D.h */; };
222A3C5B1C1B75F2003A6FFD /* DNSServiceDiscoveryDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 222A3C581C1B743B003A6FFD /* DNSServiceDiscoveryDefines.h */; };
222A3C6A1C1B7777003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; };
222A3C6B1C1B7778003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; };
@@ -131,11 +184,11 @@
222A3C6D1C1B777A003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; };
222A3C6E1C1B777B003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; };
222A3C6F1C1B777C003A6FFD /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = 222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */; };
- 2243AE391C90AECF0079023E /* CoreBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2243AE381C90AECF0079023E /* CoreBluetooth.framework */; };
22448EA31C90A7BE004F25CC /* BLE.c in Sources */ = {isa = PBXBuildFile; fileRef = 22448EA11C90A7B5004F25CC /* BLE.c */; };
22448EA41C90A7CB004F25CC /* BLE.h in Headers */ = {isa = PBXBuildFile; fileRef = 22448EA21C90A7B5004F25CC /* BLE.h */; };
22448EA71C90A837004F25CC /* coreBLE.h in Headers */ = {isa = PBXBuildFile; fileRef = 22448EA51C90A82D004F25CC /* coreBLE.h */; };
227687F31C90AD580019382D /* coreBLE.m in Sources */ = {isa = PBXBuildFile; fileRef = 22448EA61C90A82D004F25CC /* coreBLE.m */; };
+ 22C7633E1D777B940077AFCA /* D2D.c in Sources */ = {isa = PBXBuildFile; fileRef = 22C7633D1D777B8C0077AFCA /* D2D.c */; };
2E0405F50C3195F700F13B59 /* helper.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405F40C3195F700F13B59 /* helper.c */; };
2E0406150C3197CB00F13B59 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E0406140C3197CB00F13B59 /* libbsm.dylib */; };
2E04070A0C31EEEC00F13B59 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
@@ -158,7 +211,59 @@
371D0FBC1BF545FA00E5DB26 /* InterfaceTest.c in Sources */ = {isa = PBXBuildFile; fileRef = 371D0FBA1BF545FA00E5DB26 /* InterfaceTest.c */; };
371D0FBF1BF666EB00E5DB26 /* ResourceRecordTest.c in Sources */ = {isa = PBXBuildFile; fileRef = 371D0FBD1BF666EB00E5DB26 /* ResourceRecordTest.c */; };
373202101BAB4444007DE806 /* DNSMessageTest.c in Sources */ = {isa = PBXBuildFile; fileRef = 3732020F1BAB4349007DE806 /* DNSMessageTest.c */; };
+ 37538DFC1D7A424500226BE4 /* dnssd_ipc.h in Headers */ = {isa = PBXBuildFile; fileRef = F5E11B5B04A28126019798ED /* dnssd_ipc.h */; };
+ 37538DFD1D7A425700226BE4 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
+ 37538DFE1D7A427B00226BE4 /* helper-server.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EDC5E720C39EA640092701B /* helper-server.h */; };
+ 37538DFF1D7A428500226BE4 /* helpermsg-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */; };
+ 37538E001D7A429900226BE4 /* CryptoAlg.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F4B145B2AE100939099 /* CryptoAlg.h */; };
+ 37538E011D7A429900226BE4 /* CryptoSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F52145B2B1400939099 /* CryptoSupport.h */; };
+ 37538E021D7A42B000226BE4 /* nsec.h in Headers */ = {isa = PBXBuildFile; fileRef = 2124FA2B1471E98C0021D7BB /* nsec.h */; };
+ 37538E031D7A42B000226BE4 /* nsec3.h in Headers */ = {isa = PBXBuildFile; fileRef = 2127A47615C3C7B900A857FC /* nsec3.h */; };
+ 37538E041D7A42BE00226BE4 /* BLE.h in Headers */ = {isa = PBXBuildFile; fileRef = 22448EA21C90A7B5004F25CC /* BLE.h */; };
+ 37538E051D7A42D000226BE4 /* DNSServiceDiscoveryDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 222A3C581C1B743B003A6FFD /* DNSServiceDiscoveryDefines.h */; };
+ 37538E061D7A42DA00226BE4 /* dnsproxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 218E8E50156D8C0300720DA0 /* dnsproxy.h */; };
+ 37538E071D7A42E200226BE4 /* coreBLE.h in Headers */ = {isa = PBXBuildFile; fileRef = 22448EA51C90A82D004F25CC /* coreBLE.h */; };
+ 37538E081D7A42F000226BE4 /* dns_xpc.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5D516547F7200D2E8B4 /* dns_xpc.h */; };
+ 37538E091D7A42FC00226BE4 /* xpc_services.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5C9165477EB00D2E8B4 /* xpc_services.h */; };
+ 37538E0A1D7A430600226BE4 /* anonymous.h in Headers */ = {isa = PBXBuildFile; fileRef = 21DD8FBE161E9A250033C8F8 /* anonymous.h */; };
+ 37538E0B1D7A432200226BE4 /* Metrics.h in Headers */ = {isa = PBXBuildFile; fileRef = BDA3F0871C48DB6D0054FB4B /* Metrics.h */; };
+ 37538E0C1D7A435200226BE4 /* dnssec.h in Headers */ = {isa = PBXBuildFile; fileRef = 2124FA2F1471E9B50021D7BB /* dnssec.h */; };
+ 37538E0D1D7A437300226BE4 /* DNSSECSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21070E5E16486B9000A69507 /* DNSSECSupport.h */; };
+ 37538E141D7A43B600226BE4 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 37538E131D7A43B600226BE4 /* libicucore.dylib */; };
+ 37538E1B1D7A442300226BE4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDA3F0891C48DB910054FB4B /* Foundation.framework */; };
+ 37538E1C1D7A449000226BE4 /* Metrics.m in Sources */ = {isa = PBXBuildFile; fileRef = BDA3F0881C48DB6D0054FB4B /* Metrics.m */; };
+ 37538E1D1D7A449D00226BE4 /* coreBLE.m in Sources */ = {isa = PBXBuildFile; fileRef = 22448EA61C90A82D004F25CC /* coreBLE.m */; };
+ 37538E1E1D7A4F9D00226BE4 /* anonymous.c in Sources */ = {isa = PBXBuildFile; fileRef = 21DD8FBD161E9A250033C8F8 /* anonymous.c */; };
+ 37538E1F1D7A504F00226BE4 /* helper-stubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */; };
3771F67D1BA387DD0072355E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 37DDE9351BA386E70092AC61 /* main.c */; };
+ 37812CD41D7A307200F34505 /* BLE.c in Sources */ = {isa = PBXBuildFile; fileRef = 22448EA11C90A7B5004F25CC /* BLE.c */; };
+ 37812CD71D7A307200F34505 /* CryptoAlg.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F4A145B2AE100939099 /* CryptoAlg.c */; };
+ 37812CD81D7A307200F34505 /* CryptoSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F51145B2B1400939099 /* CryptoSupport.c */; };
+ 37812CD91D7A307200F34505 /* daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBEC022EAF7200000109 /* daemon.c */; };
+ 37812CDA1D7A307200F34505 /* dns_services.c in Sources */ = {isa = PBXBuildFile; fileRef = 84C5B339166553AF00C324A8 /* dns_services.c */; };
+ 37812CDB1D7A307200F34505 /* DNSDigest.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F461DB5062DBF2900672BF3 /* DNSDigest.c */; };
+ 37812CDE1D7A307200F34505 /* dnsproxy.c in Sources */ = {isa = PBXBuildFile; fileRef = 218E8E4F156D8C0300720DA0 /* dnsproxy.c */; };
+ 37812CDF1D7A307200F34505 /* DNSProxySupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21DED43415702C0F0060B6B9 /* DNSProxySupport.c */; };
+ 37812CE01D7A307200F34505 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
+ 37812CE11D7A307300F34505 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
+ 37812CE21D7A307300F34505 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
+ 37812CE31D7A307300F34505 /* dnssec.c in Sources */ = {isa = PBXBuildFile; fileRef = 213BDC6C147319F400000896 /* dnssec.c */; };
+ 37812CE41D7A307300F34505 /* DNSSECSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21070E5D16486B9000A69507 /* DNSSECSupport.c */; };
+ 37812CE51D7A307300F34505 /* GenLinkedList.c in Sources */ = {isa = PBXBuildFile; fileRef = DBAAFE2C057E8F660085CAD0 /* GenLinkedList.c */; };
+ 37812CE91D7A307300F34505 /* LegacyNATTraversal.c in Sources */ = {isa = PBXBuildFile; fileRef = 7FC8F9D406D14E66007E879D /* LegacyNATTraversal.c */; };
+ 37812CEA1D7A307300F34505 /* mDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBE9022EAF5A00000109 /* mDNS.c */; };
+ 37812CEB1D7A307300F34505 /* mDNSDebug.c in Sources */ = {isa = PBXBuildFile; fileRef = DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */; };
+ 37812CEC1D7A307300F34505 /* mDNSMacOSX.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBEB022EAF7200000109 /* mDNSMacOSX.c */; };
+ 37812CED1D7A307300F34505 /* nsec.c in Sources */ = {isa = PBXBuildFile; fileRef = 2124FA321471E9DE0021D7BB /* nsec.c */; };
+ 37812CEE1D7A307300F34505 /* nsec3.c in Sources */ = {isa = PBXBuildFile; fileRef = 2127A47515C3C7B900A857FC /* nsec3.c */; };
+ 37812CEF1D7A307300F34505 /* P2PPacketFilter.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BD2B638134FE09F002B96D5 /* P2PPacketFilter.c */; };
+ 37812CF11D7A307300F34505 /* PlatformCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FFCB6D73075D539900B8AF62 /* PlatformCommon.c */; };
+ 37812CF21D7A307300F34505 /* SymptomReporter.c in Sources */ = {isa = PBXBuildFile; fileRef = BD03E88C1AD31278005E8A81 /* SymptomReporter.c */; };
+ 37812CF31D7A307300F34505 /* uDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F70587CEF6001880B3 /* uDNS.c */; };
+ 37812CF41D7A307300F34505 /* uDNSPathEvalulation.c in Sources */ = {isa = PBXBuildFile; fileRef = 216D9ACD1720C9F5008066E1 /* uDNSPathEvalulation.c */; };
+ 37812CF51D7A307300F34505 /* uds_daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = F525E72804AA167501F1CF4D /* uds_daemon.c */; };
+ 37812CF61D7A307300F34505 /* dnsctl_server.c in Sources */ = {isa = PBXBuildFile; fileRef = 8417375A1B967CBE000CD5C2 /* dnsctl_server.c */; };
+ 37812CF71D7A307300F34505 /* xpc_services.c in Sources */ = {isa = PBXBuildFile; fileRef = 848DA5C6165477E000D2E8B4 /* xpc_services.c */; };
37DDE9331BA383D30092AC61 /* unittest.c in Sources */ = {isa = PBXBuildFile; fileRef = 37DDE9271BA3825C0092AC61 /* unittest.c */; };
37FEBD581BC789AA00638EA4 /* DNSCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F60587CEF6001880B3 /* DNSCommon.c */; };
4A7B9E8014FDA25000B84CC1 /* mDNSResponder.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A7B9E7E14FDA1BB00B84CC1 /* mDNSResponder.plist */; };
@@ -175,13 +280,60 @@
848DA5D616547F7200D2E8B4 /* dns_xpc.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5D516547F7200D2E8B4 /* dns_xpc.h */; };
84C5B33C166553F100C324A8 /* dns_services.c in Sources */ = {isa = PBXBuildFile; fileRef = 84C5B339166553AF00C324A8 /* dns_services.c */; };
84F4C090188F050200D1E1DE /* dns_services.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F4C08F188F04CF00D1E1DE /* dns_services.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ B7016F521D5D0D2900107E7C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B7016F511D5D0D2900107E7C /* Localizable.strings */; };
+ B701E7041D9DD811008F3022 /* BonjourSCStore.m in Sources */ = {isa = PBXBuildFile; fileRef = B701E7031D9DD811008F3022 /* BonjourSCStore.m */; };
+ B7024D171E82FA9500312DEF /* com.apple.preference.bonjour.tool.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = B76783AC1E82D65900DA271E /* com.apple.preference.bonjour.tool.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+ B71C8B091E79F2CD00E99939 /* BonjourSCStore.m in Sources */ = {isa = PBXBuildFile; fileRef = B701E7031D9DD811008F3022 /* BonjourSCStore.m */; };
+ B7325FE81DA4737400663834 /* CNBrowseDomainsController.m in Sources */ = {isa = PBXBuildFile; fileRef = B7325FE71DA4737400663834 /* CNBrowseDomainsController.m */; };
+ B7325FF71DA47F9100663834 /* CNDomainBrowserViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = B7A214081D1B29D6005F7DD9 /* CNDomainBrowserViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ B7325FF81DA47FB000663834 /* CNDomainBrowserViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B7A214091D1B29D6005F7DD9 /* CNDomainBrowserViewController.m */; };
+ B7325FF91DA47FB000663834 /* _CNDomainBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = B7D6CA5E1D107573005E24CF /* _CNDomainBrowser.m */; };
+ B7325FFD1DA4809400663834 /* DomainBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = B74EC1271D494C5800A1D155 /* DomainBrowser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ B7325FFF1DA480A500663834 /* DomainBrowser.strings in Resources */ = {isa = PBXBuildFile; fileRef = B7016F4F1D5D0D1900107E7C /* DomainBrowser.strings */; };
+ B74A96261DD4EDE60084A8C5 /* Preferences.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B74A96251DD4EDE60084A8C5 /* Preferences.framework */; };
+ B74F2B461E82FEAE0084960E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDA3F0891C48DB910054FB4B /* Foundation.framework */; };
+ B74F2B471E82FEFE0084960E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
+ B75700241E8347A6005CD56C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B75700231E8347A6005CD56C /* InfoPlist.strings */; };
+ B764319F1DB0423800DB376D /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF5852100DD27BD300862BDF /* ClientCommon.c */; };
+ B76431A01DB0423900DB376D /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF5852100DD27BD300862BDF /* ClientCommon.c */; };
+ B76783C11E82D8F500DA271E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B76783BC1E82D8F500DA271E /* main.m */; };
+ B76783C21E82D8F500DA271E /* BonjourPrefTool.m in Sources */ = {isa = PBXBuildFile; fileRef = B76783BE1E82D8F500DA271E /* BonjourPrefTool.m */; };
+ B7706AA91DB83E9A00593FD5 /* CNDomainBrowserView.m in Sources */ = {isa = PBXBuildFile; fileRef = B7D6CA691D1076C6005E24CF /* CNDomainBrowserView.m */; };
+ B7706AAA1DB83EA700593FD5 /* _CNDomainBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = B7D6CA5E1D107573005E24CF /* _CNDomainBrowser.m */; };
+ B7706AAB1DB83EAC00593FD5 /* CNDomainBrowserPathUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = B799209E1DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.m */; };
+ B7706AAD1DBA9C0F00593FD5 /* CNDomainBrowserViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B7A214091D1B29D6005F7DD9 /* CNDomainBrowserViewController.m */; };
+ B7706AAE1DBA9C1800593FD5 /* _CNDomainBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = B7D6CA5E1D107573005E24CF /* _CNDomainBrowser.m */; };
+ B7706AAF1DBA9C1800593FD5 /* CNDomainBrowserPathUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = B799209E1DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.m */; };
+ B778EE4D1D51113800C814A2 /* HostnameController.m in Sources */ = {isa = PBXBuildFile; fileRef = B778EE4B1D51113800C814A2 /* HostnameController.m */; };
+ B778EE501D51287100C814A2 /* BonjourSettingsController.m in Sources */ = {isa = PBXBuildFile; fileRef = B778EE4F1D51287100C814A2 /* BonjourSettingsController.m */; };
+ B79568351D53F693005E3BED /* DomainBrowser.h in Headers */ = {isa = PBXBuildFile; fileRef = B74EC12B1D494C7200A1D155 /* DomainBrowser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ B79568361D53F69B005E3BED /* CNDomainBrowserView.h in Headers */ = {isa = PBXBuildFile; fileRef = B7D6CA681D1076C6005E24CF /* CNDomainBrowserView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ B799209F1DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = B799209D1DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ B79920A01DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = B799209D1DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ B79920A11DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = B799209E1DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.m */; };
+ B79920A21DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = B799209E1DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.m */; };
+ B79920A41DA6C49700C6E02B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B79920A31DA6C49700C6E02B /* Assets.xcassets */; };
+ B7D566C91E81DA0000E43008 /* com.apple.preference.bonjour.remoteservice.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = B7D566BA1E81D8FD00E43008 /* com.apple.preference.bonjour.remoteservice.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+ B7D566CD1E81DDB600E43008 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDA3F0891C48DB910054FB4B /* Foundation.framework */; };
+ B7D566CE1E81DDB600E43008 /* PreferencePanes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */; };
+ B7D566D01E81DEC200E43008 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B7D566AC1E81D6A900E43008 /* main.m */; };
+ B7D566D11E81DEC400E43008 /* BonjourPrefRemoteViewService.m in Sources */ = {isa = PBXBuildFile; fileRef = B7D566A81E81D6A900E43008 /* BonjourPrefRemoteViewService.m */; };
+ B7D566D51E81E14E00E43008 /* ViewBridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B7D566D41E81E14E00E43008 /* ViewBridge.framework */; };
+ B7D6CA791D10770F005E24CF /* _CNDomainBrowser.m in Sources */ = {isa = PBXBuildFile; fileRef = B7D6CA5E1D107573005E24CF /* _CNDomainBrowser.m */; };
+ B7D6CA7A1D107714005E24CF /* CNDomainBrowserView.m in Sources */ = {isa = PBXBuildFile; fileRef = B7D6CA691D1076C6005E24CF /* CNDomainBrowserView.m */; };
+ B7E06B0D1DBA9DFE00E4580C /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF5852100DD27BD300862BDF /* ClientCommon.c */; };
+ B7E06B0E1DBA9E9700E4580C /* DomainBrowser.strings in Resources */ = {isa = PBXBuildFile; fileRef = B7016F4F1D5D0D1900107E7C /* DomainBrowser.strings */; };
BD03E88D1AD31278005E8A81 /* SymptomReporter.c in Sources */ = {isa = PBXBuildFile; fileRef = BD03E88C1AD31278005E8A81 /* SymptomReporter.c */; };
+ BD691B2A1ED2F47100E6F317 /* DNS64.c in Sources */ = {isa = PBXBuildFile; fileRef = BD691B281ED2F43200E6F317 /* DNS64.c */; };
+ BD691B2B1ED2F4AB00E6F317 /* DNS64.h in Headers */ = {isa = PBXBuildFile; fileRef = BD691B291ED2F43200E6F317 /* DNS64.h */; };
+ BD9BA7551EAF91FB00658CCF /* dnssdutil.c in Sources */ = {isa = PBXBuildFile; fileRef = BD9BA7541EAF91E700658CCF /* dnssdutil.c */; };
+ BD9BA7581EAF929C00658CCF /* CoreUtils.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BD9BA7571EAF929C00658CCF /* CoreUtils.framework */; };
BDA3F08A1C48DB920054FB4B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDA3F0891C48DB910054FB4B /* Foundation.framework */; };
- BDA3F08D1C48DBEA0054FB4B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDA3F0891C48DB910054FB4B /* Foundation.framework */; };
BDA3F08E1C48DCA50054FB4B /* Metrics.h in Headers */ = {isa = PBXBuildFile; fileRef = BDA3F0871C48DB6D0054FB4B /* Metrics.h */; };
BDA3F08F1C48DCA50054FB4B /* Metrics.m in Sources */ = {isa = PBXBuildFile; fileRef = BDA3F0881C48DB6D0054FB4B /* Metrics.m */; };
BDA9A7881B3A924C00523835 /* dns_sd_private.h in Headers */ = {isa = PBXBuildFile; fileRef = BDA9A7871B3A923600523835 /* dns_sd_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
BDA9A7891B3A92A500523835 /* dns_sd_private.h in Headers */ = {isa = PBXBuildFile; fileRef = BDA9A7871B3A923600523835 /* dns_sd_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ BDBF9B941ED74B9C001498A8 /* DNS64State.h in Headers */ = {isa = PBXBuildFile; fileRef = BDBF9B931ED74B8C001498A8 /* DNS64State.h */; };
D284BE540ADD80740027CCDF /* dnssd_ipc.h in Headers */ = {isa = PBXBuildFile; fileRef = F5E11B5B04A28126019798ED /* dnssd_ipc.h */; };
D284BE580ADD80740027CCDF /* mDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBE9022EAF5A00000109 /* mDNS.c */; };
D284BE590ADD80740027CCDF /* uDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F70587CEF6001880B3 /* uDNS.c */; };
@@ -217,39 +369,25 @@
D284BED10ADD80A20027CCDF /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA213D02786FC30CCA2C71 /* IOKit.framework */; };
D284BED20ADD80A20027CCDF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
D284BED50ADD80A20027CCDF /* dnsextd.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FFF4F63A06CFE4DD00459EFD /* dnsextd.8 */; };
- D284BEDE0ADD80A70027CCDF /* ddnswriteconfig.m in Sources */ = {isa = PBXBuildFile; fileRef = FFFB0DAF07B43CBA00B88D48 /* ddnswriteconfig.m */; };
- D284BEE10ADD80A70027CCDF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
- D284BEE20ADD80A70027CCDF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
- D284BEE30ADD80A70027CCDF /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
- D284BEEF0ADD80B00027CCDF /* remove_idle.tiff in Resources */ = {isa = PBXBuildFile; fileRef = FF260A2407B4464B00CE10E5 /* remove_idle.tiff */; };
- D284BEF00ADD80B00027CCDF /* add_pressed.tiff in Resources */ = {isa = PBXBuildFile; fileRef = FF260A2507B4464B00CE10E5 /* add_pressed.tiff */; };
- D284BEF10ADD80B00027CCDF /* remove_disabled.tiff in Resources */ = {isa = PBXBuildFile; fileRef = FF260A2607B4464B00CE10E5 /* remove_disabled.tiff */; };
- D284BEF20ADD80B00027CCDF /* add_idle.tiff in Resources */ = {isa = PBXBuildFile; fileRef = FF260A2707B4464B00CE10E5 /* add_idle.tiff */; };
D284BEF30ADD80B00027CCDF /* success.tiff in Resources */ = {isa = PBXBuildFile; fileRef = FF260A2807B4464B00CE10E5 /* success.tiff */; };
- D284BEF40ADD80B00027CCDF /* remove_pressed.tiff in Resources */ = {isa = PBXBuildFile; fileRef = FF260A2907B4464B00CE10E5 /* remove_pressed.tiff */; };
D284BEF50ADD80B00027CCDF /* failure.tiff in Resources */ = {isa = PBXBuildFile; fileRef = FF260A2A07B4464B00CE10E5 /* failure.tiff */; };
D284BEF60ADD80B00027CCDF /* BonjourPref.icns in Resources */ = {isa = PBXBuildFile; fileRef = FF260A3207B4466900CE10E5 /* BonjourPref.icns */; };
D284BEF70ADD80B00027CCDF /* BonjourPref.tiff in Resources */ = {isa = PBXBuildFile; fileRef = FF260A3307B4466900CE10E5 /* BonjourPref.tiff */; };
D284BEF80ADD80B00027CCDF /* DNSServiceDiscoveryPref.nib in Resources */ = {isa = PBXBuildFile; fileRef = FF260A4807B4475600CE10E5 /* DNSServiceDiscoveryPref.nib */; };
D284BEF90ADD80B00027CCDF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FF260A4B07B4477F00CE10E5 /* InfoPlist.strings */; };
D284BEFB0ADD80B00027CCDF /* inprogress.tiff in Resources */ = {isa = PBXBuildFile; fileRef = FF08480607CEB8E800AE6769 /* inprogress.tiff */; };
- D284BEFC0ADD80B00027CCDF /* installtool in Resources */ = {isa = PBXBuildFile; fileRef = FF354EB108516C63007C00E1 /* installtool */; };
D284BEFE0ADD80B00027CCDF /* DNSServiceDiscoveryPref.m in Sources */ = {isa = PBXBuildFile; fileRef = FFFB0DAC07B43CBA00B88D48 /* DNSServiceDiscoveryPref.m */; };
- D284BEFF0ADD80B00027CCDF /* PrivilegedOperations.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFB0DAD07B43CBA00B88D48 /* PrivilegedOperations.c */; };
- D284BF000ADD80B00027CCDF /* ConfigurationAuthority.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFB0DAE07B43CBA00B88D48 /* ConfigurationAuthority.c */; };
D284BF020ADD80B00027CCDF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
D284BF030ADD80B00027CCDF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
D284BF040ADD80B00027CCDF /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF2609FA07B4433800CE10E5 /* Cocoa.framework */; };
D284BF050ADD80B00027CCDF /* PreferencePanes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */; };
D284BF060ADD80B00027CCDF /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
- FF3C72AA1CE3E62200CDF81E /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FF3C72A91CE3E62200CDF81E /* libicucore.dylib */; };
FFA572330AF18F1C0055A0F1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
FFA572340AF18F1C0055A0F1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
FFA572350AF18F1C0055A0F1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
FFA5723F0AF18F450055A0F1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
FFA572400AF18F450055A0F1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
FFA572410AF18F450055A0F1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
- FFAE66F0105F0CD900162116 /* ddnswriteconfig in Resources */ = {isa = PBXBuildFile; fileRef = D284BEE80ADD80A70027CCDF /* ddnswriteconfig */; };
FFB437150EB165BD00E17C68 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA213D02786FC30CCA2C71 /* IOKit.framework */; };
FFD52A9E1AF858DD00CAD3EC /* CryptoAlg.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F4B145B2AE100939099 /* CryptoAlg.h */; };
FFF589B70E37F66800EF515C /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF5852100DD27BD300862BDF /* ClientCommon.c */; };
@@ -313,6 +451,13 @@
remoteGlobalIDString = 03067D640C83A3700022BE1F;
remoteInfo = "Build Some";
};
+ 0C1596C61D7751AD00E09998 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 0C1596AB1D773FE300E09998;
+ remoteInfo = mDNSNetMonitor;
+ };
0C2AAB311B6929F300113637 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
@@ -320,6 +465,20 @@
remoteGlobalIDString = 84C5B3341665529800C324A8;
remoteInfo = dns_services;
};
+ 0C4F36B31E206711005A536B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 37DDE92C1BA383610092AC61;
+ remoteInfo = unittests;
+ };
+ 0C52E92E1E96AD74006EFE7B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 0C635A751E9418A60026C796;
+ remoteInfo = BonjourTop;
+ };
2130257012400E9300AC839F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
@@ -383,6 +542,34 @@
remoteGlobalIDString = 84C5B3341665529800C324A8;
remoteInfo = dns_services;
};
+ B76783B81E82D83800DA271E /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B76783AB1E82D65900DA271E;
+ remoteInfo = ddnsWriteTool;
+ };
+ B7C4B72B1E71BD6000136C7A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B74EC1151D47FC7700A1D155;
+ remoteInfo = BonjourSettings;
+ };
+ B7C4B72D1E71BE3500136C7A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 03067D640C83A3700022BE1F;
+ remoteInfo = "Build Some";
+ };
+ B7D566C71E81D9E700E43008 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = B7D566B91E81D8FD00E43008;
+ remoteInfo = RemoteViewService;
+ };
BD7833EF1ABA5E3500EC51ED /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
@@ -390,19 +577,19 @@
remoteGlobalIDString = 72FB545E166D5FB00090B2D9;
remoteInfo = dnsctl;
};
- D284BF2B0ADD815A0027CCDF /* PBXContainerItemProxy */ = {
+ BD9BA7711EAFA3D500658CCF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = D284BEBF0ADD80A20027CCDF;
- remoteInfo = dnsextd;
+ remoteGlobalIDString = BD9BA7481EAF90E400658CCF;
+ remoteInfo = dnssdutil;
};
- D284BF2D0ADD81600027CCDF /* PBXContainerItemProxy */ = {
+ D284BF2B0ADD815A0027CCDF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = D284BEDB0ADD80A70027CCDF;
- remoteInfo = ddnswriteconfig;
+ remoteGlobalIDString = D284BEBF0ADD80A20027CCDF;
+ remoteInfo = dnsextd;
};
D284BF2F0ADD81630027CCDF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
@@ -432,13 +619,6 @@
remoteGlobalIDString = FFA5723C0AF18F450055A0F1;
remoteInfo = "libdns_sd profile";
};
- FFAE66F8105F0CF100162116 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = D284BEDB0ADD80A70027CCDF;
- remoteInfo = ddnswriteconfig;
- };
FFB7657C0AEED97F00583A2C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
@@ -449,6 +629,25 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
+ 0C1596AA1D773FE300E09998 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8;
+ dstSubfolderSpec = 0;
+ files = (
+ 0C6FB90F1D77767300DF6F51 /* mDNSNetMonitor.8 in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 0C635A741E9418A60026C796 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
21F51DC01B35418C0070B05C /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
@@ -528,6 +727,17 @@
);
runOnlyForDeploymentPostprocessing = 1;
};
+ B7D566C61E81D9B600E43008 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "$(CONTENTS_FOLDER_PATH)/XPCServices";
+ dstSubfolderSpec = 16;
+ files = (
+ B7D566C91E81DA0000E43008 /* com.apple.preference.bonjour.remoteservice.xpc in CopyFiles */,
+ B7024D171E82FA9500312DEF /* com.apple.preference.bonjour.tool.xpc in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
D284BE6A0ADD80740027CCDF /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
@@ -574,6 +784,36 @@
000753D303367C1C0CCA2C71 /* mDNSMacOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mDNSMacOSX.h; sourceTree = "<group>"; };
00CA213D02786FC30CCA2C71 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = "<absolute>"; };
09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
+ 0C10EC261DDB956000D7A0E3 /* LocalOnlyTimeoutTests.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = LocalOnlyTimeoutTests.c; path = ../unittests/LocalOnlyTimeoutTests.c; sourceTree = "<group>"; };
+ 0C10EC271DDB956000D7A0E3 /* LocalOnlyTimeoutTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LocalOnlyTimeoutTests.h; path = ../unittests/LocalOnlyTimeoutTests.h; sourceTree = "<group>"; };
+ 0C1596AC1D773FE300E09998 /* mDNSNetMonitor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mDNSNetMonitor; sourceTree = BUILT_PRODUCTS_DIR; };
+ 0C1596B31D7740B500E09998 /* mDNSPosix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mDNSPosix.c; path = ../../mDNSPosix/mDNSPosix.c; sourceTree = "<group>"; };
+ 0C1596B41D7740B500E09998 /* NetMonitor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NetMonitor.c; path = ../../mDNSPosix/NetMonitor.c; sourceTree = "<group>"; };
+ 0C1596B71D7740C100E09998 /* mDNSUNP.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mDNSUNP.c; path = ../../mDNSPosix/mDNSUNP.c; sourceTree = "<group>"; };
+ 0C5674B11DA2BF6300AF3367 /* mDNSCoreReceiveTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mDNSCoreReceiveTest.h; path = ../unittests/mDNSCoreReceiveTest.h; sourceTree = "<group>"; };
+ 0C5674B21DA2BF6300AF3367 /* mDNSCoreReceiveTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mDNSCoreReceiveTest.c; path = ../unittests/mDNSCoreReceiveTest.c; sourceTree = "<group>"; };
+ 0C635A761E9418A60026C796 /* bonjourtop */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = bonjourtop; sourceTree = BUILT_PRODUCTS_DIR; };
+ 0C635A7D1E9418D90026C796 /* bjIPAddr.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bjIPAddr.cpp; path = source/bjIPAddr.cpp; sourceTree = "<group>"; };
+ 0C635A7E1E9418D90026C796 /* bjMACAddr.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bjMACAddr.cpp; path = source/bjMACAddr.cpp; sourceTree = "<group>"; };
+ 0C635A7F1E9418D90026C796 /* bjsocket.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bjsocket.cpp; path = source/bjsocket.cpp; sourceTree = "<group>"; };
+ 0C635A801E9418D90026C796 /* bjstring.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bjstring.cpp; path = source/bjstring.cpp; sourceTree = "<group>"; };
+ 0C635A811E9418D90026C796 /* bjStringtoStringMap.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bjStringtoStringMap.cpp; path = source/bjStringtoStringMap.cpp; sourceTree = "<group>"; };
+ 0C635A821E9418D90026C796 /* BonjourTop.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = BonjourTop.cpp; path = source/BonjourTop.cpp; sourceTree = "<group>"; };
+ 0C635A831E9418D90026C796 /* CaptureFile.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CaptureFile.cpp; path = source/CaptureFile.cpp; sourceTree = "<group>"; };
+ 0C635A841E9418D90026C796 /* CollectBy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CollectBy.cpp; path = source/CollectBy.cpp; sourceTree = "<group>"; };
+ 0C635A851E9418D90026C796 /* DNSFrame.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DNSFrame.cpp; path = source/DNSFrame.cpp; sourceTree = "<group>"; };
+ 0C635A861E9418D90026C796 /* Frame.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Frame.cpp; path = source/Frame.cpp; sourceTree = "<group>"; };
+ 0C635A871E9418D90026C796 /* LLRBTree.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LLRBTree.cpp; path = source/LLRBTree.cpp; sourceTree = "<group>"; };
+ 0C635A881E9418D90026C796 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = source/main.cpp; sourceTree = "<group>"; };
+ 0C6FB90E1D775FE900DF6F51 /* mDNSNetMonitor.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mDNSNetMonitor.8; sourceTree = "<group>"; };
+ 0C7C00491DD553490078BA89 /* unittest_common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = unittest_common.c; path = ../unittests/unittest_common.c; sourceTree = "<group>"; };
+ 0C7C004A1DD553490078BA89 /* unittest_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = unittest_common.h; path = ../unittests/unittest_common.h; sourceTree = "<group>"; };
+ 0C7C004B1DD553490078BA89 /* mdns_macosx_ut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mdns_macosx_ut.c; path = ../unittests/mdns_macosx_ut.c; sourceTree = "<group>"; };
+ 0C7C004C1DD553490078BA89 /* mdns_ut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mdns_ut.c; path = ../unittests/mdns_ut.c; sourceTree = "<group>"; };
+ 0C7C004D1DD553490078BA89 /* uds_daemon_ut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = uds_daemon_ut.c; path = ../unittests/uds_daemon_ut.c; sourceTree = "<group>"; };
+ 0C7C004E1DD553490078BA89 /* CNameRecordTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CNameRecordTests.h; path = ../unittests/CNameRecordTests.h; sourceTree = "<group>"; };
+ 0C7C004F1DD553490078BA89 /* CNameRecordTests.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CNameRecordTests.c; path = ../unittests/CNameRecordTests.c; sourceTree = "<group>"; };
+ 0C84A2911E786AFF00E8B4C7 /* daemon_ut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = daemon_ut.c; path = ../unittests/daemon_ut.c; sourceTree = "<group>"; };
21070E5D16486B9000A69507 /* DNSSECSupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DNSSECSupport.c; sourceTree = "<group>"; };
21070E5E16486B9000A69507 /* DNSSECSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSSECSupport.h; sourceTree = "<group>"; };
2124FA2B1471E98C0021D7BB /* nsec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nsec.h; path = ../mDNSCore/nsec.h; sourceTree = "<group>"; };
@@ -603,14 +843,15 @@
21F51DBD1B3540DB0070B05C /* com.apple.dnsextd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.dnsextd.plist; sourceTree = "<group>"; };
21F51DBE1B3541030070B05C /* com.apple.mDNSResponderHelper.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.mDNSResponderHelper.plist; sourceTree = "<group>"; };
21F51DBF1B35412D0070B05C /* com.apple.mDNSResponder.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.mDNSResponder.plist; sourceTree = "<group>"; };
+ 220ABBF11D78F102008423A7 /* D2D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = D2D.h; sourceTree = "<group>"; };
222A3C561C1B7415003A6FFD /* DNSServiceDiscovery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DNSServiceDiscovery.c; sourceTree = "<group>"; };
222A3C571C1B743B003A6FFD /* DNSServiceDiscovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscovery.h; sourceTree = "<group>"; };
222A3C581C1B743B003A6FFD /* DNSServiceDiscoveryDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscoveryDefines.h; sourceTree = "<group>"; };
- 2243AE381C90AECF0079023E /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; };
22448EA11C90A7B5004F25CC /* BLE.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BLE.c; sourceTree = "<group>"; };
22448EA21C90A7B5004F25CC /* BLE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BLE.h; sourceTree = "<group>"; };
22448EA51C90A82D004F25CC /* coreBLE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coreBLE.h; sourceTree = "<group>"; };
22448EA61C90A82D004F25CC /* coreBLE.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = coreBLE.m; sourceTree = "<group>"; };
+ 22C7633D1D777B8C0077AFCA /* D2D.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = D2D.c; sourceTree = "<group>"; };
2E0405F00C31955500F13B59 /* mDNSResponderHelper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mDNSResponderHelper; sourceTree = BUILT_PRODUCTS_DIR; };
2E0405F40C3195F700F13B59 /* helper.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = helper.c; sourceTree = "<group>"; };
2E0406140C3197CB00F13B59 /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = /usr/lib/libbsm.dylib; sourceTree = "<absolute>"; };
@@ -626,6 +867,7 @@
371D0FBE1BF666EB00E5DB26 /* ResourceRecordTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ResourceRecordTest.h; path = ../unittests/ResourceRecordTest.h; sourceTree = "<group>"; };
3732020F1BAB4349007DE806 /* DNSMessageTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = DNSMessageTest.c; path = ../unittests/DNSMessageTest.c; sourceTree = "<group>"; };
373202111BAB63E8007DE806 /* DNSMessageTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DNSMessageTest.h; path = ../unittests/DNSMessageTest.h; sourceTree = "<group>"; };
+ 37538E131D7A43B600226BE4 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; };
37AF802A1BF699AF00D657F6 /* DomainNameTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = DomainNameTest.c; path = ../unittests/DomainNameTest.c; sourceTree = "<group>"; };
37AF802B1BF699AF00D657F6 /* DomainNameTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DomainNameTest.h; path = ../unittests/DomainNameTest.h; sourceTree = "<group>"; };
37DDE9271BA3825C0092AC61 /* unittest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = unittest.c; path = ../unittests/unittest.c; sourceTree = "<group>"; };
@@ -665,16 +907,66 @@
84C5B3351665529800C324A8 /* libdns_services.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libdns_services.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
84C5B339166553AF00C324A8 /* dns_services.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dns_services.c; path = Private/dns_services.c; sourceTree = "<group>"; };
84F4C08F188F04CF00D1E1DE /* dns_services.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_services.h; path = Private/dns_services.h; sourceTree = "<group>"; };
+ B7016F4F1D5D0D1900107E7C /* DomainBrowser.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = DomainBrowser.strings; sourceTree = "<group>"; };
+ B7016F511D5D0D2900107E7C /* Localizable.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = Localizable.strings; path = ../SettingsBundle/Localizable.strings; sourceTree = "<group>"; };
+ B701E7031D9DD811008F3022 /* BonjourSCStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BonjourSCStore.m; path = ../SettingsBundle/BonjourSCStore.m; sourceTree = "<group>"; };
+ B716801A1E8330B400459A35 /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = "<group>"; };
+ B72C96091D6236A500AD682A /* BonjourSCStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BonjourSCStore.h; path = ../SettingsBundle/BonjourSCStore.h; sourceTree = "<group>"; };
+ B7325FE61DA4737400663834 /* CNBrowseDomainsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CNBrowseDomainsController.h; path = ../SettingsBundle/CNBrowseDomainsController.h; sourceTree = "<group>"; };
+ B7325FE71DA4737400663834 /* CNBrowseDomainsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CNBrowseDomainsController.m; path = ../SettingsBundle/CNBrowseDomainsController.m; sourceTree = "<group>"; };
+ B7325FEE1DA47EBA00663834 /* DomainBrowser.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DomainBrowser.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ B74A96251DD4EDE60084A8C5 /* Preferences.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Preferences.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.Internal.sdk/System/Library/PrivateFrameworks/Preferences.framework; sourceTree = DEVELOPER_DIR; };
+ B74EC1161D47FC7700A1D155 /* BonjourSettings.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BonjourSettings.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+ B74EC11B1D47FC7800A1D155 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../SettingsBundle/Info.plist; sourceTree = "<group>"; };
+ B74EC1271D494C5800A1D155 /* DomainBrowser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DomainBrowser.h; sourceTree = "<group>"; };
+ B74EC1281D494C5800A1D155 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ B74EC1291D494C6700A1D155 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ B74EC12B1D494C7200A1D155 /* DomainBrowser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DomainBrowser.h; sourceTree = "<group>"; };
+ B75700231E8347A6005CD56C /* InfoPlist.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InfoPlist.strings; sourceTree = "<group>"; };
+ B76783AC1E82D65900DA271E /* com.apple.preference.bonjour.tool.xpc */ = {isa = PBXFileReference; explicitFileType = "wrapper.xpc-service"; includeInIndex = 0; path = com.apple.preference.bonjour.tool.xpc; sourceTree = BUILT_PRODUCTS_DIR; };
+ B76783BB1E82D8F500DA271E /* BonjourPrefTool-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "BonjourPrefTool-Info.plist"; sourceTree = "<group>"; };
+ B76783BC1E82D8F500DA271E /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ B76783BD1E82D8F500DA271E /* BonjourPrefTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BonjourPrefTool.h; sourceTree = "<group>"; };
+ B76783BE1E82D8F500DA271E /* BonjourPrefTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BonjourPrefTool.m; sourceTree = "<group>"; };
+ B76783BF1E82D8F500DA271E /* BonjourPrefToolProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BonjourPrefToolProtocol.h; sourceTree = "<group>"; };
+ B778EE4A1D51113800C814A2 /* HostnameController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostnameController.h; path = ../SettingsBundle/HostnameController.h; sourceTree = "<group>"; };
+ B778EE4B1D51113800C814A2 /* HostnameController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HostnameController.m; path = ../SettingsBundle/HostnameController.m; sourceTree = "<group>"; };
+ B778EE4E1D51287100C814A2 /* BonjourSettingsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BonjourSettingsController.h; path = ../SettingsBundle/BonjourSettingsController.h; sourceTree = "<group>"; };
+ B778EE4F1D51287100C814A2 /* BonjourSettingsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BonjourSettingsController.m; path = ../SettingsBundle/BonjourSettingsController.m; sourceTree = "<group>"; };
+ B799209D1DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CNDomainBrowserPathUtils.h; sourceTree = "<group>"; };
+ B799209E1DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CNDomainBrowserPathUtils.m; sourceTree = "<group>"; };
+ B79920A31DA6C49700C6E02B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = ../SettingsBundle/Assets.xcassets; sourceTree = "<group>"; };
+ B7A214081D1B29D6005F7DD9 /* CNDomainBrowserViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNDomainBrowserViewController.h; sourceTree = "<group>"; };
+ B7A214091D1B29D6005F7DD9 /* CNDomainBrowserViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CNDomainBrowserViewController.m; sourceTree = "<group>"; };
+ B7D566A51E81D6A900E43008 /* BonjourPrefRemoteViewService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "BonjourPrefRemoteViewService-Info.plist"; sourceTree = "<group>"; };
+ B7D566A71E81D6A900E43008 /* BonjourPrefRemoteViewService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BonjourPrefRemoteViewService.h; sourceTree = "<group>"; };
+ B7D566A81E81D6A900E43008 /* BonjourPrefRemoteViewService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BonjourPrefRemoteViewService.m; sourceTree = "<group>"; };
+ B7D566AB1E81D6A900E43008 /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = "<group>"; };
+ B7D566AC1E81D6A900E43008 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ B7D566BA1E81D8FD00E43008 /* com.apple.preference.bonjour.remoteservice.xpc */ = {isa = PBXFileReference; explicitFileType = "wrapper.xpc-service"; includeInIndex = 0; path = com.apple.preference.bonjour.remoteservice.xpc; sourceTree = BUILT_PRODUCTS_DIR; };
+ B7D566D41E81E14E00E43008 /* ViewBridge.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ViewBridge.framework; path = ../../../../../../System/Library/PrivateFrameworks/ViewBridge.framework; sourceTree = "<group>"; };
+ B7D6CA5D1D107573005E24CF /* _CNDomainBrowser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _CNDomainBrowser.h; sourceTree = "<group>"; };
+ B7D6CA5E1D107573005E24CF /* _CNDomainBrowser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = _CNDomainBrowser.m; sourceTree = "<group>"; };
+ B7D6CA681D1076C6005E24CF /* CNDomainBrowserView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNDomainBrowserView.h; sourceTree = "<group>"; };
+ B7D6CA691D1076C6005E24CF /* CNDomainBrowserView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CNDomainBrowserView.m; sourceTree = "<group>"; };
+ B7D6CA701D1076F3005E24CF /* DomainBrowser.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DomainBrowser.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ B7E5920F1DB687A700A38085 /* Base */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = Base; path = Base.lproj/DNSServiceDiscoveryPref.nib; sourceTree = "<group>"; };
BD03E88C1AD31278005E8A81 /* SymptomReporter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SymptomReporter.c; sourceTree = "<group>"; };
+ BD691B281ED2F43200E6F317 /* DNS64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DNS64.c; sourceTree = "<group>"; };
+ BD691B291ED2F43200E6F317 /* DNS64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNS64.h; sourceTree = "<group>"; };
+ BD9BA7531EAF90E400658CCF /* dnssdutil */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dnssdutil; sourceTree = BUILT_PRODUCTS_DIR; };
+ BD9BA7541EAF91E700658CCF /* dnssdutil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnssdutil.c; path = ../Clients/dnssdutil.c; sourceTree = "<group>"; };
+ BD9BA7571EAF929C00658CCF /* CoreUtils.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreUtils.framework; path = System/Library/PrivateFrameworks/CoreUtils.framework; sourceTree = SDKROOT; };
BDA3F0871C48DB6D0054FB4B /* Metrics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Metrics.h; sourceTree = "<group>"; };
BDA3F0881C48DB6D0054FB4B /* Metrics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Metrics.m; sourceTree = "<group>"; };
BDA3F0891C48DB910054FB4B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
- BDA9A7871B3A923600523835 /* dns_sd_private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dns_sd_private.h; path = Private/dns_sd_private.h; sourceTree = "<group>"; };
+ BDA9A7871B3A923600523835 /* dns_sd_private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dns_sd_private.h; path = ../mDNSShared/dns_sd_private.h; sourceTree = "<group>"; };
+ BDBF9B931ED74B8C001498A8 /* DNS64State.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNS64State.h; sourceTree = "<group>"; };
+ BDE238C11DF69D8300B9F696 /* dns_sd_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_sd_internal.h; path = ../mDNSShared/dns_sd_internal.h; sourceTree = "<group>"; };
D284BE730ADD80740027CCDF /* mDNSResponder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mDNSResponder; sourceTree = BUILT_PRODUCTS_DIR; };
D284BEB00ADD80920027CCDF /* dns-sd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "dns-sd"; sourceTree = BUILT_PRODUCTS_DIR; };
D284BEBE0ADD809A0027CCDF /* libjdns_sd.jnilib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libjdns_sd.jnilib; sourceTree = BUILT_PRODUCTS_DIR; };
D284BED90ADD80A20027CCDF /* dnsextd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dnsextd; sourceTree = BUILT_PRODUCTS_DIR; };
- D284BEE80ADD80A70027CCDF /* ddnswriteconfig */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ddnswriteconfig; sourceTree = BUILT_PRODUCTS_DIR; };
D284BF0C0ADD80B00027CCDF /* Bonjour.prefPane */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Bonjour.prefPane; sourceTree = BUILT_PRODUCTS_DIR; };
DB2CC4430662DD1100335AB3 /* BaseListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = BaseListener.java; path = ../mDNSShared/Java/BaseListener.java; sourceTree = SOURCE_ROOT; };
DB2CC4440662DD1100335AB3 /* BrowseListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = BrowseListener.java; path = ../mDNSShared/Java/BrowseListener.java; sourceTree = SOURCE_ROOT; };
@@ -703,21 +995,13 @@
FF25794606C9A8BF00376F7B /* dnsextd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnsextd.c; path = ../mDNSShared/dnsextd.c; sourceTree = SOURCE_ROOT; };
FF2609FA07B4433800CE10E5 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PreferencePanes.framework; path = /System/Library/Frameworks/PreferencePanes.framework; sourceTree = "<absolute>"; };
- FF260A2407B4464B00CE10E5 /* remove_idle.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = remove_idle.tiff; path = PreferencePane/Artwork/remove_idle.tiff; sourceTree = SOURCE_ROOT; };
- FF260A2507B4464B00CE10E5 /* add_pressed.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = add_pressed.tiff; path = PreferencePane/Artwork/add_pressed.tiff; sourceTree = SOURCE_ROOT; };
- FF260A2607B4464B00CE10E5 /* remove_disabled.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = remove_disabled.tiff; path = PreferencePane/Artwork/remove_disabled.tiff; sourceTree = SOURCE_ROOT; };
- FF260A2707B4464B00CE10E5 /* add_idle.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = add_idle.tiff; path = PreferencePane/Artwork/add_idle.tiff; sourceTree = SOURCE_ROOT; };
FF260A2807B4464B00CE10E5 /* success.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = success.tiff; path = PreferencePane/Artwork/success.tiff; sourceTree = SOURCE_ROOT; };
- FF260A2907B4464B00CE10E5 /* remove_pressed.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = remove_pressed.tiff; path = PreferencePane/Artwork/remove_pressed.tiff; sourceTree = SOURCE_ROOT; };
FF260A2A07B4464B00CE10E5 /* failure.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = failure.tiff; path = PreferencePane/Artwork/failure.tiff; sourceTree = SOURCE_ROOT; };
FF260A3207B4466900CE10E5 /* BonjourPref.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = BonjourPref.icns; path = PreferencePane/BonjourPref.icns; sourceTree = SOURCE_ROOT; };
FF260A3307B4466900CE10E5 /* BonjourPref.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = BonjourPref.tiff; path = PreferencePane/BonjourPref.tiff; sourceTree = SOURCE_ROOT; };
- FF260A4907B4475600CE10E5 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = PreferencePane/English.lproj/DNSServiceDiscoveryPref.nib; sourceTree = SOURCE_ROOT; };
FF260A4C07B4477F00CE10E5 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = PreferencePane/English.lproj/InfoPlist.strings; sourceTree = SOURCE_ROOT; };
FF2C5FB00A48B8680066DA11 /* DNSSDRecordRegistrar.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSSDRecordRegistrar.java; path = ../mDNSShared/Java/DNSSDRecordRegistrar.java; sourceTree = SOURCE_ROOT; };
FF2C5FB20A48B86E0066DA11 /* RegisterRecordListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = RegisterRecordListener.java; path = ../mDNSShared/Java/RegisterRecordListener.java; sourceTree = SOURCE_ROOT; };
- FF354EB108516C63007C00E1 /* installtool */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; name = installtool; path = PreferencePane/installtool; sourceTree = SOURCE_ROOT; };
- FF3C72A91CE3E62200CDF81E /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.Internal.sdk/usr/lib/libicucore.dylib; sourceTree = DEVELOPER_DIR; };
FF485D5105632E0000130380 /* mDNSResponder.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = mDNSResponder.8; path = ../mDNSShared/mDNSResponder.8; sourceTree = SOURCE_ROOT; };
FF5852100DD27BD300862BDF /* ClientCommon.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ClientCommon.c; path = ../Clients/ClientCommon.c; sourceTree = SOURCE_ROOT; };
FF85880B0BD599F40080D89F /* mDNSResponder.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mDNSResponder.sb; sourceTree = SOURCE_ROOT; };
@@ -726,20 +1010,30 @@
FFA572630AF190C20055A0F1 /* dns_sd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_sd.h; path = ../mDNSShared/dns_sd.h; sourceTree = SOURCE_ROOT; usesTabs = 0; };
FFB765840AEED9C700583A2C /* libsystem_dnssd.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_dnssd.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
FFCB6D73075D539900B8AF62 /* PlatformCommon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PlatformCommon.c; path = ../mDNSShared/PlatformCommon.c; sourceTree = SOURCE_ROOT; };
- FFE6935007C2CA7F00283007 /* ConfigurationAuthority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConfigurationAuthority.h; path = PreferencePane/ConfigurationAuthority.h; sourceTree = SOURCE_ROOT; };
FFE6935207C2CAA400283007 /* DNSServiceDiscoveryPref.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DNSServiceDiscoveryPref.h; path = PreferencePane/DNSServiceDiscoveryPref.h; sourceTree = SOURCE_ROOT; };
- FFE6935407C2CABD00283007 /* PrivilegedOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PrivilegedOperations.h; path = PreferencePane/PrivilegedOperations.h; sourceTree = SOURCE_ROOT; };
FFF4F63A06CFE4DD00459EFD /* dnsextd.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dnsextd.8; path = ../mDNSShared/dnsextd.8; sourceTree = SOURCE_ROOT; };
FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnssd_clientlib.c; path = ../mDNSShared/dnssd_clientlib.c; sourceTree = SOURCE_ROOT; };
FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnssd_clientstub.c; path = ../mDNSShared/dnssd_clientstub.c; sourceTree = SOURCE_ROOT; };
FFFB0DAC07B43CBA00B88D48 /* DNSServiceDiscoveryPref.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DNSServiceDiscoveryPref.m; sourceTree = "<group>"; };
- FFFB0DAD07B43CBA00B88D48 /* PrivilegedOperations.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = PrivilegedOperations.c; sourceTree = "<group>"; };
- FFFB0DAE07B43CBA00B88D48 /* ConfigurationAuthority.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ConfigurationAuthority.c; sourceTree = "<group>"; };
- FFFB0DAF07B43CBA00B88D48 /* ddnswriteconfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ddnswriteconfig.m; sourceTree = "<group>"; };
FFFF8F800C3307AC00722979 /* dnsextd.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dnsextd.conf; path = ../mDNSShared/dnsextd.conf; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
+ 0C1596A91D773FE300E09998 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 21B830A71D8A641F00AE2001 /* libicucore.dylib in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 0C635A731E9418A60026C796 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
213FB21612028A7A002B3A08 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -785,6 +1079,13 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 37538E1B1D7A442300226BE4 /* Foundation.framework in Frameworks */,
+ 21B830A31D8A63AE00AE2001 /* SystemConfiguration.framework in Frameworks */,
+ 21B830A61D8A63E400AE2001 /* CoreFoundation.framework in Frameworks */,
+ 21B830A21D8A63A300AE2001 /* libxml2.dylib in Frameworks */,
+ 37538E141D7A43B600226BE4 /* libicucore.dylib in Frameworks */,
+ 21B830A41D8A63BB00AE2001 /* Security.framework in Frameworks */,
+ 21B830A51D8A63CB00AE2001 /* IOKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -803,17 +1104,65 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ B7325FEA1DA47EBA00663834 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B74EC1131D47FC7700A1D155 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B74A96261DD4EDE60084A8C5 /* Preferences.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B76783A91E82D65900DA271E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B74F2B461E82FEAE0084960E /* Foundation.framework in Frameworks */,
+ B74F2B471E82FEFE0084960E /* Security.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B7D566B71E81D8FD00E43008 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B7D566CD1E81DDB600E43008 /* Foundation.framework in Frameworks */,
+ B7D566D51E81E14E00E43008 /* ViewBridge.framework in Frameworks */,
+ B7D566CE1E81DDB600E43008 /* PreferencePanes.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B7D6CA6C1D1076F3005E24CF /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ BD9BA74D1EAF90E400658CCF /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ BD9BA7581EAF929C00658CCF /* CoreUtils.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
D284BE640ADD80740027CCDF /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 2243AE391C90AECF0079023E /* CoreBluetooth.framework in Frameworks */,
D284BE650ADD80740027CCDF /* CoreFoundation.framework in Frameworks */,
- FF3C72AA1CE3E62200CDF81E /* libicucore.dylib in Frameworks */,
BDA3F08A1C48DB920054FB4B /* Foundation.framework in Frameworks */,
D284BE670ADD80740027CCDF /* IOKit.framework in Frameworks */,
D284BE680ADD80740027CCDF /* Security.framework in Frameworks */,
D284BE660ADD80740027CCDF /* SystemConfiguration.framework in Frameworks */,
+ 21B830A81D8A642200AE2001 /* libicucore.dylib in Frameworks */,
219D5542149ED645004464AE /* libxml2.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -845,17 +1194,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
- D284BEDF0ADD80A70027CCDF /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- BDA3F08D1C48DBEA0054FB4B /* Foundation.framework in Frameworks */,
- D284BEE10ADD80A70027CCDF /* Security.framework in Frameworks */,
- D284BEE20ADD80A70027CCDF /* SystemConfiguration.framework in Frameworks */,
- D284BEE30ADD80A70027CCDF /* CoreFoundation.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
D284BF010ADD80B00027CCDF /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -895,16 +1233,19 @@
08FB7794FE84155DC02AAC07 /* mDNSResponder */ = {
isa = PBXGroup;
children = (
- 2243AE381C90AECF0079023E /* CoreBluetooth.framework */,
- 729DF45F1CD40630005ECF70 /* com.apple.mDNSResponder.plist */,
08FB7795FE84155DC02AAC07 /* mDNS Server Sources */,
6575FC1F022EB78C00000109 /* Command-Line Clients */,
213FB20912028902002B3A08 /* Bonjour Events Plugin */,
DB2CC4420662DCE500335AB3 /* Java Support */,
+ B7D6CA511D107573005E24CF /* DomainBrowser */,
+ B74EC11A1D47FC7800A1D155 /* SettingsBundle */,
FFFB0DA407B43BED00B88D48 /* PreferencePane */,
08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
+ 0C1596AD1D773FE300E09998 /* mDNSNetMonitor */,
+ 0C635A771E9418A60026C796 /* BonjourTop */,
19C28FBDFE9D53C911CA2CBB /* Products */,
37DDE9241BA382280092AC61 /* Unit Tests */,
+ BD9BA7561EAF929C00658CCF /* Frameworks */,
);
name = mDNSResponder;
sourceTree = "<group>";
@@ -912,6 +1253,8 @@
08FB7795FE84155DC02AAC07 /* mDNS Server Sources */ = {
isa = PBXGroup;
children = (
+ 220ABBF11D78F102008423A7 /* D2D.h */,
+ 22C7633D1D777B8C0077AFCA /* D2D.c */,
22448EA51C90A82D004F25CC /* coreBLE.h */,
22448EA61C90A82D004F25CC /* coreBLE.m */,
22448EA11C90A7B5004F25CC /* BLE.c */,
@@ -924,12 +1267,17 @@
21F51DBD1B3540DB0070B05C /* com.apple.dnsextd.plist */,
21F51DBF1B35412D0070B05C /* com.apple.mDNSResponder.plist */,
21F51DBE1B3541030070B05C /* com.apple.mDNSResponderHelper.plist */,
+ 729DF45F1CD40630005ECF70 /* com.apple.mDNSResponder.plist */,
21A57F4A145B2AE100939099 /* CryptoAlg.c */,
21A57F4B145B2AE100939099 /* CryptoAlg.h */,
21A57F51145B2B1400939099 /* CryptoSupport.c */,
21A57F52145B2B1400939099 /* CryptoSupport.h */,
6575FBEC022EAF7200000109 /* daemon.c */,
+ BD691B281ED2F43200E6F317 /* DNS64.c */,
+ BD691B291ED2F43200E6F317 /* DNS64.h */,
+ BDBF9B931ED74B8C001498A8 /* DNS64State.h */,
FFA572630AF190C20055A0F1 /* dns_sd.h */,
+ BDE238C11DF69D8300B9F696 /* dns_sd_internal.h */,
BDA9A7871B3A923600523835 /* dns_sd_private.h */,
84C5B339166553AF00C324A8 /* dns_services.c */,
84F4C08F188F04CF00D1E1DE /* dns_services.h */,
@@ -1007,10 +1355,12 @@
DB2CC4680662DFF500335AB3 /* JavaVM.framework */,
2E0406140C3197CB00F13B59 /* libbsm.dylib */,
8415A6561897109000BDBA26 /* libdns_services.dylib */,
+ 37538E131D7A43B600226BE4 /* libicucore.dylib */,
2E8165F60C59835F00485EB2 /* libipsec.dylib */,
219D5541149ED645004464AE /* libxml2.dylib */,
- FF3C72A91CE3E62200CDF81E /* libicucore.dylib */,
+ B74A96251DD4EDE60084A8C5 /* Preferences.framework */,
FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */,
+ B7D566D41E81E14E00E43008 /* ViewBridge.framework */,
7F869685066EE02400D2A2DC /* Security.framework */,
65713D46025A293200000109 /* SystemConfiguration.framework */,
21F432971134AA6800581B69 /* WebFilterDNS.framework */,
@@ -1018,12 +1368,41 @@
name = "External Frameworks and Libraries";
sourceTree = "<group>";
};
+ 0C1596AD1D773FE300E09998 /* mDNSNetMonitor */ = {
+ isa = PBXGroup;
+ children = (
+ 0C6FB90E1D775FE900DF6F51 /* mDNSNetMonitor.8 */,
+ 0C1596B71D7740C100E09998 /* mDNSUNP.c */,
+ 0C1596B31D7740B500E09998 /* mDNSPosix.c */,
+ 0C1596B41D7740B500E09998 /* NetMonitor.c */,
+ );
+ path = mDNSNetMonitor;
+ sourceTree = "<group>";
+ };
+ 0C635A771E9418A60026C796 /* BonjourTop */ = {
+ isa = PBXGroup;
+ children = (
+ 0C635A7D1E9418D90026C796 /* bjIPAddr.cpp */,
+ 0C635A851E9418D90026C796 /* DNSFrame.cpp */,
+ 0C635A861E9418D90026C796 /* Frame.cpp */,
+ 0C635A871E9418D90026C796 /* LLRBTree.cpp */,
+ 0C635A881E9418D90026C796 /* main.cpp */,
+ 0C635A7E1E9418D90026C796 /* bjMACAddr.cpp */,
+ 0C635A7F1E9418D90026C796 /* bjsocket.cpp */,
+ 0C635A801E9418D90026C796 /* bjstring.cpp */,
+ 0C635A811E9418D90026C796 /* bjStringtoStringMap.cpp */,
+ 0C635A821E9418D90026C796 /* BonjourTop.cpp */,
+ 0C635A831E9418D90026C796 /* CaptureFile.cpp */,
+ 0C635A841E9418D90026C796 /* CollectBy.cpp */,
+ );
+ path = BonjourTop;
+ sourceTree = "<group>";
+ };
19C28FBDFE9D53C911CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
D284BF0C0ADD80B00027CCDF /* Bonjour.prefPane */,
213FB21812028A7A002B3A08 /* BonjourEvents.plugin */,
- D284BEE80ADD80A70027CCDF /* ddnswriteconfig */,
D284BEB00ADD80920027CCDF /* dns-sd */,
72FB545F166D5FB00090B2D9 /* dnsctl */,
D284BED90ADD80A20027CCDF /* dnsextd */,
@@ -1038,6 +1417,14 @@
D284BE730ADD80740027CCDF /* mDNSResponder */,
2E0405F00C31955500F13B59 /* mDNSResponderHelper */,
37DDE92D1BA383610092AC61 /* unittests */,
+ 0C1596AC1D773FE300E09998 /* mDNSNetMonitor */,
+ B7D6CA701D1076F3005E24CF /* DomainBrowser.framework */,
+ B74EC1161D47FC7700A1D155 /* BonjourSettings.bundle */,
+ B7325FEE1DA47EBA00663834 /* DomainBrowser.framework */,
+ B7D566BA1E81D8FD00E43008 /* com.apple.preference.bonjour.remoteservice.xpc */,
+ B76783AC1E82D65900DA271E /* com.apple.preference.bonjour.tool.xpc */,
+ 0C635A761E9418A60026C796 /* bonjourtop */,
+ BD9BA7531EAF90E400658CCF /* dnssdutil */,
);
name = Products;
sourceTree = "<group>";
@@ -1054,6 +1441,18 @@
37DDE9241BA382280092AC61 /* Unit Tests */ = {
isa = PBXGroup;
children = (
+ 0C84A2911E786AFF00E8B4C7 /* daemon_ut.c */,
+ 0C10EC261DDB956000D7A0E3 /* LocalOnlyTimeoutTests.c */,
+ 0C10EC271DDB956000D7A0E3 /* LocalOnlyTimeoutTests.h */,
+ 0C7C00491DD553490078BA89 /* unittest_common.c */,
+ 0C7C004A1DD553490078BA89 /* unittest_common.h */,
+ 0C7C004B1DD553490078BA89 /* mdns_macosx_ut.c */,
+ 0C7C004C1DD553490078BA89 /* mdns_ut.c */,
+ 0C7C004D1DD553490078BA89 /* uds_daemon_ut.c */,
+ 0C7C004E1DD553490078BA89 /* CNameRecordTests.h */,
+ 0C7C004F1DD553490078BA89 /* CNameRecordTests.c */,
+ 0C5674B11DA2BF6300AF3367 /* mDNSCoreReceiveTest.h */,
+ 0C5674B21DA2BF6300AF3367 /* mDNSCoreReceiveTest.c */,
37AF802A1BF699AF00D657F6 /* DomainNameTest.c */,
37AF802B1BF699AF00D657F6 /* DomainNameTest.h */,
371D0FBD1BF666EB00E5DB26 /* ResourceRecordTest.c */,
@@ -1076,10 +1475,107 @@
FF1C919F07021E3F001048AB /* dns-sd.c */,
72FB545A166D5F960090B2D9 /* dnsctl.c */,
FF5852100DD27BD300862BDF /* ClientCommon.c */,
+ BD9BA7541EAF91E700658CCF /* dnssdutil.c */,
);
name = "Command-Line Clients";
sourceTree = "<group>";
};
+ B74EC11A1D47FC7800A1D155 /* SettingsBundle */ = {
+ isa = PBXGroup;
+ children = (
+ B74EC11B1D47FC7800A1D155 /* Info.plist */,
+ B7016F511D5D0D2900107E7C /* Localizable.strings */,
+ B79920A31DA6C49700C6E02B /* Assets.xcassets */,
+ B72C96091D6236A500AD682A /* BonjourSCStore.h */,
+ B701E7031D9DD811008F3022 /* BonjourSCStore.m */,
+ B778EE4E1D51287100C814A2 /* BonjourSettingsController.h */,
+ B778EE4F1D51287100C814A2 /* BonjourSettingsController.m */,
+ B778EE4A1D51113800C814A2 /* HostnameController.h */,
+ B778EE4B1D51113800C814A2 /* HostnameController.m */,
+ B7325FE61DA4737400663834 /* CNBrowseDomainsController.h */,
+ B7325FE71DA4737400663834 /* CNBrowseDomainsController.m */,
+ );
+ path = SettingsBundle;
+ sourceTree = "<group>";
+ };
+ B76783BA1E82D8F500DA271E /* BonjourPrefTool */ = {
+ isa = PBXGroup;
+ children = (
+ B76783BB1E82D8F500DA271E /* BonjourPrefTool-Info.plist */,
+ B716801A1E8330B400459A35 /* entitlements.plist */,
+ B76783BC1E82D8F500DA271E /* main.m */,
+ B76783BD1E82D8F500DA271E /* BonjourPrefTool.h */,
+ B76783BE1E82D8F500DA271E /* BonjourPrefTool.m */,
+ B76783BF1E82D8F500DA271E /* BonjourPrefToolProtocol.h */,
+ );
+ path = BonjourPrefTool;
+ sourceTree = "<group>";
+ };
+ B7A214061D1B29D6005F7DD9 /* iOS */ = {
+ isa = PBXGroup;
+ children = (
+ B74EC1271D494C5800A1D155 /* DomainBrowser.h */,
+ B7A214081D1B29D6005F7DD9 /* CNDomainBrowserViewController.h */,
+ B7A214091D1B29D6005F7DD9 /* CNDomainBrowserViewController.m */,
+ B7016F4F1D5D0D1900107E7C /* DomainBrowser.strings */,
+ B74EC1281D494C5800A1D155 /* Info.plist */,
+ );
+ path = iOS;
+ sourceTree = "<group>";
+ };
+ B7D566A41E81D6A900E43008 /* RemoteViewService */ = {
+ isa = PBXGroup;
+ children = (
+ B7D566A51E81D6A900E43008 /* BonjourPrefRemoteViewService-Info.plist */,
+ B7D566AB1E81D6A900E43008 /* entitlements.plist */,
+ B7D566AC1E81D6A900E43008 /* main.m */,
+ B7D566A71E81D6A900E43008 /* BonjourPrefRemoteViewService.h */,
+ B7D566A81E81D6A900E43008 /* BonjourPrefRemoteViewService.m */,
+ B75700231E8347A6005CD56C /* InfoPlist.strings */,
+ );
+ path = RemoteViewService;
+ sourceTree = "<group>";
+ };
+ B7D6CA511D107573005E24CF /* DomainBrowser */ = {
+ isa = PBXGroup;
+ children = (
+ B7A214061D1B29D6005F7DD9 /* iOS */,
+ B7D6CA661D1076C6005E24CF /* macOS */,
+ B7D6CA5C1D107573005E24CF /* Shared */,
+ );
+ path = DomainBrowser;
+ sourceTree = "<group>";
+ };
+ B7D6CA5C1D107573005E24CF /* Shared */ = {
+ isa = PBXGroup;
+ children = (
+ B7D6CA5D1D107573005E24CF /* _CNDomainBrowser.h */,
+ B7D6CA5E1D107573005E24CF /* _CNDomainBrowser.m */,
+ B799209D1DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.h */,
+ B799209E1DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.m */,
+ );
+ path = Shared;
+ sourceTree = "<group>";
+ };
+ B7D6CA661D1076C6005E24CF /* macOS */ = {
+ isa = PBXGroup;
+ children = (
+ B74EC12B1D494C7200A1D155 /* DomainBrowser.h */,
+ B7D6CA681D1076C6005E24CF /* CNDomainBrowserView.h */,
+ B7D6CA691D1076C6005E24CF /* CNDomainBrowserView.m */,
+ B74EC1291D494C6700A1D155 /* Info.plist */,
+ );
+ path = macOS;
+ sourceTree = "<group>";
+ };
+ BD9BA7561EAF929C00658CCF /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ BD9BA7571EAF929C00658CCF /* CoreUtils.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
DB2CC4420662DCE500335AB3 /* Java Support */ = {
isa = PBXGroup;
children = (
@@ -1105,17 +1601,11 @@
FF260A2307B4463400CE10E5 /* Resources */ = {
isa = PBXGroup;
children = (
- FF260A2407B4464B00CE10E5 /* remove_idle.tiff */,
- FF260A2507B4464B00CE10E5 /* add_pressed.tiff */,
- FF260A2607B4464B00CE10E5 /* remove_disabled.tiff */,
- FF260A2707B4464B00CE10E5 /* add_idle.tiff */,
- FF260A2907B4464B00CE10E5 /* remove_pressed.tiff */,
FF260A2807B4464B00CE10E5 /* success.tiff */,
FF08480607CEB8E800AE6769 /* inprogress.tiff */,
FF260A2A07B4464B00CE10E5 /* failure.tiff */,
FF260A3207B4466900CE10E5 /* BonjourPref.icns */,
FF260A3307B4466900CE10E5 /* BonjourPref.tiff */,
- FF354EB108516C63007C00E1 /* installtool */,
FF260A4807B4475600CE10E5 /* DNSServiceDiscoveryPref.nib */,
FF260A4B07B4477F00CE10E5 /* InfoPlist.strings */,
);
@@ -1125,13 +1615,10 @@
FFFB0DA407B43BED00B88D48 /* PreferencePane */ = {
isa = PBXGroup;
children = (
- FFE6935007C2CA7F00283007 /* ConfigurationAuthority.h */,
- FFFB0DAE07B43CBA00B88D48 /* ConfigurationAuthority.c */,
FFE6935207C2CAA400283007 /* DNSServiceDiscoveryPref.h */,
FFFB0DAC07B43CBA00B88D48 /* DNSServiceDiscoveryPref.m */,
- FFE6935407C2CABD00283007 /* PrivilegedOperations.h */,
- FFFB0DAD07B43CBA00B88D48 /* PrivilegedOperations.c */,
- FFFB0DAF07B43CBA00B88D48 /* ddnswriteconfig.m */,
+ B76783BA1E82D8F500DA271E /* BonjourPrefTool */,
+ B7D566A41E81D6A900E43008 /* RemoteViewService */,
FF260A2307B4463400CE10E5 /* Resources */,
);
path = PreferencePane;
@@ -1175,6 +1662,31 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 37538DFB1D7A421500226BE4 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 37538E0D1D7A437300226BE4 /* DNSSECSupport.h in Headers */,
+ 37538E0C1D7A435200226BE4 /* dnssec.h in Headers */,
+ 37538E0B1D7A432200226BE4 /* Metrics.h in Headers */,
+ 37538E0A1D7A430600226BE4 /* anonymous.h in Headers */,
+ 37538E091D7A42FC00226BE4 /* xpc_services.h in Headers */,
+ 37538E081D7A42F000226BE4 /* dns_xpc.h in Headers */,
+ 37538E071D7A42E200226BE4 /* coreBLE.h in Headers */,
+ 37538E061D7A42DA00226BE4 /* dnsproxy.h in Headers */,
+ 37538E051D7A42D000226BE4 /* DNSServiceDiscoveryDefines.h in Headers */,
+ 37538E041D7A42BE00226BE4 /* BLE.h in Headers */,
+ 37538E021D7A42B000226BE4 /* nsec.h in Headers */,
+ 37538E031D7A42B000226BE4 /* nsec3.h in Headers */,
+ 37538E001D7A429900226BE4 /* CryptoAlg.h in Headers */,
+ 37538E011D7A429900226BE4 /* CryptoSupport.h in Headers */,
+ 37538DFF1D7A428500226BE4 /* helpermsg-types.h in Headers */,
+ 37538DFE1D7A427B00226BE4 /* helper-server.h in Headers */,
+ 37538DFD1D7A425700226BE4 /* helper.h in Headers */,
+ 37538DFC1D7A424500226BE4 /* dnssd_ipc.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
84C5B3331665529800C324A8 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
@@ -1183,11 +1695,39 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ B7325FEB1DA47EBA00663834 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B7325FFD1DA4809400663834 /* DomainBrowser.h in Headers */,
+ B7325FF71DA47F9100663834 /* CNDomainBrowserViewController.h in Headers */,
+ B799209F1DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B7D6CA6D1D1076F3005E24CF /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B79568351D53F693005E3BED /* DomainBrowser.h in Headers */,
+ B79568361D53F69B005E3BED /* CNDomainBrowserView.h in Headers */,
+ B79920A01DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ BD9BA7491EAF90E400658CCF /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
D284BE520ADD80740027CCDF /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
D284BE540ADD80740027CCDF /* dnssd_ipc.h in Headers */,
+ BDBF9B941ED74B9C001498A8 /* DNS64State.h in Headers */,
2E96A5260C39BE480087C4D2 /* helper.h in Headers */,
2EDC5E750C39EA640092701B /* helper-server.h in Headers */,
2ECC11A60C4FEC3800CB1885 /* helpermsg-types.h in Headers */,
@@ -1195,6 +1735,7 @@
21A57F55145B2B1400939099 /* CryptoSupport.h in Headers */,
2124FA2C1471E98C0021D7BB /* nsec.h in Headers */,
2124FA301471E9B50021D7BB /* dnssec.h in Headers */,
+ BD691B2B1ED2F4AB00E6F317 /* DNS64.h in Headers */,
218E8E53156D8C0300720DA0 /* dnsproxy.h in Headers */,
2127A47915C3C7B900A857FC /* nsec3.h in Headers */,
222A3C5B1C1B75F2003A6FFD /* DNSServiceDiscoveryDefines.h in Headers */,
@@ -1203,6 +1744,7 @@
848DA5CA165477EB00D2E8B4 /* xpc_services.h in Headers */,
BDA3F08E1C48DCA50054FB4B /* Metrics.h in Headers */,
22448EA71C90A837004F25CC /* coreBLE.h in Headers */,
+ 220ABBF21D78F10F008423A7 /* D2D.h in Headers */,
22448EA41C90A7CB004F25CC /* BLE.h in Headers */,
848DA5D616547F7200D2E8B4 /* dns_xpc.h in Headers */,
);
@@ -1231,13 +1773,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
- D284BEDC0ADD80A70027CCDF /* Headers */ = {
- isa = PBXHeadersBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
D284BEED0ADD80B00027CCDF /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
@@ -1288,6 +1823,40 @@
/* End PBXLegacyTarget section */
/* Begin PBXNativeTarget section */
+ 0C1596AB1D773FE300E09998 /* mDNSNetMonitor */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 0C1596B21D773FE300E09998 /* Build configuration list for PBXNativeTarget "mDNSNetMonitor" */;
+ buildPhases = (
+ 0C1596A81D773FE300E09998 /* Sources */,
+ 0C1596A91D773FE300E09998 /* Frameworks */,
+ 0C1596AA1D773FE300E09998 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = mDNSNetMonitor;
+ productName = mDNSNetMonitor;
+ productReference = 0C1596AC1D773FE300E09998 /* mDNSNetMonitor */;
+ productType = "com.apple.product-type.tool";
+ };
+ 0C635A751E9418A60026C796 /* BonjourTop */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 0C635A7C1E9418A60026C796 /* Build configuration list for PBXNativeTarget "BonjourTop" */;
+ buildPhases = (
+ 0C635A721E9418A60026C796 /* Sources */,
+ 0C635A731E9418A60026C796 /* Frameworks */,
+ 0C635A741E9418A60026C796 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = BonjourTop;
+ productName = BonjourTop;
+ productReference = 0C635A761E9418A60026C796 /* bonjourtop */;
+ productType = "com.apple.product-type.tool";
+ };
213FB21712028A7A002B3A08 /* BonjourEvents */ = {
isa = PBXNativeTarget;
buildConfigurationList = 213FB21B12028A7C002B3A08 /* Build configuration list for PBXNativeTarget "BonjourEvents" */;
@@ -1384,6 +1953,7 @@
37DDE9291BA383610092AC61 /* Sources */,
37DDE92A1BA383610092AC61 /* Frameworks */,
37DDE9341BA384000092AC61 /* ShellScript */,
+ 37538DFB1D7A421500226BE4 /* Headers */,
);
buildRules = (
);
@@ -1429,6 +1999,110 @@
productReference = 84C5B3351665529800C324A8 /* libdns_services.dylib */;
productType = "com.apple.product-type.library.dynamic";
};
+ B7325FED1DA47EBA00663834 /* DomainBrowser-iOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B7325FF31DA47EBA00663834 /* Build configuration list for PBXNativeTarget "DomainBrowser-iOS" */;
+ buildPhases = (
+ B7325FE91DA47EBA00663834 /* Sources */,
+ B7325FEA1DA47EBA00663834 /* Frameworks */,
+ B7325FEB1DA47EBA00663834 /* Headers */,
+ B7325FEC1DA47EBA00663834 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "DomainBrowser-iOS";
+ productName = BonjourBrowser;
+ productReference = B7325FEE1DA47EBA00663834 /* DomainBrowser.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ B74EC1151D47FC7700A1D155 /* BonjourSettings */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B74EC11E1D47FC7800A1D155 /* Build configuration list for PBXNativeTarget "BonjourSettings" */;
+ buildPhases = (
+ B74EC1121D47FC7700A1D155 /* Sources */,
+ B74EC1131D47FC7700A1D155 /* Frameworks */,
+ B74EC1141D47FC7700A1D155 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = BonjourSettings;
+ productName = BonjourSettings;
+ productReference = B74EC1161D47FC7700A1D155 /* BonjourSettings.bundle */;
+ productType = "com.apple.product-type.bundle";
+ };
+ B76783AB1E82D65900DA271E /* BonjourPrefsTool */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B76783B71E82D65900DA271E /* Build configuration list for PBXNativeTarget "BonjourPrefsTool" */;
+ buildPhases = (
+ B76783A81E82D65900DA271E /* Sources */,
+ B76783A91E82D65900DA271E /* Frameworks */,
+ B76783AA1E82D65900DA271E /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = BonjourPrefsTool;
+ productName = tool;
+ productReference = B76783AC1E82D65900DA271E /* com.apple.preference.bonjour.tool.xpc */;
+ productType = "com.apple.product-type.xpc-service";
+ };
+ B7D566B91E81D8FD00E43008 /* RemoteViewService */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B7D566C31E81D8FD00E43008 /* Build configuration list for PBXNativeTarget "RemoteViewService" */;
+ buildPhases = (
+ B7D566B61E81D8FD00E43008 /* Sources */,
+ B7D566B71E81D8FD00E43008 /* Frameworks */,
+ B7D566B81E81D8FD00E43008 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = RemoteViewService;
+ productName = remoteservice;
+ productReference = B7D566BA1E81D8FD00E43008 /* com.apple.preference.bonjour.remoteservice.xpc */;
+ productType = "com.apple.product-type.xpc-service";
+ };
+ B7D6CA6F1D1076F3005E24CF /* DomainBrowser-macOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = B7D6CA751D1076F3005E24CF /* Build configuration list for PBXNativeTarget "DomainBrowser-macOS" */;
+ buildPhases = (
+ B7D6CA6B1D1076F3005E24CF /* Sources */,
+ B7D6CA6C1D1076F3005E24CF /* Frameworks */,
+ B7D6CA6D1D1076F3005E24CF /* Headers */,
+ B7D6CA6E1D1076F3005E24CF /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "DomainBrowser-macOS";
+ productName = BonjourBrowserUI;
+ productReference = B7D6CA701D1076F3005E24CF /* DomainBrowser.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ BD9BA7481EAF90E400658CCF /* dnssdutil */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = BD9BA7501EAF90E400658CCF /* Build configuration list for PBXNativeTarget "dnssdutil" */;
+ buildPhases = (
+ BD9BA7491EAF90E400658CCF /* Headers */,
+ BD9BA74A1EAF90E400658CCF /* Sources */,
+ BD9BA74D1EAF90E400658CCF /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = dnssdutil;
+ productName = dnssdutil;
+ productReference = BD9BA7531EAF90E400658CCF /* dnssdutil */;
+ productType = "com.apple.product-type.tool";
+ };
D284BE500ADD80740027CCDF /* mDNSResponder */ = {
isa = PBXNativeTarget;
buildConfigurationList = D284BE6D0ADD80740027CCDF /* Build configuration list for PBXNativeTarget "mDNSResponder" */;
@@ -1517,24 +2191,6 @@
productReference = D284BED90ADD80A20027CCDF /* dnsextd */;
productType = "com.apple.product-type.tool";
};
- D284BEDB0ADD80A70027CCDF /* ddnswriteconfig */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = D284BEE50ADD80A70027CCDF /* Build configuration list for PBXNativeTarget "ddnswriteconfig" */;
- buildPhases = (
- D284BEDC0ADD80A70027CCDF /* Headers */,
- D284BEDD0ADD80A70027CCDF /* Sources */,
- D284BEDF0ADD80A70027CCDF /* Frameworks */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = ddnswriteconfig;
- productInstallPath = "/Library/Application Support/Bonjour";
- productName = ddnswriteconfig;
- productReference = D284BEE80ADD80A70027CCDF /* ddnswriteconfig */;
- productType = "com.apple.product-type.tool";
- };
D284BEEA0ADD80B00027CCDF /* PreferencePane */ = {
isa = PBXNativeTarget;
buildConfigurationList = D284BF080ADD80B00027CCDF /* Build configuration list for PBXNativeTarget "PreferencePane" */;
@@ -1543,11 +2199,13 @@
D284BEEE0ADD80B00027CCDF /* Resources */,
D284BEFD0ADD80B00027CCDF /* Sources */,
D284BF010ADD80B00027CCDF /* Frameworks */,
+ B7D566C61E81D9B600E43008 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
- FFAE66F9105F0CF100162116 /* PBXTargetDependency */,
+ B76783B91E82D83800DA271E /* PBXTargetDependency */,
+ B7D566C81E81D9E700E43008 /* PBXTargetDependency */,
);
name = PreferencePane;
productInstallPath = "${SYSTEM_LIBRARY_DIR}/PreferencePanes";
@@ -1615,9 +2273,40 @@
attributes = {
LastUpgradeCheck = 0700;
TargetAttributes = {
+ 0C635A751E9418A60026C796 = {
+ CreatedOnToolsVersion = 9.0;
+ DevelopmentTeam = 63ZFQSB63Y;
+ ProvisioningStyle = Automatic;
+ };
37DDE92C1BA383610092AC61 = {
CreatedOnToolsVersion = 7.0;
};
+ B7325FED1DA47EBA00663834 = {
+ CreatedOnToolsVersion = 8.0;
+ ProvisioningStyle = Automatic;
+ };
+ B74EC1151D47FC7700A1D155 = {
+ CreatedOnToolsVersion = 8.0;
+ DevelopmentTeam = 6DMBYZ9NJ7;
+ DevelopmentTeamName = "Apple Inc. - Embedded Platform";
+ ProvisioningStyle = Automatic;
+ };
+ B76783AB1E82D65900DA271E = {
+ CreatedOnToolsVersion = 8.3;
+ ProvisioningStyle = Automatic;
+ };
+ B7C4B7251E71BD5000136C7A = {
+ CreatedOnToolsVersion = 9.0;
+ ProvisioningStyle = Automatic;
+ };
+ B7D566B91E81D8FD00E43008 = {
+ CreatedOnToolsVersion = 8.3;
+ ProvisioningStyle = Automatic;
+ };
+ B7D6CA6F1D1076F3005E24CF = {
+ CreatedOnToolsVersion = 8.0;
+ ProvisioningStyle = Automatic;
+ };
};
};
buildConfigurationList = D284BE2B0ADD78180027CCDF /* Build configuration list for PBXProject "mDNSResponder" */;
@@ -1629,12 +2318,15 @@
Japanese,
French,
German,
+ Base,
+ en,
);
mainGroup = 08FB7794FE84155DC02AAC07 /* mDNSResponder */;
projectDirPath = "";
projectRoot = "";
targets = (
00AD62BB032D7A0C0CCA2C71 /* Build More */,
+ B7C4B7251E71BD5000136C7A /* Build Some iOS */,
03067D640C83A3700022BE1F /* Build Some */,
FFB7657B0AEED96B00583A2C /* Build All */,
D284BE500ADD80740027CCDF /* mDNSResponder */,
@@ -1642,8 +2334,12 @@
D284BEA50ADD80920027CCDF /* dns-sd tool */,
72FB545E166D5FB00090B2D9 /* dnsctl */,
D284BEBF0ADD80A20027CCDF /* dnsextd */,
- D284BEDB0ADD80A70027CCDF /* ddnswriteconfig */,
+ B7325FED1DA47EBA00663834 /* DomainBrowser-iOS */,
+ B7D6CA6F1D1076F3005E24CF /* DomainBrowser-macOS */,
+ B74EC1151D47FC7700A1D155 /* BonjourSettings */,
D284BEEA0ADD80B00027CCDF /* PreferencePane */,
+ B76783AB1E82D65900DA271E /* BonjourPrefsTool */,
+ B7D566B91E81D8FD00E43008 /* RemoteViewService */,
213FB21712028A7A002B3A08 /* BonjourEvents */,
2141DCF8123FFB5D0086D23E /* SystemLibraries */,
2141DD0B123FFC7F0086D23E /* SystemLibrariesStatic */,
@@ -1658,6 +2354,9 @@
D284BEB20ADD809A0027CCDF /* libjdns_sd.jnilib */,
4AE471670EAFF81900A6C5AD /* dns_sd.jar */,
37DDE92C1BA383610092AC61 /* unittests */,
+ 0C1596AB1D773FE300E09998 /* mDNSNetMonitor */,
+ 0C635A751E9418A60026C796 /* BonjourTop */,
+ BD9BA7481EAF90E400658CCF /* dnssdutil */,
);
};
/* End PBXProject section */
@@ -1670,24 +2369,57 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ B7325FEC1DA47EBA00663834 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B7325FFF1DA480A500663834 /* DomainBrowser.strings in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B74EC1141D47FC7700A1D155 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B7E06B0E1DBA9E9700E4580C /* DomainBrowser.strings in Resources */,
+ B79920A41DA6C49700C6E02B /* Assets.xcassets in Resources */,
+ B7016F521D5D0D2900107E7C /* Localizable.strings in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B76783AA1E82D65900DA271E /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B7D566B81E81D8FD00E43008 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B75700241E8347A6005CD56C /* InfoPlist.strings in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B7D6CA6E1D1076F3005E24CF /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
D284BEEE0ADD80B00027CCDF /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- D284BEEF0ADD80B00027CCDF /* remove_idle.tiff in Resources */,
- D284BEF00ADD80B00027CCDF /* add_pressed.tiff in Resources */,
- D284BEF10ADD80B00027CCDF /* remove_disabled.tiff in Resources */,
- D284BEF20ADD80B00027CCDF /* add_idle.tiff in Resources */,
D284BEF30ADD80B00027CCDF /* success.tiff in Resources */,
- D284BEF40ADD80B00027CCDF /* remove_pressed.tiff in Resources */,
D284BEF50ADD80B00027CCDF /* failure.tiff in Resources */,
D284BEF60ADD80B00027CCDF /* BonjourPref.icns in Resources */,
D284BEF70ADD80B00027CCDF /* BonjourPref.tiff in Resources */,
D284BEF80ADD80B00027CCDF /* DNSServiceDiscoveryPref.nib in Resources */,
D284BEF90ADD80B00027CCDF /* InfoPlist.strings in Resources */,
D284BEFB0ADD80B00027CCDF /* inprogress.tiff in Resources */,
- D284BEFC0ADD80B00027CCDF /* installtool in Resources */,
- FFAE66F0105F0CD900162116 /* ddnswriteconfig in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1705,7 +2437,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "if [ -e \"${SDKROOT}/usr/local/include/vproc.h\" -o -e \"${SDKROOT}/usr/include/vproc.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/vproc.h\"\nelse\ntouch \"${CONFIGURATION_TEMP_DIR}/vproc.h\"\nfi\n\nif [ -e \"${SDKROOT}/usr/lib/libipsec.dylib\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/ipsec_options.h\"\ntouch \"${CONFIGURATION_TEMP_DIR}/ipsec_options.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libipsec.a\"\nelse\necho \"#define MDNS_NO_IPSEC 1\" > ${CONFIGURATION_TEMP_DIR}/ipsec_options.h\ntouch \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/empty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libipsec.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n";
+ shellScript = "if [ -e \"${SDKROOT}/usr/local/include/vproc.h\" -o -e \"${SDKROOT}/usr/include/vproc.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/vproc.h\"\nelse\ntouch \"${CONFIGURATION_TEMP_DIR}/vproc.h\"\nfi\n\nipsec=$(ls \"${SDKROOT}/usr/lib/libipsec.*\" 2> /dev/null | wc -l)\nif [ \"$ipsec\" != \"0\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/ipsec_options.h\"\ntouch \"${CONFIGURATION_TEMP_DIR}/ipsec_options.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libipsec.a\"\nelse\necho \"#define MDNS_NO_IPSEC 1\" > ${CONFIGURATION_TEMP_DIR}/ipsec_options.h\ntouch \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/empty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libipsec.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n";
};
2130256B12400DE600AC839F /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
@@ -1735,7 +2467,7 @@
};
37DDE9341BA384000092AC61 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
+ buildActionMask = 12;
files = (
);
inputPaths = (
@@ -1765,6 +2497,19 @@
shellPath = /bin/sh;
shellScript = "/usr/bin/bison -o ${SCRIPT_OUTPUT_FILE_0} -d ${SCRIPT_INPUT_FILE_0}";
};
+ B7E2951A1E259AA000C42F6D /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "# Copy Sandbox profile\nif [[ ! \"${PLATFORM_NAME}\" =~ \"simulator\" ]] ; then\n if [ -z \"${IPHONEOS_DEPLOYMENT_TARGET}\" -a -z \"${TVOS_DEPLOYMENT_TARGET}\" -a -z \"${WATCHOS_DEPLOYMENT_TARGET}\" ] ; then\n SANDBOXDST=\"${DSTROOT}/usr/share/sandbox\"\n else\n SANDBOXDST=\"${DSTROOT}/usr/local/share/sandbox/profiles/embedded/builtin\"\n fi\n (umask 022; mkdir -p -m 0755 \"$SANDBOXDST\")\n cp \"${SRCROOT}/mDNSResponder.sb\" \"${SANDBOXDST}/mDNSResponder.sb\"\nfi";
+ };
D284BE510ADD80740027CCDF /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -1782,11 +2527,48 @@
name = "Run Script";
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/bash;
- shellScript = "# Install mDNSResponder.bundle containing language localizations\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices\ncp -R ${SRCROOT}/mDNSResponder-bundle ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle\n\n# Remove unwanted CVS directories\nfind ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle -depth -name CVS -exec rm -rf {} \\;\n\n# Expand UTF-8 files to UTF-16 (at one time this appeared to be necessary, but it's not, so we don't do it any more)\n#foreach file (`find ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle -name Localizable.strings`)\n#iconv -f utf-8 -t utf-16 ${file} > ${file}.new\n#mv -f ${file}.new ${file}\n#end\n\n# Remove French localization (not wanted for Apple B&I builds)\nrm -rf ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle/Resources/French.lproj\n\n# Copy Sandbox profile\nif [ -z \"${IPHONEOS_DEPLOYMENT_TARGET}\" -a -z \"${TVOS_DEPLOYMENT_TARGET}\" -a -z \"${WATCHOS_DEPLOYMENT_TARGET}\" ] ; then\n SANDBOXDST=\"${DSTROOT}/usr/share/sandbox\"\nelse\n SANDBOXDST=\"${DSTROOT}/usr/local/share/sandbox/profiles/embedded/builtin\"\nfi\n(umask 022; mkdir -p -m 0755 \"$SANDBOXDST\")\ncp \"${SRCROOT}/mDNSResponder.sb\" \"${SANDBOXDST}/mDNSResponder.sb\"\n";
+ shellScript = "# Install mDNSResponder.bundle containing language localizations\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices\ncp -R ${SRCROOT}/mDNSResponder-bundle ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle\n\n# Remove unwanted CVS directories\nfind ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle -depth -name CVS -exec rm -rf {} \\;\n\n# Expand UTF-8 files to UTF-16 (at one time this appeared to be necessary, but it's not, so we don't do it any more)\n#foreach file (`find ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle -name Localizable.strings`)\n#iconv -f utf-8 -t utf-16 ${file} > ${file}.new\n#mv -f ${file}.new ${file}\n#end\n\n# Remove French localization (not wanted for Apple B&I builds)\nrm -rf ${DSTROOT}${SYSTEM_LIBRARY_DIR}/CoreServices/mDNSResponder.bundle/Resources/French.lproj";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
+ 0C1596A81D773FE300E09998 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 0C1596B61D7740B500E09998 /* NetMonitor.c in Sources */,
+ 0C1596BB1D7740D700E09998 /* DNSDigest.c in Sources */,
+ 0C1596B81D7740C100E09998 /* mDNSUNP.c in Sources */,
+ 0C1596BD1D7740E300E09998 /* uDNS.c in Sources */,
+ 0C1596BC1D7740DC00E09998 /* DNSCommon.c in Sources */,
+ 0C1596C01D77410A00E09998 /* GenLinkedList.c in Sources */,
+ 0C1596BE1D7740E900E09998 /* mDNSDebug.c in Sources */,
+ 0C1596B91D7740CD00E09998 /* anonymous.c in Sources */,
+ 0C1596BF1D7740EF00E09998 /* PlatformCommon.c in Sources */,
+ 0C1596BA1D7740D200E09998 /* CryptoAlg.c in Sources */,
+ 0C1596B51D7740B500E09998 /* mDNSPosix.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 0C635A721E9418A60026C796 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 0C635A891E9418D90026C796 /* bjIPAddr.cpp in Sources */,
+ 0C635A8A1E9418D90026C796 /* bjMACAddr.cpp in Sources */,
+ 0C635A8B1E9418D90026C796 /* bjsocket.cpp in Sources */,
+ 0C635A8C1E9418D90026C796 /* bjstring.cpp in Sources */,
+ 0C635A8D1E9418D90026C796 /* bjStringtoStringMap.cpp in Sources */,
+ 0C635A8E1E9418D90026C796 /* BonjourTop.cpp in Sources */,
+ 0C635A8F1E9418D90026C796 /* CaptureFile.cpp in Sources */,
+ 0C635A901E9418D90026C796 /* CollectBy.cpp in Sources */,
+ 0C635A911E9418D90026C796 /* DNSFrame.cpp in Sources */,
+ 0C635A921E9418D90026C796 /* Frame.cpp in Sources */,
+ 0C635A931E9418D90026C796 /* LLRBTree.cpp in Sources */,
+ 0C635A941E9418D90026C796 /* main.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
213FB21512028A7A002B3A08 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1843,12 +2625,49 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 0CB1C7FC1D9C5C1100A5939F /* D2D.c in Sources */,
+ 37538E1F1D7A504F00226BE4 /* helper-stubs.c in Sources */,
+ 37538E1E1D7A4F9D00226BE4 /* anonymous.c in Sources */,
+ 37538E1D1D7A449D00226BE4 /* coreBLE.m in Sources */,
+ 37538E1C1D7A449000226BE4 /* Metrics.m in Sources */,
+ 37812CD41D7A307200F34505 /* BLE.c in Sources */,
+ 37812CD71D7A307200F34505 /* CryptoAlg.c in Sources */,
+ 37812CD81D7A307200F34505 /* CryptoSupport.c in Sources */,
+ 37812CD91D7A307200F34505 /* daemon.c in Sources */,
+ 37812CDA1D7A307200F34505 /* dns_services.c in Sources */,
+ 37812CDB1D7A307200F34505 /* DNSDigest.c in Sources */,
+ 37812CDE1D7A307200F34505 /* dnsproxy.c in Sources */,
+ 37812CDF1D7A307200F34505 /* DNSProxySupport.c in Sources */,
+ 37812CE01D7A307200F34505 /* dnssd_clientlib.c in Sources */,
+ 37812CE11D7A307300F34505 /* dnssd_clientstub.c in Sources */,
+ 37812CE21D7A307300F34505 /* dnssd_ipc.c in Sources */,
+ 37812CE31D7A307300F34505 /* dnssec.c in Sources */,
+ 37812CE41D7A307300F34505 /* DNSSECSupport.c in Sources */,
+ 37812CE51D7A307300F34505 /* GenLinkedList.c in Sources */,
+ 37812CE91D7A307300F34505 /* LegacyNATTraversal.c in Sources */,
+ 37812CEA1D7A307300F34505 /* mDNS.c in Sources */,
+ 37812CEB1D7A307300F34505 /* mDNSDebug.c in Sources */,
+ 37812CEC1D7A307300F34505 /* mDNSMacOSX.c in Sources */,
+ 37812CED1D7A307300F34505 /* nsec.c in Sources */,
+ 37812CEE1D7A307300F34505 /* nsec3.c in Sources */,
+ 37812CEF1D7A307300F34505 /* P2PPacketFilter.c in Sources */,
+ 37812CF11D7A307300F34505 /* PlatformCommon.c in Sources */,
+ 37812CF21D7A307300F34505 /* SymptomReporter.c in Sources */,
+ 37812CF31D7A307300F34505 /* uDNS.c in Sources */,
+ 37812CF41D7A307300F34505 /* uDNSPathEvalulation.c in Sources */,
+ 37812CF51D7A307300F34505 /* uds_daemon.c in Sources */,
+ 37812CF61D7A307300F34505 /* dnsctl_server.c in Sources */,
+ 37812CF71D7A307300F34505 /* xpc_services.c in Sources */,
371D0FBF1BF666EB00E5DB26 /* ResourceRecordTest.c in Sources */,
37FEBD581BC789AA00638EA4 /* DNSCommon.c in Sources */,
+ 37DDE9331BA383D30092AC61 /* unittest.c in Sources */,
371D0FBC1BF545FA00E5DB26 /* InterfaceTest.c in Sources */,
373202101BAB4444007DE806 /* DNSMessageTest.c in Sources */,
+ 0C7C00501DD553640078BA89 /* unittest_common.c in Sources */,
+ 0C5674B41DA2BF8600AF3367 /* mDNSCoreReceiveTest.c in Sources */,
+ 0C10EC281DDB956E00D7A0E3 /* LocalOnlyTimeoutTests.c in Sources */,
+ 0C7C00511DD5536E0078BA89 /* CNameRecordTests.c in Sources */,
3771F67D1BA387DD0072355E /* main.c in Sources */,
- 37DDE9331BA383D30092AC61 /* unittest.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1868,12 +2687,77 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ B7325FE91DA47EBA00663834 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B7325FF81DA47FB000663834 /* CNDomainBrowserViewController.m in Sources */,
+ B79920A11DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.m in Sources */,
+ B7325FF91DA47FB000663834 /* _CNDomainBrowser.m in Sources */,
+ B76431A01DB0423900DB376D /* ClientCommon.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B74EC1121D47FC7700A1D155 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B701E7041D9DD811008F3022 /* BonjourSCStore.m in Sources */,
+ B778EE501D51287100C814A2 /* BonjourSettingsController.m in Sources */,
+ B7706AAF1DBA9C1800593FD5 /* CNDomainBrowserPathUtils.m in Sources */,
+ B7325FE81DA4737400663834 /* CNBrowseDomainsController.m in Sources */,
+ B7706AAD1DBA9C0F00593FD5 /* CNDomainBrowserViewController.m in Sources */,
+ B778EE4D1D51113800C814A2 /* HostnameController.m in Sources */,
+ B7706AAE1DBA9C1800593FD5 /* _CNDomainBrowser.m in Sources */,
+ B7E06B0D1DBA9DFE00E4580C /* ClientCommon.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B76783A81E82D65900DA271E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B76783C11E82D8F500DA271E /* main.m in Sources */,
+ B76783C21E82D8F500DA271E /* BonjourPrefTool.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B7D566B61E81D8FD00E43008 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B7D566D11E81DEC400E43008 /* BonjourPrefRemoteViewService.m in Sources */,
+ B7D566D01E81DEC200E43008 /* main.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ B7D6CA6B1D1076F3005E24CF /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ B79920A21DA6BA8E00C6E02B /* CNDomainBrowserPathUtils.m in Sources */,
+ B7D6CA791D10770F005E24CF /* _CNDomainBrowser.m in Sources */,
+ B7D6CA7A1D107714005E24CF /* CNDomainBrowserView.m in Sources */,
+ B764319F1DB0423800DB376D /* ClientCommon.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ BD9BA74A1EAF90E400658CCF /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ BD9BA7551EAF91FB00658CCF /* dnssdutil.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
D284BE550ADD80740027CCDF /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 22C7633E1D777B940077AFCA /* D2D.c in Sources */,
227687F31C90AD580019382D /* coreBLE.m in Sources */,
D284BE580ADD80740027CCDF /* mDNS.c in Sources */,
+ BD691B2A1ED2F47100E6F317 /* DNS64.c in Sources */,
D284BE590ADD80740027CCDF /* uDNS.c in Sources */,
D284BE5A0ADD80740027CCDF /* DNSCommon.c in Sources */,
D284BE5B0ADD80740027CCDF /* DNSDigest.c in Sources */,
@@ -1938,22 +2822,16 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
- D284BEDD0ADD80A70027CCDF /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- D284BEDE0ADD80A70027CCDF /* ddnswriteconfig.m in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
D284BEFD0ADD80B00027CCDF /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D284BEFE0ADD80B00027CCDF /* DNSServiceDiscoveryPref.m in Sources */,
- D284BEFF0ADD80B00027CCDF /* PrivilegedOperations.c in Sources */,
- D284BF000ADD80B00027CCDF /* ConfigurationAuthority.c in Sources */,
+ B7706AAB1DB83EAC00593FD5 /* CNDomainBrowserPathUtils.m in Sources */,
+ B7706AA91DB83E9A00593FD5 /* CNDomainBrowserView.m in Sources */,
+ B71C8B091E79F2CD00E99939 /* BonjourSCStore.m in Sources */,
FFF589C10E37F67E00EF515C /* ClientCommon.c in Sources */,
+ B7706AAA1DB83EA700593FD5 /* _CNDomainBrowser.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2013,11 +2891,26 @@
target = 03067D640C83A3700022BE1F /* Build Some */;
targetProxy = 03067D850C849CC30022BE1F /* PBXContainerItemProxy */;
};
+ 0C1596C71D7751AD00E09998 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 0C1596AB1D773FE300E09998 /* mDNSNetMonitor */;
+ targetProxy = 0C1596C61D7751AD00E09998 /* PBXContainerItemProxy */;
+ };
0C2AAB321B6929F300113637 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 84C5B3341665529800C324A8 /* dns_services */;
targetProxy = 0C2AAB311B6929F300113637 /* PBXContainerItemProxy */;
};
+ 0C4F36B41E206711005A536B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 37DDE92C1BA383610092AC61 /* unittests */;
+ targetProxy = 0C4F36B31E206711005A536B /* PBXContainerItemProxy */;
+ };
+ 0C52E92F1E96AD74006EFE7B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 0C635A751E9418A60026C796 /* BonjourTop */;
+ targetProxy = 0C52E92E1E96AD74006EFE7B /* PBXContainerItemProxy */;
+ };
2130257112400E9300AC839F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FFA572650AF190F10055A0F1 /* SystemLibrariesDynamic */;
@@ -2063,21 +2956,41 @@
target = 84C5B3341665529800C324A8 /* dns_services */;
targetProxy = 84C5B3401665544B00C324A8 /* PBXContainerItemProxy */;
};
+ B76783B91E82D83800DA271E /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B76783AB1E82D65900DA271E /* BonjourPrefsTool */;
+ targetProxy = B76783B81E82D83800DA271E /* PBXContainerItemProxy */;
+ };
+ B7C4B72C1E71BD6000136C7A /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B74EC1151D47FC7700A1D155 /* BonjourSettings */;
+ targetProxy = B7C4B72B1E71BD6000136C7A /* PBXContainerItemProxy */;
+ };
+ B7C4B72E1E71BE3500136C7A /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 03067D640C83A3700022BE1F /* Build Some */;
+ targetProxy = B7C4B72D1E71BE3500136C7A /* PBXContainerItemProxy */;
+ };
+ B7D566C81E81D9E700E43008 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = B7D566B91E81D8FD00E43008 /* RemoteViewService */;
+ targetProxy = B7D566C71E81D9E700E43008 /* PBXContainerItemProxy */;
+ };
BD7833F01ABA5E3500EC51ED /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 72FB545E166D5FB00090B2D9 /* dnsctl */;
targetProxy = BD7833EF1ABA5E3500EC51ED /* PBXContainerItemProxy */;
};
+ BD9BA7721EAFA3D500658CCF /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = BD9BA7481EAF90E400658CCF /* dnssdutil */;
+ targetProxy = BD9BA7711EAFA3D500658CCF /* PBXContainerItemProxy */;
+ };
D284BF2C0ADD815A0027CCDF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D284BEBF0ADD80A20027CCDF /* dnsextd */;
targetProxy = D284BF2B0ADD815A0027CCDF /* PBXContainerItemProxy */;
};
- D284BF2E0ADD81600027CCDF /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = D284BEDB0ADD80A70027CCDF /* ddnswriteconfig */;
- targetProxy = D284BF2D0ADD81600027CCDF /* PBXContainerItemProxy */;
- };
D284BF300ADD81630027CCDF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D284BEEA0ADD80B00027CCDF /* PreferencePane */;
@@ -2098,11 +3011,6 @@
target = FFA5723C0AF18F450055A0F1 /* libdns_sd_profile_dynamic */;
targetProxy = FFA5726C0AF191020055A0F1 /* PBXContainerItemProxy */;
};
- FFAE66F9105F0CF100162116 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = D284BEDB0ADD80A70027CCDF /* ddnswriteconfig */;
- targetProxy = FFAE66F8105F0CF100162116 /* PBXContainerItemProxy */;
- };
FFB7657D0AEED97F00583A2C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 00AD62BB032D7A0C0CCA2C71 /* Build More */;
@@ -2114,7 +3022,7 @@
FF260A4807B4475600CE10E5 /* DNSServiceDiscoveryPref.nib */ = {
isa = PBXVariantGroup;
children = (
- FF260A4907B4475600CE10E5 /* English */,
+ B7E5920F1DB687A700A38085 /* Base */,
);
name = DNSServiceDiscoveryPref.nib;
path = PreferencePane;
@@ -2139,6 +3047,103 @@
};
name = Release;
};
+ 0C1596B01D773FE300E09998 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "USE_LIBIDN=1",
+ "USE_AWD=0",
+ "__MAC_OS_X_VERSION_MIN_REQUIRED=1",
+ "IPV6_PKTINFO=1",
+ "HAVE_IPV6=1",
+ "_BUILDING_XCODE_PROJECT_=1",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = NO;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ ../mDNSCore,
+ ../mDNSShared,
+ );
+ INSTALL_PATH = /usr/local/bin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 0C1596B11D773FE300E09998 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "HAVE_IPV6=1",
+ "_BUILDING_XCODE_PROJECT_=1",
+ "USE_AWD=0",
+ "__MAC_OS_X_VERSION_MIN_REQUIRED=1",
+ "IPV6_PKTINFO=1",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = NO;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ ../mDNSCore,
+ ../mDNSShared,
+ );
+ INSTALL_PATH = /usr/local/bin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
0C419F121BA20DF600A70FF7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -2155,9 +3160,10 @@
"mDNSResponderVersion=${MVERS}",
_LEGACY_NAT_TRAVERSAL_,
"_BUILDING_XCODE_PROJECT_=1",
- "DEBUG=1",
"BONJOUR_ON_DEMAND=1",
"USE_LIBIDN=1",
+ "USE_AWD=1",
+ "DEBUG=1",
);
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
@@ -2218,6 +3224,10 @@
"$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
);
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "HAVE_DNS64=1",
+ );
GCC_TREAT_WARNINGS_AS_ERRORS = NO;
HEADER_SEARCH_PATHS = (
"$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/PrivateHeaders",
@@ -2327,6 +3337,18 @@
0C419F1A1BA20DF600A70FF7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__APPLE_USE_RFC_3542=1",
+ "_DNS_SD_LIBDISPATCH=1",
+ "APPLE_OSX_mDNSResponder=1",
+ "__MigTypeCheck=1",
+ "mDNSResponderVersion=${MVERS}",
+ _LEGACY_NAT_TRAVERSAL_,
+ "_BUILDING_XCODE_PROJECT_=1",
+ "BONJOUR_ON_DEMAND=1",
+ "USE_LIBIDN=1",
+ "USE_AWD=1",
+ );
HEADER_SEARCH_PATHS = (
"${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders",
"${APPLE_INTERNAL_DEVELOPER_DIR}/Headers",
@@ -2341,24 +3363,23 @@
};
name = Debug;
};
- 0C419F1B1BA20DF600A70FF7 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- INSTALL_PATH = "/Library/Application Support/Bonjour";
- MACOSX_DEPLOYMENT_TARGET = 10.6;
- OTHER_LDFLAGS = "-Wl,-pie";
- PRODUCT_NAME = ddnswriteconfig;
- };
- name = Debug;
- };
0C419F1C1BA20DF600A70FF7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CODE_SIGN_IDENTITY = "-";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
GCC_ENABLE_OBJC_GC = supported;
+ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
INFOPLIST_FILE = "PreferencePane/Info-PreferencePane.plist";
INSTALL_PATH = /AppleInternal/Library/PreferencePanes;
- MACOSX_DEPLOYMENT_TARGET = 10.6;
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = Bonjour;
+ SUPPORTED_PLATFORMS = macosx;
WRAPPER_EXTENSION = prefPane;
};
name = Debug;
@@ -2602,6 +3623,98 @@
};
name = Debug;
};
+ 0C635A7A1E9418A60026C796 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DEVELOPMENT_TEAM = 63ZFQSB63Y;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = NO;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.10;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ OTHER_LDFLAGS = "-lncurses";
+ PRODUCT_NAME = bonjourtop;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ 0C635A7B1E9418A60026C796 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DEVELOPMENT_TEAM = 63ZFQSB63Y;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+ GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = NO;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.10;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ OTHER_LDFLAGS = "-lncurses";
+ PRODUCT_NAME = bonjourtop;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
213FB21A12028A7B002B3A08 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -2714,8 +3827,60 @@
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = YES;
+ DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__APPLE_USE_RFC_3542=1",
+ "_DNS_SD_LIBDISPATCH=1",
+ "APPLE_OSX_mDNSResponder=1",
+ "__MigTypeCheck=1",
+ "mDNSResponderVersion=${MVERS}",
+ _LEGACY_NAT_TRAVERSAL_,
+ "_BUILDING_XCODE_PROJECT_=1",
+ "BONJOUR_ON_DEMAND=1",
+ "USE_LIBIDN=1",
+ "USE_AWD=1",
+ "UNIT_TEST=1",
+ "NO_AWACS=1",
+ );
+ GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+ HEADER_SEARCH_PATHS = (
+ "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/PrivateHeaders",
+ ../mDNSShared,
+ "${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders",
+ "${APPLE_INTERNAL_DEVELOPER_DIR}/Headers",
+ "${CONFIGURATION_TEMP_DIR}",
+ "$(SDKROOT)/usr/include/libxml2",
+ "$(SDKROOT)/usr/local/include/",
+ "$(SDKROOT)/usr/include/",
+ );
+ LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
+ MACOSX_DEPLOYMENT_TARGET = 10.10;
+ ONLY_ACTIVE_ARCH = NO;
+ OTHER_LDFLAGS = (
+ "-weak_framework",
+ WebFilterDNS,
+ "-weak_framework",
+ DeviceToDeviceManager,
+ );
PRODUCT_NAME = unittests;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = macosx;
+ WARNING_CFLAGS = (
+ "-W",
+ "-Wall",
+ "-Wmissing-prototypes",
+ "-Wno-four-char-constants",
+ "-Wno-unknown-pragmas",
+ "-Wshadow",
+ "-Wno-format",
+ "-Wformat-security",
+ );
};
name = Release;
};
@@ -2723,118 +3888,746 @@
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
+ DEAD_CODE_STRIPPING = YES;
+ ENABLE_TESTABILITY = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__APPLE_USE_RFC_3542=1",
+ "_DNS_SD_LIBDISPATCH=1",
+ "APPLE_OSX_mDNSResponder=1",
+ "__MigTypeCheck=1",
+ "mDNSResponderVersion=${MVERS}",
+ _LEGACY_NAT_TRAVERSAL_,
+ "_BUILDING_XCODE_PROJECT_=1",
+ "DEBUG=1",
+ "BONJOUR_ON_DEMAND=1",
+ "USE_LIBIDN=1",
+ "USE_AWD=1",
+ "UNIT_TEST=1",
+ "NO_AWACS=1",
+ );
+ GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+ HEADER_SEARCH_PATHS = (
+ "$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/PrivateHeaders",
+ ../mDNSShared,
+ "${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders",
+ "${APPLE_INTERNAL_DEVELOPER_DIR}/Headers",
+ "${CONFIGURATION_TEMP_DIR}",
+ "$(SDKROOT)/usr/include/libxml2",
+ "$(SDKROOT)/usr/local/include/",
+ "$(SDKROOT)/usr/include/",
+ );
+ LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
+ MACOSX_DEPLOYMENT_TARGET = 10.10;
+ ONLY_ACTIVE_ARCH = NO;
+ OTHER_LDFLAGS = (
+ "-weak_framework",
+ WebFilterDNS,
+ "-weak_framework",
+ DeviceToDeviceManager,
+ );
PRODUCT_NAME = unittests;
+ SUPPORTED_PLATFORMS = "macosx iphoneos";
};
name = Debug;
};
- 37DDE9321BA383610092AC61 /* Development */ = {
+ 72FB5466166D5FB00090B2D9 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_ENTITLEMENTS = "dnsctl-entitlements.plist";
+ CODE_SIGN_IDENTITY = "-";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_STRICT_ALIASING = YES;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INSTALL_PATH = /usr/local/bin;
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE = "";
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ 84C5B3371665529800C324A8 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ EXECUTABLE_PREFIX = lib;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INSTALL_PATH = /usr/lib;
+ MACOSX_DEPLOYMENT_TARGET = 10.8;
+ ONLY_ACTIVE_ARCH = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ B7325FF41DA47EBA00663834 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVES = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "";
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = ../mDNSUI/DomainBrowser/iOS/Info.plist;
+ INSTALL_PATH = "@rpath";
+ IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = com.apple.coseos.network.bonjour.DomainBrowser;
+ PRODUCT_NAME = DomainBrowser;
+ SDKROOT = iphoneos.internal;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Release;
+ };
+ B7325FF51DA47EBA00663834 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BOOL_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)";
- CLANG_WARN_CONSTANT_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)";
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = NO;
- CLANG_WARN_ENUM_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)";
- CLANG_WARN_INT_CONVERSION = "$(CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION)";
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_UNREACHABLE_CODE = NO;
+ CLANG_WARN_SUSPICIOUS_MOVES = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- COPY_PHASE_STRIP = NO;
+ CODE_SIGN_IDENTITY = "";
+ CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
- GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
- GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
- GCC_WARN_ABOUT_RETURN_TYPE = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = NO;
- GCC_WARN_UNUSED_FUNCTION = NO;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.11;
+ INFOPLIST_FILE = ../mDNSUI/DomainBrowser/iOS/Info.plist;
+ INSTALL_PATH = "@rpath";
+ IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = com.apple.coseos.network.bonjour.DomainBrowser;
+ PRODUCT_NAME = DomainBrowser;
+ SDKROOT = iphoneos.internal;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Debug;
+ };
+ B74EC11C1D47FC7800A1D155 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CODE_SIGN_IDENTITY = "-";
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ INFOPLIST_FILE = SettingsBundle/Info.plist;
+ INSTALL_PATH = /AppleInternal/Library/PreferenceBundles;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = com.apple.network.bonjour.BonjourSettings;
PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = macosx;
- STRIP_INSTALLED_PRODUCT = NO;
+ SDKROOT = iphoneos.internal;
+ SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
};
- name = Development;
+ name = Release;
};
- 72FB5466166D5FB00090B2D9 /* Release */ = {
+ B74EC11D1D47FC7800A1D155 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CODE_SIGN_IDENTITY = "-";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "${inherited}",
+ );
+ INFOPLIST_FILE = SettingsBundle/Info.plist;
+ INSTALL_PATH = /AppleInternal/Library/PreferenceBundles;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = com.apple.network.bonjour.BonjourSettings;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos.internal;
+ SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ B76783B51E82D65900DA271E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "compiler-default";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_ENTITLEMENTS = PreferencePane/BonjourPrefTool/entitlements.plist;
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = "$(SRCROOT)/PreferencePane/BonjourPrefTool/BonjourPrefTool-Info.plist";
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_NAME = com.apple.preference.bonjour.tool;
+ SDKROOT = macosx.internal;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = macosx;
+ };
+ name = Release;
+ };
+ B76783B61E82D65900DA271E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "compiler-default";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_ENTITLEMENTS = PreferencePane/BonjourPrefTool/entitlements.plist;
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = "$(SRCROOT)/PreferencePane/BonjourPrefTool/BonjourPrefTool-Info.plist";
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_NAME = com.apple.preference.bonjour.tool;
+ SDKROOT = macosx.internal;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = macosx;
+ };
+ name = Debug;
+ };
+ B7C4B7261E71BD5000136C7A /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ B7C4B7271E71BD5000136C7A /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ B7D566C41E81D8FD00E43008 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "compiler-default";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- CODE_SIGN_ENTITLEMENTS = "dnsctl-entitlements.plist";
+ CODE_SIGN_ENTITLEMENTS = PreferencePane/RemoteViewService/entitlements.plist;
CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = "$(SRCROOT)/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService-Info.plist";
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_NAME = com.apple.preference.bonjour.remoteservice;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = macosx;
+ };
+ name = Release;
+ };
+ B7D566C51E81D8FD00E43008 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "compiler-default";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_ENTITLEMENTS = PreferencePane/RemoteViewService/entitlements.plist;
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
- GCC_STRICT_ALIASING = YES;
- GCC_SYMBOLS_PRIVATE_EXTERN = NO;
- GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- INSTALL_PATH = /usr/local/bin;
+ INFOPLIST_FILE = "$(SRCROOT)/PreferencePane/RemoteViewService/BonjourPrefRemoteViewService-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.9;
- PRODUCT_NAME = "$(TARGET_NAME)";
- PROVISIONING_PROFILE = "";
- SDKROOT = macosx;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_NAME = com.apple.preference.bonjour.remoteservice;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = macosx;
+ };
+ name = Debug;
+ };
+ B7D6CA761D1076F3005E24CF /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPRESSION = "respect-asset-catalog";
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ FRAMEWORK_VERSION = A;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = ../mDNSUI/DomainBrowser/macOS/Info.plist;
+ INSTALL_PATH = "@rpath";
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_BUNDLE_IDENTIFIER = com.apple.coreos.network.bonjour.DomainBrowser;
+ PRODUCT_NAME = DomainBrowser;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = macosx;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
};
name = Release;
};
- 84C5B3371665529800C324A8 /* Release */ = {
+ B7D6CA771D1076F3005E24CF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPRESSION = lossless;
+ CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- EXECUTABLE_PREFIX = lib;
+ CODE_SIGN_IDENTITY = "-";
+ COMBINE_HIDPI_IMAGES = YES;
+ CURRENT_PROJECT_VERSION = 1;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DEFINES_MODULE = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ FRAMEWORK_VERSION = A;
GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
- GCC_SYMBOLS_PRIVATE_EXTERN = NO;
- GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ INFOPLIST_FILE = ../mDNSUI/DomainBrowser/macOS/Info.plist;
+ INSTALL_PATH = "@rpath";
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = com.apple.coreos.network.bonjour.DomainBrowser;
+ PRODUCT_NAME = DomainBrowser;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = macosx;
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Debug;
+ };
+ BD9BA7511EAF90E400658CCF /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_ASSIGN_ENUM = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_CXX0X_EXTENSIONS = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES;
+ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
+ CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
+ GCC_PREPROCESSOR_DEFINITIONS = "MDNSRESPONDER_PROJECT=1";
+ GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
+ GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES;
+ GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
+ GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+ GCC_WARN_PEDANTIC = YES;
+ GCC_WARN_SHADOW = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_STRICT_SELECTOR_MATCH = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_LABEL = YES;
+ GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- INSTALL_PATH = /usr/lib;
- MACOSX_DEPLOYMENT_TARGET = 10.8;
- ONLY_ACTIVE_ARCH = NO;
+ HEADER_SEARCH_PATHS = "$(SDKROOT)${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders";
+ INSTALL_PATH = /usr/local/bin;
PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = macosx;
+ WARNING_CFLAGS = "-Wno-nullability-extension";
};
name = Release;
};
+ BD9BA7521EAF90E400658CCF /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_ASSIGN_ENUM = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_CXX0X_EXTENSIONS = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = NO;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES;
+ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
+ CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "MDNSRESPONDER_PROJECT=1",
+ "DEBUG=1",
+ );
+ GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
+ GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES;
+ GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
+ GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+ GCC_WARN_PEDANTIC = YES;
+ GCC_WARN_SHADOW = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_STRICT_SELECTOR_MATCH = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_LABEL = YES;
+ GCC_WARN_UNUSED_PARAMETER = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "$(SDKROOT)${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders";
+ INSTALL_PATH = /usr/local/bin;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ WARNING_CFLAGS = "-Wno-nullability-extension";
+ };
+ name = Debug;
+ };
D284BE290ADD78180027CCDF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -2859,6 +4652,7 @@
"_BUILDING_XCODE_PROJECT_=1",
"BONJOUR_ON_DEMAND=1",
"USE_LIBIDN=1",
+ "USE_AWD=1",
);
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
@@ -2896,6 +4690,10 @@
"$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
);
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "HAVE_DNS64=1",
+ );
GCC_TREAT_WARNINGS_AS_ERRORS = NO;
HEADER_SEARCH_PATHS = (
"$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/PrivateHeaders",
@@ -2980,24 +4778,22 @@
};
name = Release;
};
- D284BEE60ADD80A70027CCDF /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- INSTALL_PATH = "/Library/Application Support/Bonjour";
- MACOSX_DEPLOYMENT_TARGET = 10.6;
- OTHER_LDFLAGS = "-Wl,-pie";
- PRODUCT_NAME = ddnswriteconfig;
- };
- name = Release;
- };
D284BF090ADD80B00027CCDF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CODE_SIGN_IDENTITY = "-";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+ );
GCC_ENABLE_OBJC_GC = supported;
+ GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
INFOPLIST_FILE = "PreferencePane/Info-PreferencePane.plist";
INSTALL_PATH = /AppleInternal/Library/PreferencePanes;
- MACOSX_DEPLOYMENT_TARGET = 10.6;
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
PRODUCT_NAME = Bonjour;
+ SUPPORTED_PLATFORMS = macosx;
WRAPPER_EXTENSION = prefPane;
};
name = Release;
@@ -3131,6 +4927,24 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 0C1596B21D773FE300E09998 /* Build configuration list for PBXNativeTarget "mDNSNetMonitor" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 0C1596B01D773FE300E09998 /* Release */,
+ 0C1596B11D773FE300E09998 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 0C635A7C1E9418A60026C796 /* Build configuration list for PBXNativeTarget "BonjourTop" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 0C635A7A1E9418A60026C796 /* Release */,
+ 0C635A7B1E9418A60026C796 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
213FB21B12028A7C002B3A08 /* Build configuration list for PBXNativeTarget "BonjourEvents" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@@ -3197,7 +5011,6 @@
37DDE9311BA383610092AC61 /* Build configuration list for PBXNativeTarget "unittests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 37DDE9321BA383610092AC61 /* Development */,
37AF80281BF6997A00D657F6 /* Release */,
37AF80291BF6997A00D657F6 /* Debug */,
);
@@ -3231,6 +5044,69 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ B7325FF31DA47EBA00663834 /* Build configuration list for PBXNativeTarget "DomainBrowser-iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B7325FF41DA47EBA00663834 /* Release */,
+ B7325FF51DA47EBA00663834 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B74EC11E1D47FC7800A1D155 /* Build configuration list for PBXNativeTarget "BonjourSettings" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B74EC11C1D47FC7800A1D155 /* Release */,
+ B74EC11D1D47FC7800A1D155 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B76783B71E82D65900DA271E /* Build configuration list for PBXNativeTarget "BonjourPrefsTool" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B76783B51E82D65900DA271E /* Release */,
+ B76783B61E82D65900DA271E /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B7C4B7281E71BD5000136C7A /* Build configuration list for PBXAggregateTarget "Build Some iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B7C4B7261E71BD5000136C7A /* Release */,
+ B7C4B7271E71BD5000136C7A /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B7D566C31E81D8FD00E43008 /* Build configuration list for PBXNativeTarget "RemoteViewService" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B7D566C41E81D8FD00E43008 /* Release */,
+ B7D566C51E81D8FD00E43008 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ B7D6CA751D1076F3005E24CF /* Build configuration list for PBXNativeTarget "DomainBrowser-macOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ B7D6CA761D1076F3005E24CF /* Release */,
+ B7D6CA771D1076F3005E24CF /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ BD9BA7501EAF90E400658CCF /* Build configuration list for PBXNativeTarget "dnssdutil" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ BD9BA7511EAF90E400658CCF /* Release */,
+ BD9BA7521EAF90E400658CCF /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
D284BE280ADD78180027CCDF /* Build configuration list for PBXAggregateTarget "Build More" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@@ -3285,15 +5161,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- D284BEE50ADD80A70027CCDF /* Build configuration list for PBXNativeTarget "ddnswriteconfig" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- D284BEE60ADD80A70027CCDF /* Release */,
- 0C419F1B1BA20DF600A70FF7 /* Debug */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
D284BF080ADD80B00027CCDF /* Build configuration list for PBXNativeTarget "PreferencePane" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c b/mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c
index cc0d0bae..96d4a0db 100644
--- a/mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c
+++ b/mDNSResponder/mDNSMacOSX/uDNSPathEvalulation.c
@@ -18,11 +18,11 @@
#include "mDNSMacOSX.h"
#include <libproc.h>
#include <network/private.h>
+#include "dns_sd_internal.h"
//Gets the DNSPolicy from NW PATH EVALUATOR
-mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDNSBool *isBlocked)
+mDNSexport void mDNSPlatformGetDNSRoutePolicy(DNSQuestion *q, mDNSBool *isBlocked)
{
- (void) m;
q->ServiceID = -1; // initialize the ServiceID to default value of -1
// Return for non-unicast DNS queries, invalid pid, if NWPathEvaluation is already done by the client, or NWPathEvaluation not available on this OS
@@ -57,6 +57,7 @@ mDNSexport void mDNSPlatformGetDNSRoutePolicy(mDNS *const m, DNSQuestion *q, mDN
|| (q->InterfaceID == mDNSInterface_LocalOnly)
|| (q->InterfaceID == mDNSInterfaceMark)
|| (q->InterfaceID == mDNSInterface_P2P)
+ || (q->InterfaceID == mDNSInterface_BLE)
|| (q->InterfaceID == uDNSInterfaceMark))
{
client_ifindex = 0;