[Midnightbsd-cvs] src [6985] vendor/apple/mDNSResponder/561.1.1: mDNSResponder 561.1.1

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Thu Mar 19 21:14:53 EDT 2015


Revision: 6985
          http://svnweb.midnightbsd.org/src/?rev=6985
Author:   laffer1
Date:     2015-03-19 21:14:52 -0400 (Thu, 19 Mar 2015)
Log Message:
-----------
mDNSResponder 561.1.1

Added Paths:
-----------
    vendor/apple/mDNSResponder/561.1.1/
    vendor/apple/mDNSResponder/561.1.1/Clients/dnsctl.c
    vendor/apple/mDNSResponder/561.1.1/Makefile
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/BonjourEvents.c
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/LaunchDaemonInfo.plist
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/Private/dns_services.c
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/Private/dns_services_mdns.h
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/base.xcconfig
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/helper.c
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSMacOSX.c
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
    vendor/apple/mDNSResponder/561.1.1/mDNSPosix/mDNSPosix.c
    vendor/apple/mDNSResponder/561.1.1/mDNSShared/dns_sd.h
    vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_clientstub.c
    vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_ipc.h
    vendor/apple/mDNSResponder/561.1.1/mDNSWindows/mDNSWin32.c

Removed Paths:
-------------
    vendor/apple/mDNSResponder/561.1.1/Clients/dnsctl.c
    vendor/apple/mDNSResponder/561.1.1/Makefile
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/BonjourEvents.c
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/LaunchDaemonInfo.plist
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/Private/dns_services.c
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/helper.c
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSMacOSX.c
    vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
    vendor/apple/mDNSResponder/561.1.1/mDNSPosix/mDNSPosix.c
    vendor/apple/mDNSResponder/561.1.1/mDNSShared/dns_sd.h
    vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_clientstub.c
    vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_ipc.h
    vendor/apple/mDNSResponder/561.1.1/mDNSWindows/mDNSWin32.c

Deleted: vendor/apple/mDNSResponder/561.1.1/Clients/dnsctl.c
===================================================================
--- vendor/apple/mDNSResponder/dist/Clients/dnsctl.c	2014-06-30 23:58:12 UTC (rev 6706)
+++ vendor/apple/mDNSResponder/561.1.1/Clients/dnsctl.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -1,177 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*- 
- *
- * Copyright (c) 2012 Apple Inc. All rights reserved.
- *
- * dnsctl.c 
- * Command-line tool using libdns_services.dylib 
- *   
- * To build only this tool, copy and paste the following on the command line:
- * On Apple 64bit Platforms ONLY OSX/iOS:
- * clang -Wall dnsctl.c /usr/lib/libdns_services.dylib -o dnsctl
- * 
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <net/if.h> // if_nametoindex()
-
-#include <dispatch/dispatch.h>
-#include "dns_services.h"
-
-//*************************************************************************************************************
-// Globals:
-//*************************************************************************************************************
-
-static const char kFilePathSep   =  '/';
-static DNSXConnRef ClientRef     =  NULL;
-
-//*************************************************************************************************************
-// Utility Funcs:
-//*************************************************************************************************************
-
-static void printtimestamp(void) 
-{
-    struct tm tm; 
-    int ms; 
-    static char date[16];
-    static char new_date[16];
-    struct timeval tv; 
-    gettimeofday(&tv, NULL);
-    localtime_r((time_t*)&tv.tv_sec, &tm);
-    ms = tv.tv_usec/1000;
-    strftime(new_date, sizeof(new_date), "%a %d %b %Y", &tm);
-    //display date only if it has changed
-    if (strncmp(date, new_date, sizeof(new_date)))
-    {        
-        printf("DATE: ---%s---\n", new_date);
-        strncpy(date, new_date, sizeof(date));
-    }        
-    printf("%2d:%02d:%02d.%03d  ", tm.tm_hour, tm.tm_min, tm.tm_sec, ms); 
-}
-
-static void print_usage(const char *arg0)
-{
-    fprintf(stderr, "%s USAGE:                                                                  \n", arg0);
-    fprintf(stderr, "%s -DP Enable DNS Proxy with Default Parameters                            \n", arg0);
-    fprintf(stderr, "%s -DP [-o <output interface>] [-i <input interface(s)>] Enable DNS Proxy  \n", arg0);
-}
-
-//*************************************************************************************************************
-// CallBack Funcs:
-//*************************************************************************************************************
-
-// DNSXEnableProxy Callback from the Daemon
-static void dnsproxy_reply(DNSXConnRef connRef, DNSXErrorType errCode)
-{
-    (void) connRef;
-    printtimestamp();
-    switch (errCode)
-    {
-        case kDNSX_NoError          :  printf("  SUCCESS   \n");     break;
-        case kDNSX_DictError        :  printf(" DICT ERROR \n");     break;
-        case kDNSX_DaemonNotRunning :  printf(" NO DAEMON  \n");
-                                       DNSXRefDeAlloc(ClientRef);    break;
-        case kDNSX_Engaged          :  printf(" ENGAGED    \n");
-                                       DNSXRefDeAlloc(ClientRef);    break;
-        case kDNSX_UnknownErr       :
-        default                     :  printf("UNKNOWN ERR \n");
-                                       DNSXRefDeAlloc(ClientRef);    break;
-    }
-
-}
-
-//*************************************************************************************************************
-
-int main(int argc, char **argv)
-{
-    DNSXErrorType err;
-
-    // Default i/p intf is lo0 and o/p intf is primary interface
-    IfIndex Ipintfs[MaxInputIf] =  {1, 0, 0, 0, 0};
-    IfIndex Opintf = kDNSIfindexAny;
-
-    // Extract program name from argv[0], which by convention contains the path to this executable
-    const char *a0 = strrchr(argv[0], kFilePathSep) + 1; 
-    if (a0 == (const char *)1)
-        a0 = argv[0];
-
-    // Must run as root
-    if (0 != geteuid()) 
-    {        
-        fprintf(stderr, "%s MUST run as root!!\n", a0); 
-        exit(-1); 
-    }
-    if ((sizeof(argv) == 8))
-        printf("dnsctl running in 64-bit mode\n");
-    else if ((sizeof(argv) == 4))
-        printf("dnsctl running in 32-bit mode\n");
-
-    // expects atleast one argument
-    if (argc < 2)
-        goto Usage;
-
-    if ( !strcmp(argv[1], "-DP") || !strcmp(argv[1], "-dp") )
-    {
-        if (argc == 2)
-        {
-            printtimestamp();
-            printf("Proceeding to Enable DNSProxy on mDNSResponder with Default Parameters\n");
-            dispatch_queue_t my_Q = dispatch_queue_create("com.apple.dnsctl.callback_queue", NULL);
-            err = DNSXEnableProxy(&ClientRef, kDNSProxyEnable, Ipintfs, Opintf, my_Q, dnsproxy_reply);
-        }            
-        else if (argc > 2)
-        {
-            argc--;
-            argv++;
-            if (!strcmp(argv[1], "-o"))
-            {
-                Opintf = if_nametoindex(argv[2]);
-                if (!Opintf) 
-                    Opintf = atoi(argv[2]);
-                if (!Opintf) 
-                { 
-                    fprintf(stderr, "Could not parse o/p interface [%s]: Passing default primary \n", argv[2]); 
-                    Opintf = kDNSIfindexAny;
-                }
-                argc -= 2;
-                argv += 2;
-            }
-            if (argc > 2 && !strcmp(argv[1], "-i")) 
-            {
-                int i;
-                argc--;
-                argv++;
-                for (i = 0; i < MaxInputIf && argc > 1; i++)
-                {
-                    Ipintfs[i] = if_nametoindex(argv[1]);
-                    if (!Ipintfs[i])
-                        Ipintfs[i] = atoi(argv[1]);  
-                    if (!Ipintfs[i])
-                    {
-                        fprintf(stderr, "Could not parse i/p interface [%s]: Passing default lo0 \n", argv[2]); 
-                        Ipintfs[i] = 1;
-                    }
-                    argc--;
-                    argv++;
-                }
-            }  
-            printtimestamp();
-            printf("Proceeding to Enable DNSProxy on mDNSResponder \n");
-            dispatch_queue_t my_Q = dispatch_queue_create("com.apple.dnsctl.callback_queue", NULL);
-            err = DNSXEnableProxy(&ClientRef, kDNSProxyEnable, Ipintfs, Opintf, my_Q, dnsproxy_reply);                
-        }
-    }
-    else
-    {
-        goto Usage;
-    }
-
-    dispatch_main(); 
-
-Usage:
-    print_usage(a0);
-    return 0;
-}
-

Copied: vendor/apple/mDNSResponder/561.1.1/Clients/dnsctl.c (from rev 6984, vendor/apple/mDNSResponder/dist/Clients/dnsctl.c)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/Clients/dnsctl.c	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/Clients/dnsctl.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,178 @@
+/* -*- Mode: C; tab-width: 4 -*- 
+ *
+ * Copyright (c) 2012 Apple Inc. All rights reserved.
+ *
+ * dnsctl.c 
+ * Command-line tool using libdns_services.dylib 
+ *   
+ * To build only this tool, copy and paste the following on the command line:
+ * On Apple 64bit Platforms ONLY OSX/iOS:
+ * clang -Wall dnsctl.c /usr/lib/libdns_services.dylib -o dnsctl
+ * 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <net/if.h> // if_nametoindex()
+
+#include <dispatch/dispatch.h>
+#include "dns_services_mdns.h"
+
+//*************************************************************************************************************
+// Globals:
+//*************************************************************************************************************
+
+static const char kFilePathSep   =  '/';
+static DNSXConnRef ClientRef     =  NULL;
+
+//*************************************************************************************************************
+// Utility Funcs:
+//*************************************************************************************************************
+
+static void printtimestamp(void) 
+{
+    struct tm tm; 
+    int ms; 
+    static char date[16];
+    static char new_date[16];
+    struct timeval tv; 
+    gettimeofday(&tv, NULL);
+    localtime_r((time_t*)&tv.tv_sec, &tm);
+    ms = tv.tv_usec/1000;
+    strftime(new_date, sizeof(new_date), "%a %d %b %Y", &tm);
+    //display date only if it has changed
+    if (strncmp(date, new_date, sizeof(new_date)))
+    {        
+        printf("DATE: ---%s---\n", new_date);
+        strncpy(date, new_date, sizeof(date));
+    }        
+    printf("%2d:%02d:%02d.%03d  ", tm.tm_hour, tm.tm_min, tm.tm_sec, ms); 
+}
+
+static void print_usage(const char *arg0)
+{
+    fprintf(stderr, "%s USAGE:                                                                  \n", arg0);
+    fprintf(stderr, "%s -DP Enable DNS Proxy with Default Parameters                            \n", arg0);
+    fprintf(stderr, "%s -DP [-o <output interface>] [-i <input interface(s)>] Enable DNS Proxy  \n", arg0);
+}
+
+//*************************************************************************************************************
+// CallBack Funcs:
+//*************************************************************************************************************
+
+// DNSXEnableProxy Callback from the Daemon
+static void dnsproxy_reply(DNSXConnRef connRef, DNSXErrorType errCode)
+{
+    (void) connRef;
+    printtimestamp();
+    switch (errCode)
+    {
+        case kDNSX_NoError          :  printf("  SUCCESS   \n");     break;
+        case kDNSX_DictError        :  printf(" DICT ERROR \n");     break;
+        case kDNSX_DaemonNotRunning :  printf(" NO DAEMON  \n");
+                                       DNSXRefDeAlloc(ClientRef);    break;
+        case kDNSX_Engaged          :  printf(" ENGAGED    \n");
+                                       DNSXRefDeAlloc(ClientRef);    break;
+        case kDNSX_UnknownErr       :
+        default                     :  printf("UNKNOWN ERR \n");
+                                       DNSXRefDeAlloc(ClientRef);    break;
+    }
+    fflush(NULL);
+
+}
+
+//*************************************************************************************************************
+
+int main(int argc, char **argv)
+{
+    DNSXErrorType err;
+
+    // Default i/p intf is lo0 and o/p intf is primary interface
+    IfIndex Ipintfs[MaxInputIf] =  {1, 0, 0, 0, 0};
+    IfIndex Opintf = kDNSIfindexAny;
+
+    // Extract program name from argv[0], which by convention contains the path to this executable
+    const char *a0 = strrchr(argv[0], kFilePathSep) + 1; 
+    if (a0 == (const char *)1)
+        a0 = argv[0];
+
+    // Must run as root
+    if (0 != geteuid()) 
+    {        
+        fprintf(stderr, "%s MUST run as root!!\n", a0); 
+        exit(-1); 
+    }
+    if ((sizeof(argv) == 8))
+        printf("dnsctl running in 64-bit mode\n");
+    else if ((sizeof(argv) == 4))
+        printf("dnsctl running in 32-bit mode\n");
+
+    // expects atleast one argument
+    if (argc < 2)
+        goto Usage;
+
+    if ( !strcmp(argv[1], "-DP") || !strcmp(argv[1], "-dp") )
+    {
+        if (argc == 2)
+        {
+            printtimestamp();
+            printf("Proceeding to Enable DNSProxy on mDNSResponder with Default Parameters\n");
+            dispatch_queue_t my_Q = dispatch_queue_create("com.apple.dnsctl.callback_queue", NULL);
+            err = DNSXEnableProxy(&ClientRef, kDNSProxyEnable, Ipintfs, Opintf, my_Q, dnsproxy_reply);
+        }            
+        else if (argc > 2)
+        {
+            argc--;
+            argv++;
+            if (!strcmp(argv[1], "-o"))
+            {
+                Opintf = if_nametoindex(argv[2]);
+                if (!Opintf) 
+                    Opintf = atoi(argv[2]);
+                if (!Opintf) 
+                { 
+                    fprintf(stderr, "Could not parse o/p interface [%s]: Passing default primary \n", argv[2]); 
+                    Opintf = kDNSIfindexAny;
+                }
+                argc -= 2;
+                argv += 2;
+            }
+            if (argc > 2 && !strcmp(argv[1], "-i")) 
+            {
+                int i;
+                argc--;
+                argv++;
+                for (i = 0; i < MaxInputIf && argc > 1; i++)
+                {
+                    Ipintfs[i] = if_nametoindex(argv[1]);
+                    if (!Ipintfs[i])
+                        Ipintfs[i] = atoi(argv[1]);  
+                    if (!Ipintfs[i])
+                    {
+                        fprintf(stderr, "Could not parse i/p interface [%s]: Passing default lo0 \n", argv[2]); 
+                        Ipintfs[i] = 1;
+                    }
+                    argc--;
+                    argv++;
+                }
+            }  
+            printtimestamp();
+            printf("Proceeding to Enable DNSProxy on mDNSResponder \n");
+            dispatch_queue_t my_Q = dispatch_queue_create("com.apple.dnsctl.callback_queue", NULL);
+            err = DNSXEnableProxy(&ClientRef, kDNSProxyEnable, Ipintfs, Opintf, my_Q, dnsproxy_reply);                
+        }
+    }
+    else
+    {
+        goto Usage;
+    }
+
+    dispatch_main(); 
+
+Usage:
+    print_usage(a0);
+    return 0;
+}
+

Deleted: vendor/apple/mDNSResponder/561.1.1/Makefile
===================================================================
--- vendor/apple/mDNSResponder/dist/Makefile	2014-06-30 23:58:12 UTC (rev 6706)
+++ vendor/apple/mDNSResponder/561.1.1/Makefile	2015-03-20 01:14:52 UTC (rev 6985)
@@ -1,49 +0,0 @@
-#
-# Top level makefile for Build & Integration.
-# 
-# This file is used to facilitate checking the mDNSResponder project
-# directly out of CVS and submitting to B&I at Apple.
-#
-# The various platform directories contain makefiles or projects
-# specific to that platform.
-#
-#    B&I builds must respect the following target:
-#         install:
-#         installsrc:
-#         installhdrs:
-#         clean:
-#
-
-include $(MAKEFILEPATH)/pb_makefiles/platform.make
-
-MVERS = "mDNSResponder-541"
-
-DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig"
-VER = 
-ifneq ($(strip $(GCC_VERSION)),)
-	VER = -- GCC_VERSION=$(GCC_VERSION)
-endif
-echo "VER = $(VER)"
-
-installSome:
-	cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install     OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT) -target Build\ Some $(VER) 
-
-SystemLibraries:
-	cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install     OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT) -target SystemLibraries $(VER) 
-
-install:
-	cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install     OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT) $(VER) 
-	# Make sure ddnswriteconfig is owned by root:wheel, then make it setuid root executable
-	if test -e $(DDNSWRITECONFIG) ; then chown 0:80 $(DDNSWRITECONFIG) ; chmod 4555 $(DDNSWRITECONFIG) ; fi
-
-installsrc:
-	ditto . "$(SRCROOT)"
-
-installhdrs::
-	cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild installhdrs OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT)  -target SystemLibraries $(VER)
-
-java:
-	cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install  OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT) -target libjdns_sd.jnilib $(VER)
-
-clean::
-	echo clean

Copied: vendor/apple/mDNSResponder/561.1.1/Makefile (from rev 6984, vendor/apple/mDNSResponder/dist/Makefile)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/Makefile	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/Makefile	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,49 @@
+#
+# Top level makefile for Build & Integration.
+# 
+# This file is used to facilitate checking the mDNSResponder project
+# directly out of CVS and submitting to B&I at Apple.
+#
+# The various platform directories contain makefiles or projects
+# specific to that platform.
+#
+#    B&I builds must respect the following target:
+#         install:
+#         installsrc:
+#         installhdrs:
+#         clean:
+#
+
+include $(MAKEFILEPATH)/pb_makefiles/platform.make
+
+MVERS = "mDNSResponder-561.1.1"
+
+DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig"
+VER = 
+ifneq ($(strip $(GCC_VERSION)),)
+	VER = -- GCC_VERSION=$(GCC_VERSION)
+endif
+echo "VER = $(VER)"
+
+installSome:
+	cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install     OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT) -target Build\ Some $(VER) 
+
+SystemLibraries:
+	cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install     OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT) -target SystemLibraries $(VER) 
+
+install:
+	cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install     OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT) $(VER) 
+	# Make sure ddnswriteconfig is owned by root:wheel, then make it setuid root executable
+	if test -e $(DDNSWRITECONFIG) ; then chown 0:80 $(DDNSWRITECONFIG) ; chmod 4555 $(DDNSWRITECONFIG) ; fi
+
+installsrc:
+	ditto . "$(SRCROOT)"
+
+installhdrs::
+	cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild installhdrs OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT)  -target SystemLibraries $(VER)
+
+java:
+	cd "$(SRCROOT)/mDNSMacOSX"; xcodebuild install  OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) SDKROOT=$(SDKROOT) -target libjdns_sd.jnilib $(VER)
+
+clean::
+	echo clean

Deleted: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/BonjourEvents.c
===================================================================
--- vendor/apple/mDNSResponder/dist/mDNSMacOSX/BonjourEvents.c	2014-06-30 23:58:12 UTC (rev 6706)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/BonjourEvents.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -1,991 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2010 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 <CoreFoundation/CoreFoundation.h>
-#include <CoreFoundation/CFXPCBridge.h>
-#include "dns_sd.h"
-#include <UserEventAgentInterface.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <asl.h>
-#include <xpc/xpc.h>
-
-
-#pragma mark -
-#pragma mark Types
-#pragma mark -
-static const char*          sPluginIdentifier       = "com.apple.bonjour.events";
-
-// PLIST Keys
-static const CFStringRef sServiceNameKey         = CFSTR("ServiceName");
-static const CFStringRef sServiceTypeKey         = CFSTR("ServiceType");
-static const CFStringRef sServiceDomainKey       = CFSTR("ServiceDomain");
-
-static const CFStringRef sOnServiceAddKey        = CFSTR("OnServiceAdd");
-static const CFStringRef sOnServiceRemoveKey     = CFSTR("OnServiceRemove");
-
-static const CFStringRef sLaunchdTokenKey        = CFSTR("LaunchdToken");
-static const CFStringRef sLaunchdDictKey         = CFSTR("LaunchdDict");
-
-
-/************************************************
-* Launch Event Dictionary (input from launchd)
-* Passed To: ManageEventsCallback
-*-----------------------------------------------
-* Typing in this dictionary is not enforced
-* above us. So this may not be true. Type check
-* all input before using it.
-*-----------------------------------------------
-* sServiceNameKey		- CFString (Optional)
-* sServiceTypeKey		- CFString
-* sServiceDomainKey	- CFString
-*
-* One or more of the following.
-*-----------------------------------
-* sOnServiceAddKey			- CFBoolean
-* sOnServiceRemoveKey		- CFBoolean
-* sWhileServiceExistsKey	- CFBoolean
-************************************************/
-
-/************************************************
-* Browser Dictionary
-*-----------------------------------------------
-* sServiceDomainKey - CFString
-* sServiceTypeKey   - CFString
-************************************************/
-
-/************************************************
-* Event Dictionary
-*-----------------------------------------------
-* sServiceNameKey	 - CFString (Optional)
-* sLaunchdTokenKey	 - CFNumber
-************************************************/
-
-typedef struct {
-    UserEventAgentInterfaceStruct*      _UserEventAgentInterface;
-    CFUUIDRef _factoryID;
-    UInt32 _refCount;
-
-    void*                               _pluginContext;
-
-    CFMutableDictionaryRef _tokenToBrowserMap;                  // Maps a token to a browser that can be used to scan the remaining dictionaries.
-    CFMutableDictionaryRef _browsers;                           // A Dictionary of Browser Dictionaries where the resposible browser is the key.
-    CFMutableDictionaryRef _onAddEvents;                        // A Dictionary of Event Dictionaries that describe events to trigger on a service appearing.
-    CFMutableDictionaryRef _onRemoveEvents;                     // A Dictionary of Event Dictionaries that describe events to trigger on a service disappearing.
-} BonjourUserEventsPlugin;
-
-typedef struct {
-    CFIndex refCount;
-    DNSServiceRef browserRef;
-} NetBrowserInfo;
-
-#pragma mark -
-#pragma mark Prototypes
-#pragma mark -
-// COM Stuff
-static HRESULT  QueryInterface(void *myInstance, REFIID iid, LPVOID *ppv);
-static ULONG    AddRef(void* instance);
-static ULONG    Release(void* instance);
-
-static BonjourUserEventsPlugin* Alloc(CFUUIDRef factoryID);
-static void Dealloc(BonjourUserEventsPlugin* plugin);
-
-void * UserEventAgentFactory(CFAllocatorRef allocator, CFUUIDRef typeID);
-
-// Plugin Management
-static void Install(void* instance);
-static void ManageEventsCallback(
-    UserEventAgentLaunchdAction action,
-    CFNumberRef token,
-    CFTypeRef eventMatchDict,
-    void                      * vContext);
-
-
-// Plugin Guts
-void AddEventToPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken, CFDictionaryRef eventParameters);
-void RemoveEventFromPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchToken);
-
-NetBrowserInfo* CreateBrowser(BonjourUserEventsPlugin* plugin, CFStringRef type, CFStringRef domain);
-NetBrowserInfo* BrowserForSDRef(BonjourUserEventsPlugin* plugin, DNSServiceRef sdRef);
-void AddEventDictionary(CFDictionaryRef eventDict, CFMutableDictionaryRef allEventsDictionary, NetBrowserInfo* key);
-void RemoveEventFromArray(CFMutableArrayRef array, CFNumberRef launchdToken);
-
-// Net Service Browser Stuff
-void ServiceBrowserCallback (DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char* serviceName, const char* regtype, const char* replyDomain, void* context);
-void HandleTemporaryEventsForService(BonjourUserEventsPlugin* plugin, NetBrowserInfo* browser, CFStringRef serviceName, CFMutableDictionaryRef eventsDictionary);
-
-// Convence Stuff
-const char* CStringFromCFString(CFStringRef string);
-
-// NetBrowserInfo "Object"
-NetBrowserInfo* NetBrowserInfoCreate(CFStringRef serviceType, CFStringRef domain, void* context);
-const void* NetBrowserInfoRetain(CFAllocatorRef allocator, const void* info);
-void NetBrowserInfoRelease(CFAllocatorRef allocator, const void* info);
-Boolean NetBrowserInfoEqual(const void *value1, const void *value2);
-CFHashCode  NetBrowserInfoHash(const void *value);
-CFStringRef NetBrowserInfoCopyDescription(const void *value);
-
-static const CFDictionaryKeyCallBacks kNetBrowserInfoDictionaryKeyCallbacks = {
-    0,
-    NetBrowserInfoRetain,
-    NetBrowserInfoRelease,
-    NetBrowserInfoCopyDescription,
-    NetBrowserInfoEqual,
-    NetBrowserInfoHash
-};
-
-static const CFDictionaryValueCallBacks kNetBrowserInfoDictionaryValueCallbacks = {
-    0,
-    NetBrowserInfoRetain,
-    NetBrowserInfoRelease,
-    NetBrowserInfoCopyDescription,
-    NetBrowserInfoEqual
-};
-
-// COM type definition goop.
-static UserEventAgentInterfaceStruct UserEventAgentInterfaceFtbl = {
-    NULL,                   // Required padding for COM
-    QueryInterface,         // Query Interface
-    AddRef,                 // AddRef()
-    Release,                // Release()
-    Install                 // Install
-};
-
-#pragma mark -
-#pragma mark COM Management
-#pragma mark -
-
-/*****************************************************************************
-*****************************************************************************/
-static HRESULT QueryInterface(void *myInstance, REFIID iid, LPVOID *ppv)
-{
-    CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(NULL, iid);
-
-    // Test the requested ID against the valid interfaces.
-    if(CFEqual(interfaceID, kUserEventAgentInterfaceID))
-    {
-        ((BonjourUserEventsPlugin *) myInstance)->_UserEventAgentInterface->AddRef(myInstance);
-        *ppv = myInstance;
-        CFRelease(interfaceID);
-        return S_OK;
-    }
-    else if(CFEqual(interfaceID, IUnknownUUID))
-    {
-        ((BonjourUserEventsPlugin *) myInstance)->_UserEventAgentInterface->AddRef(myInstance);
-        *ppv = myInstance;
-        CFRelease(interfaceID);
-        return S_OK;
-    }
-    else //  Requested interface unknown, bail with error.
-    {
-        *ppv = NULL;
-        CFRelease(interfaceID);
-        return E_NOINTERFACE;
-    }
-}
-
-/*****************************************************************************
-*****************************************************************************/
-static ULONG AddRef(void* instance)
-{
-    BonjourUserEventsPlugin* plugin = (BonjourUserEventsPlugin*)instance;
-    return ++plugin->_refCount;
-}
-
-/*****************************************************************************
-*****************************************************************************/
-static ULONG Release(void* instance)
-{
-    BonjourUserEventsPlugin* plugin = (BonjourUserEventsPlugin*)instance;
-
-    if (plugin->_refCount != 0)
-        --plugin->_refCount;
-
-    if (plugin->_refCount == 0)
-    {
-        Dealloc(instance);
-        return 0;
-    }
-
-    return plugin->_refCount;
-}
-
-/*****************************************************************************
-* Alloc
-* -
-* Functionas as both +[alloc] and -[init] for the plugin. Add any
-* initalization of member variables here.
-*****************************************************************************/
-static BonjourUserEventsPlugin* Alloc(CFUUIDRef factoryID)
-{
-    BonjourUserEventsPlugin* plugin = malloc(sizeof(BonjourUserEventsPlugin));
-
-    plugin->_UserEventAgentInterface = &UserEventAgentInterfaceFtbl;
-    plugin->_pluginContext = NULL;
-
-    if (factoryID)
-    {
-        plugin->_factoryID = (CFUUIDRef)CFRetain(factoryID);
-        CFPlugInAddInstanceForFactory(factoryID);
-    }
-
-    plugin->_refCount = 1;
-    plugin->_tokenToBrowserMap = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kNetBrowserInfoDictionaryValueCallbacks);
-    plugin->_browsers = CFDictionaryCreateMutable(NULL, 0, &kNetBrowserInfoDictionaryKeyCallbacks, &kCFTypeDictionaryValueCallBacks);
-    plugin->_onAddEvents = CFDictionaryCreateMutable(NULL, 0, &kNetBrowserInfoDictionaryKeyCallbacks, &kCFTypeDictionaryValueCallBacks);
-    plugin->_onRemoveEvents = CFDictionaryCreateMutable(NULL, 0, &kNetBrowserInfoDictionaryKeyCallbacks, &kCFTypeDictionaryValueCallBacks);
-
-    return plugin;
-}
-
-/*****************************************************************************
-* Dealloc
-* -
-* Much like Obj-C dealloc this method is responsible for releasing any object
-* this plugin is holding. Unlike ObjC, you call directly free() instead of
-* [super dalloc].
-*****************************************************************************/
-static void Dealloc(BonjourUserEventsPlugin* plugin)
-{
-    CFUUIDRef factoryID = plugin->_factoryID;
-
-    if (factoryID)
-    {
-        CFPlugInRemoveInstanceForFactory(factoryID);
-        CFRelease(factoryID);
-    }
-
-    if (plugin->_tokenToBrowserMap)
-        CFRelease(plugin->_tokenToBrowserMap);
-
-    if (plugin->_browsers)
-        CFRelease(plugin->_browsers);
-
-    if (plugin->_onAddEvents)
-        CFRelease(plugin->_onAddEvents);
-
-    if (plugin->_onRemoveEvents)
-        CFRelease(plugin->_onRemoveEvents);
-
-    free(plugin);
-}
-
-/*******************************************************************************
-*******************************************************************************/
-void * UserEventAgentFactory(CFAllocatorRef allocator, CFUUIDRef typeID)
-{
-    (void)allocator;
-    BonjourUserEventsPlugin * result = NULL;
-
-    if (typeID && CFEqual(typeID, kUserEventAgentTypeID)) {
-        result = Alloc(kUserEventAgentFactoryID);
-    }
-
-    return (void *)result;
-}
-
-#pragma mark -
-#pragma mark Plugin Management
-#pragma mark -
-/*****************************************************************************
-* Install
-* -
-* This is invoked once when the plugin is loaded to do initial setup and
-* allow us to register with launchd. If UserEventAgent crashes, the plugin
-* will need to be reloaded, and hence this will get invoked again.
-*****************************************************************************/
-static void Install(void *instance)
-{
-    BonjourUserEventsPlugin* plugin = (BonjourUserEventsPlugin*)instance;
-
-    plugin->_pluginContext = UserEventAgentRegisterForLaunchEvents(sPluginIdentifier, &ManageEventsCallback, plugin);
-
-    if (!plugin->_pluginContext)
-    {
-        fprintf(stderr, "%s:%s failed to register for launch events.\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-}
-
-/*****************************************************************************
-* ManageEventsCallback
-* -
-* This is invoked when launchd loads a event dictionary and needs to inform
-* us what a daemon / agent is looking for.
-*****************************************************************************/
-static void ManageEventsCallback(UserEventAgentLaunchdAction action, CFNumberRef token, CFTypeRef eventMatchDict, void* vContext)
-{
-    if (action == kUserEventAgentLaunchdAdd)
-    {
-        if (!eventMatchDict)
-        {
-            fprintf(stderr, "%s:%s empty dictionary\n", sPluginIdentifier, __FUNCTION__);
-            return;
-        }
-        if (CFGetTypeID(eventMatchDict) != CFDictionaryGetTypeID())
-        {
-            fprintf(stderr, "%s:%s given non-dict for event dictionary, action %d\n", sPluginIdentifier, __FUNCTION__, action);
-            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__);
-        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__);
-        RemoveEventFromPlugin((BonjourUserEventsPlugin*)vContext, token);
-    }
-    else
-    {
-        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s unknown callback event\n", sPluginIdentifier, __FUNCTION__);
-    }
-}
-
-
-#pragma mark -
-#pragma mark Plugin Guts
-#pragma mark -
-
-/*****************************************************************************
-* AddEventToPlugin
-* -
-* This method is invoked when launchd wishes the plugin to setup a launch
-* event matching the parameters in the dictionary.
-*****************************************************************************/
-void AddEventToPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken, CFDictionaryRef eventParameters)
-{
-    CFStringRef domain = CFDictionaryGetValue(eventParameters, sServiceDomainKey);
-    CFStringRef type = CFDictionaryGetValue(eventParameters, sServiceTypeKey);
-    CFStringRef name = CFDictionaryGetValue(eventParameters, sServiceNameKey);
-    CFBooleanRef cfOnAdd = CFDictionaryGetValue(eventParameters, sOnServiceAddKey);
-    CFBooleanRef cfOnRemove = CFDictionaryGetValue(eventParameters, sOnServiceRemoveKey);
-
-    Boolean onAdd = false;
-    Boolean onRemove = false;
-
-    if (cfOnAdd && CFGetTypeID(cfOnAdd) == CFBooleanGetTypeID() && CFBooleanGetValue(cfOnAdd))
-        onAdd = true;
-
-    if (cfOnRemove && CFGetTypeID(cfOnRemove) == CFBooleanGetTypeID() && CFBooleanGetValue(cfOnRemove))
-        onRemove = true;
-
-    // A type is required. If none is specified, BAIL
-    if (!type || CFGetTypeID(type) != CFStringGetTypeID())
-    {
-        fprintf(stderr, "%s:%s: a LaunchEvent is missing a service type.\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-    // If we aren't suppose to launch on services appearing or disappearing, this service does nothing. Ignore.
-    if (!onAdd && !onRemove)
-    {
-        fprintf(stderr, "%s:%s a LaunchEvent is missing both onAdd and onRemove events\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-    // If no domain is specified, assume local.
-    if (!domain)
-    {
-        domain = CFSTR("local");
-    }
-    else if (CFGetTypeID(domain) != CFStringGetTypeID() ) // If the domain is not a string, fail
-    {
-        fprintf(stderr, "%s:%s a LaunchEvent has a domain that is not a string.\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-    // If we have a name filter, but it's not a string. This event is broken, bail.
-    if (name && CFGetTypeID(name) != CFStringGetTypeID())
-    {
-        fprintf(stderr, "%s:%s a LaunchEvent has a domain that is not a string.\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-    // Get us a browser
-    NetBrowserInfo* browser = CreateBrowser(plugin, type, domain);
-
-    if (!browser)
-    {
-        fprintf(stderr, "%s:%s cannot create browser\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-    // Create Event Dictionary
-    CFMutableDictionaryRef eventDictionary = CFDictionaryCreateMutable(NULL, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
-    // We store both the Token and the Dictionary. UserEventAgentSetLaunchEventState needs
-    // the token and UserEventAgentSetFireEvent needs both the token and the dictionary
-    CFDictionarySetValue(eventDictionary, sLaunchdTokenKey, launchdToken);
-    CFDictionarySetValue(eventDictionary, sLaunchdDictKey, eventParameters);
-
-    if (name)
-        CFDictionarySetValue(eventDictionary, sServiceNameKey, name);
-
-    // Add to the correct dictionary.
-    if (onAdd)
-    {
-        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%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__);
-        AddEventDictionary(eventDictionary, plugin->_onRemoveEvents, browser);
-    }
-
-    // Add Token Mapping
-    CFDictionarySetValue(plugin->_tokenToBrowserMap, launchdToken, browser);
-
-    // Release Memory
-    CFRelease(eventDictionary);
-}
-
-/*****************************************************************************
-* RemoveEventFromPlugin
-* -
-* This method is invoked when launchd wishes the plugin to setup a launch
-* event matching the parameters in the dictionary.
-*****************************************************************************/
-void RemoveEventFromPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken)
-{
-    NetBrowserInfo* browser = (NetBrowserInfo*)CFDictionaryGetValue(plugin->_tokenToBrowserMap, launchdToken);
-    Boolean othersUsingBrowser = false;
-
-    if (!browser)
-    {
-        long long value = 0;
-        CFNumberGetValue(launchdToken, kCFNumberLongLongType, &value);
-        fprintf(stderr, "%s:%s Launchd asked us to remove a token we did not register! ==Token:%lld== \n", sPluginIdentifier, __FUNCTION__, value);
-        return;
-    }
-
-    CFMutableArrayRef onAddEvents = (CFMutableArrayRef)CFDictionaryGetValue(plugin->_onAddEvents, browser);
-    CFMutableArrayRef onRemoveEvents = (CFMutableArrayRef)CFDictionaryGetValue(plugin->_onRemoveEvents, browser);
-
-    if (onAddEvents)
-    {
-        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%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__);
-            CFDictionaryRemoveValue(plugin->_onAddEvents, browser);
-        }
-    }
-
-    if (onRemoveEvents)
-    {
-        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%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__);
-            CFDictionaryRemoveValue(plugin->_onRemoveEvents, browser);
-        }
-    }
-
-    // Remove ourselves from the token dictionary.
-    CFDictionaryRemoveValue(plugin->_tokenToBrowserMap, launchdToken);
-
-    // Check to see if anyone else is using this browser.
-    CFIndex i;
-    CFIndex count = CFDictionaryGetCount(plugin->_tokenToBrowserMap);
-    NetBrowserInfo** browsers = malloc(count * sizeof(NetBrowserInfo*));
-
-    // Fetch the values of the token dictionary
-    CFDictionaryGetKeysAndValues(plugin->_tokenToBrowserMap, NULL, (const void**)browsers);
-
-    for (i = 0; i < count; ++i)
-    {
-        if (NetBrowserInfoEqual(browsers[i], browser))
-        {
-            othersUsingBrowser = true;
-            break;
-        }
-    }
-
-    // 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);
-        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);
-        // Decrement my reference count (it was incremented when it was added to _browsers in CreateBrowser)
-        NetBrowserInfoRelease(NULL, browser);
-    }
-
-    free(browsers);
-}
-
-
-/*****************************************************************************
-* CreateBrowser
-* -
-* This method returns a NetBrowserInfo that is looking for a type of
-* service in a domain. If no browser exists, it will create one and return it.
-*****************************************************************************/
-NetBrowserInfo* CreateBrowser(BonjourUserEventsPlugin* plugin, CFStringRef type, CFStringRef domain)
-{
-    CFIndex i;
-    CFIndex count = CFDictionaryGetCount(plugin->_browsers);
-    NetBrowserInfo* browser = NULL;
-    CFDictionaryRef* dicts = malloc(count * sizeof(CFDictionaryRef));
-    NetBrowserInfo** browsers = malloc(count * sizeof(NetBrowserInfo*));
-
-    // Fetch the values of the browser dictionary
-    CFDictionaryGetKeysAndValues(plugin->_browsers, (const void**)browsers, (const void**)dicts);
-
-
-    // Loop thru the browsers list and see if we can find a matching one.
-    for (i = 0; i < count; ++i)
-    {
-        CFDictionaryRef browserDict = dicts[i];
-
-        CFStringRef browserType = CFDictionaryGetValue(browserDict, sServiceTypeKey);
-        CFStringRef browserDomain = CFDictionaryGetValue(browserDict, sServiceDomainKey);
-
-        // If we have a matching browser, break
-        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__);
-            browser = browsers[i];
-            NetBrowserInfoRetain(NULL, browser);
-            break;
-        }
-    }
-
-    // No match found, lets create one!
-    if (!browser)
-    {
-
-        browser = NetBrowserInfoCreate(type, domain, plugin);
-
-        if (!browser)
-        {
-            fprintf(stderr, "%s:%s failed to search for %s.%s", sPluginIdentifier, __FUNCTION__, CStringFromCFString(type), CStringFromCFString(domain));
-            free(dicts);
-            free(browsers);
-            return NULL;
-        }
-
-        // Service browser created, lets add this to ourselves to the dictionary.
-        CFMutableDictionaryRef browserDict = CFDictionaryCreateMutable(NULL, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
-        CFDictionarySetValue(browserDict, sServiceTypeKey, type);
-        CFDictionarySetValue(browserDict, sServiceDomainKey, domain);
-
-        // Add the dictionary to the browsers dictionary.
-        CFDictionarySetValue(plugin->_browsers, browser, browserDict);
-
-        NetBrowserInfoRelease(NULL, browser);
-
-        // Release Memory
-        CFRelease(browserDict);
-    }
-
-    free(dicts);
-    free(browsers);
-
-    return browser;
-}
-
-/*****************************************************************************
-* BrowserForSDRef
-* -
-* This method returns a NetBrowserInfo that matches the calling SDRef passed
-* in via the callback.
-*****************************************************************************/
-NetBrowserInfo* BrowserForSDRef(BonjourUserEventsPlugin* plugin, DNSServiceRef sdRef)
-{
-    CFIndex i;
-    CFIndex count = CFDictionaryGetCount(plugin->_browsers);
-    NetBrowserInfo* browser = NULL;
-    NetBrowserInfo** browsers = malloc(count * sizeof(NetBrowserInfo*));
-
-    // Fetch the values of the browser dictionary
-    CFDictionaryGetKeysAndValues(plugin->_browsers, (const void**)browsers, NULL);
-
-    // Loop thru the browsers list and see if we can find a matching one.
-    for (i = 0; i < count; ++i)
-    {
-        NetBrowserInfo* currentBrowser = browsers[i];
-
-        if (currentBrowser->browserRef == sdRef)
-        {
-            browser = currentBrowser;
-            break;
-        }
-    }
-
-
-    free(browsers);
-
-    return browser;
-}
-
-/*****************************************************************************
-* AddEventDictionary
-* -
-* Adds a event to a browser's event dictionary
-*****************************************************************************/
-
-void AddEventDictionary(CFDictionaryRef eventDict, CFMutableDictionaryRef allEventsDictionary, NetBrowserInfo* key)
-{
-    CFMutableArrayRef eventsForBrowser = (CFMutableArrayRef)CFDictionaryGetValue(allEventsDictionary, key);
-
-    if (!eventsForBrowser) // We have no events for this browser yet, lets add him.
-    {
-        eventsForBrowser = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-        CFDictionarySetValue(allEventsDictionary, key, eventsForBrowser);
-        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s creating a new array", sPluginIdentifier, __FUNCTION__);
-    }
-    else
-    {
-        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s Incrementing refcount", sPluginIdentifier, __FUNCTION__);
-        CFRetain(eventsForBrowser);
-    }
-
-    CFArrayAppendValue(eventsForBrowser, eventDict);
-    CFRelease(eventsForBrowser);
-}
-
-/*****************************************************************************
-* RemoveEventFromArray
-* -
-* Searches a Array of Event Dictionaries to find one with a matching launchd
-* token and remove it.
-*****************************************************************************/
-
-void RemoveEventFromArray(CFMutableArrayRef array, CFNumberRef launchdToken)
-{
-    CFIndex i;
-    CFIndex count = CFArrayGetCount(array);
-
-    // Loop thru looking for us.
-    for (i = 0; i < count; )
-    {
-        CFDictionaryRef eventDict = CFArrayGetValueAtIndex(array, i);
-        CFNumberRef token = CFDictionaryGetValue(eventDict, sLaunchdTokenKey);
-
-        if (CFEqual(token, launchdToken)) // This is the same event?
-        {
-            asl_log(NULL, NULL, ASL_LEVEL_INFO, "%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.
-        }
-        else
-        {
-            ++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__);
-}
-
-#pragma mark -
-#pragma mark Net Service Browser Stuff
-#pragma mark -
-
-/*****************************************************************************
-* ServiceBrowserCallback
-* -
-* This method is the heart of the plugin. It's the runloop callback annoucing
-* the appearence and disappearance of network services.
-*****************************************************************************/
-
-void ServiceBrowserCallback (DNSServiceRef sdRef,
-                             DNSServiceFlags flags,
-                             uint32_t interfaceIndex,
-                             DNSServiceErrorType errorCode,
-                             const char*                serviceName,
-                             const char*                regtype,
-                             const char*                replyDomain,
-                             void*                      context )
-{
-    (void)interfaceIndex;
-    (void)regtype;
-    (void)replyDomain;
-    BonjourUserEventsPlugin* plugin = (BonjourUserEventsPlugin*)context;
-    NetBrowserInfo* browser = BrowserForSDRef(plugin, sdRef);
-
-    if (!browser) // Missing browser?
-    {
-        fprintf(stderr, "%s:%s ServiceBrowserCallback: missing browser\n", sPluginIdentifier, __FUNCTION__);
-        return;
-    }
-
-    if (errorCode != kDNSServiceErr_NoError)
-    {
-        fprintf(stderr, "%s:%s ServiceBrowserCallback: errcode set %d\n", sPluginIdentifier, __FUNCTION__, errorCode);
-        return;
-    }
-
-    CFStringRef cfServiceName = CFStringCreateWithCString(NULL, serviceName, kCFStringEncodingUTF8);
-
-    if (flags & kDNSServiceFlagsAdd)
-    {
-        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%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__);
-        HandleTemporaryEventsForService(plugin, browser, cfServiceName, plugin->_onRemoveEvents);
-    }
-
-    CFRelease(cfServiceName);
-}
-
-/*****************************************************************************
-* HandleTemporaryEventsForService
-* -
-* This method handles the firing of one shot events. Aka. Events that are
-* signaled when a service appears / disappears. They have a temporarly
-* signaled state.
-*****************************************************************************/
-void HandleTemporaryEventsForService(BonjourUserEventsPlugin* plugin, NetBrowserInfo* browser, CFStringRef serviceName, CFMutableDictionaryRef eventsDictionary)
-{
-    CFArrayRef events = (CFArrayRef)CFDictionaryGetValue(eventsDictionary, browser); // Get events for the browser we passed in.
-    CFIndex i;
-    CFIndex count;
-
-    if (!events)  // Somehow we have a orphan browser...
-        return;
-
-    count = CFArrayGetCount(events);
-
-    // Go thru the events and run filters, notifity if they pass.
-    for (i = 0; i < count; ++i)
-    {
-        CFDictionaryRef eventDict = (CFDictionaryRef)CFArrayGetValueAtIndex(events, i);
-        CFStringRef eventServiceName = (CFStringRef)CFDictionaryGetValue(eventDict, sServiceNameKey);
-        CFNumberRef token = (CFNumberRef) CFDictionaryGetValue(eventDict, sLaunchdTokenKey);
-        CFDictionaryRef dict = (CFDictionaryRef) CFDictionaryGetValue(eventDict, sLaunchdDictKey);
-
-        // Currently we only filter on service name, that makes this as simple as...
-        if (!eventServiceName || CFEqual(serviceName, eventServiceName))
-        {
-            uint64_t tokenUint64;
-            // 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__);
-            CFNumberGetValue(token, kCFNumberLongLongType, &tokenUint64);
-
-            xpc_object_t jobRequest = _CFXPCCreateXPCObjectFromCFObject(dict);
-
-            UserEventAgentFireEvent(plugin->_pluginContext, tokenUint64, jobRequest);
-            xpc_release(jobRequest);
-        }
-    }
-}
-
-#pragma mark -
-#pragma mark Convenience
-#pragma mark -
-
-/*****************************************************************************
-* CStringFromCFString
-* -
-* Silly convenence function for dealing with non-critical CFSTR -> cStr
-* conversions.
-*****************************************************************************/
-
-const char* CStringFromCFString(CFStringRef string)
-{
-    const char* defaultString = "??????";
-    const char* cstring;
-
-    if (!string)
-        return defaultString;
-
-    cstring = CFStringGetCStringPtr(string, kCFStringEncodingUTF8);
-
-    return (cstring) ? cstring : defaultString;
-
-}
-
-#pragma mark -
-#pragma mark NetBrowserInfo "Object"
-#pragma mark -
-/*****************************************************************************
-* NetBrowserInfoCreate
-* -
-* The method creates a NetBrowserInfo Object and initalizes it.
-*****************************************************************************/
-NetBrowserInfo* NetBrowserInfoCreate(CFStringRef serviceType, CFStringRef domain, void* context)
-{
-    NetBrowserInfo* outObj = NULL;
-    DNSServiceRef browserRef = NULL;
-    char* cServiceType = NULL;
-    char* cDomain = NULL;
-    Boolean success = true;
-
-    CFIndex serviceSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(serviceType), kCFStringEncodingUTF8);
-    cServiceType = calloc(serviceSize, 1);
-    success = CFStringGetCString(serviceType, cServiceType, serviceSize, kCFStringEncodingUTF8);
-
-
-    if (domain)
-    {
-        CFIndex domainSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(domain), kCFStringEncodingUTF8);
-        if (domainSize)
-        {
-            cDomain = calloc(domainSize, 1);
-            success = success && CFStringGetCString(domain, cDomain, domainSize, kCFStringEncodingUTF8);
-        }
-    }
-
-    if (!success)
-    {
-        fprintf(stderr, "%s:%s LaunchEvent has badly encoded service type or domain.\n", sPluginIdentifier, __FUNCTION__);
-        free(cServiceType);
-
-        if (cDomain)
-            free(cDomain);
-
-        return NULL;
-    }
-
-    DNSServiceErrorType err = DNSServiceBrowse(&browserRef, 0, 0, cServiceType, cDomain, ServiceBrowserCallback, context);
-
-    if (err != kDNSServiceErr_NoError)
-    {
-        fprintf(stderr, "%s:%s Failed to create browser for %s, %s\n", sPluginIdentifier, __FUNCTION__, cServiceType, cDomain);
-        free(cServiceType);
-
-        if (cDomain)
-            free(cDomain);
-
-        return NULL;
-    }
-
-    DNSServiceSetDispatchQueue(browserRef, dispatch_get_main_queue());
-
-
-    outObj = malloc(sizeof(NetBrowserInfo));
-
-    outObj->refCount = 1;
-    outObj->browserRef = browserRef;
-
-    asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: created new object %p", sPluginIdentifier, __FUNCTION__, outObj);
-
-    free(cServiceType);
-
-    if (cDomain)
-        free(cDomain);
-
-    return outObj;
-}
-
-/*****************************************************************************
-* NetBrowserInfoRetain
-* -
-* The method retains a NetBrowserInfo object.
-*****************************************************************************/
-const void* NetBrowserInfoRetain(CFAllocatorRef allocator, const void* info)
-{
-    (void)allocator;
-    NetBrowserInfo* obj = (NetBrowserInfo*)info;
-
-    if (!obj)
-        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);
-
-    return obj;
-}
-
-/*****************************************************************************
-* NetBrowserInfoRelease
-* -
-* The method releases a NetBrowserInfo object.
-*****************************************************************************/
-void NetBrowserInfoRelease(CFAllocatorRef allocator, const void* info)
-{
-    (void)allocator;
-    NetBrowserInfo* obj = (NetBrowserInfo*)info;
-
-    if (!obj)
-        return;
-
-    if (obj->refCount == 1)
-    {
-        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%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);
-    }
-
-}
-
-/*****************************************************************************
-* NetBrowserInfoEqual
-* -
-* The method is used to compare two NetBrowserInfo objects for equality.
-*****************************************************************************/
-Boolean NetBrowserInfoEqual(const void *value1, const void *value2)
-{
-    NetBrowserInfo* obj1 = (NetBrowserInfo*)value1;
-    NetBrowserInfo* obj2 = (NetBrowserInfo*)value2;
-
-    if (obj1->browserRef == obj2->browserRef)
-        return true;
-
-    return false;
-}
-
-/*****************************************************************************
-* NetBrowserInfoHash
-* -
-* The method is used to make a hash for the object. We can cheat and use the
-* browser pointer.
-*****************************************************************************/
-CFHashCode  NetBrowserInfoHash(const void *value)
-{
-    return (CFHashCode)((NetBrowserInfo*)value)->browserRef;
-}
-
-
-/*****************************************************************************
-* NetBrowserInfoCopyDescription
-* -
-* Make CF happy.
-*****************************************************************************/
-CFStringRef NetBrowserInfoCopyDescription(const void *value)
-{
-    (void)value;
-    return CFStringCreateWithCString(NULL, "NetBrowserInfo: No useful description", kCFStringEncodingUTF8);
-}
-

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/BonjourEvents.c (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSMacOSX/BonjourEvents.c)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/BonjourEvents.c	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/BonjourEvents.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,1001 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2010 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 <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFXPCBridge.h>
+#include "dns_sd.h"
+#include <UserEventAgentInterface.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <asl.h>
+#include <xpc/xpc.h>
+
+
+#pragma mark -
+#pragma mark Types
+#pragma mark -
+static const char*          sPluginIdentifier       = "com.apple.bonjour.events";
+
+// PLIST Keys
+static const CFStringRef sServiceNameKey         = CFSTR("ServiceName");
+static const CFStringRef sServiceTypeKey         = CFSTR("ServiceType");
+static const CFStringRef sServiceDomainKey       = CFSTR("ServiceDomain");
+
+static const CFStringRef sOnServiceAddKey        = CFSTR("OnServiceAdd");
+static const CFStringRef sOnServiceRemoveKey     = CFSTR("OnServiceRemove");
+
+static const CFStringRef sLaunchdTokenKey        = CFSTR("LaunchdToken");
+static const CFStringRef sLaunchdDictKey         = CFSTR("LaunchdDict");
+
+
+/************************************************
+* Launch Event Dictionary (input from launchd)
+* Passed To: ManageEventsCallback
+*-----------------------------------------------
+* Typing in this dictionary is not enforced
+* above us. So this may not be true. Type check
+* all input before using it.
+*-----------------------------------------------
+* sServiceNameKey		- CFString (Optional)
+* sServiceTypeKey		- CFString
+* sServiceDomainKey	- CFString
+*
+* One or more of the following.
+*-----------------------------------
+* sOnServiceAddKey			- CFBoolean
+* sOnServiceRemoveKey		- CFBoolean
+* sWhileServiceExistsKey	- CFBoolean
+************************************************/
+
+/************************************************
+* Browser Dictionary
+*-----------------------------------------------
+* sServiceDomainKey - CFString
+* sServiceTypeKey   - CFString
+************************************************/
+
+/************************************************
+* Event Dictionary
+*-----------------------------------------------
+* sServiceNameKey	 - CFString (Optional)
+* sLaunchdTokenKey	 - CFNumber
+************************************************/
+
+typedef struct {
+    UserEventAgentInterfaceStruct*      _UserEventAgentInterface;
+    CFUUIDRef _factoryID;
+    UInt32 _refCount;
+
+    void*                               _pluginContext;
+
+    CFMutableDictionaryRef _tokenToBrowserMap;                  // Maps a token to a browser that can be used to scan the remaining dictionaries.
+    CFMutableDictionaryRef _browsers;                           // A Dictionary of Browser Dictionaries where the resposible browser is the key.
+    CFMutableDictionaryRef _onAddEvents;                        // A Dictionary of Event Dictionaries that describe events to trigger on a service appearing.
+    CFMutableDictionaryRef _onRemoveEvents;                     // A Dictionary of Event Dictionaries that describe events to trigger on a service disappearing.
+} BonjourUserEventsPlugin;
+
+typedef struct {
+    CFIndex refCount;
+    DNSServiceRef browserRef;
+} NetBrowserInfo;
+
+#pragma mark -
+#pragma mark Prototypes
+#pragma mark -
+// COM Stuff
+static HRESULT  QueryInterface(void *myInstance, REFIID iid, LPVOID *ppv);
+static ULONG    AddRef(void* instance);
+static ULONG    Release(void* instance);
+
+static BonjourUserEventsPlugin* Alloc(CFUUIDRef factoryID);
+static void Dealloc(BonjourUserEventsPlugin* plugin);
+
+void * UserEventAgentFactory(CFAllocatorRef allocator, CFUUIDRef typeID);
+
+// Plugin Management
+static void Install(void* instance);
+static void ManageEventsCallback(
+    UserEventAgentLaunchdAction action,
+    CFNumberRef token,
+    CFTypeRef eventMatchDict,
+    void                      * vContext);
+
+
+// Plugin Guts
+void AddEventToPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken, CFDictionaryRef eventParameters);
+void RemoveEventFromPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchToken);
+
+NetBrowserInfo* CreateBrowser(BonjourUserEventsPlugin* plugin, CFStringRef type, CFStringRef domain);
+NetBrowserInfo* BrowserForSDRef(BonjourUserEventsPlugin* plugin, DNSServiceRef sdRef);
+void AddEventDictionary(CFDictionaryRef eventDict, CFMutableDictionaryRef allEventsDictionary, NetBrowserInfo* key);
+void RemoveEventFromArray(CFMutableArrayRef array, CFNumberRef launchdToken);
+
+// Net Service Browser Stuff
+void ServiceBrowserCallback (DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char* serviceName, const char* regtype, const char* replyDomain, void* context);
+void HandleTemporaryEventsForService(BonjourUserEventsPlugin* plugin, NetBrowserInfo* browser, CFStringRef serviceName, CFMutableDictionaryRef eventsDictionary);
+
+// Convence Stuff
+const char* CStringFromCFString(CFStringRef string);
+
+// NetBrowserInfo "Object"
+NetBrowserInfo* NetBrowserInfoCreate(CFStringRef serviceType, CFStringRef domain, void* context);
+const void* NetBrowserInfoRetain(CFAllocatorRef allocator, const void* info);
+void NetBrowserInfoRelease(CFAllocatorRef allocator, const void* info);
+Boolean NetBrowserInfoEqual(const void *value1, const void *value2);
+CFHashCode  NetBrowserInfoHash(const void *value);
+CFStringRef NetBrowserInfoCopyDescription(const void *value);
+
+static const CFDictionaryKeyCallBacks kNetBrowserInfoDictionaryKeyCallbacks = {
+    0,
+    NetBrowserInfoRetain,
+    NetBrowserInfoRelease,
+    NetBrowserInfoCopyDescription,
+    NetBrowserInfoEqual,
+    NetBrowserInfoHash
+};
+
+static const CFDictionaryValueCallBacks kNetBrowserInfoDictionaryValueCallbacks = {
+    0,
+    NetBrowserInfoRetain,
+    NetBrowserInfoRelease,
+    NetBrowserInfoCopyDescription,
+    NetBrowserInfoEqual
+};
+
+// COM type definition goop.
+static UserEventAgentInterfaceStruct UserEventAgentInterfaceFtbl = {
+    NULL,                   // Required padding for COM
+    QueryInterface,         // Query Interface
+    AddRef,                 // AddRef()
+    Release,                // Release()
+    Install                 // Install
+};
+
+#pragma mark -
+#pragma mark COM Management
+#pragma mark -
+
+/*****************************************************************************
+*****************************************************************************/
+static HRESULT QueryInterface(void *myInstance, REFIID iid, LPVOID *ppv)
+{
+    CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(NULL, iid);
+
+    // Test the requested ID against the valid interfaces.
+    if(CFEqual(interfaceID, kUserEventAgentInterfaceID))
+    {
+        ((BonjourUserEventsPlugin *) myInstance)->_UserEventAgentInterface->AddRef(myInstance);
+        *ppv = myInstance;
+        CFRelease(interfaceID);
+        return S_OK;
+    }
+    else if(CFEqual(interfaceID, IUnknownUUID))
+    {
+        ((BonjourUserEventsPlugin *) myInstance)->_UserEventAgentInterface->AddRef(myInstance);
+        *ppv = myInstance;
+        CFRelease(interfaceID);
+        return S_OK;
+    }
+    else //  Requested interface unknown, bail with error.
+    {
+        *ppv = NULL;
+        CFRelease(interfaceID);
+        return E_NOINTERFACE;
+    }
+}
+
+/*****************************************************************************
+*****************************************************************************/
+static ULONG AddRef(void* instance)
+{
+    BonjourUserEventsPlugin* plugin = (BonjourUserEventsPlugin*)instance;
+    return ++plugin->_refCount;
+}
+
+/*****************************************************************************
+*****************************************************************************/
+static ULONG Release(void* instance)
+{
+    BonjourUserEventsPlugin* plugin = (BonjourUserEventsPlugin*)instance;
+
+    if (plugin->_refCount != 0)
+        --plugin->_refCount;
+
+    if (plugin->_refCount == 0)
+    {
+        Dealloc(instance);
+        return 0;
+    }
+
+    return plugin->_refCount;
+}
+
+/*****************************************************************************
+* Alloc
+* -
+* Functionas as both +[alloc] and -[init] for the plugin. Add any
+* initalization of member variables here.
+*****************************************************************************/
+static BonjourUserEventsPlugin* Alloc(CFUUIDRef factoryID)
+{
+    BonjourUserEventsPlugin* plugin = malloc(sizeof(BonjourUserEventsPlugin));
+
+    plugin->_UserEventAgentInterface = &UserEventAgentInterfaceFtbl;
+    plugin->_pluginContext = NULL;
+
+    if (factoryID)
+    {
+        plugin->_factoryID = (CFUUIDRef)CFRetain(factoryID);
+        CFPlugInAddInstanceForFactory(factoryID);
+    }
+
+    plugin->_refCount = 1;
+    plugin->_tokenToBrowserMap = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kNetBrowserInfoDictionaryValueCallbacks);
+    plugin->_browsers = CFDictionaryCreateMutable(NULL, 0, &kNetBrowserInfoDictionaryKeyCallbacks, &kCFTypeDictionaryValueCallBacks);
+    plugin->_onAddEvents = CFDictionaryCreateMutable(NULL, 0, &kNetBrowserInfoDictionaryKeyCallbacks, &kCFTypeDictionaryValueCallBacks);
+    plugin->_onRemoveEvents = CFDictionaryCreateMutable(NULL, 0, &kNetBrowserInfoDictionaryKeyCallbacks, &kCFTypeDictionaryValueCallBacks);
+
+    return plugin;
+}
+
+/*****************************************************************************
+* Dealloc
+* -
+* Much like Obj-C dealloc this method is responsible for releasing any object
+* this plugin is holding. Unlike ObjC, you call directly free() instead of
+* [super dalloc].
+*****************************************************************************/
+static void Dealloc(BonjourUserEventsPlugin* plugin)
+{
+    CFUUIDRef factoryID = plugin->_factoryID;
+
+    if (factoryID)
+    {
+        CFPlugInRemoveInstanceForFactory(factoryID);
+        CFRelease(factoryID);
+    }
+
+    if (plugin->_tokenToBrowserMap)
+        CFRelease(plugin->_tokenToBrowserMap);
+
+    if (plugin->_browsers)
+        CFRelease(plugin->_browsers);
+
+    if (plugin->_onAddEvents)
+        CFRelease(plugin->_onAddEvents);
+
+    if (plugin->_onRemoveEvents)
+        CFRelease(plugin->_onRemoveEvents);
+
+    free(plugin);
+}
+
+/*******************************************************************************
+*******************************************************************************/
+void * UserEventAgentFactory(CFAllocatorRef allocator, CFUUIDRef typeID)
+{
+    (void)allocator;
+    BonjourUserEventsPlugin * result = NULL;
+
+    if (typeID && CFEqual(typeID, kUserEventAgentTypeID)) {
+        result = Alloc(kUserEventAgentFactoryID);
+    }
+
+    return (void *)result;
+}
+
+#pragma mark -
+#pragma mark Plugin Management
+#pragma mark -
+/*****************************************************************************
+* Install
+* -
+* This is invoked once when the plugin is loaded to do initial setup and
+* allow us to register with launchd. If UserEventAgent crashes, the plugin
+* will need to be reloaded, and hence this will get invoked again.
+*****************************************************************************/
+static void Install(void *instance)
+{
+    BonjourUserEventsPlugin* plugin = (BonjourUserEventsPlugin*)instance;
+
+    plugin->_pluginContext = UserEventAgentRegisterForLaunchEvents(sPluginIdentifier, &ManageEventsCallback, plugin);
+
+    if (!plugin->_pluginContext)
+    {
+        fprintf(stderr, "%s:%s failed to register for launch events.\n", sPluginIdentifier, __FUNCTION__);
+        return;
+    }
+
+}
+
+/*****************************************************************************
+* ManageEventsCallback
+* -
+* This is invoked when launchd loads a event dictionary and needs to inform
+* us what a daemon / agent is looking for.
+*****************************************************************************/
+static void ManageEventsCallback(UserEventAgentLaunchdAction action, CFNumberRef token, CFTypeRef eventMatchDict, void* vContext)
+{
+    if (action == kUserEventAgentLaunchdAdd)
+    {
+        if (!eventMatchDict)
+        {
+            fprintf(stderr, "%s:%s empty dictionary\n", sPluginIdentifier, __FUNCTION__);
+            return;
+        }
+        if (CFGetTypeID(eventMatchDict) != CFDictionaryGetTypeID())
+        {
+            fprintf(stderr, "%s:%s given non-dict for event dictionary, action %d\n", sPluginIdentifier, __FUNCTION__, action);
+            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__);
+        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__);
+        RemoveEventFromPlugin((BonjourUserEventsPlugin*)vContext, token);
+    }
+    else
+    {
+        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s unknown callback event\n", sPluginIdentifier, __FUNCTION__);
+    }
+}
+
+
+#pragma mark -
+#pragma mark Plugin Guts
+#pragma mark -
+
+/*****************************************************************************
+* AddEventToPlugin
+* -
+* This method is invoked when launchd wishes the plugin to setup a launch
+* event matching the parameters in the dictionary.
+*****************************************************************************/
+void AddEventToPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken, CFDictionaryRef eventParameters)
+{
+    CFStringRef domain = CFDictionaryGetValue(eventParameters, sServiceDomainKey);
+    CFStringRef type = CFDictionaryGetValue(eventParameters, sServiceTypeKey);
+    CFStringRef name = CFDictionaryGetValue(eventParameters, sServiceNameKey);
+    CFBooleanRef cfOnAdd = CFDictionaryGetValue(eventParameters, sOnServiceAddKey);
+    CFBooleanRef cfOnRemove = CFDictionaryGetValue(eventParameters, sOnServiceRemoveKey);
+
+    Boolean onAdd = false;
+    Boolean onRemove = false;
+
+    if (cfOnAdd && CFGetTypeID(cfOnAdd) == CFBooleanGetTypeID() && CFBooleanGetValue(cfOnAdd))
+        onAdd = true;
+
+    if (cfOnRemove && CFGetTypeID(cfOnRemove) == CFBooleanGetTypeID() && CFBooleanGetValue(cfOnRemove))
+        onRemove = true;
+
+    // A type is required. If none is specified, BAIL
+    if (!type || CFGetTypeID(type) != CFStringGetTypeID())
+    {
+        fprintf(stderr, "%s:%s: a LaunchEvent is missing a service type.\n", sPluginIdentifier, __FUNCTION__);
+        return;
+    }
+
+    // If we aren't suppose to launch on services appearing or disappearing, this service does nothing. Ignore.
+    if (!onAdd && !onRemove)
+    {
+        fprintf(stderr, "%s:%s a LaunchEvent is missing both onAdd and onRemove events\n", sPluginIdentifier, __FUNCTION__);
+        return;
+    }
+
+    // If no domain is specified, assume local.
+    if (!domain)
+    {
+        domain = CFSTR("local");
+    }
+    else if (CFGetTypeID(domain) != CFStringGetTypeID() ) // If the domain is not a string, fail
+    {
+        fprintf(stderr, "%s:%s a LaunchEvent has a domain that is not a string.\n", sPluginIdentifier, __FUNCTION__);
+        return;
+    }
+
+    // If we have a name filter, but it's not a string. This event is broken, bail.
+    if (name && CFGetTypeID(name) != CFStringGetTypeID())
+    {
+        fprintf(stderr, "%s:%s a LaunchEvent has a domain that is not a string.\n", sPluginIdentifier, __FUNCTION__);
+        return;
+    }
+
+    // Get us a browser
+    NetBrowserInfo* browser = CreateBrowser(plugin, type, domain);
+
+    if (!browser)
+    {
+        fprintf(stderr, "%s:%s cannot create browser\n", sPluginIdentifier, __FUNCTION__);
+        return;
+    }
+
+    // Create Event Dictionary
+    CFMutableDictionaryRef eventDictionary = CFDictionaryCreateMutable(NULL, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+    // We store both the Token and the Dictionary. UserEventAgentSetLaunchEventState needs
+    // the token and UserEventAgentSetFireEvent needs both the token and the dictionary
+    CFDictionarySetValue(eventDictionary, sLaunchdTokenKey, launchdToken);
+    CFDictionarySetValue(eventDictionary, sLaunchdDictKey, eventParameters);
+
+    if (name)
+        CFDictionarySetValue(eventDictionary, sServiceNameKey, name);
+
+    // Add to the correct dictionary.
+    if (onAdd)
+    {
+        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%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__);
+        AddEventDictionary(eventDictionary, plugin->_onRemoveEvents, browser);
+    }
+
+    // Add Token Mapping
+    CFDictionarySetValue(plugin->_tokenToBrowserMap, launchdToken, browser);
+
+    // Release Memory
+    CFRelease(eventDictionary);
+}
+
+/*****************************************************************************
+* RemoveEventFromPlugin
+* -
+* This method is invoked when launchd wishes the plugin to setup a launch
+* event matching the parameters in the dictionary.
+*****************************************************************************/
+void RemoveEventFromPlugin(BonjourUserEventsPlugin* plugin, CFNumberRef launchdToken)
+{
+    NetBrowserInfo* browser = (NetBrowserInfo*)CFDictionaryGetValue(plugin->_tokenToBrowserMap, launchdToken);
+    Boolean othersUsingBrowser = false;
+
+    if (!browser)
+    {
+        long long value = 0;
+        CFNumberGetValue(launchdToken, kCFNumberLongLongType, &value);
+        fprintf(stderr, "%s:%s Launchd asked us to remove a token we did not register! ==Token:%lld== \n", sPluginIdentifier, __FUNCTION__, value);
+        return;
+    }
+
+    CFMutableArrayRef onAddEvents = (CFMutableArrayRef)CFDictionaryGetValue(plugin->_onAddEvents, browser);
+    CFMutableArrayRef onRemoveEvents = (CFMutableArrayRef)CFDictionaryGetValue(plugin->_onRemoveEvents, browser);
+
+    if (onAddEvents)
+    {
+        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%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__);
+            CFDictionaryRemoveValue(plugin->_onAddEvents, browser);
+        }
+    }
+
+    if (onRemoveEvents)
+    {
+        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%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__);
+            CFDictionaryRemoveValue(plugin->_onRemoveEvents, browser);
+        }
+    }
+
+    // Remove ourselves from the token dictionary.
+    CFDictionaryRemoveValue(plugin->_tokenToBrowserMap, launchdToken);
+
+    // Check to see if anyone else is using this browser.
+    CFIndex i;
+    CFIndex count = CFDictionaryGetCount(plugin->_tokenToBrowserMap);
+    NetBrowserInfo** browsers = malloc(count * sizeof(NetBrowserInfo*));
+
+    // Fetch the values of the token dictionary
+    CFDictionaryGetKeysAndValues(plugin->_tokenToBrowserMap, NULL, (const void**)browsers);
+
+    for (i = 0; i < count; ++i)
+    {
+        if (NetBrowserInfoEqual(browsers[i], browser))
+        {
+            othersUsingBrowser = true;
+            break;
+        }
+    }
+
+    // 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);
+        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);
+        // Decrement my reference count (it was incremented when it was added to _browsers in CreateBrowser)
+        NetBrowserInfoRelease(NULL, browser);
+    }
+
+    free(browsers);
+}
+
+
+/*****************************************************************************
+* CreateBrowser
+* -
+* This method returns a NetBrowserInfo that is looking for a type of
+* service in a domain. If no browser exists, it will create one and return it.
+*****************************************************************************/
+NetBrowserInfo* CreateBrowser(BonjourUserEventsPlugin* plugin, CFStringRef type, CFStringRef domain)
+{
+    CFIndex i;
+    CFIndex count = CFDictionaryGetCount(plugin->_browsers);
+    NetBrowserInfo* browser = NULL;
+    CFDictionaryRef* dicts = malloc(count * sizeof(CFDictionaryRef));
+    NetBrowserInfo** browsers = malloc(count * sizeof(NetBrowserInfo*));
+
+    // Fetch the values of the browser dictionary
+    CFDictionaryGetKeysAndValues(plugin->_browsers, (const void**)browsers, (const void**)dicts);
+
+
+    // Loop thru the browsers list and see if we can find a matching one.
+    for (i = 0; i < count; ++i)
+    {
+        CFDictionaryRef browserDict = dicts[i];
+
+        CFStringRef browserType = CFDictionaryGetValue(browserDict, sServiceTypeKey);
+        CFStringRef browserDomain = CFDictionaryGetValue(browserDict, sServiceDomainKey);
+
+        // If we have a matching browser, break
+        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__);
+            browser = browsers[i];
+            NetBrowserInfoRetain(NULL, browser);
+            break;
+        }
+    }
+
+    // No match found, lets create one!
+    if (!browser)
+    {
+
+        browser = NetBrowserInfoCreate(type, domain, plugin);
+
+        if (!browser)
+        {
+            fprintf(stderr, "%s:%s failed to search for %s.%s", sPluginIdentifier, __FUNCTION__, CStringFromCFString(type), CStringFromCFString(domain));
+            free(dicts);
+            free(browsers);
+            return NULL;
+        }
+
+        // Service browser created, lets add this to ourselves to the dictionary.
+        CFMutableDictionaryRef browserDict = CFDictionaryCreateMutable(NULL, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+        CFDictionarySetValue(browserDict, sServiceTypeKey, type);
+        CFDictionarySetValue(browserDict, sServiceDomainKey, domain);
+
+        // Add the dictionary to the browsers dictionary.
+        CFDictionarySetValue(plugin->_browsers, browser, browserDict);
+
+        NetBrowserInfoRelease(NULL, browser);
+
+        // Release Memory
+        CFRelease(browserDict);
+    }
+
+    free(dicts);
+    free(browsers);
+
+    return browser;
+}
+
+/*****************************************************************************
+* BrowserForSDRef
+* -
+* This method returns a NetBrowserInfo that matches the calling SDRef passed
+* in via the callback.
+*****************************************************************************/
+NetBrowserInfo* BrowserForSDRef(BonjourUserEventsPlugin* plugin, DNSServiceRef sdRef)
+{
+    CFIndex i;
+    CFIndex count = CFDictionaryGetCount(plugin->_browsers);
+    NetBrowserInfo* browser = NULL;
+    NetBrowserInfo** browsers = malloc(count * sizeof(NetBrowserInfo*));
+
+    // Fetch the values of the browser dictionary
+    CFDictionaryGetKeysAndValues(plugin->_browsers, (const void**)browsers, NULL);
+
+    // Loop thru the browsers list and see if we can find a matching one.
+    for (i = 0; i < count; ++i)
+    {
+        NetBrowserInfo* currentBrowser = browsers[i];
+
+        if (currentBrowser->browserRef == sdRef)
+        {
+            browser = currentBrowser;
+            break;
+        }
+    }
+
+
+    free(browsers);
+
+    return browser;
+}
+
+/*****************************************************************************
+* AddEventDictionary
+* -
+* Adds a event to a browser's event dictionary
+*****************************************************************************/
+
+void AddEventDictionary(CFDictionaryRef eventDict, CFMutableDictionaryRef allEventsDictionary, NetBrowserInfo* key)
+{
+    CFMutableArrayRef eventsForBrowser = (CFMutableArrayRef)CFDictionaryGetValue(allEventsDictionary, key);
+
+    if (!eventsForBrowser) // We have no events for this browser yet, lets add him.
+    {
+        eventsForBrowser = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+        CFDictionarySetValue(allEventsDictionary, key, eventsForBrowser);
+        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s creating a new array", sPluginIdentifier, __FUNCTION__);
+    }
+    else
+    {
+        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s Incrementing refcount", sPluginIdentifier, __FUNCTION__);
+        CFRetain(eventsForBrowser);
+    }
+
+    CFArrayAppendValue(eventsForBrowser, eventDict);
+    CFRelease(eventsForBrowser);
+}
+
+/*****************************************************************************
+* RemoveEventFromArray
+* -
+* Searches a Array of Event Dictionaries to find one with a matching launchd
+* token and remove it.
+*****************************************************************************/
+
+void RemoveEventFromArray(CFMutableArrayRef array, CFNumberRef launchdToken)
+{
+    CFIndex i;
+    CFIndex count = CFArrayGetCount(array);
+
+    // Loop thru looking for us.
+    for (i = 0; i < count; )
+    {
+        CFDictionaryRef eventDict = CFArrayGetValueAtIndex(array, i);
+        CFNumberRef token = CFDictionaryGetValue(eventDict, sLaunchdTokenKey);
+
+        if (CFEqual(token, launchdToken)) // This is the same event?
+        {
+            asl_log(NULL, NULL, ASL_LEVEL_INFO, "%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.
+        }
+        else
+        {
+            ++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__);
+}
+
+#pragma mark -
+#pragma mark Net Service Browser Stuff
+#pragma mark -
+
+/*****************************************************************************
+* ServiceBrowserCallback
+* -
+* This method is the heart of the plugin. It's the runloop callback annoucing
+* the appearence and disappearance of network services.
+*****************************************************************************/
+
+void ServiceBrowserCallback (DNSServiceRef sdRef,
+                             DNSServiceFlags flags,
+                             uint32_t interfaceIndex,
+                             DNSServiceErrorType errorCode,
+                             const char*                serviceName,
+                             const char*                regtype,
+                             const char*                replyDomain,
+                             void*                      context )
+{
+    (void)interfaceIndex;
+    (void)regtype;
+    (void)replyDomain;
+    BonjourUserEventsPlugin* plugin = (BonjourUserEventsPlugin*)context;
+    NetBrowserInfo* browser = BrowserForSDRef(plugin, sdRef);
+
+    if (!browser) // Missing browser?
+    {
+        fprintf(stderr, "%s:%s ServiceBrowserCallback: missing browser\n", sPluginIdentifier, __FUNCTION__);
+        return;
+    }
+
+    if (errorCode != kDNSServiceErr_NoError)
+    {
+        fprintf(stderr, "%s:%s ServiceBrowserCallback: errcode set %d\n", sPluginIdentifier, __FUNCTION__, errorCode);
+        return;
+    }
+
+    CFStringRef cfServiceName = CFStringCreateWithCString(NULL, serviceName, kCFStringEncodingUTF8);
+    if (cfServiceName == NULL)
+    {
+        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);
+            msgCount++;
+        }
+        return;
+    }
+
+    if (flags & kDNSServiceFlagsAdd)
+    {
+        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%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__);
+        HandleTemporaryEventsForService(plugin, browser, cfServiceName, plugin->_onRemoveEvents);
+    }
+
+    CFRelease(cfServiceName);
+}
+
+/*****************************************************************************
+* HandleTemporaryEventsForService
+* -
+* This method handles the firing of one shot events. Aka. Events that are
+* signaled when a service appears / disappears. They have a temporarly
+* signaled state.
+*****************************************************************************/
+void HandleTemporaryEventsForService(BonjourUserEventsPlugin* plugin, NetBrowserInfo* browser, CFStringRef serviceName, CFMutableDictionaryRef eventsDictionary)
+{
+    CFArrayRef events = (CFArrayRef)CFDictionaryGetValue(eventsDictionary, browser); // Get events for the browser we passed in.
+    CFIndex i;
+    CFIndex count;
+
+    if (!events)  // Somehow we have a orphan browser...
+        return;
+
+    count = CFArrayGetCount(events);
+
+    // Go thru the events and run filters, notifity if they pass.
+    for (i = 0; i < count; ++i)
+    {
+        CFDictionaryRef eventDict = (CFDictionaryRef)CFArrayGetValueAtIndex(events, i);
+        CFStringRef eventServiceName = (CFStringRef)CFDictionaryGetValue(eventDict, sServiceNameKey);
+        CFNumberRef token = (CFNumberRef) CFDictionaryGetValue(eventDict, sLaunchdTokenKey);
+        CFDictionaryRef dict = (CFDictionaryRef) CFDictionaryGetValue(eventDict, sLaunchdDictKey);
+
+        // Currently we only filter on service name, that makes this as simple as...
+        if (!eventServiceName || CFEqual(serviceName, eventServiceName))
+        {
+            uint64_t tokenUint64;
+            // 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__);
+            CFNumberGetValue(token, kCFNumberLongLongType, &tokenUint64);
+
+            xpc_object_t jobRequest = _CFXPCCreateXPCObjectFromCFObject(dict);
+
+            UserEventAgentFireEvent(plugin->_pluginContext, tokenUint64, jobRequest);
+            xpc_release(jobRequest);
+        }
+    }
+}
+
+#pragma mark -
+#pragma mark Convenience
+#pragma mark -
+
+/*****************************************************************************
+* CStringFromCFString
+* -
+* Silly convenence function for dealing with non-critical CFSTR -> cStr
+* conversions.
+*****************************************************************************/
+
+const char* CStringFromCFString(CFStringRef string)
+{
+    const char* defaultString = "??????";
+    const char* cstring;
+
+    if (!string)
+        return defaultString;
+
+    cstring = CFStringGetCStringPtr(string, kCFStringEncodingUTF8);
+
+    return (cstring) ? cstring : defaultString;
+
+}
+
+#pragma mark -
+#pragma mark NetBrowserInfo "Object"
+#pragma mark -
+/*****************************************************************************
+* NetBrowserInfoCreate
+* -
+* The method creates a NetBrowserInfo Object and initalizes it.
+*****************************************************************************/
+NetBrowserInfo* NetBrowserInfoCreate(CFStringRef serviceType, CFStringRef domain, void* context)
+{
+    NetBrowserInfo* outObj = NULL;
+    DNSServiceRef browserRef = NULL;
+    char* cServiceType = NULL;
+    char* cDomain = NULL;
+    Boolean success = true;
+
+    CFIndex serviceSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(serviceType), kCFStringEncodingUTF8);
+    cServiceType = calloc(serviceSize, 1);
+    success = CFStringGetCString(serviceType, cServiceType, serviceSize, kCFStringEncodingUTF8);
+
+
+    if (domain)
+    {
+        CFIndex domainSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(domain), kCFStringEncodingUTF8);
+        if (domainSize)
+        {
+            cDomain = calloc(domainSize, 1);
+            success = success && CFStringGetCString(domain, cDomain, domainSize, kCFStringEncodingUTF8);
+        }
+    }
+
+    if (!success)
+    {
+        fprintf(stderr, "%s:%s LaunchEvent has badly encoded service type or domain.\n", sPluginIdentifier, __FUNCTION__);
+        free(cServiceType);
+
+        if (cDomain)
+            free(cDomain);
+
+        return NULL;
+    }
+
+    DNSServiceErrorType err = DNSServiceBrowse(&browserRef, 0, 0, cServiceType, cDomain, ServiceBrowserCallback, context);
+
+    if (err != kDNSServiceErr_NoError)
+    {
+        fprintf(stderr, "%s:%s Failed to create browser for %s, %s\n", sPluginIdentifier, __FUNCTION__, cServiceType, cDomain);
+        free(cServiceType);
+
+        if (cDomain)
+            free(cDomain);
+
+        return NULL;
+    }
+
+    DNSServiceSetDispatchQueue(browserRef, dispatch_get_main_queue());
+
+
+    outObj = malloc(sizeof(NetBrowserInfo));
+
+    outObj->refCount = 1;
+    outObj->browserRef = browserRef;
+
+    asl_log(NULL, NULL, ASL_LEVEL_INFO, "%s:%s: created new object %p", sPluginIdentifier, __FUNCTION__, outObj);
+
+    free(cServiceType);
+
+    if (cDomain)
+        free(cDomain);
+
+    return outObj;
+}
+
+/*****************************************************************************
+* NetBrowserInfoRetain
+* -
+* The method retains a NetBrowserInfo object.
+*****************************************************************************/
+const void* NetBrowserInfoRetain(CFAllocatorRef allocator, const void* info)
+{
+    (void)allocator;
+    NetBrowserInfo* obj = (NetBrowserInfo*)info;
+
+    if (!obj)
+        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);
+
+    return obj;
+}
+
+/*****************************************************************************
+* NetBrowserInfoRelease
+* -
+* The method releases a NetBrowserInfo object.
+*****************************************************************************/
+void NetBrowserInfoRelease(CFAllocatorRef allocator, const void* info)
+{
+    (void)allocator;
+    NetBrowserInfo* obj = (NetBrowserInfo*)info;
+
+    if (!obj)
+        return;
+
+    if (obj->refCount == 1)
+    {
+        asl_log(NULL, NULL, ASL_LEVEL_INFO, "%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);
+    }
+
+}
+
+/*****************************************************************************
+* NetBrowserInfoEqual
+* -
+* The method is used to compare two NetBrowserInfo objects for equality.
+*****************************************************************************/
+Boolean NetBrowserInfoEqual(const void *value1, const void *value2)
+{
+    NetBrowserInfo* obj1 = (NetBrowserInfo*)value1;
+    NetBrowserInfo* obj2 = (NetBrowserInfo*)value2;
+
+    if (obj1->browserRef == obj2->browserRef)
+        return true;
+
+    return false;
+}
+
+/*****************************************************************************
+* NetBrowserInfoHash
+* -
+* The method is used to make a hash for the object. We can cheat and use the
+* browser pointer.
+*****************************************************************************/
+CFHashCode  NetBrowserInfoHash(const void *value)
+{
+    return (CFHashCode)((NetBrowserInfo*)value)->browserRef;
+}
+
+
+/*****************************************************************************
+* NetBrowserInfoCopyDescription
+* -
+* Make CF happy.
+*****************************************************************************/
+CFStringRef NetBrowserInfoCopyDescription(const void *value)
+{
+    (void)value;
+    return CFStringCreateWithCString(NULL, "NetBrowserInfo: No useful description", kCFStringEncodingUTF8);
+}
+

Deleted: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/LaunchDaemonInfo.plist
===================================================================
(Binary files differ)

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/LaunchDaemonInfo.plist (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSMacOSX/LaunchDaemonInfo.plist)
===================================================================
(Binary files differ)

Deleted: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/Private/dns_services.c
===================================================================
--- vendor/apple/mDNSResponder/dist/mDNSMacOSX/Private/dns_services.c	2014-06-30 23:58:12 UTC (rev 6706)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/Private/dns_services.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -1,212 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2012 Apple Inc. All rights reserved.
- *
- * PRIVATE DNSX CLIENT LIBRARY --FOR Apple Platforms ONLY OSX/iOS--
- * Resides in /usr/lib/libdns_services.dylib
- */
-
-#include "dns_services.h"
-#include "dns_xpc.h"
-#include <xpc/xpc.h>
-#include <Block.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <syslog.h>
-
-//*************************************************************************************************************
-// Globals
-
-#define connection_t xpc_connection_t
-
-struct _DNSXConnRef_t
-{
-    connection_t      conn_ref;      // xpc_connection between client and daemon
-    dispatch_queue_t  lib_q;         // internal queue created in library itself   
-    void              *AppCallBack;  // Callback function ptr for Client
-    dispatch_queue_t  client_q;      // Queue specified by client for scheduling its Callback
-};
-
-//*************************************************************************************************************
-// Utility Functions
-
-static bool LogDebugEnabled()
-{
-    return false;
-}
-
-static void LogDebug(const char *prefix, xpc_object_t o)
-{
-    if (!LogDebugEnabled()) 
-        return;
-    
-    char *desc = xpc_copy_description(o);
-    syslog(LOG_INFO, "%s: %s", prefix, desc); 
-    free(desc);
-}
-
-//**************************************************************************************************************
-
-void DNSXRefDeAlloc(DNSXConnRef connRef)
-{
-    if (!connRef)
-    {
-        syslog(LOG_WARNING, "dns_services: DNSXRefDeAlloc called with NULL DNSXConnRef");
-        return;
-    }
-
-    // Schedule this work on the internal library queue
-    dispatch_sync(connRef->lib_q, ^{
-
-        xpc_release(connRef->conn_ref);
-        connRef->AppCallBack = NULL;
-        dispatch_release(connRef->client_q);
-
-    });
-
-    dispatch_release(connRef->lib_q);
-    free(connRef);
-
-    syslog(LOG_INFO, "dns_services: DNSXRefDeAlloc successfully DeAllocated connRef");
-
-}
-
-// Sends the Msg(Dictionary) to the Server
-static DNSXErrorType SendMsgToServer(DNSXConnRef *connRef, xpc_object_t msg, bool old_conn)
-{
-    DNSXErrorType errx = kDNSX_NoError;
-
-    LogDebug("dns_services: SendMsgToServer", msg);
-    
-    xpc_connection_set_event_handler((*connRef)->conn_ref, ^(xpc_object_t recv_msg)
-    {
-        xpc_type_t type = xpc_get_type(recv_msg);
-
-        if (type == XPC_TYPE_DICTIONARY)
-        {
-            LogDebug("dns_services: SendMsgToServer SUCCESS CALLBACK FROM SERVER", recv_msg);
-            syslog(LOG_INFO, "dns_services: Successfully Sent Msg to the Daemon");
-            uint64_t daemon_status = xpc_dictionary_get_uint64(recv_msg, kDNSDaemonReply);
- 
-            // Schedule the AppCallBacks on the Client Specified Queue
-            switch (daemon_status)
-            {   
-                case kDNSDaemonEngaged:
-                        dispatch_async((*connRef)->client_q, ^{  
-                                        ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_Engaged);
-                                        }); 
-                                        break;
-                case kDNSMsgReceived:
-                        dispatch_async((*connRef)->client_q, ^{
-                                        ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_NoError);
-                                        }); 
-                                        break;
-                default:
-                        dispatch_async((*connRef)->client_q, ^{
-                                        ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_UnknownErr);
-                                        }); 
-                                        break;
-            }   
-
-        }
-        else
-        {
-            LogDebug("dns_services: SendMsgToServer UNEXPECTED CALLBACK FROM SERVER", recv_msg);
-            syslog(LOG_WARNING, "dns_services: Connection failed since NO privileges to access service OR Daemon NOT Running");
-            dispatch_async((*connRef)->client_q, ^{
-                            ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_DaemonNotRunning);
-                            });
-        }
-    });
-    
-    // To prevent Over-Resume of a connection
-    if (!old_conn)
-        xpc_connection_resume((*connRef)->conn_ref);
-    xpc_connection_send_message((*connRef)->conn_ref, msg);
-    if (!errx)
-        syslog(LOG_INFO, "dns_services: SendMSgToServer sent Msg Dict successfully to Daemon");
-    return errx;
-}
-
-// Creates a new DNSX Connection Reference(DNSXConnRef).
-// If DNSXConnRef exists, you may want to use that depending on the use case
-static DNSXErrorType InitConnection(DNSXConnRef *connRef, const char *servname, dispatch_queue_t clientq, void *AppCallBack)
-{
-    if (!connRef)
-    {
-        syslog(LOG_WARNING, "dns_services: InitConnection() called with NULL DNSXConnRef");
-        return kDNSX_BadParam;   
-    }
-
-    *connRef = malloc(sizeof(struct _DNSXConnRef_t));
-    if (!(*connRef))
-    {
-        syslog(LOG_WARNING, "dns_services: InitConnection() No memory to allocate");
-        return kDNSX_NoMem;
-    }
-
-    // Initialize the DNSXConnRef  
-    dispatch_retain(clientq);
-    (*connRef)->client_q     = clientq;
-    (*connRef)->AppCallBack  = AppCallBack;    
-    (*connRef)->lib_q        = dispatch_queue_create("com.apple.mDNSResponder.libdns_services.q", NULL); 
-    (*connRef)->conn_ref     = xpc_connection_create_mach_service(servname, (*connRef)->lib_q, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
-
-    syslog(LOG_INFO, "dns_services: InitConnection() successfully create a new DNSXConnRef");
-    return kDNSX_NoError;
-}
-
-DNSXErrorType DNSXEnableProxy(DNSXConnRef *connRef, DNSProxyParameters proxyparam, IfIndex inIfindexArr[MaxInputIf], 
-                               IfIndex outIfindex, dispatch_queue_t clientq, DNSXEnableProxyReply callBack)
-{
-
-    DNSXErrorType errx = kDNSX_NoError;
-    bool old_conn = false;    
-
-    // Sanity Checks
-    if (!connRef || !callBack || !clientq)
-    {
-        syslog(LOG_WARNING, "dns_services: DNSXEnableProxy called with NULL DNSXConnRef OR Callback OR ClientQ parameter");
-        return kDNSX_BadParam;
-    }   
-
-    // If no connRef, get it from InitConnection()
-    if (!*connRef)
-    {
-        errx = InitConnection(connRef, kDNSProxyService, clientq, callBack);
-        if (errx) // On error InitConnection() leaves *connRef set to NULL
-        {
-            syslog(LOG_WARNING, "dns_services: Since InitConnection() returned %d error returning w/o sending msg", errx);
-            return errx;
-        }
-    }
-    else // Client already has a valid connRef
-    {
-        old_conn = true;
-    }
-
-    // Create Dictionary To Send
-    xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); 
-    if (!dict)
-    {
-        syslog(LOG_WARNING, "dns_services: DNSXEnableProxy could not create the Msg Dict To Send!");
-        DNSXRefDeAlloc(*connRef);
-        return kDNSX_DictError;
-    }
-
-    xpc_dictionary_set_uint64(dict, kDNSProxyParameters, proxyparam);
-
-    xpc_dictionary_set_uint64(dict, kDNSInIfindex0,      inIfindexArr[0]);
-    xpc_dictionary_set_uint64(dict, kDNSInIfindex1,      inIfindexArr[1]);
-    xpc_dictionary_set_uint64(dict, kDNSInIfindex2,      inIfindexArr[2]); 
-    xpc_dictionary_set_uint64(dict, kDNSInIfindex3,      inIfindexArr[3]);
-    xpc_dictionary_set_uint64(dict, kDNSInIfindex4,      inIfindexArr[4]);
-
-    xpc_dictionary_set_uint64(dict, kDNSOutIfindex,      outIfindex);
- 
-    errx = SendMsgToServer(connRef, dict, old_conn);
-    xpc_release(dict);
-
-    return errx; 
-}
-

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/Private/dns_services.c (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSMacOSX/Private/dns_services.c)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/Private/dns_services.c	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/Private/dns_services.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,212 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2012 Apple Inc. All rights reserved.
+ *
+ * PRIVATE DNSX CLIENT LIBRARY --FOR Apple Platforms ONLY OSX/iOS--
+ * Resides in /usr/lib/libdns_services.dylib
+ */
+
+#include "dns_services_mdns.h"
+#include "dns_xpc.h"
+#include <xpc/xpc.h>
+#include <Block.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+//*************************************************************************************************************
+// Globals
+
+#define connection_t xpc_connection_t
+
+struct _DNSXConnRef_t
+{
+    connection_t      conn_ref;      // xpc_connection between client and daemon
+    dispatch_queue_t  lib_q;         // internal queue created in library itself   
+    void              *AppCallBack;  // Callback function ptr for Client
+    dispatch_queue_t  client_q;      // Queue specified by client for scheduling its Callback
+};
+
+//*************************************************************************************************************
+// Utility Functions
+
+static bool LogDebugEnabled()
+{
+    return true;
+}
+
+static void LogDebug(const char *prefix, xpc_object_t o)
+{
+    if (!LogDebugEnabled()) 
+        return;
+    
+    char *desc = xpc_copy_description(o);
+    syslog(LOG_INFO, "%s: %s", prefix, desc); 
+    free(desc);
+}
+
+//**************************************************************************************************************
+
+void DNSXRefDeAlloc(DNSXConnRef connRef)
+{
+    if (!connRef)
+    {
+        syslog(LOG_WARNING, "dns_services: DNSXRefDeAlloc called with NULL DNSXConnRef");
+        return;
+    }
+
+    // Schedule this work on the internal library queue
+    dispatch_sync(connRef->lib_q, ^{
+
+        xpc_release(connRef->conn_ref);
+        connRef->AppCallBack = NULL;
+        dispatch_release(connRef->client_q);
+
+    });
+
+    dispatch_release(connRef->lib_q);
+    free(connRef);
+
+    syslog(LOG_INFO, "dns_services: DNSXRefDeAlloc successfully DeAllocated connRef");
+
+}
+
+// Sends the Msg(Dictionary) to the Server
+static DNSXErrorType SendMsgToServer(DNSXConnRef *connRef, xpc_object_t msg, bool old_conn)
+{
+    DNSXErrorType errx = kDNSX_NoError;
+
+    LogDebug("dns_services: SendMsgToServer", msg);
+    
+    xpc_connection_set_event_handler((*connRef)->conn_ref, ^(xpc_object_t recv_msg)
+    {
+        xpc_type_t type = xpc_get_type(recv_msg);
+
+        if (type == XPC_TYPE_DICTIONARY)
+        {
+            LogDebug("dns_services: SendMsgToServer SUCCESS CALLBACK FROM SERVER", recv_msg);
+            syslog(LOG_INFO, "dns_services: Successfully Sent Msg to the Daemon");
+            uint64_t daemon_status = xpc_dictionary_get_uint64(recv_msg, kDNSDaemonReply);
+ 
+            // Schedule the AppCallBacks on the Client Specified Queue
+            switch (daemon_status)
+            {   
+                case kDNSDaemonEngaged:
+                        dispatch_async((*connRef)->client_q, ^{  
+                                        ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_Engaged);
+                                        }); 
+                                        break;
+                case kDNSMsgReceived:
+                        dispatch_async((*connRef)->client_q, ^{
+                                        ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_NoError);
+                                        }); 
+                                        break;
+                default:
+                        dispatch_async((*connRef)->client_q, ^{
+                                        ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_UnknownErr);
+                                        }); 
+                                        break;
+            }   
+
+        }
+        else
+        {
+            LogDebug("dns_services: SendMsgToServer UNEXPECTED CALLBACK FROM SERVER", recv_msg);
+            syslog(LOG_WARNING, "dns_services: Connection failed since NO privileges to access service OR Daemon NOT Running");
+            dispatch_async((*connRef)->client_q, ^{
+                            ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_DaemonNotRunning);
+                            });
+        }
+    });
+    
+    // To prevent Over-Resume of a connection
+    if (!old_conn)
+        xpc_connection_resume((*connRef)->conn_ref);
+    xpc_connection_send_message((*connRef)->conn_ref, msg);
+    if (!errx)
+        syslog(LOG_INFO, "dns_services: SendMSgToServer sent Msg Dict successfully to Daemon");
+    return errx;
+}
+
+// Creates a new DNSX Connection Reference(DNSXConnRef).
+// If DNSXConnRef exists, you may want to use that depending on the use case
+static DNSXErrorType InitConnection(DNSXConnRef *connRef, const char *servname, dispatch_queue_t clientq, void *AppCallBack)
+{
+    if (!connRef)
+    {
+        syslog(LOG_WARNING, "dns_services: InitConnection() called with NULL DNSXConnRef");
+        return kDNSX_BadParam;   
+    }
+
+    *connRef = malloc(sizeof(struct _DNSXConnRef_t));
+    if (!(*connRef))
+    {
+        syslog(LOG_WARNING, "dns_services: InitConnection() No memory to allocate");
+        return kDNSX_NoMem;
+    }
+
+    // Initialize the DNSXConnRef  
+    dispatch_retain(clientq);
+    (*connRef)->client_q     = clientq;
+    (*connRef)->AppCallBack  = AppCallBack;    
+    (*connRef)->lib_q        = dispatch_queue_create("com.apple.mDNSResponder.libdns_services.q", NULL); 
+    (*connRef)->conn_ref     = xpc_connection_create_mach_service(servname, (*connRef)->lib_q, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
+
+    syslog(LOG_INFO, "dns_services: InitConnection() successfully create a new DNSXConnRef");
+    return kDNSX_NoError;
+}
+
+DNSXErrorType DNSXEnableProxy(DNSXConnRef *connRef, DNSProxyParameters proxyparam, IfIndex inIfindexArr[MaxInputIf], 
+                               IfIndex outIfindex, dispatch_queue_t clientq, DNSXEnableProxyReply callBack)
+{
+
+    DNSXErrorType errx = kDNSX_NoError;
+    bool old_conn = false;    
+
+    // Sanity Checks
+    if (!connRef || !callBack || !clientq)
+    {
+        syslog(LOG_WARNING, "dns_services: DNSXEnableProxy called with NULL DNSXConnRef OR Callback OR ClientQ parameter");
+        return kDNSX_BadParam;
+    }   
+
+    // If no connRef, get it from InitConnection()
+    if (!*connRef)
+    {
+        errx = InitConnection(connRef, kDNSProxyService, clientq, callBack);
+        if (errx) // On error InitConnection() leaves *connRef set to NULL
+        {
+            syslog(LOG_WARNING, "dns_services: Since InitConnection() returned %d error returning w/o sending msg", errx);
+            return errx;
+        }
+    }
+    else // Client already has a valid connRef
+    {
+        old_conn = true;
+    }
+
+    // Create Dictionary To Send
+    xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); 
+    if (!dict)
+    {
+        syslog(LOG_WARNING, "dns_services: DNSXEnableProxy could not create the Msg Dict To Send!");
+        DNSXRefDeAlloc(*connRef);
+        return kDNSX_DictError;
+    }
+
+    xpc_dictionary_set_uint64(dict, kDNSProxyParameters, proxyparam);
+
+    xpc_dictionary_set_uint64(dict, kDNSInIfindex0,      inIfindexArr[0]);
+    xpc_dictionary_set_uint64(dict, kDNSInIfindex1,      inIfindexArr[1]);
+    xpc_dictionary_set_uint64(dict, kDNSInIfindex2,      inIfindexArr[2]); 
+    xpc_dictionary_set_uint64(dict, kDNSInIfindex3,      inIfindexArr[3]);
+    xpc_dictionary_set_uint64(dict, kDNSInIfindex4,      inIfindexArr[4]);
+
+    xpc_dictionary_set_uint64(dict, kDNSOutIfindex,      outIfindex);
+ 
+    errx = SendMsgToServer(connRef, dict, old_conn);
+    xpc_release(dict);
+
+    return errx; 
+}
+

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/Private/dns_services_mdns.h (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSMacOSX/Private/dns_services_mdns.h)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/Private/dns_services_mdns.h	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/Private/dns_services_mdns.h	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,124 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2012 Apple Inc. All rights reserved.
+ *
+ *
+ * @header      Interface to DNSX SPI
+ *
+ * @discussion  Describes the functions and data structures
+ *              that make up the DNSX SPI
+ */
+
+#ifndef _DNS_SERVICES_H
+#define _DNS_SERVICES_H
+
+#include <dispatch/dispatch.h>
+
+// DNSXConnRef: Opaque internal data type
+typedef struct _DNSXConnRef_t *DNSXConnRef;
+
+typedef enum
+{
+    kDNSX_NoError                   =  0,
+    kDNSX_UnknownErr                = -65537,   /* 0xFFFE FFFF */
+    kDNSX_NoMem                     = -65539,
+    kDNSX_BadParam                  = -65540,
+    kDNSX_DaemonNotRunning          = -65563,   /* Background daemon not running */
+    kDNSX_DictError                 = -65565,   /* Dictionary Error */
+    kDNSX_Engaged                   = -65566,   /* DNS Proxy is in use by another client */
+    kDNSX_Timeout                   = -65568    
+} DNSXErrorType;
+
+// A max of 5 input interfaces can be processed at one time
+#define MaxInputIf 5
+#define IfIndex uint64_t
+#define kDNSIfindexAny 0
+
+// Enable DNS Proxy with an appropriate parameter defined below
+typedef enum
+{
+    kDNSProxyEnable = 1
+    // Other values reserved for future use
+} DNSProxyParameters;
+
+/*********************************************************************************************
+*
+*  Enable DNS Proxy Functionality
+*
+*********************************************************************************************/
+
+/* DNSXEnableProxy : Turns ON the DNS Proxy (Details below)
+ *
+ * DNSXEnableProxyReply() parameters:
+ *
+ * connRef:                  The DNSXConnRef initialized by DNSXEnableProxy().
+ *
+ * errCode:                  Will be kDNSX_NoError on success, otherwise will indicate the 
+ *                           failure that occurred.  Other parameters are undefined if 
+ *                           errCode is nonzero.
+ *
+ */
+
+typedef void (*DNSXEnableProxyReply)
+(
+    DNSXConnRef           connRef,
+    DNSXErrorType         errCode 
+);
+
+/* DNSXEnableProxy
+ * 
+ * Enables the DNS Proxy functionality which will remain ON until the client terminates explictly (or exits/crashes).
+ * Client can turn it OFF by passing the returned DNSXConnRef to DNSXRefDeAlloc()
+ * 
+ * DNSXEnableProxy() Parameters:
+ *
+ * connRef:                   A pointer to DNSXConnRef that is initialized to NULL when called for the first  
+ *                            time. If the call succeeds it will be initialized to a non-NULL value.
+ *                            Client terminates the DNS Proxy by passing this DNSXConnRef to DNSXRefDeAlloc().
+ *
+ * proxyparam:                Enable DNS Proxy functionality with parameters that are described in
+ *                            DNSProxyParameters above.
+ *
+ * inIfindexArr[MaxInputIf]:  List of input interfaces from which the DNS queries will be accepted and
+ *                            forwarded to the output interface specified below. The daemon processes
+ *                            MaxInputIf entries in the list. For eg. if one has less than MaxInputIfs
+ *                            values, just initialize the other values to be 0. Note: This field needs to
+ *                            be initialized by the client.
+ *
+ * outIfindex:                Output interface on which the query will be forwarded.
+ *                            Passing kDNSIfindexAny causes DNS Queries to be sent on the primary interface.
+ *
+ * clientq:                   Queue the client wants to schedule the callBack on (Note: Must not be NULL)
+ *
+ * callBack:                  CallBack function for the client that indicates success or failure.
+ *                            Note: callback may be invoked more than once, For eg. if enabling DNS Proxy
+ *                            first succeeds and the daemon possibly crashes sometime later. 
+ *
+ * return value:              Returns kDNSX_NoError when no error otherwise returns an error code indicating
+ *                            the error that occurred. Note: A return value of kDNSX_NoError does not mean 
+ *                            that DNS Proxy was successfully enabled. The callBack may asynchronously
+ *                            return an error (such as kDNSX_DaemonNotRunning/ kDNSX_Engaged)
+ *
+ */
+
+DNSXErrorType DNSXEnableProxy
+(
+    DNSXConnRef              *connRef,
+    DNSProxyParameters       proxyparam,
+    IfIndex                  inIfindexArr[MaxInputIf],
+    IfIndex                  outIfindex,
+    dispatch_queue_t         clientq,
+    DNSXEnableProxyReply     callBack
+);
+
+/* DNSXRefDeAlloc()
+ *
+ * Terminate a connection with the daemon and free memory associated with the DNSXConnRef.
+ * Used to Disable DNS Proxy on that connection.
+ *
+ * connRef:        A DNSXConnRef initialized by any of the DNSX*() calls.
+ *
+ */
+void DNSXRefDeAlloc(DNSXConnRef connRef);
+
+#endif  /* _DNS_SERVICES_H */

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/base.xcconfig (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSMacOSX/base.xcconfig)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/base.xcconfig	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/base.xcconfig	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,8 @@
+#include "<DEVELOPER_DIR>/AppleInternal/XcodeConfig/SimulatorSupport.xcconfig"
+
+// Set INSTALL_PATH[sdk=macosx*] when SimulatorSupport.xcconfig is unavailable
+INSTALL_PATH[sdk=macosx*] = $(INSTALL_PATH_ACTUAL)
+
+// Use $(INSTALL_PATH_PREFIX) instead of $(SDKROOT) as an unconditional prefix
+PUBLIC_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/include
+PRIVATE_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/local/include

Deleted: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/helper.c
===================================================================
--- vendor/apple/mDNSResponder/dist/mDNSMacOSX/helper.c	2014-06-30 23:58:12 UTC (rev 6706)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/helper.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -1,2867 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2007-2012 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 <sys/cdefs.h>
-#include <arpa/inet.h>
-#include <bsm/libbsm.h>
-#include <net/if.h>
-#include <net/route.h>
-#include <net/if_dl.h>
-#include <net/if_types.h>
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#include <netinet6/in6_var.h>
-#include <netinet6/nd6.h>
-#include <netinet6/ipsec.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <asl.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <Security/Security.h>
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <SystemConfiguration/SCPreferencesSetSpecific.h>
-#include <TargetConditionals.h>
-#include <IOKit/pwr_mgt/IOPMLib.h>
-#include <net/bpf.h>
-#include <sys/sysctl.h>
-
-#include "mDNSEmbeddedAPI.h"
-#include "dns_sd.h"
-#include "dnssd_ipc.h"
-#include "libpfkey.h"
-#include "helper.h"
-#include "helpermsgServer.h"
-#include "helper-server.h"
-#include "ipsec_options.h"
-#include "P2PPacketFilter.h"
-
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-
-#ifndef RTF_IFSCOPE
-#define RTF_IFSCOPE 0x1000000
-#endif
-
-#if TARGET_OS_EMBEDDED
-#ifndef MDNS_NO_IPSEC
-#define MDNS_NO_IPSEC 1
-#endif
-#define NO_CFUSERNOTIFICATION 1
-#define NO_SECURITYFRAMEWORK 1
-#endif
-
-// Embed the client stub code here, so we can access private functions like ConnectToServer, create_hdr, deliver_request
-#include "../mDNSShared/dnssd_ipc.c"
-#include "../mDNSShared/dnssd_clientstub.c"
-
-typedef struct sadb_x_policy *ipsec_policy_t;
-
-unsigned short InetChecksum(unsigned short *ptr,int nbytes);
-unsigned long in_cksum(unsigned short *ptr,int nbytes);
-void TCPCheckSum(int af, struct tcphdr *t, int tcplen, v6addr_t sadd6, v6addr_t dadd6);
-
-uid_t mDNSResponderUID;
-gid_t mDNSResponderGID;
-static const char kTunnelAddressInterface[] = "lo0";
-
-void
-debug_(const char *func, const char *fmt, ...)
-{
-    char buf[2048];
-    va_list ap;
-
-    va_start(ap, fmt);
-    vsnprintf(buf, sizeof(buf), fmt, ap);
-    va_end(ap);
-    helplog(ASL_LEVEL_DEBUG, "%s: %s", func, buf);
-}
-
-static int
-authorized(audit_token_t *token)
-{
-    int ok = 0;
-    pid_t pid = (pid_t)-1;
-    uid_t euid = (uid_t)-1;
-
-    audit_token_to_au32(*token, NULL, &euid, NULL, NULL, NULL, &pid, NULL,
-                        NULL);
-    ok = (euid == mDNSResponderUID || euid == 0);
-    if (!ok)
-        helplog(ASL_LEVEL_NOTICE,
-                "Unauthorized access by euid=%lu pid=%lu",
-                (unsigned long)euid, (unsigned long)pid);
-    return ok;
-}
-
-kern_return_t
-do_mDNSExit(__unused mach_port_t port, audit_token_t token)
-{
-    debug("entry");
-    if (!authorized(&token))
-        goto fin;
-    helplog(ASL_LEVEL_INFO, "exit");
-    exit(0);
-
-fin:
-    debug("fin");
-    return KERN_SUCCESS;
-}
-
-kern_return_t do_mDNSRequestBPF(__unused mach_port_t port, audit_token_t token)
-{
-    if (!authorized(&token)) return KERN_SUCCESS;
-    DNSServiceRef ref;
-    DNSServiceErrorType err = ConnectToServer(&ref, 0, send_bpf, NULL, NULL, NULL);
-    if (err) { helplog(ASL_LEVEL_ERR, "do_mDNSRequestBPF: ConnectToServer %d", err); return err; }
-
-    char *ptr;
-    size_t len = sizeof(DNSServiceFlags);
-    ipc_msg_hdr *hdr = create_hdr(send_bpf, &len, &ptr, 0, ref);
-    if (!hdr) { DNSServiceRefDeallocate(ref); return kDNSServiceErr_NoMemory; }
-    put_flags(0, &ptr);
-    deliver_request(hdr, ref);      // Will free hdr for us
-    DNSServiceRefDeallocate(ref);
-    update_idle_timer();
-    return KERN_SUCCESS;
-}
-
-kern_return_t do_mDNSPowerRequest(__unused mach_port_t port, int key, int interval, int *err, audit_token_t token)
-{
-    *err = -1;
-    if (!authorized(&token)) { *err = kmDNSHelperNotAuthorized; goto fin; }
-
-    CFArrayRef events = IOPMCopyScheduledPowerEvents();
-    if (events)
-    {
-        int i;
-        CFIndex count = CFArrayGetCount(events);
-        for (i=0; i<count; i++)
-        {
-            CFDictionaryRef dict = CFArrayGetValueAtIndex(events, i);
-            CFStringRef id = CFDictionaryGetValue(dict, CFSTR(kIOPMPowerEventAppNameKey));
-            if (CFEqual(id, CFSTR("mDNSResponderHelper")))
-            {
-                CFDateRef EventTime = CFDictionaryGetValue(dict, CFSTR(kIOPMPowerEventTimeKey));
-                CFStringRef EventType = CFDictionaryGetValue(dict, CFSTR(kIOPMPowerEventTypeKey));
-                IOReturn result = IOPMCancelScheduledPowerEvent(EventTime, id, EventType);
-                //helplog(ASL_LEVEL_ERR, "Deleting old event %s");
-                if (result) helplog(ASL_LEVEL_ERR, "IOPMCancelScheduledPowerEvent %d failed %d", i, result);
-            }
-        }
-        CFRelease(events);
-    }
-
-    if (key < 0)            // mDNSPowerRequest(-1,-1) means "clear any stale schedules" (see above)
-        *err = 0;
-    else if (key == 0)      // mDNSPowerRequest(0, 0) means "sleep now"
-    {
-        IOReturn r = IOPMSleepSystem(IOPMFindPowerManagement(MACH_PORT_NULL));
-        if (r) { usleep(100000); helplog(ASL_LEVEL_ERR, "IOPMSleepSystem %d", r); }
-        *err = r;
-    }
-    else if (key > 0)
-    {
-        CFDateRef w = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent() + interval);
-        if (w)
-        {
-            IOReturn r = IOPMSchedulePowerEvent(w, CFSTR("mDNSResponderHelper"), key ? CFSTR(kIOPMAutoWake) : CFSTR(kIOPMAutoSleep));
-            if (r) { usleep(100000); helplog(ASL_LEVEL_ERR, "IOPMSchedulePowerEvent(%d) %d %x", interval, r, r); }
-            *err = r;
-            CFRelease(w);
-        }
-    }
-fin:
-    update_idle_timer();
-    return KERN_SUCCESS;
-}
-
-kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int ifindex, int family, v6addr_t ip, ethaddr_t eth, int *err, audit_token_t token)
-{
-    #define IPv6FMTSTRING "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X"
-    #define IPv6FMTARGS  ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]
-    #if 0
-    if (family == 4)
-        helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry %d IPv%d %d.%d.%d.%d %02X:%02X:%02X:%02X:%02X:%02X",
-                ifindex, family, ip[0], ip[1], ip[2], ip[3], eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
-    else
-        helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry %d IPv%d " IPv6FMTSTRING " %02X:%02X:%02X:%02X:%02X:%02X",
-                ifindex, family, IPv6FMTARGS, eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
-    #endif
-
-    *err = -1;
-    if (!authorized(&token)) { *err = kmDNSHelperNotAuthorized; goto fin; }
-
-    static int s = -1, seq = 0;
-    if (s < 0)
-    {
-        s = socket(PF_ROUTE, SOCK_RAW, 0);
-        if (s < 0) helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: socket(PF_ROUTE, SOCK_RAW, 0) failed %d (%s)", errno, strerror(errno));
-    }
-
-    if (s >= 0)
-    {
-        struct timeval tv;
-        gettimeofday(&tv, 0);
-        if (family == 4)
-        {
-            struct { struct rt_msghdr hdr; struct sockaddr_inarp dst; struct sockaddr_dl sdl; } rtmsg;
-            memset(&rtmsg, 0, sizeof(rtmsg));
-
-            rtmsg.hdr.rtm_msglen         = sizeof(rtmsg);
-            rtmsg.hdr.rtm_version        = RTM_VERSION;
-            rtmsg.hdr.rtm_type           = RTM_ADD;
-            rtmsg.hdr.rtm_index          = ifindex;
-            rtmsg.hdr.rtm_flags          = RTF_HOST | RTF_STATIC | RTF_IFSCOPE;
-            rtmsg.hdr.rtm_addrs          = RTA_DST | RTA_GATEWAY;
-            rtmsg.hdr.rtm_pid            = 0;
-            rtmsg.hdr.rtm_seq            = seq++;
-            rtmsg.hdr.rtm_errno          = 0;
-            rtmsg.hdr.rtm_use            = 0;
-            rtmsg.hdr.rtm_inits          = RTV_EXPIRE;
-            rtmsg.hdr.rtm_rmx.rmx_expire = tv.tv_sec + 30;
-
-            rtmsg.dst.sin_len            = sizeof(rtmsg.dst);
-            rtmsg.dst.sin_family         = AF_INET;
-            rtmsg.dst.sin_port           = 0;
-            rtmsg.dst.sin_addr.s_addr    = *(in_addr_t*)ip;
-            rtmsg.dst.sin_srcaddr.s_addr = 0;
-            rtmsg.dst.sin_tos            = 0;
-            rtmsg.dst.sin_other          = 0;
-
-            rtmsg.sdl.sdl_len            = sizeof(rtmsg.sdl);
-            rtmsg.sdl.sdl_family         = AF_LINK;
-            rtmsg.sdl.sdl_index          = ifindex;
-            rtmsg.sdl.sdl_type           = IFT_ETHER;
-            rtmsg.sdl.sdl_nlen           = 0;
-            rtmsg.sdl.sdl_alen           = ETHER_ADDR_LEN;
-            rtmsg.sdl.sdl_slen           = 0;
-
-            // Target MAC address goes in rtmsg.sdl.sdl_data[0..5]; (See LLADDR() in /usr/include/net/if_dl.h)
-            memcpy(rtmsg.sdl.sdl_data, eth, sizeof(ethaddr_t));
-
-            int len = write(s, (char *)&rtmsg, sizeof(rtmsg));
-            if (len < 0)
-                helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: write(%d) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s)",
-                        sizeof(rtmsg), ifindex, ip[0], ip[1], ip[2], ip[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno));
-            len = read(s, (char *)&rtmsg, sizeof(rtmsg));
-            if (len < 0 || rtmsg.hdr.rtm_errno)
-                helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: read (%d) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s) %d",
-                        sizeof(rtmsg), ifindex, ip[0], ip[1], ip[2], ip[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno), rtmsg.hdr.rtm_errno);
-
-            *err = 0;
-        }
-        else
-        {
-            struct { struct rt_msghdr hdr; struct sockaddr_in6 dst; struct sockaddr_dl sdl; } rtmsg;
-            memset(&rtmsg, 0, sizeof(rtmsg));
-
-            rtmsg.hdr.rtm_msglen         = sizeof(rtmsg);
-            rtmsg.hdr.rtm_version        = RTM_VERSION;
-            rtmsg.hdr.rtm_type           = RTM_ADD;
-            rtmsg.hdr.rtm_index          = ifindex;
-            rtmsg.hdr.rtm_flags          = RTF_HOST | RTF_STATIC | RTF_IFSCOPE;
-            rtmsg.hdr.rtm_addrs          = RTA_DST | RTA_GATEWAY;
-            rtmsg.hdr.rtm_pid            = 0;
-            rtmsg.hdr.rtm_seq            = seq++;
-            rtmsg.hdr.rtm_errno          = 0;
-            rtmsg.hdr.rtm_use            = 0;
-            rtmsg.hdr.rtm_inits          = RTV_EXPIRE;
-            rtmsg.hdr.rtm_rmx.rmx_expire = tv.tv_sec + 30;
-
-            rtmsg.dst.sin6_len           = sizeof(rtmsg.dst);
-            rtmsg.dst.sin6_family        = AF_INET6;
-            rtmsg.dst.sin6_port          = 0;
-            rtmsg.dst.sin6_flowinfo      = 0;
-            rtmsg.dst.sin6_addr          = *(struct in6_addr*)ip;
-            rtmsg.dst.sin6_scope_id      = ifindex;
-
-            rtmsg.sdl.sdl_len            = sizeof(rtmsg.sdl);
-            rtmsg.sdl.sdl_family         = AF_LINK;
-            rtmsg.sdl.sdl_index          = ifindex;
-            rtmsg.sdl.sdl_type           = IFT_ETHER;
-            rtmsg.sdl.sdl_nlen           = 0;
-            rtmsg.sdl.sdl_alen           = ETHER_ADDR_LEN;
-            rtmsg.sdl.sdl_slen           = 0;
-
-            // Target MAC address goes in rtmsg.sdl.sdl_data[0..5]; (See LLADDR() in /usr/include/net/if_dl.h)
-            memcpy(rtmsg.sdl.sdl_data, eth, sizeof(ethaddr_t));
-
-            int len = write(s, (char *)&rtmsg, sizeof(rtmsg));
-            if (len < 0)
-                helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: write(%d) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s)",
-                        sizeof(rtmsg), ifindex, IPv6FMTARGS, rtmsg.hdr.rtm_seq, len, errno, strerror(errno));
-            len = read(s, (char *)&rtmsg, sizeof(rtmsg));
-            if (len < 0 || rtmsg.hdr.rtm_errno)
-                helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: read (%d) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s) %d",
-                        sizeof(rtmsg), ifindex, IPv6FMTARGS, rtmsg.hdr.rtm_seq, len, errno, strerror(errno), rtmsg.hdr.rtm_errno);
-
-            *err = 0;
-        }
-
-    }
-
-fin:
-    update_idle_timer();
-    return KERN_SUCCESS;
-}
-
-kern_return_t do_mDNSNotify(__unused mach_port_t port, const char *title, const char *msg, audit_token_t token)
-{
-    if (!authorized(&token)) return KERN_SUCCESS;
-
-#ifndef NO_CFUSERNOTIFICATION
-    static const char footer[] = "(Note: This message only appears on machines with 17.x.x.x IP addresses — i.e. at Apple — not on customer machines.)";
-    CFStringRef alertHeader  = CFStringCreateWithCString(NULL, title,  kCFStringEncodingUTF8);
-    CFStringRef alertBody    = CFStringCreateWithCString(NULL, msg,    kCFStringEncodingUTF8);
-    CFStringRef alertFooter  = CFStringCreateWithCString(NULL, footer, kCFStringEncodingUTF8);
-    CFStringRef alertMessage = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@\r\r%@"), alertBody, alertFooter);
-    CFRelease(alertBody);
-    CFRelease(alertFooter);
-    int err = CFUserNotificationDisplayNotice(0.0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage, NULL);
-    if (err) helplog(ASL_LEVEL_ERR, "CFUserNotificationDisplayNotice returned %d", err);
-    CFRelease(alertHeader);
-    CFRelease(alertMessage);
-#else
-    (void)title;
-    (void)msg;
-#endif /* NO_CFUSERNOTIFICATION */
-
-    update_idle_timer();
-    return KERN_SUCCESS;
-}
-
-char usercompname[MAX_DOMAIN_LABEL+1] = {0}; // the last computer name the user saw
-char userhostname[MAX_DOMAIN_LABEL+1] = {0}; // the last local host name the user saw
-char lastcompname[MAX_DOMAIN_LABEL+1] = {0}; // the last computer name saved to preferences
-char lasthostname[MAX_DOMAIN_LABEL+1] = {0}; // the last local host name saved to preferences
-
-#ifndef NO_CFUSERNOTIFICATION
-static CFStringRef CFS_OQ = NULL;
-static CFStringRef CFS_CQ = NULL;
-static CFStringRef CFS_Format = NULL;
-static CFStringRef CFS_ComputerName = NULL;
-static CFStringRef CFS_ComputerNameMsg = NULL;
-static CFStringRef CFS_LocalHostName = NULL;
-static CFStringRef CFS_LocalHostNameMsg = NULL;
-static CFStringRef CFS_Problem = NULL;
-
-static CFUserNotificationRef gNotification    = NULL;
-static CFRunLoopSourceRef gNotificationRLS = NULL;
-
-static void NotificationCallBackDismissed(CFUserNotificationRef userNotification, CFOptionFlags responseFlags)
-{
-    debug("entry");
-    (void)responseFlags;    // Unused
-    if (userNotification != gNotification) helplog(ASL_LEVEL_ERR, "NotificationCallBackDismissed: Wrong CFUserNotificationRef");
-    if (gNotificationRLS)
-    {
-        // Caution: don't use CFRunLoopGetCurrent() here, because the currently executing thread may not be our "CFRunLoopRun" thread.
-        // We need to explicitly specify the desired CFRunLoop from which we want to remove this event source.
-        CFRunLoopRemoveSource(gRunLoop, gNotificationRLS, kCFRunLoopDefaultMode);
-        CFRelease(gNotificationRLS);
-        gNotificationRLS = NULL;
-        CFRelease(gNotification);
-        gNotification = NULL;
-    }
-    // By dismissing the alert, the user has conceptually acknowleged the rename.
-    // (e.g. the machine's name is now officially "computer-2.local", not "computer.local".)
-    // If we get *another* conflict, the new alert should refer to the 'old' name
-    // as now being "computer-2.local", not "computer.local"
-    usercompname[0] = 0;
-    userhostname[0] = 0;
-    lastcompname[0] = 0;
-    lasthostname[0] = 0;
-    update_idle_timer();
-    unpause_idle_timer();
-}
-
-static void ShowNameConflictNotification(CFMutableArrayRef header, CFStringRef subtext)
-{
-    CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-    if (!dictionary) return;
-
-    debug("entry");
-
-    CFDictionarySetValue(dictionary, kCFUserNotificationAlertHeaderKey, header);
-    CFDictionarySetValue(dictionary, kCFUserNotificationAlertMessageKey, subtext);
-
-    CFURLRef urlRef = CFURLCreateWithFileSystemPath(NULL, CFSTR("/System/Library/CoreServices/mDNSResponder.bundle"), kCFURLPOSIXPathStyle, true);
-    if (urlRef) { CFDictionarySetValue(dictionary, kCFUserNotificationLocalizationURLKey, urlRef); CFRelease(urlRef); }
-
-    if (gNotification)  // If notification already on-screen, update it in place
-        CFUserNotificationUpdate(gNotification, 0, kCFUserNotificationCautionAlertLevel, dictionary);
-    else                // else, we need to create it
-    {
-        SInt32 error;
-        gNotification = CFUserNotificationCreate(NULL, 0, kCFUserNotificationCautionAlertLevel, &error, dictionary);
-        if (!gNotification || error) { helplog(ASL_LEVEL_ERR, "ShowNameConflictNotification: CFUserNotificationRef: Error %d", error); return; }
-        gNotificationRLS = CFUserNotificationCreateRunLoopSource(NULL, gNotification, NotificationCallBackDismissed, 0);
-        if (!gNotificationRLS) { helplog(ASL_LEVEL_ERR,"ShowNameConflictNotification: RLS"); CFRelease(gNotification); gNotification = NULL; return; }
-        // Caution: don't use CFRunLoopGetCurrent() here, because the currently executing thread may not be our "CFRunLoopRun" thread.
-        // We need to explicitly specify the desired CFRunLoop to which we want to add this event source.
-        CFRunLoopAddSource(gRunLoop, gNotificationRLS, kCFRunLoopDefaultMode);
-        debug("gRunLoop=%p gNotification=%p gNotificationRLS=%p", gRunLoop, gNotification, gNotificationRLS);
-        pause_idle_timer();
-    }
-
-    CFRelease(dictionary);
-}
-
-static CFMutableArrayRef GetHeader(const char* oldname, const char* newname, const CFStringRef msg, const char* suffix)
-{
-    CFMutableArrayRef alertHeader = NULL;
-
-    const CFStringRef cfoldname = CFStringCreateWithCString(NULL, oldname,  kCFStringEncodingUTF8);
-    // NULL newname means we've given up trying to construct a name that doesn't conflict
-    const CFStringRef cfnewname = newname ? CFStringCreateWithCString(NULL, newname,  kCFStringEncodingUTF8) : NULL;
-    // We tag a zero-width non-breaking space at the end of the literal text to guarantee that, no matter what
-    // arbitrary computer name the user may choose, this exact text (with zero-width non-breaking space added)
-    // can never be one that occurs in the Localizable.strings translation file.
-    if (!cfoldname)
-        helplog(ASL_LEVEL_ERR,"Could not construct CFStrings for old=%s", newname);
-    else if (newname && !cfnewname)
-        helplog(ASL_LEVEL_ERR,"Could not construct CFStrings for new=%s", newname);
-    else
-    {
-        const CFStringRef s1 = CFStringCreateWithFormat(NULL, NULL, CFS_Format, cfoldname, suffix);
-        const CFStringRef s2 = cfnewname ? CFStringCreateWithFormat(NULL, NULL, CFS_Format, cfnewname, suffix) : NULL;
-
-        alertHeader = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-
-        if (!s1)
-            helplog(ASL_LEVEL_ERR, "Could not construct secondary CFString for old=%s", oldname);
-        else if (cfnewname && !s2)
-            helplog(ASL_LEVEL_ERR, "Could not construct secondary CFString for new=%s", newname);
-        else if (!alertHeader)
-            helplog(ASL_LEVEL_ERR, "Could not construct CFArray for notification");
-        else
-        {
-            // Make sure someone is logged in.  We don't want this popping up over the login window
-            uid_t uid;
-            gid_t gid;
-            CFStringRef userName = SCDynamicStoreCopyConsoleUser(NULL, &uid, &gid);
-            if (userName)
-            {
-                CFRelease(userName);
-                CFArrayAppendValue(alertHeader, msg); // Opening phrase of message, provided by caller
-                CFArrayAppendValue(alertHeader, CFS_OQ); CFArrayAppendValue(alertHeader, s1); CFArrayAppendValue(alertHeader, CFS_CQ);
-                CFArrayAppendValue(alertHeader, CFSTR(" is already in use on this network. "));
-                if (s2)
-                {
-                    CFArrayAppendValue(alertHeader, CFSTR("The name has been changed to "));
-                    CFArrayAppendValue(alertHeader, CFS_OQ); CFArrayAppendValue(alertHeader, s2); CFArrayAppendValue(alertHeader, CFS_CQ);
-                    CFArrayAppendValue(alertHeader, CFSTR("."));
-                }
-                else
-                    CFArrayAppendValue(alertHeader, CFSTR("All attempts to find an available name by adding a number to the name were also unsuccessful."));
-            }
-        }
-        if (s1) CFRelease(s1);
-        if (s2) CFRelease(s2);
-    }
-    if (cfoldname) CFRelease(cfoldname);
-    if (cfnewname) CFRelease(cfnewname);
-
-    return alertHeader;
-}
-#endif /* ndef NO_CFUSERNOTIFICATION */
-
-static void update_notification(void)
-{
-#ifndef NO_CFUSERNOTIFICATION
-    debug("entry ucn=%s, uhn=%s, lcn=%s, lhn=%s", usercompname, userhostname, lastcompname, lasthostname);
-    if (!CFS_OQ)
-    {
-        // Note: the "\xEF\xBB\xBF" byte sequence in the CFS_Format string is the UTF-8 encoding of the zero-width non-breaking space character.
-        // By appending this invisible character on the end of literal names, we ensure the these strings cannot inadvertently match any string
-        // in the localization file -- since we know for sure that none of our strings in the localization file contain the ZWNBS character.
-        //
-        // For languages that are written right to left, when we mix English (host names could be in english with brackets etc. and the
-        // rest in Arabic) we need unicode markups for proper formatting. The Unicode sequence 202C (UTF8 E2 80 AC), 200E (UTF8 E2 80 8E) and
-        // 202B (UTF8 E2 80 AB) helps with the formatting. See <rdar://problem/8629082> for more details.
-        CFS_OQ               = CFStringCreateWithCString(NULL, "“\xE2\x80\xAB",  kCFStringEncodingUTF8);
-        CFS_CQ               = CFStringCreateWithCString(NULL, "\xE2\x80\xAC”",  kCFStringEncodingUTF8);
-        CFS_Format           = CFStringCreateWithCString(NULL, "%@%s\xEF\xBB\xBF\xE2\x80\x8E", kCFStringEncodingUTF8);
-        CFS_ComputerName     = CFStringCreateWithCString(NULL, "The name of your computer ",  kCFStringEncodingUTF8);
-        CFS_ComputerNameMsg  = CFStringCreateWithCString(NULL, "To change the name of your computer, "
-                                                         "open System Preferences and click Sharing, then type the name in the Computer Name field.",  kCFStringEncodingUTF8);
-        CFS_LocalHostName    = CFStringCreateWithCString(NULL, "This computer’s local hostname ",  kCFStringEncodingUTF8);
-        CFS_LocalHostNameMsg = CFStringCreateWithCString(NULL, "To change the local hostname, "
-                                                         "open System Preferences and click Sharing, then click “Edit” and type the name in the Local Hostname field.",  kCFStringEncodingUTF8);
-        CFS_Problem          = CFStringCreateWithCString(NULL, "This may indicate a problem with the local network. "
-                                                         "Please inform your network administrator.",  kCFStringEncodingUTF8);
-    }
-
-    if (!usercompname[0] && !userhostname[0])
-    {
-        if (gNotificationRLS)
-        {
-            debug("canceling notification %p", gNotification);
-            CFUserNotificationCancel(gNotification);
-            unpause_idle_timer();
-        }
-    }
-    else
-    {
-        CFMutableArrayRef header = NULL;
-        CFStringRef* subtext = NULL;
-        if (userhostname[0] && !lasthostname[0]) // we've given up trying to construct a name that doesn't conflict
-        {
-            header = GetHeader(userhostname, NULL, CFS_LocalHostName, ".local");
-            subtext = &CFS_Problem;
-        }
-        else if (usercompname[0])
-        {
-            header = GetHeader(usercompname, lastcompname, CFS_ComputerName, "");
-            subtext = &CFS_ComputerNameMsg;
-        }
-        else
-        {
-            header = GetHeader(userhostname, lasthostname, CFS_LocalHostName, ".local");
-            subtext = &CFS_LocalHostNameMsg;
-        }
-        ShowNameConflictNotification(header, *subtext);
-        CFRelease(header);
-    }
-#endif
-}
-
-kern_return_t
-do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, const char* new, audit_token_t token)
-{
-    SCPreferencesRef session = NULL;
-    Boolean ok = FALSE;
-    Boolean locked = FALSE;
-    CFStringRef cfstr = NULL;
-    char* user = NULL;
-    char* last = NULL;
-    Boolean needUpdate = FALSE;
-
-    debug("entry %s old=%s new=%s", key==kmDNSComputerName ? "ComputerName" : (key==kmDNSLocalHostName ? "LocalHostName" : "UNKNOWN"), old, new);
-    if (!authorized(&token)) goto fin;
-
-    switch ((enum mDNSPreferencesSetNameKey)key)
-    {
-    case kmDNSComputerName:
-        user = usercompname;
-        last = lastcompname;
-        break;
-    case kmDNSLocalHostName:
-        user = userhostname;
-        last = lasthostname;
-        break;
-    default:
-        debug("unrecognized key: %d", key);
-        goto fin;
-    }
-
-    if (!last)
-    {
-        helplog(ASL_LEVEL_ERR, "%s: no last ptr", __func__);
-        goto fin;
-    }
-
-    if (!user)
-    {
-        helplog(ASL_LEVEL_ERR, "%s: no user ptr", __func__);
-        goto fin;
-    }
-
-    if (0 == strncmp(old, new, MAX_DOMAIN_LABEL+1))
-    {
-        // old and new are same means the config changed i.e, the user has set something in the preferences pane.
-        // This means the conflict has been resolved. We need to dismiss the dialogue.
-        if (last[0] && 0 != strncmp(last, new, MAX_DOMAIN_LABEL+1))
-        {
-            last[0] = 0;
-            user[0] = 0;
-            needUpdate = TRUE;
-        }
-        goto fin;
-    }
-    else
-    {
-        // old and new are not same, this means there is a conflict. For the first conflict, we show
-        // the old value and the new value. For all subsequent conflicts, while the dialogue is still
-        // up, we do a real time update of the "new" value in the dialogue. That's why we update just
-        // "last" here and not "user".
-        if (strncmp(last, new, MAX_DOMAIN_LABEL+1))
-        {
-            strncpy(last, new, MAX_DOMAIN_LABEL);
-            needUpdate = TRUE;
-        }
-    }
-
-    // If we are not showing the dialogue, we need to remember the first "old" value so that
-    // we maintain the same through the lifetime of the dialogue. Subsequence conflicts don't
-    // update the "old" value.
-    if (!user[0])
-    {
-        strncpy(user, old, MAX_DOMAIN_LABEL);
-        needUpdate = TRUE;
-    }
-
-    if (!new[0]) // we've given up trying to construct a name that doesn't conflict
-        goto fin;
-
-    cfstr = CFStringCreateWithCString(NULL, new, kCFStringEncodingUTF8);
-
-    session = SCPreferencesCreate(NULL, CFSTR(kmDNSHelperServiceName), NULL);
-
-    if (cfstr == NULL || session == NULL)
-    {
-        debug("SCPreferencesCreate failed");
-        goto fin;
-    }
-    if (!SCPreferencesLock(session, 0))
-    {
-        debug("lock failed");
-        goto fin;
-    }
-    locked = TRUE;
-
-    switch ((enum mDNSPreferencesSetNameKey)key)
-    {
-    case kmDNSComputerName:
-    {
-        // We want to write the new Computer Name to System Preferences, without disturbing the user-selected
-        // system-wide default character set used for things like AppleTalk NBP and NETBIOS service advertising.
-        // Note that this encoding is not used for the computer name, but since both are set by the same call,
-        // we need to take care to set the name without changing the character set.
-        CFStringEncoding encoding = kCFStringEncodingUTF8;
-        CFStringRef unused = SCDynamicStoreCopyComputerName(NULL, &encoding);
-        if (unused) { CFRelease(unused); unused = NULL; }
-        else encoding = kCFStringEncodingUTF8;
-
-        ok = SCPreferencesSetComputerName(session, cfstr, encoding);
-    }
-    break;
-    case kmDNSLocalHostName:
-        ok = SCPreferencesSetLocalHostName(session, cfstr);
-        break;
-    default:
-        break;
-    }
-
-    if (!ok || !SCPreferencesCommitChanges(session) ||
-        !SCPreferencesApplyChanges(session))
-    {
-        debug("SCPreferences update failed");
-        goto fin;
-    }
-    debug("succeeded");
-
-fin:
-    if (NULL != cfstr)
-        CFRelease(cfstr);
-    if (NULL != session)
-    {
-        if (locked)
-            SCPreferencesUnlock(session);
-        CFRelease(session);
-    }
-    update_idle_timer();
-    if (needUpdate) update_notification();
-    return KERN_SUCCESS;
-}
-
-enum DNSKeyFormat
-{
-    formatNotDNSKey, formatDdnsTypeItem, formatDnsPrefixedServiceItem, formatBtmmPrefixedServiceItem
-};
-
-// On Mac OS X on Intel, the four-character string seems to be stored backwards, at least sometimes.
-// I suspect some overenthusiastic inexperienced engineer said, "On Intel everything's backwards,
-// therefore I need to add some byte swapping in this API to make this four-character string backwards too."
-// To cope with this we allow *both* "ddns" and "sndd" as valid item types.
-
-static const char dnsprefix[] = "dns:";
-static const char ddns[] = "ddns";
-static const char ddnsrev[] = "sndd";
-static const char btmmprefix[] = "btmmdns:";
-
-#ifndef NO_SECURITYFRAMEWORK
-static enum DNSKeyFormat
-getDNSKeyFormat(SecKeychainItemRef item, SecKeychainAttributeList **attributesp)
-{
-    static UInt32 tags[4] =
-    {
-        kSecTypeItemAttr, kSecServiceItemAttr, kSecAccountItemAttr, kSecLabelItemAttr
-    };
-    static SecKeychainAttributeInfo attributeInfo =
-    {
-        sizeof(tags)/sizeof(tags[0]), tags, NULL
-    };
-    SecKeychainAttributeList *attributes = NULL;
-    enum DNSKeyFormat format;
-    Boolean malformed = FALSE;
-    OSStatus status = noErr;
-    int i = 0;
-
-    *attributesp = NULL;
-    if (noErr != (status = SecKeychainItemCopyAttributesAndData(item,
-                                                                &attributeInfo, NULL, &attributes, NULL, NULL)))
-    {
-        debug("SecKeychainItemCopyAttributesAndData %d - skipping",
-              status);
-        goto skip;
-    }
-    if (attributeInfo.count != attributes->count)
-        malformed = TRUE;
-    for (i = 0; !malformed && i < (int)attributeInfo.count; ++i)
-        if (attributeInfo.tag[i] != attributes->attr[i].tag)
-            malformed = TRUE;
-    if (malformed)
-    {
-        debug(
-            "malformed result from SecKeychainItemCopyAttributesAndData - skipping");
-        goto skip;
-    }
-
-    debug("entry (\"%.*s\", \"%.*s\", \"%.*s\")",
-          (int)attributes->attr[0].length, attributes->attr[0].data,
-          (int)attributes->attr[1].length, attributes->attr[1].data,
-          (int)attributes->attr[2].length, attributes->attr[2].data);
-    if (attributes->attr[1].length >= MAX_ESCAPED_DOMAIN_NAME +
-        sizeof(dnsprefix)-1)
-    {
-        debug("kSecServiceItemAttr too long (%u) - skipping",
-              (unsigned int)attributes->attr[1].length);
-        goto skip;
-    }
-    if (attributes->attr[2].length >= MAX_ESCAPED_DOMAIN_NAME)
-    {
-        debug("kSecAccountItemAttr too long (%u) - skipping",
-              (unsigned int)attributes->attr[2].length);
-        goto skip;
-    }
-    if (attributes->attr[1].length >= sizeof(dnsprefix)-1 &&
-        0 == strncasecmp(attributes->attr[1].data, dnsprefix,
-                         sizeof(dnsprefix)-1))
-        format = formatDnsPrefixedServiceItem;
-    else if (attributes->attr[1].length >= sizeof(btmmprefix)-1 &&
-             0 == strncasecmp(attributes->attr[1].data, btmmprefix, sizeof(btmmprefix)-1))
-        format = formatBtmmPrefixedServiceItem;
-    else if (attributes->attr[0].length == sizeof(ddns)-1 &&
-             0 == strncasecmp(attributes->attr[0].data, ddns, sizeof(ddns)-1))
-        format = formatDdnsTypeItem;
-    else if (attributes->attr[0].length == sizeof(ddnsrev)-1 &&
-             0 == strncasecmp(attributes->attr[0].data, ddnsrev, sizeof(ddnsrev)-1))
-        format = formatDdnsTypeItem;
-    else
-    {
-        debug("uninterested in this entry");
-        goto skip;
-    }
-    *attributesp = attributes;
-    debug("accepting this entry");
-    return format;
-
-skip:
-    SecKeychainItemFreeAttributesAndData(attributes, NULL);
-    return formatNotDNSKey;
-}
-
-// Insert the attributes as defined by mDNSKeyChainAttributes
-static CFPropertyListRef
-getKeychainItemInfo(SecKeychainItemRef item,
-                    SecKeychainAttributeList *attributes, enum DNSKeyFormat format)
-{
-    CFMutableArrayRef entry = NULL;
-    CFDataRef data = NULL;
-    OSStatus status = noErr;
-    UInt32 keylen = 0;
-    void *keyp = 0;
-
-    if (NULL == (entry = CFArrayCreateMutable(NULL, 0,
-                                              &kCFTypeArrayCallBacks)))
-    {
-        debug("CFArrayCreateMutable failed");
-        goto error;
-    }
-
-    // Insert the Account attribute (kmDNSKcWhere)
-    switch ((enum DNSKeyFormat)format)
-    {
-    case formatDdnsTypeItem:
-        data = CFDataCreate(kCFAllocatorDefault,
-                            attributes->attr[1].data, attributes->attr[1].length);
-        break;
-    case formatDnsPrefixedServiceItem:
-    case formatBtmmPrefixedServiceItem:
-        data = CFDataCreate(kCFAllocatorDefault,
-                            attributes->attr[1].data, attributes->attr[1].length);
-        break;
-    default:
-        assert("unknown DNSKeyFormat value");
-        break;
-    }
-    if (NULL == data)
-    {
-        debug("CFDataCreate for attr[1] failed");
-        goto error;
-    }
-    CFArrayAppendValue(entry, data);
-    CFRelease(data);
-
-    // Insert the Where attribute (kmDNSKcAccount)
-    if (NULL == (data = CFDataCreate(kCFAllocatorDefault,
-                                     attributes->attr[2].data, attributes->attr[2].length)))
-    {
-        debug("CFDataCreate for attr[2] failed");
-        goto error;
-    }
-    CFArrayAppendValue(entry, data);
-    CFRelease(data);
-
-    // Insert the Key attribute (kmDNSKcKey)
-    if (noErr != (status = SecKeychainItemCopyAttributesAndData(item, NULL,
-                                                                NULL, NULL, &keylen, &keyp)))
-    {
-        debug("could not retrieve key for \"%.*s\": %d",
-              (int)attributes->attr[1].length, attributes->attr[1].data,
-              status);
-        goto error;
-    }
-    data = CFDataCreate(kCFAllocatorDefault, keyp, keylen);
-    SecKeychainItemFreeAttributesAndData(NULL, keyp);
-    if (NULL == data)
-    {
-        debug("CFDataCreate for keyp failed");
-        goto error;
-    }
-    CFArrayAppendValue(entry, data);
-    CFRelease(data);
-
-    // Insert the Name attribute (kmDNSKcName)
-    if (NULL == (data = CFDataCreate(kCFAllocatorDefault,
-                                     attributes->attr[3].data, attributes->attr[3].length)))
-    {
-        debug("CFDataCreate for attr[3] failed");
-        goto error;
-    }
-    CFArrayAppendValue(entry, data);
-    CFRelease(data);
-    return entry;
-
-error:
-    if (NULL != entry)
-        CFRelease(entry);
-    return NULL;
-}
-#endif
-
-kern_return_t
-do_mDNSKeychainGetSecrets(__unused mach_port_t port, __unused unsigned int *numsecrets,
-                          __unused vm_offset_t *secrets, __unused mach_msg_type_number_t *secretsCnt, __unused int *err,
-                          __unused audit_token_t token)
-{
-#ifndef NO_SECURITYFRAMEWORK
-    CFWriteStreamRef stream = NULL;
-    CFDataRef result = NULL;
-    CFPropertyListRef entry = NULL;
-    CFMutableArrayRef keys = NULL;
-    SecKeychainRef skc = NULL;
-    SecKeychainItemRef item = NULL;
-    SecKeychainSearchRef search = NULL;
-    SecKeychainAttributeList *attributes = NULL;
-    enum DNSKeyFormat format;
-    OSStatus status = 0;
-
-    debug("entry");
-    *err = 0;
-    *numsecrets = 0;
-    *secrets = (vm_offset_t)NULL;
-    if (!authorized(&token))
-    {
-        *err = kmDNSHelperNotAuthorized;
-        goto fin;
-    }
-    if (NULL == (keys = CFArrayCreateMutable(NULL, 0,
-                                             &kCFTypeArrayCallBacks)))
-    {
-        debug("CFArrayCreateMutable failed");
-        *err = kmDNSHelperCreationFailed;
-        goto fin;
-    }
-    if (noErr != (status = SecKeychainCopyDefault(&skc)))
-    {
-        *err = kmDNSHelperKeychainCopyDefaultFailed;
-        goto fin;
-    }
-    if (noErr != (status = SecKeychainSearchCreateFromAttributes(skc, kSecGenericPasswordItemClass, NULL, &search)))
-    {
-        *err = kmDNSHelperKeychainSearchCreationFailed;
-        goto fin;
-    }
-    for (status = SecKeychainSearchCopyNext(search, &item);
-         noErr == status;
-         status = SecKeychainSearchCopyNext(search, &item))
-    {
-        if (formatNotDNSKey != (format = getDNSKeyFormat(item,
-                                                         &attributes)) &&
-            NULL != (entry = getKeychainItemInfo(item, attributes,
-                                                 format)))
-        {
-            CFArrayAppendValue(keys, entry);
-            CFRelease(entry);
-        }
-        SecKeychainItemFreeAttributesAndData(attributes, NULL);
-        CFRelease(item);
-    }
-    if (errSecItemNotFound != status)
-        helplog(ASL_LEVEL_ERR, "%s: SecKeychainSearchCopyNext failed: %d",
-                __func__, status);
-    if (NULL == (stream =
-                     CFWriteStreamCreateWithAllocatedBuffers(kCFAllocatorDefault,
-                                                             kCFAllocatorDefault)))
-    {
-        *err = kmDNSHelperCreationFailed;
-        debug("CFWriteStreamCreateWithAllocatedBuffers failed");
-        goto fin;
-    }
-    CFWriteStreamOpen(stream);
-    if (0 == CFPropertyListWriteToStream(keys, stream,
-                                         kCFPropertyListBinaryFormat_v1_0, NULL))
-    {
-        *err = kmDNSHelperPListWriteFailed;
-        debug("CFPropertyListWriteToStream failed");
-        goto fin;
-    }
-    result = CFWriteStreamCopyProperty(stream,
-                                       kCFStreamPropertyDataWritten);
-    if (KERN_SUCCESS != vm_allocate(mach_task_self(), secrets,
-                                    CFDataGetLength(result), VM_FLAGS_ANYWHERE))
-    {
-        *err = kmDNSHelperCreationFailed;
-        debug("vm_allocate failed");
-        goto fin;
-    }
-    CFDataGetBytes(result, CFRangeMake(0, CFDataGetLength(result)),
-                   (void *)*secrets);
-    *secretsCnt = CFDataGetLength(result);
-    *numsecrets = CFArrayGetCount(keys);
-    debug("succeeded");
-
-fin:
-    debug("returning %u secrets", *numsecrets);
-    if (NULL != stream)
-    {
-        CFWriteStreamClose(stream);
-        CFRelease(stream);
-    }
-    if (NULL != result)
-        CFRelease(result);
-    if (NULL != keys)
-        CFRelease(keys);
-    if (NULL != search)
-        CFRelease(search);
-    if (NULL != skc)
-        CFRelease(skc);
-    update_idle_timer();
-    return KERN_SUCCESS;
-#else
-    return KERN_FAILURE;
-#endif
-}
-
-#ifndef MDNS_NO_IPSEC
-typedef enum _mDNSTunnelPolicyWhich
-{
-    kmDNSTunnelPolicySetup,
-    kmDNSTunnelPolicyTeardown,
-    kmDNSTunnelPolicyGenerate
-} mDNSTunnelPolicyWhich;
-
-// For kmDNSTunnelPolicySetup, you can setup IPv6-in-IPv6 tunnel or IPv6-in-IPv4 tunnel
-// kmDNSNoTunnel is used for other Policy types
-typedef enum _mDNSTunnelType
-{
-    kmDNSNoTunnel,
-    kmDNSIPv6IPv4Tunnel,
-    kmDNSIPv6IPv6Tunnel
-} mDNSTunnelType;
-
-static const uint8_t kWholeV6Mask = 128;
-
-#endif /* ifndef MDNS_NO_IPSEC */
-
-#ifndef MDNS_NO_IPSEC
-
-static const char g_racoon_config_dir[] = "/var/run/racoon/";
-static const char g_racoon_config_dir_old[] = "/etc/racoon/remote/";
-
-CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
-CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey;
-
-// Major version  6 is 10.2.x (Jaguar)
-// Major version  7 is 10.3.x (Panther)
-// Major version  8 is 10.4.x (Tiger)
-// Major version  9 is 10.5.x (Leopard)
-// Major version 10 is 10.6.x (SnowLeopard)
-static int MacOSXSystemBuildNumber(char* letter_out, int* minor_out)
-{
-    int major = 0, minor = 0;
-    char letter = 0, buildver[256]="<Unknown>";
-    CFDictionaryRef vers = _CFCopySystemVersionDictionary();
-    if (vers)
-    {
-        CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey);
-        if (cfbuildver) CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8);
-        sscanf(buildver, "%d%c%d", &major, &letter, &minor);
-        CFRelease(vers);
-    }
-    else
-        helplog(ASL_LEVEL_NOTICE, "_CFCopySystemVersionDictionary failed");
-
-    if (!major) { major=10; letter = 'A'; minor = 190; helplog(ASL_LEVEL_NOTICE, "Note: No Major Build Version number found; assuming 10A190"); }
-    if (letter_out) *letter_out = letter;
-    if (minor_out) *minor_out = minor;
-    return(major);
-}
-
-static int UseOldRacoon()
-{
-    static int g_oldRacoon = -1;
-
-    if (g_oldRacoon == -1)
-    {
-        char letter = 0;
-        int minor = 0;
-        g_oldRacoon = (MacOSXSystemBuildNumber(&letter, &minor) < 10);
-        debug("%s", g_oldRacoon ? "old" : "new");
-    }
-
-    return g_oldRacoon;
-}
-
-static int RacoonSignal()
-{
-    return UseOldRacoon() ? SIGHUP : SIGUSR1;
-}
-
-static const char* GetRacoonConfigDir()
-{
-    return UseOldRacoon() ? g_racoon_config_dir_old : g_racoon_config_dir;
-}
-
-static const char* GetOldRacoonConfigDir()
-{
-    return UseOldRacoon() ? NULL : g_racoon_config_dir_old;
-}
-
-static const char racoon_config_file[] = "anonymous.conf";
-static const char racoon_config_file_orig[] = "anonymous.conf.orig";
-
-static const char configHeader[] = "# BackToMyMac\n";
-
-static int IsFamiliarRacoonConfiguration(const char* racoon_config_path)
-{
-    int fd = open(racoon_config_path, O_RDONLY);
-    debug("entry %s", racoon_config_path);
-    if (0 > fd)
-    {
-        helplog(ASL_LEVEL_NOTICE, "open \"%s\" failed: %s", racoon_config_path, strerror(errno));
-        return 0;
-    }
-    else
-    {
-        char header[sizeof(configHeader)] = {0};
-        ssize_t bytesRead = read(fd, header, sizeof(header)-1);
-        close(fd);
-        if (bytesRead != sizeof(header)-1) return 0;
-        return (0 == memcmp(header, configHeader, sizeof(header)-1));
-    }
-}
-
-static void
-revertAnonymousRacoonConfiguration(const char* dir)
-{
-    if (!dir) return;
-
-    debug("entry %s", dir);
-
-    char racoon_config_path[64];
-    strlcpy(racoon_config_path, dir, sizeof(racoon_config_path));
-    strlcat(racoon_config_path, racoon_config_file, sizeof(racoon_config_path));
-
-    struct stat s;
-    int ret = stat(racoon_config_path, &s);
-    debug("stat(%s): %d errno=%d", racoon_config_path, ret, errno);
-    if (ret == 0)
-    {
-        if (IsFamiliarRacoonConfiguration(racoon_config_path))
-        {
-            helplog(ASL_LEVEL_INFO, "\"%s\" looks familiar, unlinking", racoon_config_path);
-            unlink(racoon_config_path);
-        }
-        else
-        {
-            helplog(ASL_LEVEL_NOTICE, "\"%s\" does not look familiar, leaving in place", racoon_config_path);
-            return;
-        }
-    }
-    else if (errno != ENOENT)
-    {
-        helplog(ASL_LEVEL_NOTICE, "stat failed for \"%s\", leaving in place: %s", racoon_config_path, strerror(errno));
-        return;
-    }
-
-    char racoon_config_path_orig[64];
-    strlcpy(racoon_config_path_orig, dir, sizeof(racoon_config_path_orig));
-    strlcat(racoon_config_path_orig, racoon_config_file_orig, sizeof(racoon_config_path_orig));
-
-    ret = stat(racoon_config_path_orig, &s);
-    debug("stat(%s): %d errno=%d", racoon_config_path_orig, ret, errno);
-    if (ret == 0)
-    {
-        if (0 > rename(racoon_config_path_orig, racoon_config_path))
-            helplog(ASL_LEVEL_NOTICE, "rename \"%s\" \"%s\" failed: %s", racoon_config_path_orig, racoon_config_path, strerror(errno));
-        else
-            debug("reverted \"%s\" to \"%s\"", racoon_config_path_orig, racoon_config_path);
-    }
-    else if (errno != ENOENT)
-    {
-        helplog(ASL_LEVEL_NOTICE, "stat failed for \"%s\", leaving in place: %s", racoon_config_path_orig, strerror(errno));
-        return;
-    }
-}
-
-static void
-moveAsideAnonymousRacoonConfiguration(const char* dir)
-{
-    if (!dir) return;
-
-    debug("entry %s", dir);
-
-    char racoon_config_path[64];
-    strlcpy(racoon_config_path, dir, sizeof(racoon_config_path));
-    strlcat(racoon_config_path, racoon_config_file, sizeof(racoon_config_path));
-
-    struct stat s;
-    int ret = stat(racoon_config_path, &s);
-    if (ret == 0)
-    {
-        if (IsFamiliarRacoonConfiguration(racoon_config_path))
-        {
-            helplog(ASL_LEVEL_INFO, "\"%s\" looks familiar, unlinking", racoon_config_path);
-            unlink(racoon_config_path);
-        }
-        else
-        {
-            char racoon_config_path_orig[64];
-            strlcpy(racoon_config_path_orig, dir, sizeof(racoon_config_path_orig));
-            strlcat(racoon_config_path_orig, racoon_config_file_orig, sizeof(racoon_config_path_orig));
-            if (0 > rename(racoon_config_path, racoon_config_path_orig)) // If we didn't write it, move it to the side so it can be reverted later
-                helplog(ASL_LEVEL_NOTICE, "rename \"%s\" to \"%s\" failed: %s", racoon_config_path, racoon_config_path_orig, strerror(errno));
-            else
-                debug("successfully renamed \"%s\" to \"%s\"", racoon_config_path, racoon_config_path_orig);
-        }
-    }
-    else if (errno != ENOENT)
-    {
-        helplog(ASL_LEVEL_NOTICE, "stat failed for \"%s\", leaving in place: %s", racoon_config_path, strerror(errno));
-        return;
-    }
-}
-
-static int
-ensureExistenceOfRacoonConfigDir(const char* const racoon_config_dir)
-{
-    struct stat s;
-    int ret = stat(racoon_config_dir, &s);
-    if (ret != 0)
-    {
-        if (errno != ENOENT)
-        {
-            helplog(ASL_LEVEL_ERR, "stat of \"%s\" failed (%d): %s",
-                    racoon_config_dir, ret, strerror(errno));
-            return -1;
-        }
-        else
-        {
-            ret = mkdir(racoon_config_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
-            if (ret != 0)
-            {
-                helplog(ASL_LEVEL_ERR, "mkdir \"%s\" failed: %s",
-                        racoon_config_dir, strerror(errno));
-                return -1;
-            }
-            else
-                helplog(ASL_LEVEL_INFO, "created directory \"%s\"", racoon_config_dir);
-        }
-    }
-    else if (!(s.st_mode & S_IFDIR))
-    {
-        helplog(ASL_LEVEL_ERR, "\"%s\" is not a directory!",
-                racoon_config_dir);
-        return -1;
-    }
-
-    return 0;
-}
-
-static int
-createAnonymousRacoonConfiguration(const char *fqdn)
-{
-    static const char config1[] =
-        "remote anonymous {\n"
-        "  exchange_mode aggressive;\n"
-        "  doi ipsec_doi;\n"
-        "  situation identity_only;\n"
-        "  verify_identifier off;\n"
-        "  generate_policy on;\n"
-        "  shared_secret keychain_by_id \"";
-    static const char config2[] =
-        "\";\n"
-        "  nonce_size 16;\n"
-        "  lifetime time 15 min;\n"
-        "  initial_contact on;\n"
-        "  support_proxy on;\n"
-        "  nat_traversal force;\n"
-        "  proposal_check claim;\n"
-        "  proposal {\n"
-        "    encryption_algorithm aes;\n"
-        "    hash_algorithm sha256;\n"
-        "    authentication_method pre_shared_key;\n"
-        "    dh_group 2;\n"
-        "    lifetime time 15 min;\n"
-        "  }\n"
-        "  proposal {\n"
-        "    encryption_algorithm aes;\n"
-        "    hash_algorithm sha1;\n"
-        "    authentication_method pre_shared_key;\n"
-        "    dh_group 2;\n"
-        "    lifetime time 15 min;\n"
-        "  }\n"
-        "}\n\n"
-        "sainfo anonymous { \n"
-        "  pfs_group 2;\n"
-        "  lifetime time 10 min;\n"
-        "  encryption_algorithm aes;\n"
-        "  authentication_algorithm hmac_sha256,hmac_sha1;\n"
-        "  compression_algorithm deflate;\n"
-        "}\n";
-    char tmp_config_path[64];
-    char racoon_config_path[64];
-    const char* const racoon_config_dir = GetRacoonConfigDir();
-    const char* const racoon_config_dir_old = GetOldRacoonConfigDir();
-    int fd = -1;
-
-    debug("entry");
-
-    if (0 > ensureExistenceOfRacoonConfigDir(racoon_config_dir))
-        return -1;
-
-    strlcpy(tmp_config_path, racoon_config_dir, sizeof(tmp_config_path));
-    strlcat(tmp_config_path, "tmp.XXXXXX", sizeof(tmp_config_path));
-
-    fd = mkstemp(tmp_config_path);
-
-    if (0 > fd)
-    {
-        helplog(ASL_LEVEL_ERR, "mkstemp \"%s\" failed: %s",
-                tmp_config_path, strerror(errno));
-        return -1;
-    }
-    write(fd, configHeader, sizeof(configHeader)-1);
-    write(fd, config1, sizeof(config1)-1);
-    write(fd, fqdn, strlen(fqdn));
-    write(fd, config2, sizeof(config2)-1);
-    close(fd);
-
-    strlcpy(racoon_config_path, racoon_config_dir, sizeof(racoon_config_path));
-    strlcat(racoon_config_path, racoon_config_file, sizeof(racoon_config_path));
-
-    moveAsideAnonymousRacoonConfiguration(racoon_config_dir_old);
-    moveAsideAnonymousRacoonConfiguration(racoon_config_dir);
-
-    if (0 > rename(tmp_config_path, racoon_config_path))
-    {
-        unlink(tmp_config_path);
-        helplog(ASL_LEVEL_ERR, "rename \"%s\" \"%s\" failed: %s",
-                tmp_config_path, racoon_config_path, strerror(errno));
-        revertAnonymousRacoonConfiguration(racoon_config_dir_old);
-        revertAnonymousRacoonConfiguration(racoon_config_dir);
-        return -1;
-    }
-
-    debug("successfully renamed \"%s\" \"%s\"", tmp_config_path, racoon_config_path);
-    return 0;
-}
-
-static int
-notifyRacoon(void)
-{
-    debug("entry");
-    static const char racoon_pid_path[] = "/var/run/racoon.pid";
-    char buf[] = "18446744073709551615"; /* largest 64-bit integer */
-    char *p = NULL;
-    ssize_t n = 0;
-    unsigned long m = 0;
-    int fd = open(racoon_pid_path, O_RDONLY);
-
-    if (0 > fd)
-    {
-        debug("open \"%s\" failed, and that's OK: %s", racoon_pid_path,
-              strerror(errno));
-        return kmDNSHelperRacoonNotificationFailed;
-    }
-    n = read(fd, buf, sizeof(buf)-1);
-    close(fd);
-    if (1 > n)
-    {
-        debug("read of \"%s\" failed: %s", racoon_pid_path,
-              n == 0 ? "empty file" : strerror(errno));
-        return kmDNSHelperRacoonNotificationFailed;
-    }
-    buf[n] = '\0';
-    m = strtoul(buf, &p, 10);
-    if (*p != '\0' && !isspace(*p))
-    {
-        debug("invalid PID \"%s\" (around '%c')", buf, *p);
-        return kmDNSHelperRacoonNotificationFailed;
-    }
-    if (2 > m)
-    {
-        debug("refusing to kill PID %lu", m);
-        return kmDNSHelperRacoonNotificationFailed;
-    }
-    if (0 != kill(m, RacoonSignal()))
-    {
-        debug("Could not signal racoon (%lu): %s", m, strerror(errno));
-        return kmDNSHelperRacoonNotificationFailed;
-    }
-    debug("Sent racoon (%lu) signal %d", m, RacoonSignal());
-    return 0;
-}
-
-static void
-closefds(int from)
-{
-    int fd = 0;
-    struct dirent entry, *entryp = NULL;
-    DIR *dirp = opendir("/dev/fd");
-
-    if (dirp == NULL)
-    {
-        /* fall back to the erroneous getdtablesize method */
-        for (fd = from; fd < getdtablesize(); ++fd)
-            close(fd);
-        return;
-    }
-    while (0 == readdir_r(dirp, &entry, &entryp) && NULL != entryp)
-    {
-        fd = atoi(entryp->d_name);
-        if (fd >= from && fd != dirfd(dirp))
-            close(fd);
-    }
-    closedir(dirp);
-}
-
-static int
-startRacoonOld(void)
-{
-    debug("entry");
-    char * const racoon_args[] = { "/usr/sbin/racoon", "-e", NULL   };
-    ssize_t n = 0;
-    pid_t pid = 0;
-    int status = 0;
-
-    if (0 == (pid = fork()))
-    {
-        closefds(0);
-        execve(racoon_args[0], racoon_args, NULL);
-        helplog(ASL_LEVEL_ERR, "execve of \"%s\" failed: %s",
-                racoon_args[0], strerror(errno));
-        exit(2);
-    }
-    helplog(ASL_LEVEL_NOTICE, "racoon (pid=%lu) started",
-            (unsigned long)pid);
-    n = waitpid(pid, &status, 0);
-    if (-1 == n)
-    {
-        helplog(ASL_LEVEL_ERR, "Unexpected waitpid failure: %s",
-                strerror(errno));
-        return kmDNSHelperRacoonStartFailed;
-    }
-    else if (pid != n)
-    {
-        helplog(ASL_LEVEL_ERR, "Unexpected waitpid return value %d",
-                (int)n);
-        return kmDNSHelperRacoonStartFailed;
-    }
-    else if (WIFSIGNALED(status))
-    {
-        helplog(ASL_LEVEL_ERR,
-                "racoon (pid=%lu) terminated due to signal %d",
-                (unsigned long)pid, WTERMSIG(status));
-        return kmDNSHelperRacoonStartFailed;
-    }
-    else if (WIFSTOPPED(status))
-    {
-        helplog(ASL_LEVEL_ERR,
-                "racoon (pid=%lu) has stopped due to signal %d",
-                (unsigned long)pid, WSTOPSIG(status));
-        return kmDNSHelperRacoonStartFailed;
-    }
-    else if (0 != WEXITSTATUS(status))
-    {
-        helplog(ASL_LEVEL_ERR,
-                "racoon (pid=%lu) exited with status %d",
-                (unsigned long)pid, WEXITSTATUS(status));
-        return kmDNSHelperRacoonStartFailed;
-    }
-    debug("racoon (pid=%lu) daemonized normally", (unsigned long)pid);
-    return 0;
-}
-
-// constant and structure for the racoon control socket
-#define VPNCTL_CMD_PING 0x0004
-typedef struct vpnctl_hdr_struct
-{
-    u_int16_t msg_type;
-    u_int16_t flags;
-    u_int32_t cookie;
-    u_int32_t reserved;
-    u_int16_t result;
-    u_int16_t len;
-} vpnctl_hdr;
-
-static int
-startRacoon(void)
-{
-    debug("entry");
-    int fd = socket(PF_UNIX, SOCK_STREAM, 0);
-    if (0 > fd)
-    {
-        helplog(ASL_LEVEL_ERR, "Could not create endpoint for racoon control socket: %d %s",
-                errno, strerror(errno));
-        return kmDNSHelperRacoonStartFailed;
-    }
-
-    struct sockaddr_un saddr;
-    memset(&saddr, 0, sizeof(saddr));
-    saddr.sun_family = AF_UNIX;
-    saddr.sun_len = sizeof(saddr);
-    static const char racoon_control_sock_path[] = "/var/run/vpncontrol.sock";
-    strcpy(saddr.sun_path, racoon_control_sock_path);
-    int result = connect(fd, (struct sockaddr*) &saddr, saddr.sun_len);
-    if (0 > result)
-    {
-        helplog(ASL_LEVEL_ERR, "Could not connect racoon control socket %s: %d %s",
-                racoon_control_sock_path, errno, strerror(errno));
-        return kmDNSHelperRacoonStartFailed;
-    }
-
-    u_int32_t btmm_cookie = 0x4d4d5442;
-    vpnctl_hdr h = { htons(VPNCTL_CMD_PING), 0, btmm_cookie, 0, 0, 0 };
-    size_t bytes = 0;
-    ssize_t ret = 0;
-
-    while (bytes < sizeof(vpnctl_hdr))
-    {
-        ret = write(fd, ((unsigned char*)&h)+bytes, sizeof(vpnctl_hdr) - bytes);
-        if (ret == -1)
-        {
-            helplog(ASL_LEVEL_ERR, "Could not write to racoon control socket: %d %s",
-                    errno, strerror(errno));
-            return kmDNSHelperRacoonStartFailed;
-        }
-        bytes += ret;
-    }
-
-    int nfds = fd + 1;
-    fd_set fds;
-    int counter = 0;
-    struct timeval tv;
-    bytes = 0;
-    h.cookie = 0;
-
-    for (counter = 0; counter < 100; counter++)
-    {
-        FD_ZERO(&fds);
-        FD_SET(fd, &fds);
-        tv = (struct timeval){ 0, 10000 }; // 10 milliseconds * 100 iterations = 1 second max wait time
-
-        result = select(nfds, &fds, (fd_set*)NULL, (fd_set*)NULL, &tv);
-        if (result > 0)
-        {
-            if (FD_ISSET(fd, &fds))
-            {
-                ret = read(fd, ((unsigned char*)&h)+bytes, sizeof(vpnctl_hdr) - bytes);
-
-                if (ret == -1)
-                {
-                    helplog(ASL_LEVEL_ERR, "Could not read from racoon control socket: %d %s",
-                            strerror(errno));
-                    break;
-                }
-                bytes += ret;
-                if (bytes >= sizeof(vpnctl_hdr)) break;
-            }
-            else
-            {
-                debug("select returned but fd_isset not on expected fd\n");
-            }
-        }
-        else if (result < 0)
-        {
-            debug("select returned %d errno %d %s\n", result, errno, strerror(errno));
-            if (errno != EINTR) break;
-        }
-    }
-
-    close(fd);
-
-    if (bytes < sizeof(vpnctl_hdr) || h.cookie != btmm_cookie) return kmDNSHelperRacoonStartFailed;
-
-    debug("racoon started");
-    return 0;
-}
-
-static int
-kickRacoon(void)
-{
-    if ( 0 == notifyRacoon() )
-        return 0;
-    return UseOldRacoon() ? startRacoonOld() : startRacoon();
-}
-
-#endif /* ndef MDNS_NO_IPSEC */
-
-int
-do_mDNSConfigureServer(__unused mach_port_t port, int updown, const char *fqdn, audit_token_t token)
-{
-#ifndef MDNS_NO_IPSEC
-    debug("entry");
-    if (!authorized(&token)) goto fin;
-
-    switch ((enum mDNSUpDown)updown)
-    {
-    case kmDNSUp:
-        if (0 != createAnonymousRacoonConfiguration(fqdn)) goto fin;
-        break;
-    case kmDNSDown:
-        revertAnonymousRacoonConfiguration(GetOldRacoonConfigDir());
-        revertAnonymousRacoonConfiguration(GetRacoonConfigDir());
-        break;
-    default:
-        goto fin;
-    }
-
-    if (0 != kickRacoon())
-        goto fin;
-    debug("succeeded");
-
-fin:
-#else
-    (void)port; (void)updown; (void)fqdn; (void)token;
-#endif
-    update_idle_timer();
-    return KERN_SUCCESS;
-}
-
-#ifndef MDNS_NO_IPSEC
-
-static unsigned int routeSeq = 1;
-
-static int
-setupTunnelRoute(v6addr_t local, v6addr_t remote)
-{
-    struct
-    {
-        struct rt_msghdr hdr;
-        struct sockaddr_in6 dst;
-        struct sockaddr_in6 gtwy;
-    } msg;
-    int err = 0;
-    int s = -1;
-
-    if (0 > (s = socket(PF_ROUTE, SOCK_RAW, AF_INET)))
-    {
-        helplog(ASL_LEVEL_ERR, "socket(PF_ROUTE, ...) failed: %s",
-                strerror(errno));
-        err = kmDNSHelperRoutingSocketCreationFailed;
-        goto fin;
-    }
-    memset(&msg, 0, sizeof(msg));
-    msg.hdr.rtm_msglen = sizeof(msg);
-    msg.hdr.rtm_type = RTM_ADD;
-    /* The following flags are set by `route add -inet6 -host ...` */
-    msg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_HOST | RTF_STATIC;
-    msg.hdr.rtm_version = RTM_VERSION;
-    msg.hdr.rtm_seq = routeSeq++;
-    msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
-    msg.hdr.rtm_inits = RTV_MTU;
-    msg.hdr.rtm_rmx.rmx_mtu = 1280;
-
-    msg.dst.sin6_len = sizeof(msg.dst);
-    msg.dst.sin6_family = AF_INET6;
-    memcpy(&msg.dst.sin6_addr, remote, sizeof(msg.dst.sin6_addr));
-
-    msg.gtwy.sin6_len = sizeof(msg.gtwy);
-    msg.gtwy.sin6_family = AF_INET6;
-    memcpy(&msg.gtwy.sin6_addr, local, sizeof(msg.gtwy.sin6_addr));
-
-    /* send message, ignore error when route already exists */
-    if (0 > write(s, &msg, msg.hdr.rtm_msglen))
-    {
-        int errno_ = errno;
-
-        debug("write to routing socket failed: %s", strerror(errno_));
-        if (EEXIST != errno_)
-        {
-            err = kmDNSHelperRouteAdditionFailed;
-            goto fin;
-        }
-    }
-
-fin:
-    if (0 <= s)
-        close(s);
-    return err;
-}
-
-static int
-teardownTunnelRoute(v6addr_t remote)
-{
-    struct
-    {
-        struct rt_msghdr hdr;
-        struct sockaddr_in6 dst;
-    } msg;
-    int err = 0;
-    int s = -1;
-
-    if (0 > (s = socket(PF_ROUTE, SOCK_RAW, AF_INET)))
-    {
-        helplog(ASL_LEVEL_ERR, "socket(PF_ROUTE, ...) failed: %s",
-                strerror(errno));
-        err = kmDNSHelperRoutingSocketCreationFailed;
-        goto fin;
-    }
-    memset(&msg, 0, sizeof(msg));
-
-    msg.hdr.rtm_msglen = sizeof(msg);
-    msg.hdr.rtm_type = RTM_DELETE;
-    msg.hdr.rtm_version = RTM_VERSION;
-    msg.hdr.rtm_seq = routeSeq++;
-    msg.hdr.rtm_addrs = RTA_DST;
-
-    msg.dst.sin6_len = sizeof(msg.dst);
-    msg.dst.sin6_family = AF_INET6;
-    memcpy(&msg.dst.sin6_addr, remote, sizeof(msg.dst.sin6_addr));
-    if (0 > write(s, &msg, msg.hdr.rtm_msglen))
-    {
-        int errno_ = errno;
-
-        debug("write to routing socket failed: %s", strerror(errno_));
-        if (ESRCH != errno_)
-        {
-            err = kmDNSHelperRouteDeletionFailed;
-            goto fin;
-        }
-    }
-
-fin:
-    if (0 <= s)
-        close(s);
-    return err;
-}
-
-static int
-v4addr_to_string(v4addr_t addr, char *buf, size_t buflen)
-{
-    if (NULL == inet_ntop(AF_INET, addr, buf, buflen))
-    {
-        helplog(ASL_LEVEL_ERR, "inet_ntop failed: %s",
-                strerror(errno));
-        return kmDNSHelperInvalidNetworkAddress;
-    }
-    else
-        return 0;
-}
-
-static int
-v6addr_to_string(v6addr_t addr, char *buf, size_t buflen)
-{
-    if (NULL == inet_ntop(AF_INET6, addr, buf, buflen))
-    {
-        helplog(ASL_LEVEL_ERR, "inet_ntop failed: %s",
-                strerror(errno));
-        return kmDNSHelperInvalidNetworkAddress;
-    }
-    else
-        return 0;
-}
-
-/* Caller owns object returned in `policy' */
-static int
-generateTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, int in,
-                     v4addr_t src, uint16_t src_port,
-                     v4addr_t dst, uint16_t dst_port,
-                     v6addr_t src6, v6addr_t dst6,
-                     ipsec_policy_t *policy, size_t *len)
-{
-    char srcs[INET_ADDRSTRLEN], dsts[INET_ADDRSTRLEN];
-    char srcs6[INET6_ADDRSTRLEN], dsts6[INET6_ADDRSTRLEN];
-    char buf[512];
-    char *inOut = in ? "in" : "out";
-    ssize_t n = 0;
-    int err = 0;
-
-    *policy = NULL;
-    *len = 0;
-
-    switch (which)
-    {
-    case kmDNSTunnelPolicySetup:
-        if (type == kmDNSIPv6IPv4Tunnel)
-        {
-            if (0 != (err = v4addr_to_string(src, srcs, sizeof(srcs))))
-                goto fin;
-            if (0 != (err = v4addr_to_string(dst, dsts, sizeof(dsts))))
-                goto fin;
-            n = snprintf(buf, sizeof(buf),
-                         "%s ipsec esp/tunnel/%s[%u]-%s[%u]/require",
-                         inOut, srcs, src_port, dsts, dst_port);
-        }
-        else if (type == kmDNSIPv6IPv6Tunnel)
-        {
-            if (0 != (err = v6addr_to_string(src6, srcs6, sizeof(srcs6))))
-                goto fin;
-            if (0 != (err = v6addr_to_string(dst6, dsts6, sizeof(dsts6))))
-                goto fin;
-            n = snprintf(buf, sizeof(buf),
-                         "%s ipsec esp/tunnel/%s-%s/require",
-                         inOut, srcs6, dsts6);
-        }
-        break;
-    case kmDNSTunnelPolicyTeardown:
-        n = strlcpy(buf, inOut, sizeof(buf));
-        break;
-    case kmDNSTunnelPolicyGenerate:
-        n = snprintf(buf, sizeof(buf), "%s generate", inOut);
-        break;
-    default:
-        err = kmDNSHelperIPsecPolicyCreationFailed;
-        goto fin;
-    }
-
-    if (n >= (int)sizeof(buf))
-    {
-        err = kmDNSHelperResultTooLarge;
-        goto fin;
-    }
-
-    debug("policy=\"%s\"", buf);
-    if (NULL == (*policy = (ipsec_policy_t)ipsec_set_policy(buf, n)))
-    {
-        helplog(ASL_LEVEL_ERR,
-                "Could not create IPsec policy from \"%s\"", buf);
-        err = kmDNSHelperIPsecPolicyCreationFailed;
-        goto fin;
-    }
-    *len = ((ipsec_policy_t)(*policy))->sadb_x_policy_len * 8;
-
-fin:
-    return err;
-}
-
-static int
-sendPolicy(int s, int setup,
-           struct sockaddr *src, uint8_t src_bits,
-           struct sockaddr *dst, uint8_t dst_bits,
-           ipsec_policy_t policy, size_t len)
-{
-    static unsigned int policySeq = 0;
-    int err = 0;
-
-    debug("entry, setup=%d", setup);
-    if (setup)
-        err = pfkey_send_spdadd(s, src, src_bits, dst, dst_bits, -1,
-                                (char *)policy, len, policySeq++);
-    else
-        err = pfkey_send_spddelete(s, src, src_bits, dst, dst_bits, -1,
-                                   (char *)policy, len, policySeq++);
-    if (0 > err)
-    {
-        helplog(ASL_LEVEL_ERR, "Could not set IPsec policy: %s",
-                ipsec_strerror());
-        err = kmDNSHelperIPsecPolicySetFailed;
-        goto fin;
-    }
-    else
-        err = 0;
-    debug("succeeded");
-
-fin:
-    return err;
-}
-
-static int
-removeSA(int s, struct sockaddr *src, struct sockaddr *dst)
-{
-    int err = 0;
-
-    debug("entry");
-    err = pfkey_send_delete_all(s, SADB_SATYPE_ESP, IPSEC_MODE_ANY, src, dst);
-    if (0 > err)
-    {
-        helplog(ASL_LEVEL_ERR, "Could not remove IPsec SA: %s", ipsec_strerror());
-        err = kmDNSHelperIPsecRemoveSAFailed;
-        goto fin;
-    }
-    err = pfkey_send_delete_all(s, SADB_SATYPE_ESP, IPSEC_MODE_ANY, dst, src);
-    if (0 > err)
-    {
-        helplog(ASL_LEVEL_ERR, "Could not remove IPsec SA: %s", ipsec_strerror());
-        err = kmDNSHelperIPsecRemoveSAFailed;
-        goto fin;
-    }
-    else
-        err = 0;
-
-    debug("succeeded");
-
-fin:
-    return err;
-}
-
-static int
-doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type,
-               v6addr_t loc_inner, uint8_t loc_bits,
-               v4addr_t loc_outer, uint16_t loc_port,
-               v6addr_t rmt_inner, uint8_t rmt_bits,
-               v4addr_t rmt_outer, uint16_t rmt_port,
-               v6addr_t loc_outer6, v6addr_t rmt_outer6)
-{
-    struct sockaddr_in6 sin6_loc;
-    struct sockaddr_in6 sin6_rmt;
-    ipsec_policy_t policy = NULL;
-    size_t len = 0;
-    int s = -1;
-    int err = 0;
-
-    debug("entry");
-    if (0 > (s = pfkey_open()))
-    {
-        helplog(ASL_LEVEL_ERR,
-                "Could not create IPsec policy socket: %s",
-                ipsec_strerror());
-        err = kmDNSHelperIPsecPolicySocketCreationFailed;
-        goto fin;
-    }
-
-    memset(&sin6_loc, 0, sizeof(sin6_loc));
-    sin6_loc.sin6_len = sizeof(sin6_loc);
-    sin6_loc.sin6_family = AF_INET6;
-    sin6_loc.sin6_port = htons(0);
-    memcpy(&sin6_loc.sin6_addr, loc_inner, sizeof(sin6_loc.sin6_addr));
-
-    memset(&sin6_rmt, 0, sizeof(sin6_rmt));
-    sin6_rmt.sin6_len = sizeof(sin6_rmt);
-    sin6_rmt.sin6_family = AF_INET6;
-    sin6_rmt.sin6_port = htons(0);
-    memcpy(&sin6_rmt.sin6_addr, rmt_inner, sizeof(sin6_rmt.sin6_addr));
-
-    int setup = which != kmDNSTunnelPolicyTeardown;
-
-    if (0 != (err = generateTunnelPolicy(which, type, 1,
-                                         rmt_outer, rmt_port,
-                                         loc_outer, loc_port,
-                                         rmt_outer6, loc_outer6,
-                                         &policy, &len)))
-        goto fin;
-    if (0 != (err = sendPolicy(s, setup,
-                               (struct sockaddr *)&sin6_rmt, rmt_bits,
-                               (struct sockaddr *)&sin6_loc, loc_bits,
-                               policy, len)))
-        goto fin;
-    if (NULL != policy)
-    {
-        free(policy);
-        policy = NULL;
-    }
-    if (0 != (err = generateTunnelPolicy(which, type, 0,
-                                         loc_outer, loc_port,
-                                         rmt_outer, rmt_port,
-                                         loc_outer6, rmt_outer6,
-                                         &policy, &len)))
-        goto fin;
-    if (0 != (err = sendPolicy(s, setup,
-                               (struct sockaddr *)&sin6_loc, loc_bits,
-                               (struct sockaddr *)&sin6_rmt, rmt_bits,
-                               policy, len)))
-        goto fin;
-
-    if (which == kmDNSTunnelPolicyTeardown)
-    {
-        if (rmt_port)       // Outer tunnel is IPv4
-        {
-            if (loc_outer && rmt_outer)
-            {
-                struct sockaddr_in sin_loc;
-                struct sockaddr_in sin_rmt;
-                memset(&sin_loc, 0, sizeof(sin_loc));
-                sin_loc.sin_len = sizeof(sin_loc);
-                sin_loc.sin_family = AF_INET;
-                memcpy(&sin_loc.sin_addr, loc_outer, sizeof(sin_loc.sin_addr));
-
-                memset(&sin_rmt, 0, sizeof(sin_rmt));
-                sin_rmt.sin_len = sizeof(sin_rmt);
-                sin_rmt.sin_family = AF_INET;
-                memcpy(&sin_rmt.sin_addr, rmt_outer, sizeof(sin_rmt.sin_addr));
-                if (0 != (err = removeSA(s, (struct sockaddr *)&sin_loc, (struct sockaddr *)&sin_rmt)))
-                    goto fin;
-            }
-        }
-        else
-        {
-            if (loc_outer6 && rmt_outer6)
-            {
-                struct sockaddr_in6 sin6_lo;
-                struct sockaddr_in6 sin6_rm;
-
-                memset(&sin6_lo, 0, sizeof(sin6_lo));
-                sin6_lo.sin6_len = sizeof(sin6_lo);
-                sin6_lo.sin6_family = AF_INET6;
-                memcpy(&sin6_lo.sin6_addr, loc_outer6, sizeof(sin6_lo.sin6_addr));
-
-                memset(&sin6_rm, 0, sizeof(sin6_rm));
-                sin6_rm.sin6_len = sizeof(sin6_rm);
-                sin6_rm.sin6_family = AF_INET6;
-                memcpy(&sin6_rm.sin6_addr, rmt_outer6, sizeof(sin6_rm.sin6_addr));
-                if (0 != (err = removeSA(s, (struct sockaddr *)&sin6_lo, (struct sockaddr *)&sin6_rm)))
-                    goto fin;
-            }
-        }
-    }
-
-
-    debug("succeeded");
-
-fin:
-    if (s >= 0)
-        pfkey_close(s);
-    if (NULL != policy)
-        free(policy);
-    return err;
-}
-
-#endif /* ndef MDNS_NO_IPSEC */
-
-int
-do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
-                         v6addr_t loc_inner, v6addr_t loc_outer6, uint16_t loc_port,
-                         v6addr_t rmt_inner, v6addr_t rmt_outer6, uint16_t rmt_port,
-                         const char *id, int *err, audit_token_t token)
-{
-#ifndef MDNS_NO_IPSEC
-    static const char config[] =
-        "%s"
-        "remote %s [%u] {\n"
-        "  disconnect_on_idle idle_timeout 600 idle_direction idle_outbound;\n"
-        "  exchange_mode aggressive;\n"
-        "  doi ipsec_doi;\n"
-        "  situation identity_only;\n"
-        "  verify_identifier off;\n"
-        "  generate_policy on;\n"
-        "  my_identifier user_fqdn \"%s\";\n"
-        "  shared_secret keychain \"%s\";\n"
-        "  nonce_size 16;\n"
-        "  lifetime time 15 min;\n"
-        "  initial_contact on;\n"
-        "  support_proxy on;\n"
-        "  nat_traversal force;\n"
-        "  proposal_check claim;\n"
-        "  proposal {\n"
-        "    encryption_algorithm aes;\n"
-        "    hash_algorithm sha256;\n"
-        "    authentication_method pre_shared_key;\n"
-        "    dh_group 2;\n"
-        "    lifetime time 15 min;\n"
-        "  }\n"
-        "  proposal {\n"
-        "    encryption_algorithm aes;\n"
-        "    hash_algorithm sha1;\n"
-        "    authentication_method pre_shared_key;\n"
-        "    dh_group 2;\n"
-        "    lifetime time 15 min;\n"
-        "  }\n"
-        "}\n\n"
-        "sainfo address %s any address %s any {\n"
-        "  pfs_group 2;\n"
-        "  lifetime time 10 min;\n"
-        "  encryption_algorithm aes;\n"
-        "  authentication_algorithm hmac_sha256,hmac_sha1;\n"
-        "  compression_algorithm deflate;\n"
-        "}\n\n"
-        "sainfo address %s any address %s any {\n"
-        "  pfs_group 2;\n"
-        "  lifetime time 10 min;\n"
-        "  encryption_algorithm aes;\n"
-        "  authentication_algorithm hmac_sha256,hmac_sha1;\n"
-        "  compression_algorithm deflate;\n"
-        "}\n";
-    char path[PATH_MAX] = "";
-    char li[INET6_ADDRSTRLEN], lo[INET_ADDRSTRLEN], lo6[INET6_ADDRSTRLEN],
-         ri[INET6_ADDRSTRLEN], ro[INET_ADDRSTRLEN], ro6[INET6_ADDRSTRLEN];
-    FILE *fp = NULL;
-    int fd = -1;
-    char tmp_path[PATH_MAX] = "";
-    v4addr_t loc_outer, rmt_outer;
-
-    debug("entry");
-    *err = 0;
-    if (!authorized(&token))
-    {
-        *err = kmDNSHelperNotAuthorized;
-        goto fin;
-    }
-    switch ((enum mDNSAutoTunnelSetKeysReplaceDelete)replacedelete)
-    {
-    case kmDNSAutoTunnelSetKeysReplace:
-    case kmDNSAutoTunnelSetKeysDelete:
-        break;
-    default:
-        *err = kmDNSHelperInvalidTunnelSetKeysOperation;
-        goto fin;
-    }
-
-    if (0 != (*err = v6addr_to_string(loc_inner, li, sizeof(li))))
-        goto fin;
-    if (0 != (*err = v6addr_to_string(rmt_inner, ri, sizeof(ri))))
-        goto fin;
-
-    debug("loc_inner=%s rmt_inner=%s", li, ri);
-    if (!rmt_port)
-    {
-        loc_outer[0] = loc_outer[1] = loc_outer[2] = loc_outer[3] = 0;
-        rmt_outer[0] = rmt_outer[1] = rmt_outer[2] = rmt_outer[3] = 0;
-
-        if (0 != (*err = v6addr_to_string(loc_outer6, lo6, sizeof(lo6))))
-            goto fin;
-        if (0 != (*err = v6addr_to_string(rmt_outer6, ro6, sizeof(ro6))))
-            goto fin;
-        debug("IPv6 outer tunnel: loc_outer6=%s rmt_outer6=%s", lo6, ro6);
-        if ((int)sizeof(path) <= snprintf(path, sizeof(path),
-                                          "%s%s.conf", GetRacoonConfigDir(), ro6))
-        {
-            *err = kmDNSHelperResultTooLarge;
-            goto fin;
-        }
-    }
-    else
-    {
-        loc_outer[0] = loc_outer6[0];
-        loc_outer[1] = loc_outer6[1];
-        loc_outer[2] = loc_outer6[2];
-        loc_outer[3] = loc_outer6[3];
-
-        rmt_outer[0] = rmt_outer6[0];
-        rmt_outer[1] = rmt_outer6[1];
-        rmt_outer[2] = rmt_outer6[2];
-        rmt_outer[3] = rmt_outer6[3];
-
-        if (0 != (*err = v4addr_to_string(loc_outer, lo, sizeof(lo))))
-            goto fin;
-        if (0 != (*err = v4addr_to_string(rmt_outer, ro, sizeof(ro))))
-            goto fin;
-        debug("IPv4 outer tunnel: loc_outer=%s loc_port=%u rmt_outer=%s rmt_port=%u",
-              lo, loc_port, ro, rmt_port);
-
-        if ((int)sizeof(path) <= snprintf(path, sizeof(path),
-                                          "%s%s.%u.conf", GetRacoonConfigDir(), ro,
-                                          rmt_port))
-        {
-            *err = kmDNSHelperResultTooLarge;
-            goto fin;
-        }
-    }
-
-
-
-    if (kmDNSAutoTunnelSetKeysReplace == replacedelete)
-    {
-        if (0 > ensureExistenceOfRacoonConfigDir(GetRacoonConfigDir()))
-        {
-            *err = kmDNSHelperRacoonConfigCreationFailed;
-            goto fin;
-        }
-        if ((int)sizeof(tmp_path) <=
-            snprintf(tmp_path, sizeof(tmp_path), "%s.XXXXXX", path))
-        {
-            *err = kmDNSHelperResultTooLarge;
-            goto fin;
-        }
-        if (0 > (fd = mkstemp(tmp_path)))
-        {
-            helplog(ASL_LEVEL_ERR, "mkstemp \"%s\" failed: %s",
-                    tmp_path, strerror(errno));
-            *err = kmDNSHelperRacoonConfigCreationFailed;
-            goto fin;
-        }
-        if (NULL == (fp = fdopen(fd, "w")))
-        {
-            helplog(ASL_LEVEL_ERR, "fdopen: %s",
-                    strerror(errno));
-            *err = kmDNSHelperRacoonConfigCreationFailed;
-            goto fin;
-        }
-        fd = -1;
-        fprintf(fp, config, configHeader, (!rmt_port ? ro6 : ro), rmt_port, id, id, ri, li, li, ri);
-        fclose(fp);
-        fp = NULL;
-        if (0 > rename(tmp_path, path))
-        {
-            helplog(ASL_LEVEL_ERR,
-                    "rename \"%s\" \"%s\" failed: %s",
-                    tmp_path, path, strerror(errno));
-            *err = kmDNSHelperRacoonConfigCreationFailed;
-            goto fin;
-        }
-    }
-    else
-    {
-        if (0 != unlink(path))
-            debug("unlink \"%s\" failed: %s", path,
-                  strerror(errno));
-    }
-
-    if (0 != (*err = doTunnelPolicy(kmDNSTunnelPolicyTeardown, kmDNSNoTunnel,
-                                    loc_inner, kWholeV6Mask, loc_outer, loc_port,
-                                    rmt_inner, kWholeV6Mask, rmt_outer, rmt_port, loc_outer6, rmt_outer6)))
-        goto fin;
-    if (kmDNSAutoTunnelSetKeysReplace == replacedelete &&
-        0 != (*err = doTunnelPolicy(kmDNSTunnelPolicySetup, (!rmt_port ? kmDNSIPv6IPv6Tunnel : kmDNSIPv6IPv4Tunnel),
-                                    loc_inner, kWholeV6Mask, loc_outer, loc_port,
-                                    rmt_inner, kWholeV6Mask, rmt_outer, rmt_port, loc_outer6, rmt_outer6)))
-        goto fin;
-
-    if (0 != (*err = teardownTunnelRoute(rmt_inner)))
-        goto fin;
-    if (kmDNSAutoTunnelSetKeysReplace == replacedelete &&
-        0 != (*err = setupTunnelRoute(loc_inner, rmt_inner)))
-        goto fin;
-
-    if (kmDNSAutoTunnelSetKeysReplace == replacedelete &&
-        0 != (*err = kickRacoon()))
-        goto fin;
-
-    debug("succeeded");
-
-fin:
-    if (NULL != fp)
-        fclose(fp);
-    if (0 <= fd)
-        close(fd);
-    unlink(tmp_path);
-#else
-    (void)replacedelete; (void)loc_inner; (void)loc_outer6; (void)loc_port; (void)rmt_inner;
-    (void)rmt_outer6; (void)rmt_port; (void)id; (void)token;
-
-    *err = kmDNSHelperIPsecDisabled;
-#endif /* MDNS_NO_IPSEC */
-    update_idle_timer();
-    return KERN_SUCCESS;
-}
-
-kern_return_t
-do_mDNSSendWakeupPacket(__unused mach_port_t port, unsigned ifid, const char *eth_addr, const char *ip_addr, int iteration, audit_token_t token)
-{
-    int bpf_fd, i, j;
-    struct ifreq ifr;
-    char ifname[IFNAMSIZ];
-    char packet[512];
-    char *ptr = packet;
-    char bpf_device[12];
-    struct ether_addr *ea;
-    (void) ip_addr; // unused
-    (void) iteration; // unused
-    (void) token; // unused
-
-    if (if_indextoname(ifid, ifname) == NULL)
-    {
-        helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket invalid interface index %u", ifid);
-        return errno;
-    }
-
-    ea = ether_aton(eth_addr);
-    if (ea == NULL)
-    {
-        helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket invalid ethernet address %s", eth_addr);
-        return errno;
-    }
-
-    for (i = 0; i < 100; i++)
-    {
-        snprintf(bpf_device, sizeof(bpf_device), "/dev/bpf%d", i);
-        bpf_fd = open(bpf_device, O_RDWR, 0);
-        if (bpf_fd == -1)
-            continue;
-        else break;
-    }
-
-    if (bpf_fd == -1)
-    {
-        helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket cannot find a bpf device");
-        return ENXIO;
-    }
-
-    memset(&ifr, 0, sizeof(ifr));
-    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-
-    if (ioctl(bpf_fd, BIOCSETIF, (char *)&ifr) < 0)
-    {
-        helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket BIOCSETIF failed %s", strerror(errno));
-        return errno;
-    }
-
-    // 0x00 Destination address
-    for (i=0; i<6; i++) *ptr++ = ea->octet[i];
-
-    // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
-    for (i=0; i<6; i++) *ptr++ = 0;
-
-    // 0x0C Ethertype (0x0842)
-    *ptr++ = 0x08;
-    *ptr++ = 0x42;
-
-    // 0x0E Wakeup sync sequence
-    for (i=0; i<6; i++) *ptr++ = 0xFF;
-
-    // 0x14 Wakeup data
-    for (j=0; j<16; j++) for (i=0; i<6; i++) *ptr++ = ea->octet[i];
-
-    // 0x74 Password
-    for (i=0; i<6; i++) *ptr++ = 0;
-
-    if (write(bpf_fd, packet, ptr - packet) < 0)
-    {
-        helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket write failed %s", strerror(errno));
-        return errno;
-    }
-    helplog(ASL_LEVEL_INFO, "do_mDNSSendWakeupPacket sent unicast eth_addr %s, ip_addr %s", eth_addr, ip_addr);
-    // Send a broadcast one to handle ethernet switches that don't flood forward packets with
-    // unknown mac addresses.
-    for (i=0; i<6; i++) packet[i] = 0xFF;
-    if (write(bpf_fd, packet, ptr - packet) < 0)
-    {
-        helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket write failed %s", strerror(errno));
-        return errno;
-    }
-    helplog(ASL_LEVEL_INFO, "do_mDNSSendWakeupPacket sent broadcast eth_addr %s, ip_addr %s", eth_addr, ip_addr);
-    close(bpf_fd);
-    return KERN_SUCCESS;
-}
-
-// Open the specified port for protocol in the P2P firewall.
-kern_return_t
-do_mDNSPacketFilterControl(__unused mach_port_t port, uint32_t command, const char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray, audit_token_t token)
-{
-    (void) token; // unused
-    int error;
-    kern_return_t result = KERN_SUCCESS;
-
-    helplog(ASL_LEVEL_INFO, "do_mDNSPacketFilterControl: command %d ifname %s, count %d",
-            command, ifname, count);
-
-    switch (command)
-    {
-    case PF_SET_RULES:
-        error = P2PPacketFilterAddBonjourRuleSet(ifname, count, portArray, protocolArray);
-        if (error)
-        {
-            helplog(ASL_LEVEL_ERR, "P2PPacketFilterAddBonjourRuleSet failed %s", strerror(error));
-            result = KERN_FAILURE;
-        }
-        break;
-
-    case PF_CLEAR_RULES:
-        error = P2PPacketFilterClearBonjourRules();
-        if (error)
-        {
-            helplog(ASL_LEVEL_ERR, "P2PPacketFilterClearBonjourRules failed %s", strerror(error));
-            result = KERN_FAILURE;
-        }
-        break;
-
-    default:
-        helplog(ASL_LEVEL_ERR, "do_mDNSPacketFilterControl: invalid command %d", command);
-        result = KERN_INVALID_ARGUMENT;
-        break;
-    }
-
-    return result;
-}
-
-unsigned long
-in_cksum(unsigned short *ptr,int nbytes)
-{
-    unsigned long sum;
-    u_short oddbyte;
-
-    /*
-     * Our algorithm is simple, using a 32-bit accumulator (sum),
-     * we add sequential 16-bit words to it, and at the end, fold back
-     * all the carry bits from the top 16 bits into the lower 16 bits.
-     */
-    sum = 0;
-    while (nbytes > 1) {
-        sum += *ptr++;
-        nbytes -= 2;
-    }
-
-    /* mop up an odd byte, if necessary */
-    if (nbytes == 1) {
-        /* make sure top half is zero */
-        oddbyte = 0;
-
-        /* one byte only */
-        *((u_char *)&oddbyte) = *(u_char *)ptr;
-        sum += oddbyte;
-    }
-    /* Add back carry outs from top 16 bits to low 16 bits. */
-    sum = (sum >> 16) + (sum & 0xffff);
-
-    /* add carry */
-    sum += (sum >> 16);
-
-    return sum;
-}
-
-unsigned short
-InetChecksum(unsigned short *ptr,int nbytes)
-{
-    unsigned long sum;
-
-    sum = in_cksum(ptr, nbytes);
-    return (unsigned short)~sum;
-}
-
-void TCPCheckSum(int af, struct tcphdr *t, int tcplen, v6addr_t sadd6, v6addr_t dadd6)
-{
-    unsigned long sum = 0;
-    unsigned short *ptr;
-
-    /* TCP header checksum */
-    sum = in_cksum((unsigned short *)t, tcplen);
-
-    if (af == AF_INET)
-    {
-        /* Pseudo header */
-        ptr = (unsigned short *)sadd6;
-        sum += *ptr++;
-        sum += *ptr++;
-        ptr = (unsigned short *)dadd6;
-        sum += *ptr++;
-        sum += *ptr++;
-    }
-    else if (af == AF_INET6)
-    {
-        /* Pseudo header */
-        ptr = (unsigned short *)sadd6;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        ptr = (unsigned short *)dadd6;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-        sum += *ptr++;
-    }
-
-    sum += htons(tcplen);
-    sum += htons(IPPROTO_TCP);
-
-    while (sum >> 16)
-        sum = (sum >> 16) + (sum & 0xFFFF);
-
-    t->th_sum = ~sum;
-
-}
-
-kern_return_t do_mDNSSendKeepalive(__unused mach_port_t port, v6addr_t sadd6, v6addr_t dadd6, uint16_t lport, uint16_t rport, unsigned seq, unsigned ack, uint16_t win, audit_token_t token)
-{
-    struct packet4 {
-        struct ip ip;
-        struct tcphdr tcp;
-    } packet4;
-    struct packet6 {
-        struct tcphdr tcp;
-    } packet6;
-    int sock, on;
-    struct tcphdr *t;
-    int af;
-    struct sockaddr_storage ss_to;
-    struct sockaddr_in *sin_to = (struct sockaddr_in *)&ss_to;
-    struct sockaddr_in6 *sin6_to = (struct sockaddr_in6 *)&ss_to;
-    void *packet;
-    ssize_t packetlen;
-    char ctlbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
-    struct msghdr msghdr;
-    struct iovec iov;
-    ssize_t len;
-
-    if (!authorized(&token))
-    {
-        helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: Not authorized");
-        return kmDNSHelperNotAuthorized;
-    }
-
-    helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: called");
-
-    // all the incoming arguments are in network order
-    if ((*(unsigned *)(sadd6 +4) == 0) && (*(unsigned *)(sadd6 + 8) == 0) && (*(unsigned *)(sadd6 + 12) == 0))
-    {
-        af = AF_INET;
-        memset(&packet4, 0, sizeof (packet4));
-
-        /* Fill in all the IP header information - should be in host order*/
-        packet4.ip.ip_v = 4;            /* 4-bit Version */
-        packet4.ip.ip_hl = 5;       /* 4-bit Header Length */
-        packet4.ip.ip_tos = 0;      /* 8-bit Type of service */
-        packet4.ip.ip_len = 40;     /* 16-bit Total length */
-        packet4.ip.ip_id = 9864;        /* 16-bit ID field */
-        packet4.ip.ip_off = 0;      /* 13-bit Fragment offset */
-        packet4.ip.ip_ttl = 63;     /* 8-bit Time To Live */
-        packet4.ip.ip_p = IPPROTO_TCP;  /* 8-bit Protocol */
-        packet4.ip.ip_sum = 0;      /* 16-bit Header checksum (below) */
-        memcpy(&packet4.ip.ip_src.s_addr, sadd6, 4);
-        memcpy(&packet4.ip.ip_dst.s_addr, dadd6, 4);
-
-        /* IP header checksum */
-        packet4.ip.ip_sum = InetChecksum((unsigned short *)&packet4.ip, 20);
-        t = &packet4.tcp;
-        packet = &packet4;
-        packetlen = 40; // sum of IPv4 header len(20) and TCP header len(20)
-    }
-    else
-    {
-        af = AF_INET6;
-        memset(&packet6, 0, sizeof (packet6));
-        t = &packet6.tcp;
-        packet = &packet6;
-        // We don't send IPv6 header, hence just the TCP header len (20)
-        packetlen = 20;
-    }
-
-    /* Fill in all the TCP header information */
-    t->th_sport = lport;        /* 16-bit Source port number */
-    t->th_dport = rport;        /* 16-bit Destination port */
-    t->th_seq = seq;            /* 32-bit Sequence Number */
-    t->th_ack = ack;            /* 32-bit Acknowledgement Number */
-    t->th_off = 5;              /* Data offset */
-    t->th_flags = TH_ACK;
-    t->th_win = win;
-    t->th_sum = 0;              /* 16-bit checksum (below) */
-    t->th_urp = 0;              /* 16-bit urgent offset */
-
-    TCPCheckSum(af, t, 20, sadd6, dadd6);
-
-    /* Open up a RAW socket */
-    if ((sock = socket(af, SOCK_RAW, IPPROTO_TCP)) < 0)
-    {
-        helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: socket %s", strerror(errno));
-        return errno;
-    }
-
-
-    if (af == AF_INET)
-    {
-        on = 1;
-        if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)))
-        {
-            close(sock);
-            helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: setsockopt %s", strerror(errno));
-            return errno;
-        }
-
-        memset(sin_to, 0, sizeof(struct sockaddr_in));
-        sin_to->sin_len = sizeof(struct sockaddr_in);
-        sin_to->sin_family = AF_INET;
-        memcpy(&sin_to->sin_addr, sadd6, sizeof(struct in_addr));
-        sin_to->sin_port = rport;
-
-        msghdr.msg_control = NULL;
-        msghdr.msg_controllen = 0;
-
-    }
-    else
-    {
-        struct cmsghdr *ctl;
-
-        memset(sin6_to, 0, sizeof(struct sockaddr_in6));
-        sin6_to->sin6_len = sizeof(struct sockaddr_in6);
-        sin6_to->sin6_family = AF_INET6;
-        memcpy(&sin6_to->sin6_addr, dadd6, sizeof(struct in6_addr));
-
-        sin6_to->sin6_port = rport;
-        sin6_to->sin6_flowinfo = 0;
-
-
-        msghdr.msg_control = ctlbuf;
-        msghdr.msg_controllen = sizeof(ctlbuf);
-        ctl = CMSG_FIRSTHDR(&msghdr);
-        ctl->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
-        ctl->cmsg_level = IPPROTO_IPV6;
-        ctl->cmsg_type = IPV6_PKTINFO;
-        struct in6_pktinfo *pktinfo = (struct in6_pktinfo *) CMSG_DATA(ctl);
-        memcpy(&pktinfo->ipi6_addr, sadd6, sizeof(struct in6_addr));
-        pktinfo->ipi6_ifindex = 0;
-    }
-
-    msghdr.msg_name = (struct sockaddr *)&ss_to;
-    msghdr.msg_namelen = ss_to.ss_len;
-    iov.iov_base = packet;
-    iov.iov_len = packetlen;
-    msghdr.msg_iov = &iov;
-    msghdr.msg_iovlen = 1;
-    msghdr.msg_flags = 0;
-again:
-    len = sendmsg(sock, &msghdr, 0);
-    if (len == -1)
-    {
-        if (errno == EINTR)
-            goto again;
-    }
-
-    if (len != packetlen)
-    {
-        helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: sendmsg failed %s", strerror(errno));
-    }
-    else
-    {
-        char source[INET6_ADDRSTRLEN], dest[INET6_ADDRSTRLEN];
-
-        inet_ntop(af, (void *)sadd6, source, sizeof(source));
-        inet_ntop(af, (void *)dadd6, dest, sizeof(dest));
-
-        helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: Success Source %s:%d, Dest %s:%d, %u, %u, %u", source, ntohs(lport), dest, ntohs(rport), ntohl(seq), ntohl(ack), ntohs(win));
-
-    }
-    close(sock);
-    return KERN_SUCCESS;
-}
-
-
-kern_return_t do_mDNSRetrieveTCPInfo(__unused mach_port_t port, int family, v6addr_t laddr, uint16_t lport, v6addr_t raddr, uint16_t  rport,
-                                     uint32_t *seq, uint32_t *ack, uint16_t *win, int32_t *intfid, audit_token_t token)
-{
-    struct tcp_info   ti;
-    struct info_tuple itpl;
-    int               mib[4];
-    unsigned int      miblen;
-    size_t            len;
-    size_t            sz;
-
-    memset(&itpl, 0, sizeof(struct info_tuple));
-    memset(&ti,   0, sizeof(struct tcp_info));
-
-    if (!authorized(&token))
-    {
-        helplog(ASL_LEVEL_ERR, "mDNSRetrieveTCPInfo: Not authorized");
-        return kmDNSHelperNotAuthorized;
-    }
-
-    if (family == AF_INET)
-    {
-        memcpy(&itpl.itpl_local_sin.sin_addr,  laddr, sizeof(struct in_addr));
-        memcpy(&itpl.itpl_remote_sin.sin_addr, raddr, sizeof(struct in_addr));
-        itpl.itpl_local_sin.sin_port    = lport;
-        itpl.itpl_remote_sin.sin_port   = rport;
-        itpl.itpl_local_sin.sin_family  = AF_INET;
-        itpl.itpl_remote_sin.sin_family = AF_INET;
-    }
-    else
-    {
-        memcpy(&itpl.itpl_local_sin6.sin6_addr,  laddr, sizeof(struct in6_addr));
-        memcpy(&itpl.itpl_remote_sin6.sin6_addr, raddr, sizeof(struct in6_addr));
-        itpl.itpl_local_sin6.sin6_port    = lport;
-        itpl.itpl_remote_sin6.sin6_port   = rport;
-        itpl.itpl_local_sin6.sin6_family  = AF_INET6;
-        itpl.itpl_remote_sin6.sin6_family = AF_INET6;
-    }
-    itpl.itpl_proto = IPPROTO_TCP;
-    sz = sizeof(mib)/sizeof(mib[0]);
-    if (sysctlnametomib("net.inet.tcp.info", mib, &sz) == -1)
-    {
-        helplog(ASL_LEVEL_ERR, "do_RetrieveTCPInfo: sysctlnametomib failed %d, %s", errno, strerror(errno));
-        return errno;
-    }
-    miblen = (unsigned int)sz;
-    len    = sizeof(struct tcp_info);
-    if (sysctl(mib, miblen, &ti, &len, &itpl, sizeof(struct info_tuple)) == -1)
-    {
-        helplog(ASL_LEVEL_ERR, "do_RetrieveTCPInfo: sysctl failed %d, %s", errno, strerror(errno));
-        return errno;
-    }
-
-    *seq    = ti.tcpi_snd_nxt - 1;
-    *ack    = ti.tcpi_rcv_nxt;
-    *win    = ti.tcpi_rcv_space >> ti.tcpi_rcv_wscale;
-    *intfid = ti.tcpi_last_outif;
-    return KERN_SUCCESS;
-}
-
-static int getMACAddress(int family, v6addr_t raddr, v6addr_t gaddr, int *gfamily, ethaddr_t eth)
-{
-    struct
-    {
-        struct rt_msghdr m_rtm;
-        char   m_space[512];
-    } m_rtmsg;
-
-    struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
-    char  *cp  = m_rtmsg.m_space;
-    int    seq = 6367, sock, rlen, i;
-    struct sockaddr_in      *sin  = NULL;
-    struct sockaddr_in6     *sin6 = NULL;
-    struct sockaddr_dl      *sdl  = NULL;
-    struct sockaddr_storage  sins;
-    struct sockaddr_dl       sdl_m;
-
-#define NEXTADDR(w, s, len)         \
-    if (rtm->rtm_addrs & (w))       \
-    {                               \
-        bcopy((char *)s, cp, len);  \
-        cp += len;                  \
-    }
-
-    bzero(&sins,  sizeof(struct sockaddr_storage));
-    bzero(&sdl_m, sizeof(struct sockaddr_dl));
-    bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
-
-    sock = socket(PF_ROUTE, SOCK_RAW, 0);
-    if (sock < 0)
-    {
-        helplog(ASL_LEVEL_ERR, "mDNSGetRemoteMAC: Can not open the socket - %s", strerror(errno));
-        return errno;
-    }
-
-    rtm->rtm_addrs   |= RTA_DST | RTA_GATEWAY;
-    rtm->rtm_type     = RTM_GET;
-    rtm->rtm_flags    = 0;
-    rtm->rtm_version  = RTM_VERSION;
-    rtm->rtm_seq      = ++seq;
-
-    sdl_m.sdl_len     = sizeof(sdl_m);
-    sdl_m.sdl_family  = AF_LINK;
-    if (family == AF_INET)
-    {
-        sin = (struct sockaddr_in*)&sins;
-        sin->sin_family = AF_INET;
-        sin->sin_len    = sizeof(struct sockaddr_in);
-        memcpy(&sin->sin_addr, raddr, sizeof(struct in_addr));
-        NEXTADDR(RTA_DST, sin, sin->sin_len);
-    }
-    else if (family == AF_INET6)
-    {
-        sin6 = (struct sockaddr_in6 *)&sins;
-        sin6->sin6_len    = sizeof(struct sockaddr_in6);
-        sin6->sin6_family = AF_INET6;
-        memcpy(&sin6->sin6_addr, raddr, sizeof(struct in6_addr));
-        NEXTADDR(RTA_DST, sin6, sin6->sin6_len);
-    }
-    NEXTADDR(RTA_GATEWAY, &sdl_m, sdl_m.sdl_len);
-    rtm->rtm_msglen = rlen = cp - (char *)&m_rtmsg;
-
-    if (write(sock, (char *)&m_rtmsg, rlen) < 0)
-    {
-        helplog(ASL_LEVEL_INFO, "do_mDNSGetRemoteMAC: writing to routing socket: %s", strerror(errno));
-        close(sock);
-        return errno;
-    }
-
-    do
-    {
-        rlen = read(sock, (char *)&m_rtmsg, sizeof(m_rtmsg));
-    }
-    while (rlen > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != getpid()));
-
-    if (rlen < 0)
-        helplog(ASL_LEVEL_ERR, "do_mDNSGetRemoteMAC: Read from routing socket failed");
-
-    if (family == AF_INET)
-    {
-        sin = (struct sockaddr_in *) (rtm + 1);
-        sdl = (struct sockaddr_dl *) (sin->sin_len + (char *) sin);
-    }
-    else if (family == AF_INET6)
-    {
-        sin6 = (struct sockaddr_in6 *) (rtm +1);
-        sdl  = (struct sockaddr_dl  *) (sin6->sin6_len + (char *) sin6);
-    }
-    // If the address is not on the local net, we get the IP address of the gateway.
-    // We would have to repeat the process to get the MAC address of the gateway
-    *gfamily = sdl->sdl_family;
-    if (sdl->sdl_family == AF_INET)
-    {
-        struct sockaddr_in *new_sin = (struct sockaddr_in *)(sin->sin_len +(char*) sin);
-        memcpy(gaddr, &new_sin->sin_addr, sizeof(struct in_addr));
-        close(sock);
-        return -1;
-    }
-    else if (sdl->sdl_family == AF_INET6)
-    {
-        struct sockaddr_in6 *new_sin6 = (struct sockaddr_in6 *)(sin6->sin6_len +(char*) sin6);
-        memcpy(gaddr, &new_sin6->sin6_addr, sizeof(struct in6_addr));
-        close(sock);
-        return -1;
-    }
-
-    unsigned char *ptr = (unsigned char *)LLADDR(sdl);
-    for (i = 0; i < ETHER_ADDR_LEN; i++)
-        (eth)[i] = *(ptr +i);
-
-    close(sock);
-    return KERN_SUCCESS;
-}
-
-kern_return_t do_mDNSGetRemoteMAC(__unused mach_port_t port, int family, v6addr_t raddr, ethaddr_t eth, audit_token_t token)
-{
-    int      ret = 0;
-    v6addr_t gateway;
-    int      gfamily;
-    int      count = 0;
-
-    if (!authorized(&token))
-    {
-        helplog(ASL_LEVEL_ERR, "mDNSGetRemoteMAC: Not authorized");
-        return kmDNSHelperNotAuthorized;
-    }
-
-    do
-    {
-        ret = getMACAddress(family, raddr, gateway, &gfamily, eth);
-        if (ret == -1)
-        {
-            memcpy(raddr, gateway, sizeof(family));
-            family = gfamily;
-            count++;
-        }
-    }
-    while ((ret == -1) && (count < 5));
-    return ret;
-}
-
-
-kern_return_t do_mDNSStoreSPSMACAddress(__unused mach_port_t port, int family, v6addr_t spsaddr, const char *ifname, audit_token_t token)
-{
-    ethaddr_t              eth;
-    char                   spsip[INET6_ADDRSTRLEN];
-    int                    ret        = 0;
-    CFStringRef            sckey      = NULL;
-    SCDynamicStoreRef      store      = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:StoreSPSMACAddress"), NULL, NULL);
-    SCDynamicStoreRef      ipstore    = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetIPv6Addresses"), NULL, NULL);
-    CFMutableDictionaryRef dict       = NULL;
-    CFStringRef            entityname = NULL;
-    CFDictionaryRef        ipdict     = NULL;
-    CFArrayRef             addrs      = NULL;
-
-    if (!authorized(&token))
-    {
-        helplog(ASL_LEVEL_ERR, "mDNSStoreSPSMAC: Not authorized");
-        return kmDNSHelperNotAuthorized;
-    }
-
-    if ((store == NULL) || (ipstore == NULL))
-    {
-        helplog(ASL_LEVEL_ERR, "Unable to access SC Dynamic Store");
-        return KERN_FAILURE;
-    }
-
-    // Get the MAC address of the Sleep Proxy Server
-    memset(eth, 0, sizeof(eth));
-    ret = do_mDNSGetRemoteMAC(port, family, spsaddr, eth, token);
-    if (ret !=  KERN_SUCCESS)
-    {
-        helplog(ASL_LEVEL_ERR, "mDNSStoreSPSMAC: Failed to determine the MAC address");
-        goto fin;
-    }
-
-    // Create/Update the dynamic store entry for the specified interface
-    sckey = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", ifname, "/BonjourSleepProxyAddress");
-    dict  = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-    if (!dict)
-    {
-        helplog(ASL_LEVEL_ERR, "SPSCreateDict: Could not create CFDictionary dict");
-        ret = KERN_FAILURE;
-        goto fin;
-    }
-
-    CFStringRef macaddr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
-    CFDictionarySetValue(dict, CFSTR("MACAddress"), macaddr);
-    if (NULL != macaddr) CFRelease(macaddr);
-
-    if( NULL == inet_ntop(family, (void *)spsaddr, spsip, sizeof(spsip)))
-    {
-         helplog(ASL_LEVEL_ERR, "inet_ntop failed: %s", strerror(errno));
-         ret = kmDNSHelperInvalidNetworkAddress;
-         goto fin;
-    }
-
-    CFStringRef ipaddr = CFStringCreateWithCString(NULL, spsip, kCFStringEncodingUTF8);
-    CFDictionarySetValue(dict, CFSTR("IPAddress"), ipaddr);
-    if (NULL != ipaddr) CFRelease(ipaddr);
-
-    // Get the current IPv6 addresses on this interface and store them so NAs can be sent on wakeup
-    if ((entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/IPv6"), ifname)) != NULL)
-    {
-        if ((ipdict = SCDynamicStoreCopyValue(ipstore, entityname)) != NULL)
-        {
-            if((addrs = CFDictionaryGetValue(ipdict, CFSTR("Addresses"))) != NULL)
-            {
-                addrs = CFRetain(addrs);
-                CFDictionarySetValue(dict, CFSTR("RegisteredAddresses"), addrs);
-            }
-        }
-    }
-    SCDynamicStoreSetValue(store, sckey, dict);
-
-fin:
-    if (store)      CFRelease(store);
-    if (ipstore)    CFRelease(ipstore);
-    if (sckey)      CFRelease(sckey);
-    if (dict)       CFRelease(dict);
-    if (ipdict)     CFRelease(ipdict);
-    if (entityname) CFRelease(entityname);
-    if (addrs)      CFRelease(addrs);
-
-    update_idle_timer();
-    return ret;
-}

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/helper.c (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSMacOSX/helper.c)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/helper.c	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/helper.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,2867 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2007-2012 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 <sys/cdefs.h>
+#include <arpa/inet.h>
+#include <bsm/libbsm.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+#include <netinet6/ipsec.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <asl.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <Security/Security.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPreferencesSetSpecific.h>
+#include <TargetConditionals.h>
+#include <IOKit/pwr_mgt/IOPMLib.h>
+#include <net/bpf.h>
+#include <sys/sysctl.h>
+
+#include "mDNSEmbeddedAPI.h"
+#include "dns_sd.h"
+#include "dnssd_ipc.h"
+#include "libpfkey.h"
+#include "helper.h"
+#include "helpermsgServer.h"
+#include "helper-server.h"
+#include "ipsec_options.h"
+#include "P2PPacketFilter.h"
+
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#ifndef RTF_IFSCOPE
+#define RTF_IFSCOPE 0x1000000
+#endif
+
+#if TARGET_OS_EMBEDDED
+#ifndef MDNS_NO_IPSEC
+#define MDNS_NO_IPSEC 1
+#endif
+#define NO_CFUSERNOTIFICATION 1
+#define NO_SECURITYFRAMEWORK 1
+#endif
+
+// Embed the client stub code here, so we can access private functions like ConnectToServer, create_hdr, deliver_request
+#include "../mDNSShared/dnssd_ipc.c"
+#include "../mDNSShared/dnssd_clientstub.c"
+
+typedef struct sadb_x_policy *ipsec_policy_t;
+
+unsigned short InetChecksum(unsigned short *ptr,int nbytes);
+unsigned long in_cksum(unsigned short *ptr,int nbytes);
+void TCPCheckSum(int af, struct tcphdr *t, int tcplen, v6addr_t sadd6, v6addr_t dadd6);
+
+uid_t mDNSResponderUID;
+gid_t mDNSResponderGID;
+
+void
+debug_(const char *func, const char *fmt, ...)
+{
+    char buf[2048];
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, ap);
+    va_end(ap);
+    helplog(ASL_LEVEL_DEBUG, "%s: %s", func, buf);
+}
+
+static int
+authorized(audit_token_t *token)
+{
+    int ok = 0;
+    pid_t pid = (pid_t)-1;
+    uid_t euid = (uid_t)-1;
+
+    audit_token_to_au32(*token, NULL, &euid, NULL, NULL, NULL, &pid, NULL,
+                        NULL);
+    ok = (euid == mDNSResponderUID || euid == 0);
+    if (!ok)
+        helplog(ASL_LEVEL_NOTICE,
+                "Unauthorized access by euid=%lu pid=%lu",
+                (unsigned long)euid, (unsigned long)pid);
+    return ok;
+}
+
+kern_return_t
+do_mDNSExit(__unused mach_port_t port, audit_token_t token)
+{
+    debug("entry");
+    if (!authorized(&token))
+        goto fin;
+    helplog(ASL_LEVEL_INFO, "exit");
+    exit(0);
+
+fin:
+    debug("fin");
+    return KERN_SUCCESS;
+}
+
+kern_return_t do_mDNSRequestBPF(__unused mach_port_t port, audit_token_t token)
+{
+    if (!authorized(&token)) return KERN_SUCCESS;
+    DNSServiceRef ref;
+    DNSServiceErrorType err = ConnectToServer(&ref, 0, send_bpf, NULL, NULL, NULL);
+    if (err) { helplog(ASL_LEVEL_ERR, "do_mDNSRequestBPF: ConnectToServer %d", err); return err; }
+
+    char *ptr;
+    size_t len = sizeof(DNSServiceFlags);
+    ipc_msg_hdr *hdr = create_hdr(send_bpf, &len, &ptr, 0, ref);
+    if (!hdr) { DNSServiceRefDeallocate(ref); return kDNSServiceErr_NoMemory; }
+    put_flags(0, &ptr);
+    deliver_request(hdr, ref);      // Will free hdr for us
+    DNSServiceRefDeallocate(ref);
+    update_idle_timer();
+    return KERN_SUCCESS;
+}
+
+kern_return_t do_mDNSPowerRequest(__unused mach_port_t port, int key, int interval, int *err, audit_token_t token)
+{
+    *err = -1;
+    if (!authorized(&token)) { *err = kmDNSHelperNotAuthorized; goto fin; }
+
+    CFArrayRef events = IOPMCopyScheduledPowerEvents();
+    if (events)
+    {
+        int i;
+        CFIndex count = CFArrayGetCount(events);
+        for (i=0; i<count; i++)
+        {
+            CFDictionaryRef dict = CFArrayGetValueAtIndex(events, i);
+            CFStringRef id = CFDictionaryGetValue(dict, CFSTR(kIOPMPowerEventAppNameKey));
+            if (CFEqual(id, CFSTR("mDNSResponderHelper")))
+            {
+                CFDateRef EventTime = CFDictionaryGetValue(dict, CFSTR(kIOPMPowerEventTimeKey));
+                CFStringRef EventType = CFDictionaryGetValue(dict, CFSTR(kIOPMPowerEventTypeKey));
+                IOReturn result = IOPMCancelScheduledPowerEvent(EventTime, id, EventType);
+                //helplog(ASL_LEVEL_ERR, "Deleting old event %s");
+                if (result) helplog(ASL_LEVEL_ERR, "IOPMCancelScheduledPowerEvent %d failed %d", i, result);
+            }
+        }
+        CFRelease(events);
+    }
+
+    if (key < 0)            // mDNSPowerRequest(-1,-1) means "clear any stale schedules" (see above)
+        *err = 0;
+    else if (key == 0)      // mDNSPowerRequest(0, 0) means "sleep now"
+    {
+        IOReturn r = IOPMSleepSystem(IOPMFindPowerManagement(MACH_PORT_NULL));
+        if (r) { usleep(100000); helplog(ASL_LEVEL_ERR, "IOPMSleepSystem %d", r); }
+        *err = r;
+    }
+    else if (key > 0)
+    {
+        CFDateRef w = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent() + interval);
+        if (w)
+        {
+            IOReturn r = IOPMSchedulePowerEvent(w, CFSTR("mDNSResponderHelper"), key ? CFSTR(kIOPMAutoWake) : CFSTR(kIOPMAutoSleep));
+            if (r) { usleep(100000); helplog(ASL_LEVEL_ERR, "IOPMSchedulePowerEvent(%d) %d %x", interval, r, r); }
+            *err = r;
+            CFRelease(w);
+        }
+    }
+fin:
+    update_idle_timer();
+    return KERN_SUCCESS;
+}
+
+kern_return_t do_mDNSSetLocalAddressCacheEntry(__unused mach_port_t port, int ifindex, int family, v6addr_t ip, ethaddr_t eth, int *err, audit_token_t token)
+{
+    #define IPv6FMTSTRING "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X"
+    #define IPv6FMTARGS  ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]
+    #if 0
+    if (family == 4)
+        helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry %d IPv%d %d.%d.%d.%d %02X:%02X:%02X:%02X:%02X:%02X",
+                ifindex, family, ip[0], ip[1], ip[2], ip[3], eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
+    else
+        helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry %d IPv%d " IPv6FMTSTRING " %02X:%02X:%02X:%02X:%02X:%02X",
+                ifindex, family, IPv6FMTARGS, eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
+    #endif
+
+    *err = -1;
+    if (!authorized(&token)) { *err = kmDNSHelperNotAuthorized; goto fin; }
+
+    static int s = -1, seq = 0;
+    if (s < 0)
+    {
+        s = socket(PF_ROUTE, SOCK_RAW, 0);
+        if (s < 0) helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: socket(PF_ROUTE, SOCK_RAW, 0) failed %d (%s)", errno, strerror(errno));
+    }
+
+    if (s >= 0)
+    {
+        struct timeval tv;
+        gettimeofday(&tv, 0);
+        if (family == 4)
+        {
+            struct { struct rt_msghdr hdr; struct sockaddr_inarp dst; struct sockaddr_dl sdl; } rtmsg;
+            memset(&rtmsg, 0, sizeof(rtmsg));
+
+            rtmsg.hdr.rtm_msglen         = sizeof(rtmsg);
+            rtmsg.hdr.rtm_version        = RTM_VERSION;
+            rtmsg.hdr.rtm_type           = RTM_ADD;
+            rtmsg.hdr.rtm_index          = ifindex;
+            rtmsg.hdr.rtm_flags          = RTF_HOST | RTF_STATIC | RTF_IFSCOPE;
+            rtmsg.hdr.rtm_addrs          = RTA_DST | RTA_GATEWAY;
+            rtmsg.hdr.rtm_pid            = 0;
+            rtmsg.hdr.rtm_seq            = seq++;
+            rtmsg.hdr.rtm_errno          = 0;
+            rtmsg.hdr.rtm_use            = 0;
+            rtmsg.hdr.rtm_inits          = RTV_EXPIRE;
+            rtmsg.hdr.rtm_rmx.rmx_expire = tv.tv_sec + 30;
+
+            rtmsg.dst.sin_len            = sizeof(rtmsg.dst);
+            rtmsg.dst.sin_family         = AF_INET;
+            rtmsg.dst.sin_port           = 0;
+            rtmsg.dst.sin_addr.s_addr    = *(in_addr_t*)ip;
+            rtmsg.dst.sin_srcaddr.s_addr = 0;
+            rtmsg.dst.sin_tos            = 0;
+            rtmsg.dst.sin_other          = 0;
+
+            rtmsg.sdl.sdl_len            = sizeof(rtmsg.sdl);
+            rtmsg.sdl.sdl_family         = AF_LINK;
+            rtmsg.sdl.sdl_index          = ifindex;
+            rtmsg.sdl.sdl_type           = IFT_ETHER;
+            rtmsg.sdl.sdl_nlen           = 0;
+            rtmsg.sdl.sdl_alen           = ETHER_ADDR_LEN;
+            rtmsg.sdl.sdl_slen           = 0;
+
+            // Target MAC address goes in rtmsg.sdl.sdl_data[0..5]; (See LLADDR() in /usr/include/net/if_dl.h)
+            memcpy(rtmsg.sdl.sdl_data, eth, sizeof(ethaddr_t));
+
+            int len = write(s, (char *)&rtmsg, sizeof(rtmsg));
+            if (len < 0)
+                helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: write(%d) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s)",
+                        sizeof(rtmsg), ifindex, ip[0], ip[1], ip[2], ip[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno));
+            len = read(s, (char *)&rtmsg, sizeof(rtmsg));
+            if (len < 0 || rtmsg.hdr.rtm_errno)
+                helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: read (%d) interface %d address %d.%d.%d.%d seq %d result %d errno %d (%s) %d",
+                        sizeof(rtmsg), ifindex, ip[0], ip[1], ip[2], ip[3], rtmsg.hdr.rtm_seq, len, errno, strerror(errno), rtmsg.hdr.rtm_errno);
+
+            *err = 0;
+        }
+        else
+        {
+            struct { struct rt_msghdr hdr; struct sockaddr_in6 dst; struct sockaddr_dl sdl; } rtmsg;
+            memset(&rtmsg, 0, sizeof(rtmsg));
+
+            rtmsg.hdr.rtm_msglen         = sizeof(rtmsg);
+            rtmsg.hdr.rtm_version        = RTM_VERSION;
+            rtmsg.hdr.rtm_type           = RTM_ADD;
+            rtmsg.hdr.rtm_index          = ifindex;
+            rtmsg.hdr.rtm_flags          = RTF_HOST | RTF_STATIC | RTF_IFSCOPE;
+            rtmsg.hdr.rtm_addrs          = RTA_DST | RTA_GATEWAY;
+            rtmsg.hdr.rtm_pid            = 0;
+            rtmsg.hdr.rtm_seq            = seq++;
+            rtmsg.hdr.rtm_errno          = 0;
+            rtmsg.hdr.rtm_use            = 0;
+            rtmsg.hdr.rtm_inits          = RTV_EXPIRE;
+            rtmsg.hdr.rtm_rmx.rmx_expire = tv.tv_sec + 30;
+
+            rtmsg.dst.sin6_len           = sizeof(rtmsg.dst);
+            rtmsg.dst.sin6_family        = AF_INET6;
+            rtmsg.dst.sin6_port          = 0;
+            rtmsg.dst.sin6_flowinfo      = 0;
+            rtmsg.dst.sin6_addr          = *(struct in6_addr*)ip;
+            rtmsg.dst.sin6_scope_id      = ifindex;
+
+            rtmsg.sdl.sdl_len            = sizeof(rtmsg.sdl);
+            rtmsg.sdl.sdl_family         = AF_LINK;
+            rtmsg.sdl.sdl_index          = ifindex;
+            rtmsg.sdl.sdl_type           = IFT_ETHER;
+            rtmsg.sdl.sdl_nlen           = 0;
+            rtmsg.sdl.sdl_alen           = ETHER_ADDR_LEN;
+            rtmsg.sdl.sdl_slen           = 0;
+
+            // Target MAC address goes in rtmsg.sdl.sdl_data[0..5]; (See LLADDR() in /usr/include/net/if_dl.h)
+            memcpy(rtmsg.sdl.sdl_data, eth, sizeof(ethaddr_t));
+
+            int len = write(s, (char *)&rtmsg, sizeof(rtmsg));
+            if (len < 0)
+                helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: write(%d) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s)",
+                        sizeof(rtmsg), ifindex, IPv6FMTARGS, rtmsg.hdr.rtm_seq, len, errno, strerror(errno));
+            len = read(s, (char *)&rtmsg, sizeof(rtmsg));
+            if (len < 0 || rtmsg.hdr.rtm_errno)
+                helplog(ASL_LEVEL_ERR, "do_mDNSSetLocalAddressCacheEntry: read (%d) interface %d address " IPv6FMTSTRING " seq %d result %d errno %d (%s) %d",
+                        sizeof(rtmsg), ifindex, IPv6FMTARGS, rtmsg.hdr.rtm_seq, len, errno, strerror(errno), rtmsg.hdr.rtm_errno);
+
+            *err = 0;
+        }
+
+    }
+
+fin:
+    update_idle_timer();
+    return KERN_SUCCESS;
+}
+
+kern_return_t do_mDNSNotify(__unused mach_port_t port, const char *title, const char *msg, audit_token_t token)
+{
+    if (!authorized(&token)) return KERN_SUCCESS;
+
+#ifndef NO_CFUSERNOTIFICATION
+    static const char footer[] = "(Note: This message only appears on machines with 17.x.x.x IP addresses — i.e. at Apple — not on customer machines.)";
+    CFStringRef alertHeader  = CFStringCreateWithCString(NULL, title,  kCFStringEncodingUTF8);
+    CFStringRef alertBody    = CFStringCreateWithCString(NULL, msg,    kCFStringEncodingUTF8);
+    CFStringRef alertFooter  = CFStringCreateWithCString(NULL, footer, kCFStringEncodingUTF8);
+    CFStringRef alertMessage = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@\r\r%@"), alertBody, alertFooter);
+    CFRelease(alertBody);
+    CFRelease(alertFooter);
+    int err = CFUserNotificationDisplayNotice(0.0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage, NULL);
+    if (err) helplog(ASL_LEVEL_ERR, "CFUserNotificationDisplayNotice returned %d", err);
+    CFRelease(alertHeader);
+    CFRelease(alertMessage);
+#else
+    (void)title;
+    (void)msg;
+#endif /* NO_CFUSERNOTIFICATION */
+
+    update_idle_timer();
+    return KERN_SUCCESS;
+}
+
+char usercompname[MAX_DOMAIN_LABEL+1] = {0}; // the last computer name the user saw
+char userhostname[MAX_DOMAIN_LABEL+1] = {0}; // the last local host name the user saw
+char lastcompname[MAX_DOMAIN_LABEL+1] = {0}; // the last computer name saved to preferences
+char lasthostname[MAX_DOMAIN_LABEL+1] = {0}; // the last local host name saved to preferences
+
+#ifndef NO_CFUSERNOTIFICATION
+static CFStringRef CFS_OQ = NULL;
+static CFStringRef CFS_CQ = NULL;
+static CFStringRef CFS_Format = NULL;
+static CFStringRef CFS_ComputerName = NULL;
+static CFStringRef CFS_ComputerNameMsg = NULL;
+static CFStringRef CFS_LocalHostName = NULL;
+static CFStringRef CFS_LocalHostNameMsg = NULL;
+static CFStringRef CFS_Problem = NULL;
+
+static CFUserNotificationRef gNotification    = NULL;
+static CFRunLoopSourceRef gNotificationRLS = NULL;
+
+static void NotificationCallBackDismissed(CFUserNotificationRef userNotification, CFOptionFlags responseFlags)
+{
+    debug("entry");
+    (void)responseFlags;    // Unused
+    if (userNotification != gNotification) helplog(ASL_LEVEL_ERR, "NotificationCallBackDismissed: Wrong CFUserNotificationRef");
+    if (gNotificationRLS)
+    {
+        // Caution: don't use CFRunLoopGetCurrent() here, because the currently executing thread may not be our "CFRunLoopRun" thread.
+        // We need to explicitly specify the desired CFRunLoop from which we want to remove this event source.
+        CFRunLoopRemoveSource(gRunLoop, gNotificationRLS, kCFRunLoopDefaultMode);
+        CFRelease(gNotificationRLS);
+        gNotificationRLS = NULL;
+        CFRelease(gNotification);
+        gNotification = NULL;
+    }
+    // By dismissing the alert, the user has conceptually acknowleged the rename.
+    // (e.g. the machine's name is now officially "computer-2.local", not "computer.local".)
+    // If we get *another* conflict, the new alert should refer to the 'old' name
+    // as now being "computer-2.local", not "computer.local"
+    usercompname[0] = 0;
+    userhostname[0] = 0;
+    lastcompname[0] = 0;
+    lasthostname[0] = 0;
+    update_idle_timer();
+    unpause_idle_timer();
+}
+
+static void ShowNameConflictNotification(CFMutableArrayRef header, CFStringRef subtext)
+{
+    CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+    if (!dictionary) return;
+
+    debug("entry");
+
+    CFDictionarySetValue(dictionary, kCFUserNotificationAlertHeaderKey, header);
+    CFDictionarySetValue(dictionary, kCFUserNotificationAlertMessageKey, subtext);
+
+    CFURLRef urlRef = CFURLCreateWithFileSystemPath(NULL, CFSTR("/System/Library/CoreServices/mDNSResponder.bundle"), kCFURLPOSIXPathStyle, true);
+    if (urlRef) { CFDictionarySetValue(dictionary, kCFUserNotificationLocalizationURLKey, urlRef); CFRelease(urlRef); }
+
+    if (gNotification)  // If notification already on-screen, update it in place
+        CFUserNotificationUpdate(gNotification, 0, kCFUserNotificationCautionAlertLevel, dictionary);
+    else                // else, we need to create it
+    {
+        SInt32 error;
+        gNotification = CFUserNotificationCreate(NULL, 0, kCFUserNotificationCautionAlertLevel, &error, dictionary);
+        if (!gNotification || error) { helplog(ASL_LEVEL_ERR, "ShowNameConflictNotification: CFUserNotificationRef: Error %d", error); return; }
+        gNotificationRLS = CFUserNotificationCreateRunLoopSource(NULL, gNotification, NotificationCallBackDismissed, 0);
+        if (!gNotificationRLS) { helplog(ASL_LEVEL_ERR,"ShowNameConflictNotification: RLS"); CFRelease(gNotification); gNotification = NULL; return; }
+        // Caution: don't use CFRunLoopGetCurrent() here, because the currently executing thread may not be our "CFRunLoopRun" thread.
+        // We need to explicitly specify the desired CFRunLoop to which we want to add this event source.
+        CFRunLoopAddSource(gRunLoop, gNotificationRLS, kCFRunLoopDefaultMode);
+        debug("gRunLoop=%p gNotification=%p gNotificationRLS=%p", gRunLoop, gNotification, gNotificationRLS);
+        pause_idle_timer();
+    }
+
+    CFRelease(dictionary);
+}
+
+static CFMutableArrayRef GetHeader(const char* oldname, const char* newname, const CFStringRef msg, const char* suffix)
+{
+    CFMutableArrayRef alertHeader = NULL;
+
+    const CFStringRef cfoldname = CFStringCreateWithCString(NULL, oldname,  kCFStringEncodingUTF8);
+    // NULL newname means we've given up trying to construct a name that doesn't conflict
+    const CFStringRef cfnewname = newname ? CFStringCreateWithCString(NULL, newname,  kCFStringEncodingUTF8) : NULL;
+    // We tag a zero-width non-breaking space at the end of the literal text to guarantee that, no matter what
+    // arbitrary computer name the user may choose, this exact text (with zero-width non-breaking space added)
+    // can never be one that occurs in the Localizable.strings translation file.
+    if (!cfoldname)
+        helplog(ASL_LEVEL_ERR,"Could not construct CFStrings for old=%s", newname);
+    else if (newname && !cfnewname)
+        helplog(ASL_LEVEL_ERR,"Could not construct CFStrings for new=%s", newname);
+    else
+    {
+        const CFStringRef s1 = CFStringCreateWithFormat(NULL, NULL, CFS_Format, cfoldname, suffix);
+        const CFStringRef s2 = cfnewname ? CFStringCreateWithFormat(NULL, NULL, CFS_Format, cfnewname, suffix) : NULL;
+
+        alertHeader = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+        if (!s1)
+            helplog(ASL_LEVEL_ERR, "Could not construct secondary CFString for old=%s", oldname);
+        else if (cfnewname && !s2)
+            helplog(ASL_LEVEL_ERR, "Could not construct secondary CFString for new=%s", newname);
+        else if (!alertHeader)
+            helplog(ASL_LEVEL_ERR, "Could not construct CFArray for notification");
+        else
+        {
+            // Make sure someone is logged in.  We don't want this popping up over the login window
+            uid_t uid;
+            gid_t gid;
+            CFStringRef userName = SCDynamicStoreCopyConsoleUser(NULL, &uid, &gid);
+            if (userName)
+            {
+                CFRelease(userName);
+                CFArrayAppendValue(alertHeader, msg); // Opening phrase of message, provided by caller
+                CFArrayAppendValue(alertHeader, CFS_OQ); CFArrayAppendValue(alertHeader, s1); CFArrayAppendValue(alertHeader, CFS_CQ);
+                CFArrayAppendValue(alertHeader, CFSTR(" is already in use on this network. "));
+                if (s2)
+                {
+                    CFArrayAppendValue(alertHeader, CFSTR("The name has been changed to "));
+                    CFArrayAppendValue(alertHeader, CFS_OQ); CFArrayAppendValue(alertHeader, s2); CFArrayAppendValue(alertHeader, CFS_CQ);
+                    CFArrayAppendValue(alertHeader, CFSTR("."));
+                }
+                else
+                    CFArrayAppendValue(alertHeader, CFSTR("All attempts to find an available name by adding a number to the name were also unsuccessful."));
+            }
+        }
+        if (s1) CFRelease(s1);
+        if (s2) CFRelease(s2);
+    }
+    if (cfoldname) CFRelease(cfoldname);
+    if (cfnewname) CFRelease(cfnewname);
+
+    return alertHeader;
+}
+#endif /* ndef NO_CFUSERNOTIFICATION */
+
+static void update_notification(void)
+{
+#ifndef NO_CFUSERNOTIFICATION
+    debug("entry ucn=%s, uhn=%s, lcn=%s, lhn=%s", usercompname, userhostname, lastcompname, lasthostname);
+    if (!CFS_OQ)
+    {
+        // Note: the "\xEF\xBB\xBF" byte sequence in the CFS_Format string is the UTF-8 encoding of the zero-width non-breaking space character.
+        // By appending this invisible character on the end of literal names, we ensure the these strings cannot inadvertently match any string
+        // in the localization file -- since we know for sure that none of our strings in the localization file contain the ZWNBS character.
+        //
+        // For languages that are written right to left, when we mix English (host names could be in english with brackets etc. and the
+        // rest in Arabic) we need unicode markups for proper formatting. The Unicode sequence 202C (UTF8 E2 80 AC), 200E (UTF8 E2 80 8E) and
+        // 202B (UTF8 E2 80 AB) helps with the formatting. See <rdar://problem/8629082> for more details.
+        CFS_OQ               = CFStringCreateWithCString(NULL, "“\xE2\x80\xAB",  kCFStringEncodingUTF8);
+        CFS_CQ               = CFStringCreateWithCString(NULL, "\xE2\x80\xAC”",  kCFStringEncodingUTF8);
+        CFS_Format           = CFStringCreateWithCString(NULL, "%@%s\xEF\xBB\xBF\xE2\x80\x8E", kCFStringEncodingUTF8);
+        CFS_ComputerName     = CFStringCreateWithCString(NULL, "The name of your computer ",  kCFStringEncodingUTF8);
+        CFS_ComputerNameMsg  = CFStringCreateWithCString(NULL, "To change the name of your computer, "
+                                                         "open System Preferences and click Sharing, then type the name in the Computer Name field.",  kCFStringEncodingUTF8);
+        CFS_LocalHostName    = CFStringCreateWithCString(NULL, "This computer’s local hostname ",  kCFStringEncodingUTF8);
+        CFS_LocalHostNameMsg = CFStringCreateWithCString(NULL, "To change the local hostname, "
+                                                         "open System Preferences and click Sharing, then click “Edit” and type the name in the Local Hostname field.",  kCFStringEncodingUTF8);
+        CFS_Problem          = CFStringCreateWithCString(NULL, "This may indicate a problem with the local network. "
+                                                         "Please inform your network administrator.",  kCFStringEncodingUTF8);
+    }
+
+    if (!usercompname[0] && !userhostname[0])
+    {
+        if (gNotificationRLS)
+        {
+            debug("canceling notification %p", gNotification);
+            CFUserNotificationCancel(gNotification);
+            unpause_idle_timer();
+        }
+    }
+    else
+    {
+        CFMutableArrayRef header = NULL;
+        CFStringRef* subtext = NULL;
+        if (userhostname[0] && !lasthostname[0]) // we've given up trying to construct a name that doesn't conflict
+        {
+            header = GetHeader(userhostname, NULL, CFS_LocalHostName, ".local");
+            subtext = &CFS_Problem;
+        }
+        else if (usercompname[0])
+        {
+            header = GetHeader(usercompname, lastcompname, CFS_ComputerName, "");
+            subtext = &CFS_ComputerNameMsg;
+        }
+        else
+        {
+            header = GetHeader(userhostname, lasthostname, CFS_LocalHostName, ".local");
+            subtext = &CFS_LocalHostNameMsg;
+        }
+        ShowNameConflictNotification(header, *subtext);
+        CFRelease(header);
+    }
+#endif
+}
+
+kern_return_t
+do_mDNSPreferencesSetName(__unused mach_port_t port, int key, const char* old, const char* new, audit_token_t token)
+{
+    SCPreferencesRef session = NULL;
+    Boolean ok = FALSE;
+    Boolean locked = FALSE;
+    CFStringRef cfstr = NULL;
+    char* user = NULL;
+    char* last = NULL;
+    Boolean needUpdate = FALSE;
+
+    debug("entry %s old=%s new=%s", key==kmDNSComputerName ? "ComputerName" : (key==kmDNSLocalHostName ? "LocalHostName" : "UNKNOWN"), old, new);
+    if (!authorized(&token)) goto fin;
+
+    switch ((enum mDNSPreferencesSetNameKey)key)
+    {
+    case kmDNSComputerName:
+        user = usercompname;
+        last = lastcompname;
+        break;
+    case kmDNSLocalHostName:
+        user = userhostname;
+        last = lasthostname;
+        break;
+    default:
+        debug("unrecognized key: %d", key);
+        goto fin;
+    }
+
+    if (!last)
+    {
+        helplog(ASL_LEVEL_ERR, "%s: no last ptr", __func__);
+        goto fin;
+    }
+
+    if (!user)
+    {
+        helplog(ASL_LEVEL_ERR, "%s: no user ptr", __func__);
+        goto fin;
+    }
+
+    if (0 == strncmp(old, new, MAX_DOMAIN_LABEL+1))
+    {
+        // old and new are same means the config changed i.e, the user has set something in the preferences pane.
+        // This means the conflict has been resolved. We need to dismiss the dialogue.
+        if (last[0] && 0 != strncmp(last, new, MAX_DOMAIN_LABEL+1))
+        {
+            last[0] = 0;
+            user[0] = 0;
+            needUpdate = TRUE;
+        }
+        goto fin;
+    }
+    else
+    {
+        // old and new are not same, this means there is a conflict. For the first conflict, we show
+        // the old value and the new value. For all subsequent conflicts, while the dialogue is still
+        // up, we do a real time update of the "new" value in the dialogue. That's why we update just
+        // "last" here and not "user".
+        if (strncmp(last, new, MAX_DOMAIN_LABEL+1))
+        {
+            strncpy(last, new, MAX_DOMAIN_LABEL);
+            needUpdate = TRUE;
+        }
+    }
+
+    // If we are not showing the dialogue, we need to remember the first "old" value so that
+    // we maintain the same through the lifetime of the dialogue. Subsequence conflicts don't
+    // update the "old" value.
+    if (!user[0])
+    {
+        strncpy(user, old, MAX_DOMAIN_LABEL);
+        needUpdate = TRUE;
+    }
+
+    if (!new[0]) // we've given up trying to construct a name that doesn't conflict
+        goto fin;
+
+    cfstr = CFStringCreateWithCString(NULL, new, kCFStringEncodingUTF8);
+
+    session = SCPreferencesCreate(NULL, CFSTR(kmDNSHelperServiceName), NULL);
+
+    if (cfstr == NULL || session == NULL)
+    {
+        debug("SCPreferencesCreate failed");
+        goto fin;
+    }
+    if (!SCPreferencesLock(session, 0))
+    {
+        debug("lock failed");
+        goto fin;
+    }
+    locked = TRUE;
+
+    switch ((enum mDNSPreferencesSetNameKey)key)
+    {
+    case kmDNSComputerName:
+    {
+        // We want to write the new Computer Name to System Preferences, without disturbing the user-selected
+        // system-wide default character set used for things like AppleTalk NBP and NETBIOS service advertising.
+        // Note that this encoding is not used for the computer name, but since both are set by the same call,
+        // we need to take care to set the name without changing the character set.
+        CFStringEncoding encoding = kCFStringEncodingUTF8;
+        CFStringRef unused = SCDynamicStoreCopyComputerName(NULL, &encoding);
+        if (unused) { CFRelease(unused); unused = NULL; }
+        else encoding = kCFStringEncodingUTF8;
+
+        ok = SCPreferencesSetComputerName(session, cfstr, encoding);
+    }
+    break;
+    case kmDNSLocalHostName:
+        ok = SCPreferencesSetLocalHostName(session, cfstr);
+        break;
+    default:
+        break;
+    }
+
+    if (!ok || !SCPreferencesCommitChanges(session) ||
+        !SCPreferencesApplyChanges(session))
+    {
+        debug("SCPreferences update failed");
+        goto fin;
+    }
+    debug("succeeded");
+
+fin:
+    if (NULL != cfstr)
+        CFRelease(cfstr);
+    if (NULL != session)
+    {
+        if (locked)
+            SCPreferencesUnlock(session);
+        CFRelease(session);
+    }
+    update_idle_timer();
+    if (needUpdate) update_notification();
+    return KERN_SUCCESS;
+}
+
+enum DNSKeyFormat
+{
+    formatNotDNSKey, formatDdnsTypeItem, formatDnsPrefixedServiceItem, formatBtmmPrefixedServiceItem
+};
+
+// On Mac OS X on Intel, the four-character string seems to be stored backwards, at least sometimes.
+// I suspect some overenthusiastic inexperienced engineer said, "On Intel everything's backwards,
+// therefore I need to add some byte swapping in this API to make this four-character string backwards too."
+// To cope with this we allow *both* "ddns" and "sndd" as valid item types.
+
+
+#ifndef NO_SECURITYFRAMEWORK
+static const char btmmprefix[] = "btmmdns:";
+static const char dnsprefix[] = "dns:";
+static const char ddns[] = "ddns";
+static const char ddnsrev[] = "sndd";
+
+static enum DNSKeyFormat
+getDNSKeyFormat(SecKeychainItemRef item, SecKeychainAttributeList **attributesp)
+{
+    static UInt32 tags[4] =
+    {
+        kSecTypeItemAttr, kSecServiceItemAttr, kSecAccountItemAttr, kSecLabelItemAttr
+    };
+    static SecKeychainAttributeInfo attributeInfo =
+    {
+        sizeof(tags)/sizeof(tags[0]), tags, NULL
+    };
+    SecKeychainAttributeList *attributes = NULL;
+    enum DNSKeyFormat format;
+    Boolean malformed = FALSE;
+    OSStatus status = noErr;
+    int i = 0;
+
+    *attributesp = NULL;
+    if (noErr != (status = SecKeychainItemCopyAttributesAndData(item,
+                                                                &attributeInfo, NULL, &attributes, NULL, NULL)))
+    {
+        debug("SecKeychainItemCopyAttributesAndData %d - skipping",
+              status);
+        goto skip;
+    }
+    if (attributeInfo.count != attributes->count)
+        malformed = TRUE;
+    for (i = 0; !malformed && i < (int)attributeInfo.count; ++i)
+        if (attributeInfo.tag[i] != attributes->attr[i].tag)
+            malformed = TRUE;
+    if (malformed)
+    {
+        debug(
+            "malformed result from SecKeychainItemCopyAttributesAndData - skipping");
+        goto skip;
+    }
+
+    debug("entry (\"%.*s\", \"%.*s\", \"%.*s\")",
+          (int)attributes->attr[0].length, attributes->attr[0].data,
+          (int)attributes->attr[1].length, attributes->attr[1].data,
+          (int)attributes->attr[2].length, attributes->attr[2].data);
+    if (attributes->attr[1].length >= MAX_ESCAPED_DOMAIN_NAME +
+        sizeof(dnsprefix)-1)
+    {
+        debug("kSecServiceItemAttr too long (%u) - skipping",
+              (unsigned int)attributes->attr[1].length);
+        goto skip;
+    }
+    if (attributes->attr[2].length >= MAX_ESCAPED_DOMAIN_NAME)
+    {
+        debug("kSecAccountItemAttr too long (%u) - skipping",
+              (unsigned int)attributes->attr[2].length);
+        goto skip;
+    }
+    if (attributes->attr[1].length >= sizeof(dnsprefix)-1 &&
+        0 == strncasecmp(attributes->attr[1].data, dnsprefix,
+                         sizeof(dnsprefix)-1))
+        format = formatDnsPrefixedServiceItem;
+    else if (attributes->attr[1].length >= sizeof(btmmprefix)-1 &&
+             0 == strncasecmp(attributes->attr[1].data, btmmprefix, sizeof(btmmprefix)-1))
+        format = formatBtmmPrefixedServiceItem;
+    else if (attributes->attr[0].length == sizeof(ddns)-1 &&
+             0 == strncasecmp(attributes->attr[0].data, ddns, sizeof(ddns)-1))
+        format = formatDdnsTypeItem;
+    else if (attributes->attr[0].length == sizeof(ddnsrev)-1 &&
+             0 == strncasecmp(attributes->attr[0].data, ddnsrev, sizeof(ddnsrev)-1))
+        format = formatDdnsTypeItem;
+    else
+    {
+        debug("uninterested in this entry");
+        goto skip;
+    }
+    *attributesp = attributes;
+    debug("accepting this entry");
+    return format;
+
+skip:
+    SecKeychainItemFreeAttributesAndData(attributes, NULL);
+    return formatNotDNSKey;
+}
+
+// Insert the attributes as defined by mDNSKeyChainAttributes
+static CFPropertyListRef
+getKeychainItemInfo(SecKeychainItemRef item,
+                    SecKeychainAttributeList *attributes, enum DNSKeyFormat format)
+{
+    CFMutableArrayRef entry = NULL;
+    CFDataRef data = NULL;
+    OSStatus status = noErr;
+    UInt32 keylen = 0;
+    void *keyp = 0;
+
+    if (NULL == (entry = CFArrayCreateMutable(NULL, 0,
+                                              &kCFTypeArrayCallBacks)))
+    {
+        debug("CFArrayCreateMutable failed");
+        goto error;
+    }
+
+    // Insert the Account attribute (kmDNSKcWhere)
+    switch ((enum DNSKeyFormat)format)
+    {
+    case formatDdnsTypeItem:
+        data = CFDataCreate(kCFAllocatorDefault,
+                            attributes->attr[1].data, attributes->attr[1].length);
+        break;
+    case formatDnsPrefixedServiceItem:
+    case formatBtmmPrefixedServiceItem:
+        data = CFDataCreate(kCFAllocatorDefault,
+                            attributes->attr[1].data, attributes->attr[1].length);
+        break;
+    default:
+        assert("unknown DNSKeyFormat value");
+        break;
+    }
+    if (NULL == data)
+    {
+        debug("CFDataCreate for attr[1] failed");
+        goto error;
+    }
+    CFArrayAppendValue(entry, data);
+    CFRelease(data);
+
+    // Insert the Where attribute (kmDNSKcAccount)
+    if (NULL == (data = CFDataCreate(kCFAllocatorDefault,
+                                     attributes->attr[2].data, attributes->attr[2].length)))
+    {
+        debug("CFDataCreate for attr[2] failed");
+        goto error;
+    }
+    CFArrayAppendValue(entry, data);
+    CFRelease(data);
+
+    // Insert the Key attribute (kmDNSKcKey)
+    if (noErr != (status = SecKeychainItemCopyAttributesAndData(item, NULL,
+                                                                NULL, NULL, &keylen, &keyp)))
+    {
+        debug("could not retrieve key for \"%.*s\": %d",
+              (int)attributes->attr[1].length, attributes->attr[1].data,
+              status);
+        goto error;
+    }
+    data = CFDataCreate(kCFAllocatorDefault, keyp, keylen);
+    SecKeychainItemFreeAttributesAndData(NULL, keyp);
+    if (NULL == data)
+    {
+        debug("CFDataCreate for keyp failed");
+        goto error;
+    }
+    CFArrayAppendValue(entry, data);
+    CFRelease(data);
+
+    // Insert the Name attribute (kmDNSKcName)
+    if (NULL == (data = CFDataCreate(kCFAllocatorDefault,
+                                     attributes->attr[3].data, attributes->attr[3].length)))
+    {
+        debug("CFDataCreate for attr[3] failed");
+        goto error;
+    }
+    CFArrayAppendValue(entry, data);
+    CFRelease(data);
+    return entry;
+
+error:
+    if (NULL != entry)
+        CFRelease(entry);
+    return NULL;
+}
+#endif
+
+kern_return_t
+do_mDNSKeychainGetSecrets(__unused mach_port_t port, __unused unsigned int *numsecrets,
+                          __unused vm_offset_t *secrets, __unused mach_msg_type_number_t *secretsCnt, __unused int *err,
+                          __unused audit_token_t token)
+{
+#ifndef NO_SECURITYFRAMEWORK
+    CFWriteStreamRef stream = NULL;
+    CFDataRef result = NULL;
+    CFPropertyListRef entry = NULL;
+    CFMutableArrayRef keys = NULL;
+    SecKeychainRef skc = NULL;
+    SecKeychainItemRef item = NULL;
+    SecKeychainSearchRef search = NULL;
+    SecKeychainAttributeList *attributes = NULL;
+    enum DNSKeyFormat format;
+    OSStatus status = 0;
+
+    debug("entry");
+    *err = 0;
+    *numsecrets = 0;
+    *secrets = (vm_offset_t)NULL;
+    if (!authorized(&token))
+    {
+        *err = kmDNSHelperNotAuthorized;
+        goto fin;
+    }
+    if (NULL == (keys = CFArrayCreateMutable(NULL, 0,
+                                             &kCFTypeArrayCallBacks)))
+    {
+        debug("CFArrayCreateMutable failed");
+        *err = kmDNSHelperCreationFailed;
+        goto fin;
+    }
+    if (noErr != (status = SecKeychainCopyDefault(&skc)))
+    {
+        *err = kmDNSHelperKeychainCopyDefaultFailed;
+        goto fin;
+    }
+    if (noErr != (status = SecKeychainSearchCreateFromAttributes(skc, kSecGenericPasswordItemClass, NULL, &search)))
+    {
+        *err = kmDNSHelperKeychainSearchCreationFailed;
+        goto fin;
+    }
+    for (status = SecKeychainSearchCopyNext(search, &item);
+         noErr == status;
+         status = SecKeychainSearchCopyNext(search, &item))
+    {
+        if (formatNotDNSKey != (format = getDNSKeyFormat(item,
+                                                         &attributes)) &&
+            NULL != (entry = getKeychainItemInfo(item, attributes,
+                                                 format)))
+        {
+            CFArrayAppendValue(keys, entry);
+            CFRelease(entry);
+        }
+        SecKeychainItemFreeAttributesAndData(attributes, NULL);
+        CFRelease(item);
+    }
+    if (errSecItemNotFound != status)
+        helplog(ASL_LEVEL_ERR, "%s: SecKeychainSearchCopyNext failed: %d",
+                __func__, status);
+    if (NULL == (stream =
+                     CFWriteStreamCreateWithAllocatedBuffers(kCFAllocatorDefault,
+                                                             kCFAllocatorDefault)))
+    {
+        *err = kmDNSHelperCreationFailed;
+        debug("CFWriteStreamCreateWithAllocatedBuffers failed");
+        goto fin;
+    }
+    CFWriteStreamOpen(stream);
+    if (0 == CFPropertyListWriteToStream(keys, stream,
+                                         kCFPropertyListBinaryFormat_v1_0, NULL))
+    {
+        *err = kmDNSHelperPListWriteFailed;
+        debug("CFPropertyListWriteToStream failed");
+        goto fin;
+    }
+    result = CFWriteStreamCopyProperty(stream,
+                                       kCFStreamPropertyDataWritten);
+    if (KERN_SUCCESS != vm_allocate(mach_task_self(), secrets,
+                                    CFDataGetLength(result), VM_FLAGS_ANYWHERE))
+    {
+        *err = kmDNSHelperCreationFailed;
+        debug("vm_allocate failed");
+        goto fin;
+    }
+    CFDataGetBytes(result, CFRangeMake(0, CFDataGetLength(result)),
+                   (void *)*secrets);
+    *secretsCnt = CFDataGetLength(result);
+    *numsecrets = CFArrayGetCount(keys);
+    debug("succeeded");
+
+fin:
+    debug("returning %u secrets", *numsecrets);
+    if (NULL != stream)
+    {
+        CFWriteStreamClose(stream);
+        CFRelease(stream);
+    }
+    if (NULL != result)
+        CFRelease(result);
+    if (NULL != keys)
+        CFRelease(keys);
+    if (NULL != search)
+        CFRelease(search);
+    if (NULL != skc)
+        CFRelease(skc);
+    update_idle_timer();
+    return KERN_SUCCESS;
+#else
+    return KERN_FAILURE;
+#endif
+}
+
+#ifndef MDNS_NO_IPSEC
+typedef enum _mDNSTunnelPolicyWhich
+{
+    kmDNSTunnelPolicySetup,
+    kmDNSTunnelPolicyTeardown,
+    kmDNSTunnelPolicyGenerate
+} mDNSTunnelPolicyWhich;
+
+// For kmDNSTunnelPolicySetup, you can setup IPv6-in-IPv6 tunnel or IPv6-in-IPv4 tunnel
+// kmDNSNoTunnel is used for other Policy types
+typedef enum _mDNSTunnelType
+{
+    kmDNSNoTunnel,
+    kmDNSIPv6IPv4Tunnel,
+    kmDNSIPv6IPv6Tunnel
+} mDNSTunnelType;
+
+static const uint8_t kWholeV6Mask = 128;
+
+#endif /* ifndef MDNS_NO_IPSEC */
+
+#ifndef MDNS_NO_IPSEC
+
+static const char g_racoon_config_dir[] = "/var/run/racoon/";
+static const char g_racoon_config_dir_old[] = "/etc/racoon/remote/";
+
+CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
+CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey;
+
+// Major version  6 is 10.2.x (Jaguar)
+// Major version  7 is 10.3.x (Panther)
+// Major version  8 is 10.4.x (Tiger)
+// Major version  9 is 10.5.x (Leopard)
+// Major version 10 is 10.6.x (SnowLeopard)
+static int MacOSXSystemBuildNumber(char* letter_out, int* minor_out)
+{
+    int major = 0, minor = 0;
+    char letter = 0, buildver[256]="<Unknown>";
+    CFDictionaryRef vers = _CFCopySystemVersionDictionary();
+    if (vers)
+    {
+        CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey);
+        if (cfbuildver) CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8);
+        sscanf(buildver, "%d%c%d", &major, &letter, &minor);
+        CFRelease(vers);
+    }
+    else
+        helplog(ASL_LEVEL_NOTICE, "_CFCopySystemVersionDictionary failed");
+
+    if (!major) { major=10; letter = 'A'; minor = 190; helplog(ASL_LEVEL_NOTICE, "Note: No Major Build Version number found; assuming 10A190"); }
+    if (letter_out) *letter_out = letter;
+    if (minor_out) *minor_out = minor;
+    return(major);
+}
+
+static int UseOldRacoon()
+{
+    static int g_oldRacoon = -1;
+
+    if (g_oldRacoon == -1)
+    {
+        char letter = 0;
+        int minor = 0;
+        g_oldRacoon = (MacOSXSystemBuildNumber(&letter, &minor) < 10);
+        debug("%s", g_oldRacoon ? "old" : "new");
+    }
+
+    return g_oldRacoon;
+}
+
+static int RacoonSignal()
+{
+    return UseOldRacoon() ? SIGHUP : SIGUSR1;
+}
+
+static const char* GetRacoonConfigDir()
+{
+    return UseOldRacoon() ? g_racoon_config_dir_old : g_racoon_config_dir;
+}
+
+static const char* GetOldRacoonConfigDir()
+{
+    return UseOldRacoon() ? NULL : g_racoon_config_dir_old;
+}
+
+static const char racoon_config_file[] = "anonymous.conf";
+static const char racoon_config_file_orig[] = "anonymous.conf.orig";
+
+static const char configHeader[] = "# BackToMyMac\n";
+
+static int IsFamiliarRacoonConfiguration(const char* racoon_config_path)
+{
+    int fd = open(racoon_config_path, O_RDONLY);
+    debug("entry %s", racoon_config_path);
+    if (0 > fd)
+    {
+        helplog(ASL_LEVEL_NOTICE, "open \"%s\" failed: %s", racoon_config_path, strerror(errno));
+        return 0;
+    }
+    else
+    {
+        char header[sizeof(configHeader)] = {0};
+        ssize_t bytesRead = read(fd, header, sizeof(header)-1);
+        close(fd);
+        if (bytesRead != sizeof(header)-1) return 0;
+        return (0 == memcmp(header, configHeader, sizeof(header)-1));
+    }
+}
+
+static void
+revertAnonymousRacoonConfiguration(const char* dir)
+{
+    if (!dir) return;
+
+    debug("entry %s", dir);
+
+    char racoon_config_path[64];
+    strlcpy(racoon_config_path, dir, sizeof(racoon_config_path));
+    strlcat(racoon_config_path, racoon_config_file, sizeof(racoon_config_path));
+
+    struct stat s;
+    int ret = stat(racoon_config_path, &s);
+    debug("stat(%s): %d errno=%d", racoon_config_path, ret, errno);
+    if (ret == 0)
+    {
+        if (IsFamiliarRacoonConfiguration(racoon_config_path))
+        {
+            helplog(ASL_LEVEL_INFO, "\"%s\" looks familiar, unlinking", racoon_config_path);
+            unlink(racoon_config_path);
+        }
+        else
+        {
+            helplog(ASL_LEVEL_NOTICE, "\"%s\" does not look familiar, leaving in place", racoon_config_path);
+            return;
+        }
+    }
+    else if (errno != ENOENT)
+    {
+        helplog(ASL_LEVEL_NOTICE, "stat failed for \"%s\", leaving in place: %s", racoon_config_path, strerror(errno));
+        return;
+    }
+
+    char racoon_config_path_orig[64];
+    strlcpy(racoon_config_path_orig, dir, sizeof(racoon_config_path_orig));
+    strlcat(racoon_config_path_orig, racoon_config_file_orig, sizeof(racoon_config_path_orig));
+
+    ret = stat(racoon_config_path_orig, &s);
+    debug("stat(%s): %d errno=%d", racoon_config_path_orig, ret, errno);
+    if (ret == 0)
+    {
+        if (0 > rename(racoon_config_path_orig, racoon_config_path))
+            helplog(ASL_LEVEL_NOTICE, "rename \"%s\" \"%s\" failed: %s", racoon_config_path_orig, racoon_config_path, strerror(errno));
+        else
+            debug("reverted \"%s\" to \"%s\"", racoon_config_path_orig, racoon_config_path);
+    }
+    else if (errno != ENOENT)
+    {
+        helplog(ASL_LEVEL_NOTICE, "stat failed for \"%s\", leaving in place: %s", racoon_config_path_orig, strerror(errno));
+        return;
+    }
+}
+
+static void
+moveAsideAnonymousRacoonConfiguration(const char* dir)
+{
+    if (!dir) return;
+
+    debug("entry %s", dir);
+
+    char racoon_config_path[64];
+    strlcpy(racoon_config_path, dir, sizeof(racoon_config_path));
+    strlcat(racoon_config_path, racoon_config_file, sizeof(racoon_config_path));
+
+    struct stat s;
+    int ret = stat(racoon_config_path, &s);
+    if (ret == 0)
+    {
+        if (IsFamiliarRacoonConfiguration(racoon_config_path))
+        {
+            helplog(ASL_LEVEL_INFO, "\"%s\" looks familiar, unlinking", racoon_config_path);
+            unlink(racoon_config_path);
+        }
+        else
+        {
+            char racoon_config_path_orig[64];
+            strlcpy(racoon_config_path_orig, dir, sizeof(racoon_config_path_orig));
+            strlcat(racoon_config_path_orig, racoon_config_file_orig, sizeof(racoon_config_path_orig));
+            if (0 > rename(racoon_config_path, racoon_config_path_orig)) // If we didn't write it, move it to the side so it can be reverted later
+                helplog(ASL_LEVEL_NOTICE, "rename \"%s\" to \"%s\" failed: %s", racoon_config_path, racoon_config_path_orig, strerror(errno));
+            else
+                debug("successfully renamed \"%s\" to \"%s\"", racoon_config_path, racoon_config_path_orig);
+        }
+    }
+    else if (errno != ENOENT)
+    {
+        helplog(ASL_LEVEL_NOTICE, "stat failed for \"%s\", leaving in place: %s", racoon_config_path, strerror(errno));
+        return;
+    }
+}
+
+static int
+ensureExistenceOfRacoonConfigDir(const char* const racoon_config_dir)
+{
+    struct stat s;
+    int ret = stat(racoon_config_dir, &s);
+    if (ret != 0)
+    {
+        if (errno != ENOENT)
+        {
+            helplog(ASL_LEVEL_ERR, "stat of \"%s\" failed (%d): %s",
+                    racoon_config_dir, ret, strerror(errno));
+            return -1;
+        }
+        else
+        {
+            ret = mkdir(racoon_config_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+            if (ret != 0)
+            {
+                helplog(ASL_LEVEL_ERR, "mkdir \"%s\" failed: %s",
+                        racoon_config_dir, strerror(errno));
+                return -1;
+            }
+            else
+                helplog(ASL_LEVEL_INFO, "created directory \"%s\"", racoon_config_dir);
+        }
+    }
+    else if (!(s.st_mode & S_IFDIR))
+    {
+        helplog(ASL_LEVEL_ERR, "\"%s\" is not a directory!",
+                racoon_config_dir);
+        return -1;
+    }
+
+    return 0;
+}
+
+static int
+createAnonymousRacoonConfiguration(const char *fqdn)
+{
+    static const char config1[] =
+        "remote anonymous {\n"
+        "  exchange_mode aggressive;\n"
+        "  doi ipsec_doi;\n"
+        "  situation identity_only;\n"
+        "  verify_identifier off;\n"
+        "  generate_policy on;\n"
+        "  shared_secret keychain_by_id \"";
+    static const char config2[] =
+        "\";\n"
+        "  nonce_size 16;\n"
+        "  lifetime time 15 min;\n"
+        "  initial_contact on;\n"
+        "  support_proxy on;\n"
+        "  nat_traversal force;\n"
+        "  proposal_check claim;\n"
+        "  proposal {\n"
+        "    encryption_algorithm aes;\n"
+        "    hash_algorithm sha256;\n"
+        "    authentication_method pre_shared_key;\n"
+        "    dh_group 2;\n"
+        "    lifetime time 15 min;\n"
+        "  }\n"
+        "  proposal {\n"
+        "    encryption_algorithm aes;\n"
+        "    hash_algorithm sha1;\n"
+        "    authentication_method pre_shared_key;\n"
+        "    dh_group 2;\n"
+        "    lifetime time 15 min;\n"
+        "  }\n"
+        "}\n\n"
+        "sainfo anonymous { \n"
+        "  pfs_group 2;\n"
+        "  lifetime time 10 min;\n"
+        "  encryption_algorithm aes;\n"
+        "  authentication_algorithm hmac_sha256,hmac_sha1;\n"
+        "  compression_algorithm deflate;\n"
+        "}\n";
+    char tmp_config_path[64];
+    char racoon_config_path[64];
+    const char* const racoon_config_dir = GetRacoonConfigDir();
+    const char* const racoon_config_dir_old = GetOldRacoonConfigDir();
+    int fd = -1;
+
+    debug("entry");
+
+    if (0 > ensureExistenceOfRacoonConfigDir(racoon_config_dir))
+        return -1;
+
+    strlcpy(tmp_config_path, racoon_config_dir, sizeof(tmp_config_path));
+    strlcat(tmp_config_path, "tmp.XXXXXX", sizeof(tmp_config_path));
+
+    fd = mkstemp(tmp_config_path);
+
+    if (0 > fd)
+    {
+        helplog(ASL_LEVEL_ERR, "mkstemp \"%s\" failed: %s",
+                tmp_config_path, strerror(errno));
+        return -1;
+    }
+    write(fd, configHeader, sizeof(configHeader)-1);
+    write(fd, config1, sizeof(config1)-1);
+    write(fd, fqdn, strlen(fqdn));
+    write(fd, config2, sizeof(config2)-1);
+    close(fd);
+
+    strlcpy(racoon_config_path, racoon_config_dir, sizeof(racoon_config_path));
+    strlcat(racoon_config_path, racoon_config_file, sizeof(racoon_config_path));
+
+    moveAsideAnonymousRacoonConfiguration(racoon_config_dir_old);
+    moveAsideAnonymousRacoonConfiguration(racoon_config_dir);
+
+    if (0 > rename(tmp_config_path, racoon_config_path))
+    {
+        unlink(tmp_config_path);
+        helplog(ASL_LEVEL_ERR, "rename \"%s\" \"%s\" failed: %s",
+                tmp_config_path, racoon_config_path, strerror(errno));
+        revertAnonymousRacoonConfiguration(racoon_config_dir_old);
+        revertAnonymousRacoonConfiguration(racoon_config_dir);
+        return -1;
+    }
+
+    debug("successfully renamed \"%s\" \"%s\"", tmp_config_path, racoon_config_path);
+    return 0;
+}
+
+static int
+notifyRacoon(void)
+{
+    debug("entry");
+    static const char racoon_pid_path[] = "/var/run/racoon.pid";
+    char buf[] = "18446744073709551615"; /* largest 64-bit integer */
+    char *p = NULL;
+    ssize_t n = 0;
+    unsigned long m = 0;
+    int fd = open(racoon_pid_path, O_RDONLY);
+
+    if (0 > fd)
+    {
+        debug("open \"%s\" failed, and that's OK: %s", racoon_pid_path,
+              strerror(errno));
+        return kmDNSHelperRacoonNotificationFailed;
+    }
+    n = read(fd, buf, sizeof(buf)-1);
+    close(fd);
+    if (1 > n)
+    {
+        debug("read of \"%s\" failed: %s", racoon_pid_path,
+              n == 0 ? "empty file" : strerror(errno));
+        return kmDNSHelperRacoonNotificationFailed;
+    }
+    buf[n] = '\0';
+    m = strtoul(buf, &p, 10);
+    if (*p != '\0' && !isspace(*p))
+    {
+        debug("invalid PID \"%s\" (around '%c')", buf, *p);
+        return kmDNSHelperRacoonNotificationFailed;
+    }
+    if (2 > m)
+    {
+        debug("refusing to kill PID %lu", m);
+        return kmDNSHelperRacoonNotificationFailed;
+    }
+    if (0 != kill(m, RacoonSignal()))
+    {
+        debug("Could not signal racoon (%lu): %s", m, strerror(errno));
+        return kmDNSHelperRacoonNotificationFailed;
+    }
+    debug("Sent racoon (%lu) signal %d", m, RacoonSignal());
+    return 0;
+}
+
+static void
+closefds(int from)
+{
+    int fd = 0;
+    struct dirent entry, *entryp = NULL;
+    DIR *dirp = opendir("/dev/fd");
+
+    if (dirp == NULL)
+    {
+        /* fall back to the erroneous getdtablesize method */
+        for (fd = from; fd < getdtablesize(); ++fd)
+            close(fd);
+        return;
+    }
+    while (0 == readdir_r(dirp, &entry, &entryp) && NULL != entryp)
+    {
+        fd = atoi(entryp->d_name);
+        if (fd >= from && fd != dirfd(dirp))
+            close(fd);
+    }
+    closedir(dirp);
+}
+
+static int
+startRacoonOld(void)
+{
+    debug("entry");
+    char * const racoon_args[] = { "/usr/sbin/racoon", "-e", NULL   };
+    ssize_t n = 0;
+    pid_t pid = 0;
+    int status = 0;
+
+    if (0 == (pid = fork()))
+    {
+        closefds(0);
+        execve(racoon_args[0], racoon_args, NULL);
+        helplog(ASL_LEVEL_ERR, "execve of \"%s\" failed: %s",
+                racoon_args[0], strerror(errno));
+        exit(2);
+    }
+    helplog(ASL_LEVEL_NOTICE, "racoon (pid=%lu) started",
+            (unsigned long)pid);
+    n = waitpid(pid, &status, 0);
+    if (-1 == n)
+    {
+        helplog(ASL_LEVEL_ERR, "Unexpected waitpid failure: %s",
+                strerror(errno));
+        return kmDNSHelperRacoonStartFailed;
+    }
+    else if (pid != n)
+    {
+        helplog(ASL_LEVEL_ERR, "Unexpected waitpid return value %d",
+                (int)n);
+        return kmDNSHelperRacoonStartFailed;
+    }
+    else if (WIFSIGNALED(status))
+    {
+        helplog(ASL_LEVEL_ERR,
+                "racoon (pid=%lu) terminated due to signal %d",
+                (unsigned long)pid, WTERMSIG(status));
+        return kmDNSHelperRacoonStartFailed;
+    }
+    else if (WIFSTOPPED(status))
+    {
+        helplog(ASL_LEVEL_ERR,
+                "racoon (pid=%lu) has stopped due to signal %d",
+                (unsigned long)pid, WSTOPSIG(status));
+        return kmDNSHelperRacoonStartFailed;
+    }
+    else if (0 != WEXITSTATUS(status))
+    {
+        helplog(ASL_LEVEL_ERR,
+                "racoon (pid=%lu) exited with status %d",
+                (unsigned long)pid, WEXITSTATUS(status));
+        return kmDNSHelperRacoonStartFailed;
+    }
+    debug("racoon (pid=%lu) daemonized normally", (unsigned long)pid);
+    return 0;
+}
+
+// constant and structure for the racoon control socket
+#define VPNCTL_CMD_PING 0x0004
+typedef struct vpnctl_hdr_struct
+{
+    u_int16_t msg_type;
+    u_int16_t flags;
+    u_int32_t cookie;
+    u_int32_t reserved;
+    u_int16_t result;
+    u_int16_t len;
+} vpnctl_hdr;
+
+static int
+startRacoon(void)
+{
+    debug("entry");
+    int fd = socket(PF_UNIX, SOCK_STREAM, 0);
+    if (0 > fd)
+    {
+        helplog(ASL_LEVEL_ERR, "Could not create endpoint for racoon control socket: %d %s",
+                errno, strerror(errno));
+        return kmDNSHelperRacoonStartFailed;
+    }
+
+    struct sockaddr_un saddr;
+    memset(&saddr, 0, sizeof(saddr));
+    saddr.sun_family = AF_UNIX;
+    saddr.sun_len = sizeof(saddr);
+    static const char racoon_control_sock_path[] = "/var/run/vpncontrol.sock";
+    strcpy(saddr.sun_path, racoon_control_sock_path);
+    int result = connect(fd, (struct sockaddr*) &saddr, saddr.sun_len);
+    if (0 > result)
+    {
+        helplog(ASL_LEVEL_ERR, "Could not connect racoon control socket %s: %d %s",
+                racoon_control_sock_path, errno, strerror(errno));
+        return kmDNSHelperRacoonStartFailed;
+    }
+
+    u_int32_t btmm_cookie = 0x4d4d5442;
+    vpnctl_hdr h = { htons(VPNCTL_CMD_PING), 0, btmm_cookie, 0, 0, 0 };
+    size_t bytes = 0;
+    ssize_t ret = 0;
+
+    while (bytes < sizeof(vpnctl_hdr))
+    {
+        ret = write(fd, ((unsigned char*)&h)+bytes, sizeof(vpnctl_hdr) - bytes);
+        if (ret == -1)
+        {
+            helplog(ASL_LEVEL_ERR, "Could not write to racoon control socket: %d %s",
+                    errno, strerror(errno));
+            return kmDNSHelperRacoonStartFailed;
+        }
+        bytes += ret;
+    }
+
+    int nfds = fd + 1;
+    fd_set fds;
+    int counter = 0;
+    struct timeval tv;
+    bytes = 0;
+    h.cookie = 0;
+
+    for (counter = 0; counter < 100; counter++)
+    {
+        FD_ZERO(&fds);
+        FD_SET(fd, &fds);
+        tv = (struct timeval){ 0, 10000 }; // 10 milliseconds * 100 iterations = 1 second max wait time
+
+        result = select(nfds, &fds, (fd_set*)NULL, (fd_set*)NULL, &tv);
+        if (result > 0)
+        {
+            if (FD_ISSET(fd, &fds))
+            {
+                ret = read(fd, ((unsigned char*)&h)+bytes, sizeof(vpnctl_hdr) - bytes);
+
+                if (ret == -1)
+                {
+                    helplog(ASL_LEVEL_ERR, "Could not read from racoon control socket: %d %s",
+                            strerror(errno));
+                    break;
+                }
+                bytes += ret;
+                if (bytes >= sizeof(vpnctl_hdr)) break;
+            }
+            else
+            {
+                debug("select returned but fd_isset not on expected fd\n");
+            }
+        }
+        else if (result < 0)
+        {
+            debug("select returned %d errno %d %s\n", result, errno, strerror(errno));
+            if (errno != EINTR) break;
+        }
+    }
+
+    close(fd);
+
+    if (bytes < sizeof(vpnctl_hdr) || h.cookie != btmm_cookie) return kmDNSHelperRacoonStartFailed;
+
+    debug("racoon started");
+    return 0;
+}
+
+static int
+kickRacoon(void)
+{
+    if ( 0 == notifyRacoon() )
+        return 0;
+    return UseOldRacoon() ? startRacoonOld() : startRacoon();
+}
+
+#endif /* ndef MDNS_NO_IPSEC */
+
+int
+do_mDNSConfigureServer(__unused mach_port_t port, int updown, const char *fqdn, audit_token_t token)
+{
+#ifndef MDNS_NO_IPSEC
+    debug("entry");
+    if (!authorized(&token)) goto fin;
+
+    switch ((enum mDNSUpDown)updown)
+    {
+    case kmDNSUp:
+        if (0 != createAnonymousRacoonConfiguration(fqdn)) goto fin;
+        break;
+    case kmDNSDown:
+        revertAnonymousRacoonConfiguration(GetOldRacoonConfigDir());
+        revertAnonymousRacoonConfiguration(GetRacoonConfigDir());
+        break;
+    default:
+        goto fin;
+    }
+
+    if (0 != kickRacoon())
+        goto fin;
+    debug("succeeded");
+
+fin:
+#else
+    (void)port; (void)updown; (void)fqdn; (void)token;
+#endif
+    update_idle_timer();
+    return KERN_SUCCESS;
+}
+
+#ifndef MDNS_NO_IPSEC
+
+static unsigned int routeSeq = 1;
+
+static int
+setupTunnelRoute(v6addr_t local, v6addr_t remote)
+{
+    struct
+    {
+        struct rt_msghdr hdr;
+        struct sockaddr_in6 dst;
+        struct sockaddr_in6 gtwy;
+    } msg;
+    int err = 0;
+    int s = -1;
+
+    if (0 > (s = socket(PF_ROUTE, SOCK_RAW, AF_INET)))
+    {
+        helplog(ASL_LEVEL_ERR, "socket(PF_ROUTE, ...) failed: %s",
+                strerror(errno));
+        err = kmDNSHelperRoutingSocketCreationFailed;
+        goto fin;
+    }
+    memset(&msg, 0, sizeof(msg));
+    msg.hdr.rtm_msglen = sizeof(msg);
+    msg.hdr.rtm_type = RTM_ADD;
+    /* The following flags are set by `route add -inet6 -host ...` */
+    msg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_HOST | RTF_STATIC;
+    msg.hdr.rtm_version = RTM_VERSION;
+    msg.hdr.rtm_seq = routeSeq++;
+    msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
+    msg.hdr.rtm_inits = RTV_MTU;
+    msg.hdr.rtm_rmx.rmx_mtu = 1280;
+
+    msg.dst.sin6_len = sizeof(msg.dst);
+    msg.dst.sin6_family = AF_INET6;
+    memcpy(&msg.dst.sin6_addr, remote, sizeof(msg.dst.sin6_addr));
+
+    msg.gtwy.sin6_len = sizeof(msg.gtwy);
+    msg.gtwy.sin6_family = AF_INET6;
+    memcpy(&msg.gtwy.sin6_addr, local, sizeof(msg.gtwy.sin6_addr));
+
+    /* send message, ignore error when route already exists */
+    if (0 > write(s, &msg, msg.hdr.rtm_msglen))
+    {
+        int errno_ = errno;
+
+        debug("write to routing socket failed: %s", strerror(errno_));
+        if (EEXIST != errno_)
+        {
+            err = kmDNSHelperRouteAdditionFailed;
+            goto fin;
+        }
+    }
+
+fin:
+    if (0 <= s)
+        close(s);
+    return err;
+}
+
+static int
+teardownTunnelRoute(v6addr_t remote)
+{
+    struct
+    {
+        struct rt_msghdr hdr;
+        struct sockaddr_in6 dst;
+    } msg;
+    int err = 0;
+    int s = -1;
+
+    if (0 > (s = socket(PF_ROUTE, SOCK_RAW, AF_INET)))
+    {
+        helplog(ASL_LEVEL_ERR, "socket(PF_ROUTE, ...) failed: %s",
+                strerror(errno));
+        err = kmDNSHelperRoutingSocketCreationFailed;
+        goto fin;
+    }
+    memset(&msg, 0, sizeof(msg));
+
+    msg.hdr.rtm_msglen = sizeof(msg);
+    msg.hdr.rtm_type = RTM_DELETE;
+    msg.hdr.rtm_version = RTM_VERSION;
+    msg.hdr.rtm_seq = routeSeq++;
+    msg.hdr.rtm_addrs = RTA_DST;
+
+    msg.dst.sin6_len = sizeof(msg.dst);
+    msg.dst.sin6_family = AF_INET6;
+    memcpy(&msg.dst.sin6_addr, remote, sizeof(msg.dst.sin6_addr));
+    if (0 > write(s, &msg, msg.hdr.rtm_msglen))
+    {
+        int errno_ = errno;
+
+        debug("write to routing socket failed: %s", strerror(errno_));
+        if (ESRCH != errno_)
+        {
+            err = kmDNSHelperRouteDeletionFailed;
+            goto fin;
+        }
+    }
+
+fin:
+    if (0 <= s)
+        close(s);
+    return err;
+}
+
+static int
+v4addr_to_string(v4addr_t addr, char *buf, size_t buflen)
+{
+    if (NULL == inet_ntop(AF_INET, addr, buf, buflen))
+    {
+        helplog(ASL_LEVEL_ERR, "inet_ntop failed: %s",
+                strerror(errno));
+        return kmDNSHelperInvalidNetworkAddress;
+    }
+    else
+        return 0;
+}
+
+static int
+v6addr_to_string(v6addr_t addr, char *buf, size_t buflen)
+{
+    if (NULL == inet_ntop(AF_INET6, addr, buf, buflen))
+    {
+        helplog(ASL_LEVEL_ERR, "inet_ntop failed: %s",
+                strerror(errno));
+        return kmDNSHelperInvalidNetworkAddress;
+    }
+    else
+        return 0;
+}
+
+/* Caller owns object returned in `policy' */
+static int
+generateTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type, int in,
+                     v4addr_t src, uint16_t src_port,
+                     v4addr_t dst, uint16_t dst_port,
+                     v6addr_t src6, v6addr_t dst6,
+                     ipsec_policy_t *policy, size_t *len)
+{
+    char srcs[INET_ADDRSTRLEN], dsts[INET_ADDRSTRLEN];
+    char srcs6[INET6_ADDRSTRLEN], dsts6[INET6_ADDRSTRLEN];
+    char buf[512];
+    char *inOut = in ? "in" : "out";
+    ssize_t n = 0;
+    int err = 0;
+
+    *policy = NULL;
+    *len = 0;
+
+    switch (which)
+    {
+    case kmDNSTunnelPolicySetup:
+        if (type == kmDNSIPv6IPv4Tunnel)
+        {
+            if (0 != (err = v4addr_to_string(src, srcs, sizeof(srcs))))
+                goto fin;
+            if (0 != (err = v4addr_to_string(dst, dsts, sizeof(dsts))))
+                goto fin;
+            n = snprintf(buf, sizeof(buf),
+                         "%s ipsec esp/tunnel/%s[%u]-%s[%u]/require",
+                         inOut, srcs, src_port, dsts, dst_port);
+        }
+        else if (type == kmDNSIPv6IPv6Tunnel)
+        {
+            if (0 != (err = v6addr_to_string(src6, srcs6, sizeof(srcs6))))
+                goto fin;
+            if (0 != (err = v6addr_to_string(dst6, dsts6, sizeof(dsts6))))
+                goto fin;
+            n = snprintf(buf, sizeof(buf),
+                         "%s ipsec esp/tunnel/%s-%s/require",
+                         inOut, srcs6, dsts6);
+        }
+        break;
+    case kmDNSTunnelPolicyTeardown:
+        n = strlcpy(buf, inOut, sizeof(buf));
+        break;
+    case kmDNSTunnelPolicyGenerate:
+        n = snprintf(buf, sizeof(buf), "%s generate", inOut);
+        break;
+    default:
+        err = kmDNSHelperIPsecPolicyCreationFailed;
+        goto fin;
+    }
+
+    if (n >= (int)sizeof(buf))
+    {
+        err = kmDNSHelperResultTooLarge;
+        goto fin;
+    }
+
+    debug("policy=\"%s\"", buf);
+    if (NULL == (*policy = (ipsec_policy_t)ipsec_set_policy(buf, n)))
+    {
+        helplog(ASL_LEVEL_ERR,
+                "Could not create IPsec policy from \"%s\"", buf);
+        err = kmDNSHelperIPsecPolicyCreationFailed;
+        goto fin;
+    }
+    *len = ((ipsec_policy_t)(*policy))->sadb_x_policy_len * 8;
+
+fin:
+    return err;
+}
+
+static int
+sendPolicy(int s, int setup,
+           struct sockaddr *src, uint8_t src_bits,
+           struct sockaddr *dst, uint8_t dst_bits,
+           ipsec_policy_t policy, size_t len)
+{
+    static unsigned int policySeq = 0;
+    int err = 0;
+
+    debug("entry, setup=%d", setup);
+    if (setup)
+        err = pfkey_send_spdadd(s, src, src_bits, dst, dst_bits, -1,
+                                (char *)policy, len, policySeq++);
+    else
+        err = pfkey_send_spddelete(s, src, src_bits, dst, dst_bits, -1,
+                                   (char *)policy, len, policySeq++);
+    if (0 > err)
+    {
+        helplog(ASL_LEVEL_ERR, "Could not set IPsec policy: %s",
+                ipsec_strerror());
+        err = kmDNSHelperIPsecPolicySetFailed;
+        goto fin;
+    }
+    else
+        err = 0;
+    debug("succeeded");
+
+fin:
+    return err;
+}
+
+static int
+removeSA(int s, struct sockaddr *src, struct sockaddr *dst)
+{
+    int err = 0;
+
+    debug("entry");
+    err = pfkey_send_delete_all(s, SADB_SATYPE_ESP, IPSEC_MODE_ANY, src, dst);
+    if (0 > err)
+    {
+        helplog(ASL_LEVEL_ERR, "Could not remove IPsec SA: %s", ipsec_strerror());
+        err = kmDNSHelperIPsecRemoveSAFailed;
+        goto fin;
+    }
+    err = pfkey_send_delete_all(s, SADB_SATYPE_ESP, IPSEC_MODE_ANY, dst, src);
+    if (0 > err)
+    {
+        helplog(ASL_LEVEL_ERR, "Could not remove IPsec SA: %s", ipsec_strerror());
+        err = kmDNSHelperIPsecRemoveSAFailed;
+        goto fin;
+    }
+    else
+        err = 0;
+
+    debug("succeeded");
+
+fin:
+    return err;
+}
+
+static int
+doTunnelPolicy(mDNSTunnelPolicyWhich which, mDNSTunnelType type,
+               v6addr_t loc_inner, uint8_t loc_bits,
+               v4addr_t loc_outer, uint16_t loc_port,
+               v6addr_t rmt_inner, uint8_t rmt_bits,
+               v4addr_t rmt_outer, uint16_t rmt_port,
+               v6addr_t loc_outer6, v6addr_t rmt_outer6)
+{
+    struct sockaddr_in6 sin6_loc;
+    struct sockaddr_in6 sin6_rmt;
+    ipsec_policy_t policy = NULL;
+    size_t len = 0;
+    int s = -1;
+    int err = 0;
+
+    debug("entry");
+    if (0 > (s = pfkey_open()))
+    {
+        helplog(ASL_LEVEL_ERR,
+                "Could not create IPsec policy socket: %s",
+                ipsec_strerror());
+        err = kmDNSHelperIPsecPolicySocketCreationFailed;
+        goto fin;
+    }
+
+    memset(&sin6_loc, 0, sizeof(sin6_loc));
+    sin6_loc.sin6_len = sizeof(sin6_loc);
+    sin6_loc.sin6_family = AF_INET6;
+    sin6_loc.sin6_port = htons(0);
+    memcpy(&sin6_loc.sin6_addr, loc_inner, sizeof(sin6_loc.sin6_addr));
+
+    memset(&sin6_rmt, 0, sizeof(sin6_rmt));
+    sin6_rmt.sin6_len = sizeof(sin6_rmt);
+    sin6_rmt.sin6_family = AF_INET6;
+    sin6_rmt.sin6_port = htons(0);
+    memcpy(&sin6_rmt.sin6_addr, rmt_inner, sizeof(sin6_rmt.sin6_addr));
+
+    int setup = which != kmDNSTunnelPolicyTeardown;
+
+    if (0 != (err = generateTunnelPolicy(which, type, 1,
+                                         rmt_outer, rmt_port,
+                                         loc_outer, loc_port,
+                                         rmt_outer6, loc_outer6,
+                                         &policy, &len)))
+        goto fin;
+    if (0 != (err = sendPolicy(s, setup,
+                               (struct sockaddr *)&sin6_rmt, rmt_bits,
+                               (struct sockaddr *)&sin6_loc, loc_bits,
+                               policy, len)))
+        goto fin;
+    if (NULL != policy)
+    {
+        free(policy);
+        policy = NULL;
+    }
+    if (0 != (err = generateTunnelPolicy(which, type, 0,
+                                         loc_outer, loc_port,
+                                         rmt_outer, rmt_port,
+                                         loc_outer6, rmt_outer6,
+                                         &policy, &len)))
+        goto fin;
+    if (0 != (err = sendPolicy(s, setup,
+                               (struct sockaddr *)&sin6_loc, loc_bits,
+                               (struct sockaddr *)&sin6_rmt, rmt_bits,
+                               policy, len)))
+        goto fin;
+
+    if (which == kmDNSTunnelPolicyTeardown)
+    {
+        if (rmt_port)       // Outer tunnel is IPv4
+        {
+            if (loc_outer && rmt_outer)
+            {
+                struct sockaddr_in sin_loc;
+                struct sockaddr_in sin_rmt;
+                memset(&sin_loc, 0, sizeof(sin_loc));
+                sin_loc.sin_len = sizeof(sin_loc);
+                sin_loc.sin_family = AF_INET;
+                memcpy(&sin_loc.sin_addr, loc_outer, sizeof(sin_loc.sin_addr));
+
+                memset(&sin_rmt, 0, sizeof(sin_rmt));
+                sin_rmt.sin_len = sizeof(sin_rmt);
+                sin_rmt.sin_family = AF_INET;
+                memcpy(&sin_rmt.sin_addr, rmt_outer, sizeof(sin_rmt.sin_addr));
+                if (0 != (err = removeSA(s, (struct sockaddr *)&sin_loc, (struct sockaddr *)&sin_rmt)))
+                    goto fin;
+            }
+        }
+        else
+        {
+            if (loc_outer6 && rmt_outer6)
+            {
+                struct sockaddr_in6 sin6_lo;
+                struct sockaddr_in6 sin6_rm;
+
+                memset(&sin6_lo, 0, sizeof(sin6_lo));
+                sin6_lo.sin6_len = sizeof(sin6_lo);
+                sin6_lo.sin6_family = AF_INET6;
+                memcpy(&sin6_lo.sin6_addr, loc_outer6, sizeof(sin6_lo.sin6_addr));
+
+                memset(&sin6_rm, 0, sizeof(sin6_rm));
+                sin6_rm.sin6_len = sizeof(sin6_rm);
+                sin6_rm.sin6_family = AF_INET6;
+                memcpy(&sin6_rm.sin6_addr, rmt_outer6, sizeof(sin6_rm.sin6_addr));
+                if (0 != (err = removeSA(s, (struct sockaddr *)&sin6_lo, (struct sockaddr *)&sin6_rm)))
+                    goto fin;
+            }
+        }
+    }
+
+
+    debug("succeeded");
+
+fin:
+    if (s >= 0)
+        pfkey_close(s);
+    if (NULL != policy)
+        free(policy);
+    return err;
+}
+
+#endif /* ndef MDNS_NO_IPSEC */
+
+int
+do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
+                         v6addr_t loc_inner, v6addr_t loc_outer6, uint16_t loc_port,
+                         v6addr_t rmt_inner, v6addr_t rmt_outer6, uint16_t rmt_port,
+                         const char *id, int *err, audit_token_t token)
+{
+#ifndef MDNS_NO_IPSEC
+    static const char config[] =
+        "%s"
+        "remote %s [%u] {\n"
+        "  disconnect_on_idle idle_timeout 600 idle_direction idle_outbound;\n"
+        "  exchange_mode aggressive;\n"
+        "  doi ipsec_doi;\n"
+        "  situation identity_only;\n"
+        "  verify_identifier off;\n"
+        "  generate_policy on;\n"
+        "  my_identifier user_fqdn \"%s\";\n"
+        "  shared_secret keychain \"%s\";\n"
+        "  nonce_size 16;\n"
+        "  lifetime time 15 min;\n"
+        "  initial_contact on;\n"
+        "  support_proxy on;\n"
+        "  nat_traversal force;\n"
+        "  proposal_check claim;\n"
+        "  proposal {\n"
+        "    encryption_algorithm aes;\n"
+        "    hash_algorithm sha256;\n"
+        "    authentication_method pre_shared_key;\n"
+        "    dh_group 2;\n"
+        "    lifetime time 15 min;\n"
+        "  }\n"
+        "  proposal {\n"
+        "    encryption_algorithm aes;\n"
+        "    hash_algorithm sha1;\n"
+        "    authentication_method pre_shared_key;\n"
+        "    dh_group 2;\n"
+        "    lifetime time 15 min;\n"
+        "  }\n"
+        "}\n\n"
+        "sainfo address %s any address %s any {\n"
+        "  pfs_group 2;\n"
+        "  lifetime time 10 min;\n"
+        "  encryption_algorithm aes;\n"
+        "  authentication_algorithm hmac_sha256,hmac_sha1;\n"
+        "  compression_algorithm deflate;\n"
+        "}\n\n"
+        "sainfo address %s any address %s any {\n"
+        "  pfs_group 2;\n"
+        "  lifetime time 10 min;\n"
+        "  encryption_algorithm aes;\n"
+        "  authentication_algorithm hmac_sha256,hmac_sha1;\n"
+        "  compression_algorithm deflate;\n"
+        "}\n";
+    char path[PATH_MAX] = "";
+    char li[INET6_ADDRSTRLEN], lo[INET_ADDRSTRLEN], lo6[INET6_ADDRSTRLEN],
+         ri[INET6_ADDRSTRLEN], ro[INET_ADDRSTRLEN], ro6[INET6_ADDRSTRLEN];
+    FILE *fp = NULL;
+    int fd = -1;
+    char tmp_path[PATH_MAX] = "";
+    v4addr_t loc_outer, rmt_outer;
+
+    debug("entry");
+    *err = 0;
+    if (!authorized(&token))
+    {
+        *err = kmDNSHelperNotAuthorized;
+        goto fin;
+    }
+    switch ((enum mDNSAutoTunnelSetKeysReplaceDelete)replacedelete)
+    {
+    case kmDNSAutoTunnelSetKeysReplace:
+    case kmDNSAutoTunnelSetKeysDelete:
+        break;
+    default:
+        *err = kmDNSHelperInvalidTunnelSetKeysOperation;
+        goto fin;
+    }
+
+    if (0 != (*err = v6addr_to_string(loc_inner, li, sizeof(li))))
+        goto fin;
+    if (0 != (*err = v6addr_to_string(rmt_inner, ri, sizeof(ri))))
+        goto fin;
+
+    debug("loc_inner=%s rmt_inner=%s", li, ri);
+    if (!rmt_port)
+    {
+        loc_outer[0] = loc_outer[1] = loc_outer[2] = loc_outer[3] = 0;
+        rmt_outer[0] = rmt_outer[1] = rmt_outer[2] = rmt_outer[3] = 0;
+
+        if (0 != (*err = v6addr_to_string(loc_outer6, lo6, sizeof(lo6))))
+            goto fin;
+        if (0 != (*err = v6addr_to_string(rmt_outer6, ro6, sizeof(ro6))))
+            goto fin;
+        debug("IPv6 outer tunnel: loc_outer6=%s rmt_outer6=%s", lo6, ro6);
+        if ((int)sizeof(path) <= snprintf(path, sizeof(path),
+                                          "%s%s.conf", GetRacoonConfigDir(), ro6))
+        {
+            *err = kmDNSHelperResultTooLarge;
+            goto fin;
+        }
+    }
+    else
+    {
+        loc_outer[0] = loc_outer6[0];
+        loc_outer[1] = loc_outer6[1];
+        loc_outer[2] = loc_outer6[2];
+        loc_outer[3] = loc_outer6[3];
+
+        rmt_outer[0] = rmt_outer6[0];
+        rmt_outer[1] = rmt_outer6[1];
+        rmt_outer[2] = rmt_outer6[2];
+        rmt_outer[3] = rmt_outer6[3];
+
+        if (0 != (*err = v4addr_to_string(loc_outer, lo, sizeof(lo))))
+            goto fin;
+        if (0 != (*err = v4addr_to_string(rmt_outer, ro, sizeof(ro))))
+            goto fin;
+        debug("IPv4 outer tunnel: loc_outer=%s loc_port=%u rmt_outer=%s rmt_port=%u",
+              lo, loc_port, ro, rmt_port);
+
+        if ((int)sizeof(path) <= snprintf(path, sizeof(path),
+                                          "%s%s.%u.conf", GetRacoonConfigDir(), ro,
+                                          rmt_port))
+        {
+            *err = kmDNSHelperResultTooLarge;
+            goto fin;
+        }
+    }
+
+
+
+    if (kmDNSAutoTunnelSetKeysReplace == replacedelete)
+    {
+        if (0 > ensureExistenceOfRacoonConfigDir(GetRacoonConfigDir()))
+        {
+            *err = kmDNSHelperRacoonConfigCreationFailed;
+            goto fin;
+        }
+        if ((int)sizeof(tmp_path) <=
+            snprintf(tmp_path, sizeof(tmp_path), "%s.XXXXXX", path))
+        {
+            *err = kmDNSHelperResultTooLarge;
+            goto fin;
+        }
+        if (0 > (fd = mkstemp(tmp_path)))
+        {
+            helplog(ASL_LEVEL_ERR, "mkstemp \"%s\" failed: %s",
+                    tmp_path, strerror(errno));
+            *err = kmDNSHelperRacoonConfigCreationFailed;
+            goto fin;
+        }
+        if (NULL == (fp = fdopen(fd, "w")))
+        {
+            helplog(ASL_LEVEL_ERR, "fdopen: %s",
+                    strerror(errno));
+            *err = kmDNSHelperRacoonConfigCreationFailed;
+            goto fin;
+        }
+        fd = -1;
+        fprintf(fp, config, configHeader, (!rmt_port ? ro6 : ro), rmt_port, id, id, ri, li, li, ri);
+        fclose(fp);
+        fp = NULL;
+        if (0 > rename(tmp_path, path))
+        {
+            helplog(ASL_LEVEL_ERR,
+                    "rename \"%s\" \"%s\" failed: %s",
+                    tmp_path, path, strerror(errno));
+            *err = kmDNSHelperRacoonConfigCreationFailed;
+            goto fin;
+        }
+    }
+    else
+    {
+        if (0 != unlink(path))
+            debug("unlink \"%s\" failed: %s", path,
+                  strerror(errno));
+    }
+
+    if (0 != (*err = doTunnelPolicy(kmDNSTunnelPolicyTeardown, kmDNSNoTunnel,
+                                    loc_inner, kWholeV6Mask, loc_outer, loc_port,
+                                    rmt_inner, kWholeV6Mask, rmt_outer, rmt_port, loc_outer6, rmt_outer6)))
+        goto fin;
+    if (kmDNSAutoTunnelSetKeysReplace == replacedelete &&
+        0 != (*err = doTunnelPolicy(kmDNSTunnelPolicySetup, (!rmt_port ? kmDNSIPv6IPv6Tunnel : kmDNSIPv6IPv4Tunnel),
+                                    loc_inner, kWholeV6Mask, loc_outer, loc_port,
+                                    rmt_inner, kWholeV6Mask, rmt_outer, rmt_port, loc_outer6, rmt_outer6)))
+        goto fin;
+
+    if (0 != (*err = teardownTunnelRoute(rmt_inner)))
+        goto fin;
+    if (kmDNSAutoTunnelSetKeysReplace == replacedelete &&
+        0 != (*err = setupTunnelRoute(loc_inner, rmt_inner)))
+        goto fin;
+
+    if (kmDNSAutoTunnelSetKeysReplace == replacedelete &&
+        0 != (*err = kickRacoon()))
+        goto fin;
+
+    debug("succeeded");
+
+fin:
+    if (NULL != fp)
+        fclose(fp);
+    if (0 <= fd)
+        close(fd);
+    unlink(tmp_path);
+#else
+    (void)replacedelete; (void)loc_inner; (void)loc_outer6; (void)loc_port; (void)rmt_inner;
+    (void)rmt_outer6; (void)rmt_port; (void)id; (void)token;
+
+    *err = kmDNSHelperIPsecDisabled;
+#endif /* MDNS_NO_IPSEC */
+    update_idle_timer();
+    return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mDNSSendWakeupPacket(__unused mach_port_t port, unsigned ifid, const char *eth_addr, const char *ip_addr, int iteration, audit_token_t token)
+{
+    int bpf_fd, i, j;
+    struct ifreq ifr;
+    char ifname[IFNAMSIZ];
+    char packet[512];
+    char *ptr = packet;
+    char bpf_device[12];
+    struct ether_addr *ea;
+    (void) ip_addr; // unused
+    (void) iteration; // unused
+    (void) token; // unused
+
+    if (if_indextoname(ifid, ifname) == NULL)
+    {
+        helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket invalid interface index %u", ifid);
+        return errno;
+    }
+
+    ea = ether_aton(eth_addr);
+    if (ea == NULL)
+    {
+        helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket invalid ethernet address %s", eth_addr);
+        return errno;
+    }
+
+    for (i = 0; i < 100; i++)
+    {
+        snprintf(bpf_device, sizeof(bpf_device), "/dev/bpf%d", i);
+        bpf_fd = open(bpf_device, O_RDWR, 0);
+        if (bpf_fd == -1)
+            continue;
+        else break;
+    }
+
+    if (bpf_fd == -1)
+    {
+        helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket cannot find a bpf device");
+        return ENXIO;
+    }
+
+    memset(&ifr, 0, sizeof(ifr));
+    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+    if (ioctl(bpf_fd, BIOCSETIF, (char *)&ifr) < 0)
+    {
+        helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket BIOCSETIF failed %s", strerror(errno));
+        return errno;
+    }
+
+    // 0x00 Destination address
+    for (i=0; i<6; i++) *ptr++ = ea->octet[i];
+
+    // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
+    for (i=0; i<6; i++) *ptr++ = 0;
+
+    // 0x0C Ethertype (0x0842)
+    *ptr++ = 0x08;
+    *ptr++ = 0x42;
+
+    // 0x0E Wakeup sync sequence
+    for (i=0; i<6; i++) *ptr++ = 0xFF;
+
+    // 0x14 Wakeup data
+    for (j=0; j<16; j++) for (i=0; i<6; i++) *ptr++ = ea->octet[i];
+
+    // 0x74 Password
+    for (i=0; i<6; i++) *ptr++ = 0;
+
+    if (write(bpf_fd, packet, ptr - packet) < 0)
+    {
+        helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket write failed %s", strerror(errno));
+        return errno;
+    }
+    helplog(ASL_LEVEL_INFO, "do_mDNSSendWakeupPacket sent unicast eth_addr %s, ip_addr %s", eth_addr, ip_addr);
+    // Send a broadcast one to handle ethernet switches that don't flood forward packets with
+    // unknown mac addresses.
+    for (i=0; i<6; i++) packet[i] = 0xFF;
+    if (write(bpf_fd, packet, ptr - packet) < 0)
+    {
+        helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket write failed %s", strerror(errno));
+        return errno;
+    }
+    helplog(ASL_LEVEL_INFO, "do_mDNSSendWakeupPacket sent broadcast eth_addr %s, ip_addr %s", eth_addr, ip_addr);
+    close(bpf_fd);
+    return KERN_SUCCESS;
+}
+
+// Open the specified port for protocol in the P2P firewall.
+kern_return_t
+do_mDNSPacketFilterControl(__unused mach_port_t port, uint32_t command, const char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray, audit_token_t token)
+{
+    (void) token; // unused
+    int error;
+    kern_return_t result = KERN_SUCCESS;
+
+    helplog(ASL_LEVEL_INFO, "do_mDNSPacketFilterControl: command %d ifname %s, count %d",
+            command, ifname, count);
+
+    switch (command)
+    {
+    case PF_SET_RULES:
+        error = P2PPacketFilterAddBonjourRuleSet(ifname, count, portArray, protocolArray);
+        if (error)
+        {
+            helplog(ASL_LEVEL_ERR, "P2PPacketFilterAddBonjourRuleSet failed %s", strerror(error));
+            result = KERN_FAILURE;
+        }
+        break;
+
+    case PF_CLEAR_RULES:
+        error = P2PPacketFilterClearBonjourRules();
+        if (error)
+        {
+            helplog(ASL_LEVEL_ERR, "P2PPacketFilterClearBonjourRules failed %s", strerror(error));
+            result = KERN_FAILURE;
+        }
+        break;
+
+    default:
+        helplog(ASL_LEVEL_ERR, "do_mDNSPacketFilterControl: invalid command %d", command);
+        result = KERN_INVALID_ARGUMENT;
+        break;
+    }
+
+    return result;
+}
+
+unsigned long
+in_cksum(unsigned short *ptr,int nbytes)
+{
+    unsigned long sum;
+    u_short oddbyte;
+
+    /*
+     * Our algorithm is simple, using a 32-bit accumulator (sum),
+     * we add sequential 16-bit words to it, and at the end, fold back
+     * all the carry bits from the top 16 bits into the lower 16 bits.
+     */
+    sum = 0;
+    while (nbytes > 1) {
+        sum += *ptr++;
+        nbytes -= 2;
+    }
+
+    /* mop up an odd byte, if necessary */
+    if (nbytes == 1) {
+        /* make sure top half is zero */
+        oddbyte = 0;
+
+        /* one byte only */
+        *((u_char *)&oddbyte) = *(u_char *)ptr;
+        sum += oddbyte;
+    }
+    /* Add back carry outs from top 16 bits to low 16 bits. */
+    sum = (sum >> 16) + (sum & 0xffff);
+
+    /* add carry */
+    sum += (sum >> 16);
+
+    return sum;
+}
+
+unsigned short
+InetChecksum(unsigned short *ptr,int nbytes)
+{
+    unsigned long sum;
+
+    sum = in_cksum(ptr, nbytes);
+    return (unsigned short)~sum;
+}
+
+void TCPCheckSum(int af, struct tcphdr *t, int tcplen, v6addr_t sadd6, v6addr_t dadd6)
+{
+    unsigned long sum = 0;
+    unsigned short *ptr;
+
+    /* TCP header checksum */
+    sum = in_cksum((unsigned short *)t, tcplen);
+
+    if (af == AF_INET)
+    {
+        /* Pseudo header */
+        ptr = (unsigned short *)sadd6;
+        sum += *ptr++;
+        sum += *ptr++;
+        ptr = (unsigned short *)dadd6;
+        sum += *ptr++;
+        sum += *ptr++;
+    }
+    else if (af == AF_INET6)
+    {
+        /* Pseudo header */
+        ptr = (unsigned short *)sadd6;
+        sum += *ptr++;
+        sum += *ptr++;
+        sum += *ptr++;
+        sum += *ptr++;
+        sum += *ptr++;
+        sum += *ptr++;
+        sum += *ptr++;
+        sum += *ptr++;
+        ptr = (unsigned short *)dadd6;
+        sum += *ptr++;
+        sum += *ptr++;
+        sum += *ptr++;
+        sum += *ptr++;
+        sum += *ptr++;
+        sum += *ptr++;
+        sum += *ptr++;
+        sum += *ptr++;
+    }
+
+    sum += htons(tcplen);
+    sum += htons(IPPROTO_TCP);
+
+    while (sum >> 16)
+        sum = (sum >> 16) + (sum & 0xFFFF);
+
+    t->th_sum = ~sum;
+
+}
+
+kern_return_t do_mDNSSendKeepalive(__unused mach_port_t port, v6addr_t sadd6, v6addr_t dadd6, uint16_t lport, uint16_t rport, unsigned seq, unsigned ack, uint16_t win, audit_token_t token)
+{
+    struct packet4 {
+        struct ip ip;
+        struct tcphdr tcp;
+    } packet4;
+    struct packet6 {
+        struct tcphdr tcp;
+    } packet6;
+    int sock, on;
+    struct tcphdr *t;
+    int af;
+    struct sockaddr_storage ss_to;
+    struct sockaddr_in *sin_to = (struct sockaddr_in *)&ss_to;
+    struct sockaddr_in6 *sin6_to = (struct sockaddr_in6 *)&ss_to;
+    void *packet;
+    ssize_t packetlen;
+    char ctlbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
+    struct msghdr msghdr;
+    struct iovec iov;
+    ssize_t len;
+
+    if (!authorized(&token))
+    {
+        helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: Not authorized");
+        return kmDNSHelperNotAuthorized;
+    }
+
+    helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: called");
+
+    // all the incoming arguments are in network order
+    if ((*(unsigned *)(sadd6 +4) == 0) && (*(unsigned *)(sadd6 + 8) == 0) && (*(unsigned *)(sadd6 + 12) == 0))
+    {
+        af = AF_INET;
+        memset(&packet4, 0, sizeof (packet4));
+
+        /* Fill in all the IP header information - should be in host order*/
+        packet4.ip.ip_v = 4;            /* 4-bit Version */
+        packet4.ip.ip_hl = 5;       /* 4-bit Header Length */
+        packet4.ip.ip_tos = 0;      /* 8-bit Type of service */
+        packet4.ip.ip_len = 40;     /* 16-bit Total length */
+        packet4.ip.ip_id = 9864;        /* 16-bit ID field */
+        packet4.ip.ip_off = 0;      /* 13-bit Fragment offset */
+        packet4.ip.ip_ttl = 63;     /* 8-bit Time To Live */
+        packet4.ip.ip_p = IPPROTO_TCP;  /* 8-bit Protocol */
+        packet4.ip.ip_sum = 0;      /* 16-bit Header checksum (below) */
+        memcpy(&packet4.ip.ip_src.s_addr, sadd6, 4);
+        memcpy(&packet4.ip.ip_dst.s_addr, dadd6, 4);
+
+        /* IP header checksum */
+        packet4.ip.ip_sum = InetChecksum((unsigned short *)&packet4.ip, 20);
+        t = &packet4.tcp;
+        packet = &packet4;
+        packetlen = 40; // sum of IPv4 header len(20) and TCP header len(20)
+    }
+    else
+    {
+        af = AF_INET6;
+        memset(&packet6, 0, sizeof (packet6));
+        t = &packet6.tcp;
+        packet = &packet6;
+        // We don't send IPv6 header, hence just the TCP header len (20)
+        packetlen = 20;
+    }
+
+    /* Fill in all the TCP header information */
+    t->th_sport = lport;        /* 16-bit Source port number */
+    t->th_dport = rport;        /* 16-bit Destination port */
+    t->th_seq = seq;            /* 32-bit Sequence Number */
+    t->th_ack = ack;            /* 32-bit Acknowledgement Number */
+    t->th_off = 5;              /* Data offset */
+    t->th_flags = TH_ACK;
+    t->th_win = win;
+    t->th_sum = 0;              /* 16-bit checksum (below) */
+    t->th_urp = 0;              /* 16-bit urgent offset */
+
+    TCPCheckSum(af, t, 20, sadd6, dadd6);
+
+    /* Open up a RAW socket */
+    if ((sock = socket(af, SOCK_RAW, IPPROTO_TCP)) < 0)
+    {
+        helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: socket %s", strerror(errno));
+        return errno;
+    }
+
+
+    if (af == AF_INET)
+    {
+        on = 1;
+        if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)))
+        {
+            close(sock);
+            helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: setsockopt %s", strerror(errno));
+            return errno;
+        }
+
+        memset(sin_to, 0, sizeof(struct sockaddr_in));
+        sin_to->sin_len = sizeof(struct sockaddr_in);
+        sin_to->sin_family = AF_INET;
+        memcpy(&sin_to->sin_addr, sadd6, sizeof(struct in_addr));
+        sin_to->sin_port = rport;
+
+        msghdr.msg_control = NULL;
+        msghdr.msg_controllen = 0;
+
+    }
+    else
+    {
+        struct cmsghdr *ctl;
+
+        memset(sin6_to, 0, sizeof(struct sockaddr_in6));
+        sin6_to->sin6_len = sizeof(struct sockaddr_in6);
+        sin6_to->sin6_family = AF_INET6;
+        memcpy(&sin6_to->sin6_addr, dadd6, sizeof(struct in6_addr));
+
+        sin6_to->sin6_port = rport;
+        sin6_to->sin6_flowinfo = 0;
+
+
+        msghdr.msg_control = ctlbuf;
+        msghdr.msg_controllen = sizeof(ctlbuf);
+        ctl = CMSG_FIRSTHDR(&msghdr);
+        ctl->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+        ctl->cmsg_level = IPPROTO_IPV6;
+        ctl->cmsg_type = IPV6_PKTINFO;
+        struct in6_pktinfo *pktinfo = (struct in6_pktinfo *) CMSG_DATA(ctl);
+        memcpy(&pktinfo->ipi6_addr, sadd6, sizeof(struct in6_addr));
+        pktinfo->ipi6_ifindex = 0;
+    }
+
+    msghdr.msg_name = (struct sockaddr *)&ss_to;
+    msghdr.msg_namelen = ss_to.ss_len;
+    iov.iov_base = packet;
+    iov.iov_len = packetlen;
+    msghdr.msg_iov = &iov;
+    msghdr.msg_iovlen = 1;
+    msghdr.msg_flags = 0;
+again:
+    len = sendmsg(sock, &msghdr, 0);
+    if (len == -1)
+    {
+        if (errno == EINTR)
+            goto again;
+    }
+
+    if (len != packetlen)
+    {
+        helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: sendmsg failed %s", strerror(errno));
+    }
+    else
+    {
+        char source[INET6_ADDRSTRLEN], dest[INET6_ADDRSTRLEN];
+
+        inet_ntop(af, (void *)sadd6, source, sizeof(source));
+        inet_ntop(af, (void *)dadd6, dest, sizeof(dest));
+
+        helplog(ASL_LEVEL_ERR, "mDNSSendKeepalive: Success Source %s:%d, Dest %s:%d, %u, %u, %u", source, ntohs(lport), dest, ntohs(rport), ntohl(seq), ntohl(ack), ntohs(win));
+
+    }
+    close(sock);
+    return KERN_SUCCESS;
+}
+
+
+kern_return_t do_mDNSRetrieveTCPInfo(__unused mach_port_t port, int family, v6addr_t laddr, uint16_t lport, v6addr_t raddr, uint16_t  rport,
+                                     uint32_t *seq, uint32_t *ack, uint16_t *win, int32_t *intfid, audit_token_t token)
+{
+    struct tcp_info   ti;
+    struct info_tuple itpl;
+    int               mib[4];
+    unsigned int      miblen;
+    size_t            len;
+    size_t            sz;
+
+    memset(&itpl, 0, sizeof(struct info_tuple));
+    memset(&ti,   0, sizeof(struct tcp_info));
+
+    if (!authorized(&token))
+    {
+        helplog(ASL_LEVEL_ERR, "mDNSRetrieveTCPInfo: Not authorized");
+        return kmDNSHelperNotAuthorized;
+    }
+
+    if (family == AF_INET)
+    {
+        memcpy(&itpl.itpl_local_sin.sin_addr,  laddr, sizeof(struct in_addr));
+        memcpy(&itpl.itpl_remote_sin.sin_addr, raddr, sizeof(struct in_addr));
+        itpl.itpl_local_sin.sin_port    = lport;
+        itpl.itpl_remote_sin.sin_port   = rport;
+        itpl.itpl_local_sin.sin_family  = AF_INET;
+        itpl.itpl_remote_sin.sin_family = AF_INET;
+    }
+    else
+    {
+        memcpy(&itpl.itpl_local_sin6.sin6_addr,  laddr, sizeof(struct in6_addr));
+        memcpy(&itpl.itpl_remote_sin6.sin6_addr, raddr, sizeof(struct in6_addr));
+        itpl.itpl_local_sin6.sin6_port    = lport;
+        itpl.itpl_remote_sin6.sin6_port   = rport;
+        itpl.itpl_local_sin6.sin6_family  = AF_INET6;
+        itpl.itpl_remote_sin6.sin6_family = AF_INET6;
+    }
+    itpl.itpl_proto = IPPROTO_TCP;
+    sz = sizeof(mib)/sizeof(mib[0]);
+    if (sysctlnametomib("net.inet.tcp.info", mib, &sz) == -1)
+    {
+        helplog(ASL_LEVEL_ERR, "do_RetrieveTCPInfo: sysctlnametomib failed %d, %s", errno, strerror(errno));
+        return errno;
+    }
+    miblen = (unsigned int)sz;
+    len    = sizeof(struct tcp_info);
+    if (sysctl(mib, miblen, &ti, &len, &itpl, sizeof(struct info_tuple)) == -1)
+    {
+        helplog(ASL_LEVEL_ERR, "do_RetrieveTCPInfo: sysctl failed %d, %s", errno, strerror(errno));
+        return errno;
+    }
+
+    *seq    = ti.tcpi_snd_nxt - 1;
+    *ack    = ti.tcpi_rcv_nxt;
+    *win    = ti.tcpi_rcv_space >> ti.tcpi_rcv_wscale;
+    *intfid = ti.tcpi_last_outif;
+    return KERN_SUCCESS;
+}
+
+static int getMACAddress(int family, v6addr_t raddr, v6addr_t gaddr, int *gfamily, ethaddr_t eth)
+{
+    struct
+    {
+        struct rt_msghdr m_rtm;
+        char   m_space[512];
+    } m_rtmsg;
+
+    struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
+    char  *cp  = m_rtmsg.m_space;
+    int    seq = 6367, sock, rlen, i;
+    struct sockaddr_in      *sin  = NULL;
+    struct sockaddr_in6     *sin6 = NULL;
+    struct sockaddr_dl      *sdl  = NULL;
+    struct sockaddr_storage  sins;
+    struct sockaddr_dl       sdl_m;
+
+#define NEXTADDR(w, s, len)         \
+    if (rtm->rtm_addrs & (w))       \
+    {                               \
+        bcopy((char *)s, cp, len);  \
+        cp += len;                  \
+    }
+
+    bzero(&sins,  sizeof(struct sockaddr_storage));
+    bzero(&sdl_m, sizeof(struct sockaddr_dl));
+    bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
+
+    sock = socket(PF_ROUTE, SOCK_RAW, 0);
+    if (sock < 0)
+    {
+        helplog(ASL_LEVEL_ERR, "mDNSGetRemoteMAC: Can not open the socket - %s", strerror(errno));
+        return errno;
+    }
+
+    rtm->rtm_addrs   |= RTA_DST | RTA_GATEWAY;
+    rtm->rtm_type     = RTM_GET;
+    rtm->rtm_flags    = 0;
+    rtm->rtm_version  = RTM_VERSION;
+    rtm->rtm_seq      = ++seq;
+
+    sdl_m.sdl_len     = sizeof(sdl_m);
+    sdl_m.sdl_family  = AF_LINK;
+    if (family == AF_INET)
+    {
+        sin = (struct sockaddr_in*)&sins;
+        sin->sin_family = AF_INET;
+        sin->sin_len    = sizeof(struct sockaddr_in);
+        memcpy(&sin->sin_addr, raddr, sizeof(struct in_addr));
+        NEXTADDR(RTA_DST, sin, sin->sin_len);
+    }
+    else if (family == AF_INET6)
+    {
+        sin6 = (struct sockaddr_in6 *)&sins;
+        sin6->sin6_len    = sizeof(struct sockaddr_in6);
+        sin6->sin6_family = AF_INET6;
+        memcpy(&sin6->sin6_addr, raddr, sizeof(struct in6_addr));
+        NEXTADDR(RTA_DST, sin6, sin6->sin6_len);
+    }
+    NEXTADDR(RTA_GATEWAY, &sdl_m, sdl_m.sdl_len);
+    rtm->rtm_msglen = rlen = cp - (char *)&m_rtmsg;
+
+    if (write(sock, (char *)&m_rtmsg, rlen) < 0)
+    {
+        helplog(ASL_LEVEL_INFO, "do_mDNSGetRemoteMAC: writing to routing socket: %s", strerror(errno));
+        close(sock);
+        return errno;
+    }
+
+    do
+    {
+        rlen = read(sock, (char *)&m_rtmsg, sizeof(m_rtmsg));
+    }
+    while (rlen > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != getpid()));
+
+    if (rlen < 0)
+        helplog(ASL_LEVEL_ERR, "do_mDNSGetRemoteMAC: Read from routing socket failed");
+
+    if (family == AF_INET)
+    {
+        sin = (struct sockaddr_in *) (rtm + 1);
+        sdl = (struct sockaddr_dl *) (sin->sin_len + (char *) sin);
+    }
+    else if (family == AF_INET6)
+    {
+        sin6 = (struct sockaddr_in6 *) (rtm +1);
+        sdl  = (struct sockaddr_dl  *) (sin6->sin6_len + (char *) sin6);
+    }
+    // If the address is not on the local net, we get the IP address of the gateway.
+    // We would have to repeat the process to get the MAC address of the gateway
+    *gfamily = sdl->sdl_family;
+    if (sdl->sdl_family == AF_INET)
+    {
+        struct sockaddr_in *new_sin = (struct sockaddr_in *)(sin->sin_len +(char*) sin);
+        memcpy(gaddr, &new_sin->sin_addr, sizeof(struct in_addr));
+        close(sock);
+        return -1;
+    }
+    else if (sdl->sdl_family == AF_INET6)
+    {
+        struct sockaddr_in6 *new_sin6 = (struct sockaddr_in6 *)(sin6->sin6_len +(char*) sin6);
+        memcpy(gaddr, &new_sin6->sin6_addr, sizeof(struct in6_addr));
+        close(sock);
+        return -1;
+    }
+
+    unsigned char *ptr = (unsigned char *)LLADDR(sdl);
+    for (i = 0; i < ETHER_ADDR_LEN; i++)
+        (eth)[i] = *(ptr +i);
+
+    close(sock);
+    return KERN_SUCCESS;
+}
+
+kern_return_t do_mDNSGetRemoteMAC(__unused mach_port_t port, int family, v6addr_t raddr, ethaddr_t eth, audit_token_t token)
+{
+    int      ret = 0;
+    v6addr_t gateway;
+    int      gfamily;
+    int      count = 0;
+
+    if (!authorized(&token))
+    {
+        helplog(ASL_LEVEL_ERR, "mDNSGetRemoteMAC: Not authorized");
+        return kmDNSHelperNotAuthorized;
+    }
+
+    do
+    {
+        ret = getMACAddress(family, raddr, gateway, &gfamily, eth);
+        if (ret == -1)
+        {
+            memcpy(raddr, gateway, sizeof(family));
+            family = gfamily;
+            count++;
+        }
+    }
+    while ((ret == -1) && (count < 5));
+    return ret;
+}
+
+
+kern_return_t do_mDNSStoreSPSMACAddress(__unused mach_port_t port, int family, v6addr_t spsaddr, const char *ifname, audit_token_t token)
+{
+    ethaddr_t              eth;
+    char                   spsip[INET6_ADDRSTRLEN];
+    int                    ret        = 0;
+    CFStringRef            sckey      = NULL;
+    SCDynamicStoreRef      store      = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:StoreSPSMACAddress"), NULL, NULL);
+    SCDynamicStoreRef      ipstore    = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetIPv6Addresses"), NULL, NULL);
+    CFMutableDictionaryRef dict       = NULL;
+    CFStringRef            entityname = NULL;
+    CFDictionaryRef        ipdict     = NULL;
+    CFArrayRef             addrs      = NULL;
+
+    if (!authorized(&token))
+    {
+        helplog(ASL_LEVEL_ERR, "mDNSStoreSPSMAC: Not authorized");
+        return kmDNSHelperNotAuthorized;
+    }
+
+    if ((store == NULL) || (ipstore == NULL))
+    {
+        helplog(ASL_LEVEL_ERR, "Unable to access SC Dynamic Store");
+        return KERN_FAILURE;
+    }
+
+    // Get the MAC address of the Sleep Proxy Server
+    memset(eth, 0, sizeof(eth));
+    ret = do_mDNSGetRemoteMAC(port, family, spsaddr, eth, token);
+    if (ret !=  KERN_SUCCESS)
+    {
+        helplog(ASL_LEVEL_ERR, "mDNSStoreSPSMAC: Failed to determine the MAC address");
+        goto fin;
+    }
+
+    // Create/Update the dynamic store entry for the specified interface
+    sckey = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", ifname, "/BonjourSleepProxyAddress");
+    dict  = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+    if (!dict)
+    {
+        helplog(ASL_LEVEL_ERR, "SPSCreateDict: Could not create CFDictionary dict");
+        ret = KERN_FAILURE;
+        goto fin;
+    }
+
+    CFStringRef macaddr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]);
+    CFDictionarySetValue(dict, CFSTR("MACAddress"), macaddr);
+    if (NULL != macaddr) CFRelease(macaddr);
+
+    if( NULL == inet_ntop(family, (void *)spsaddr, spsip, sizeof(spsip)))
+    {
+         helplog(ASL_LEVEL_ERR, "inet_ntop failed: %s", strerror(errno));
+         ret = kmDNSHelperInvalidNetworkAddress;
+         goto fin;
+    }
+
+    CFStringRef ipaddr = CFStringCreateWithCString(NULL, spsip, kCFStringEncodingUTF8);
+    CFDictionarySetValue(dict, CFSTR("IPAddress"), ipaddr);
+    if (NULL != ipaddr) CFRelease(ipaddr);
+
+    // Get the current IPv6 addresses on this interface and store them so NAs can be sent on wakeup
+    if ((entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/IPv6"), ifname)) != NULL)
+    {
+        if ((ipdict = SCDynamicStoreCopyValue(ipstore, entityname)) != NULL)
+        {
+            if((addrs = CFDictionaryGetValue(ipdict, CFSTR("Addresses"))) != NULL)
+            {
+                addrs = CFRetain(addrs);
+                CFDictionarySetValue(dict, CFSTR("RegisteredAddresses"), addrs);
+            }
+        }
+    }
+    SCDynamicStoreSetValue(store, sckey, dict);
+
+fin:
+    if (store)      CFRelease(store);
+    if (ipstore)    CFRelease(ipstore);
+    if (sckey)      CFRelease(sckey);
+    if (dict)       CFRelease(dict);
+    if (ipdict)     CFRelease(ipdict);
+    if (entityname) CFRelease(entityname);
+    if (addrs)      CFRelease(addrs);
+
+    update_idle_timer();
+    return ret;
+}

Deleted: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSMacOSX.c
===================================================================
--- vendor/apple/mDNSResponder/dist/mDNSMacOSX/mDNSMacOSX.c	2014-06-30 23:58:12 UTC (rev 6706)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSMacOSX.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -1,10441 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2013 Apple Computer, 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.
- */
-
-// ***************************************************************************
-// mDNSMacOSX.c:
-// Supporting routines to run mDNS on a CFRunLoop platform
-// ***************************************************************************
-
-// For debugging, set LIST_ALL_INTERFACES to 1 to display all found interfaces,
-// including ones that mDNSResponder chooses not to use.
-#define LIST_ALL_INTERFACES 0
-
-#include "mDNSEmbeddedAPI.h"        // Defines the interface provided to the client layer above
-#include "DNSCommon.h"
-#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 "PlatformCommon.h"
-#include "uds_daemon.h"
-#include "CryptoSupport.h"
-
-#include <stdio.h>
-#include <stdarg.h>                 // For va_list support
-#include <stdlib.h>                 // For arc4random
-#include <net/if.h>
-#include <net/if_types.h>           // For IFT_ETHER
-#include <net/if_dl.h>
-#include <net/bpf.h>                // For BIOCSETIF etc.
-#include <sys/uio.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/event.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <time.h>                   // platform support for UTC time
-#include <arpa/inet.h>              // for inet_aton
-#include <pthread.h>
-#include <netdb.h>                  // for getaddrinfo
-#include <sys/sockio.h>             // for SIOCGIFEFLAGS
-#include <notify.h>
-#include <netinet/in.h>             // For IP_RECVTTL
-#ifndef IP_RECVTTL
-#define IP_RECVTTL 24               // bool; receive reception TTL w/dgram
-#endif
-
-#include <netinet/in_systm.h>       // For n_long, required by <netinet/ip.h> below
-#include <netinet/ip.h>             // For IPTOS_LOWDELAY etc.
-#include <netinet6/in6_var.h>       // For IN6_IFF_NOTREADY etc.
-#include <netinet6/nd6.h>           // For ND6_INFINITE_LIFETIME etc.
-
-#include <netinet/tcp.h>
-
-#include <DebugServices.h>
-#include "dnsinfo.h"
-
-#include <ifaddrs.h>
-
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOMessage.h>
-
-#include <IOKit/ps/IOPowerSources.h>
-#include <IOKit/ps/IOPowerSourcesPrivate.h>
-#include <IOKit/ps/IOPSKeys.h>
-
-#include <mach/mach_error.h>
-#include <mach/mach_port.h>
-#include <mach/mach_time.h>
-#include "helper.h"
-#include "P2PPacketFilter.h"
-
-#include <asl.h>
-#include <SystemConfiguration/SCPrivate.h>
-
-// Include definition of opaque_presence_indication for KEV_DL_NODE_PRESENCE handling logic.
-#include <Kernel/IOKit/apple80211/apple80211_var.h>
-
-#if APPLE_OSX_mDNSResponder
-#include <DeviceToDeviceManager/DeviceToDeviceManager.h>
-#include <AWACS.h>
-#if !NO_D2D
-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));
-
-#endif // ! NO_D2D
-
-#else
-#define NO_D2D 1
-#define NO_AWACS 1
-#endif // APPLE_OSX_mDNSResponder
-
-#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
-#include <IOKit/platform/IOPlatformSupportPrivate.h>
-#endif // APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
-
-
-#define kInterfaceSpecificOption "interface="
-
-#define mDNS_IOREG_KEY               "mDNS_KEY"
-#define mDNS_IOREG_VALUE             "2009-07-30"
-#define mDNS_IOREG_KA_KEY            "mDNS_Keepalive"
-#define mDNS_USER_CLIENT_CREATE_TYPE 'mDNS'
-
-// cache the InterfaceID of the AWDL interface 
-static mDNSInterfaceID AWDLInterfaceID;
-
-// ***************************************************************************
-// Globals
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark - Globals
-#endif
-
-// By default we don't offer sleep proxy service
-// If OfferSleepProxyService is set non-zero (typically via command-line switch),
-// then we'll offer sleep proxy service on desktop Macs that are set to never sleep.
-// We currently do not offer sleep proxy service on laptops, or on machines that are set to go to sleep.
-mDNSexport int OfferSleepProxyService = 0;
-mDNSexport int DisableSleepProxyClient = 0;
-mDNSexport int UseInternalSleepProxy = 1;       // Set to non-zero to use internal (in-NIC) Sleep Proxy
-
-mDNSexport int OSXVers, iOSVers;
-mDNSexport int KQueueFD;
-
-#ifndef NO_SECURITYFRAMEWORK
-static CFArrayRef ServerCerts;
-OSStatus SSLSetAllowAnonymousCiphers(SSLContextRef context, Boolean enable);
-#endif /* NO_SECURITYFRAMEWORK */
-
-static CFStringRef NetworkChangedKey_IPv4;
-static CFStringRef NetworkChangedKey_IPv6;
-static CFStringRef NetworkChangedKey_Hostnames;
-static CFStringRef NetworkChangedKey_Computername;
-static CFStringRef NetworkChangedKey_DNS;
-static CFStringRef NetworkChangedKey_StateInterfacePrefix;
-static CFStringRef NetworkChangedKey_DynamicDNS       = CFSTR("Setup:/Network/DynamicDNS");
-static CFStringRef NetworkChangedKey_BackToMyMac      = CFSTR("Setup:/Network/BackToMyMac");
-static CFStringRef NetworkChangedKey_BTMMConnectivity = CFSTR("State:/Network/Connectivity");
-static CFStringRef NetworkChangedKey_PowerSettings    = CFSTR("State:/IOKit/PowerManagement/CurrentSettings");
-
-static char HINFO_HWstring_buffer[32];
-static char *HINFO_HWstring = "Device";
-static int HINFO_HWstring_prefixlen = 6;
-
-mDNSexport int WatchDogReportingThreshold = 250;
-
-dispatch_queue_t SSLqueue;
-
-//To prevent blocking the main queue, all writes to DynamicStore happen on the DynamicStoreQueue
-static dispatch_queue_t DynamicStoreQueue;
-
-#if TARGET_OS_EMBEDDED
-#define kmDNSResponderManagedPrefsID CFSTR("/Library/Managed Preferences/mobile/com.apple.mDNSResponder.plist")
-#endif
-
-#if APPLE_OSX_mDNSResponder
-static mDNSu8 SPMetricPortability   = 99;
-static mDNSu8 SPMetricMarginalPower = 99;
-static mDNSu8 SPMetricTotalPower    = 99;
-static mDNSu8 SPMetricFeatures      = 1; /* The current version supports TCP Keep Alive Feature */
-mDNSexport domainname ActiveDirectoryPrimaryDomain;
-mDNSexport int ActiveDirectoryPrimaryDomainLabelCount;
-mDNSexport mDNSAddr ActiveDirectoryPrimaryDomainServer;
-#endif // APPLE_OSX_mDNSResponder
-
-// Don't send triggers too often. We arbitrarily limit it to three minutes.
-#define DNS_TRIGGER_INTERVAL (180 * mDNSPlatformOneSecond)
-
-// Used by AutoTunnel
-const char btmmprefix[] = "btmmdns:";
-const char dnsprefix[] = "dns:";
-
-// String Array used to write list of private domains to Dynamic Store
-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, NULL);
-        if (interface->RR_PTR.resrec.RecordType)
-            external_start_advertising_service(&interface->RR_PTR.resrec, NULL);
-    }
-}
-
-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, NULL);
-        if (interface->RR_PTR.resrec.RecordType)
-            external_stop_advertising_service(&interface->RR_PTR.resrec, NULL);
-    }
-}
-
-// 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;
-    AuthRecord               ar;
-    D2DServiceInstance       instanceHandle;
-    D2DTransportType         transportType;
-} 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 mStatus DNSNameCompressionParseBytes(mDNS *const m, const mDNSu8 *const lhs, const mDNSu16 lhs_len, const mDNSu8 *const rhs, const mDNSu16 rhs_len, AuthRecord *rr)
-{
-    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("DNSNameCompressionParseBytes: failed to get large RR"); m->rec.r.resrec.RecordType = 0; return mStatus_UnknownErr; }
-    else LogInfo("DNSNameCompressionParseBytes: got rr: %s", CRDisplayString(m, &m->rec.r));
-
-    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;
-}
-
-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))
-        {
-            mDNS_Deregister(&mDNSStorage, &ptr->ar);
-            LogInfo("xD2DClearCache: Clearing cache record and deregistering %s", ARDisplayString(&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);
-}
-
-mDNSlocal void 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; }
-
-    (*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);
-    }
-}
-
-mDNSlocal mStatus xD2DParse(mDNS *const m, const mDNSu8 * const lhs, const mDNSu16 lhs_len, const mDNSu8 * const rhs, const mDNSu16 rhs_len, AuthRecord *rr)
-{
-    if (*(lhs + (lhs_len - 1)) == compression_packet_v1)
-        return DNSNameCompressionParseBytes(m, lhs, lhs_len, rhs, rhs_len, rr);
-    else
-        return mStatus_Incompatible;
-}
-
-mDNSlocal 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 = mDNSPlatformMemAllocate(sizeof(D2DRecordListElem) + (valueSize < sizeof(RData) ? 0 : valueSize - sizeof(RData)));
-
-        if (ptr == NULL) { LogMsg("xD2DAddToCache: memory allocation failure"); return; }
-
-        err = xD2DParse(m, (const mDNSu8 * const)key, (const mDNSu16)keySize, (const mDNSu8 * const)value, (const mDNSu16)valueSize, &ptr->ar);
-        if (err)
-        {
-            LogMsg("xD2DAddToCache: xD2DParse returned error: %d", err);
-            PrintHelper(__func__, (mDNSu8 *)key, (mDNSu16)keySize, (mDNSu8 *)value, (mDNSu16)valueSize);
-            mDNSPlatformMemFree(ptr);
-            return;
-        }
-        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;
-
-    if ( key == NULL || value == NULL || keySize == 0 || valueSize == 0) { LogMsg("xD2DFindInList: NULL Byte * passed in or length == 0"); return NULL; }
-
-    arptr = mDNSPlatformMemAllocate(sizeof(D2DRecordListElem) + (valueSize < sizeof(RData) ? 0 : valueSize - sizeof(RData)));
-    if (arptr == NULL) { LogMsg("xD2DFindInList: memory allocation failure"); return NULL; }
-
-    if (xD2DParse(m, (const mDNSu8 *const)key, (const mDNSu16)keySize, (const mDNSu8 *const)value, (const mDNSu16)valueSize, &arptr->ar) != mStatus_NoError)
-    {
-        LogMsg("xD2DFindInList: xD2DParse failed for key: %p (%u) value: %p (%u)", key, keySize, value, valueSize);
-        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;
-}
-
-mDNSlocal 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;
-}
-
-mDNSexport void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags)
-{
-    domainname lower;
-
-    if (qtype == kDNSServiceType_A || qtype == kDNSServiceType_AAAA)
-    {
-        LogInfo("external_start_browsing_for_service: ignoring address record");
-        return;
-    }
-
-    DomainnameToLower(typeDomain, &lower);
-
-    if (!D2DBrowseListRefCount(&lower, qtype))
-    {
-        D2DTransportType transportType, excludedTransport;
-
-        LogInfo("external_start_browsing_for_service: Starting browse for: %##s %s", 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)
-{
-    domainname lower;
-
-    if (qtype == kDNSServiceType_A || qtype == kDNSServiceType_AAAA)
-    {
-        LogInfo("external_stop_browsing_for_service: ignoring address record");
-        return;
-    }
-
-    DomainnameToLower(typeDomain, &lower);
-
-    D2DBrowseListRelease(&lower, qtype);
-    if (!D2DBrowseListRefCount(&lower, qtype))
-    {
-        D2DTransportType transportType, excludedTransport;
-
-        LogInfo("external_stop_browsing_for_service: Stopping browse for: %##s %s", 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)
-{
-    domainname lower;
-    mDNSu8 *rhs = NULL;
-    mDNSu8 *end = NULL;
-    D2DTransportType transportType, excludedTransport;
-    DomainnameToLower(resourceRecord->name, &lower);
-
-    LogInfo("external_start_advertising_service: %s", 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)
-{
-    domainname lower;
-    mDNSu8 *rhs = NULL;
-    mDNSu8 *end = NULL;
-    D2DTransportType transportType, excludedTransport;
-    DomainnameToLower(resourceRecord->name, &lower);
-
-    LogInfo("external_stop_advertising_service: %s", RRDisplayString(&mDNSStorage, resourceRecord));
-
-    // 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, NULL);
-        external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_SRV, NULL);
-    }
-}
-
-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, NULL);
-        external_stop_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_SRV, NULL);
-    }
-}
-
-#elif APPLE_OSX_mDNSResponder
-
-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;}
-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
-#pragma mark -
-#pragma mark - Utility Functions
-#endif
-
-// We only attempt to send and receive multicast packets on interfaces that are
-// (a) flagged as multicast-capable
-// (b) *not* flagged as point-to-point (e.g. modem)
-// Typically point-to-point interfaces are modems (including mobile-phone pseudo-modems), and we don't want
-// to run up the user's bill sending multicast traffic over a link where there's only a single device at the
-// other end, and that device (e.g. a modem bank) is probably not answering Multicast DNS queries anyway.
-#define MulticastInterface(i) (((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT))
-
-mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg)  // Both strings are UTF-8 text
-{
-    static int notifyCount = 0;
-    if (notifyCount) return;
-
-    // If we display our alert early in the boot process, then it vanishes once the desktop appears.
-    // To avoid this, we don't try to display alerts in the first three minutes after boot.
-    if ((mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return;
-
-    // Unless ForceAlerts is defined, we only show these bug report alerts on machines that have a 17.x.x.x address
-    #if !ForceAlerts
-    {
-        // Determine if we're at Apple (17.*.*.*)
-        NetworkInterfaceInfoOSX *i;
-        for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
-            if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && i->ifinfo.ip.ip.v4.b[0] == 17)
-                break;
-        if (!i) return; // If not at Apple, don't show the alert
-    }
-    #endif
-
-    LogMsg("%s", title);
-    LogMsg("%s", msg);
-    // Display a notification to the user
-    notifyCount++;
-
-#ifndef NO_CFUSERNOTIFICATION
-    mDNSNotify(title, msg);
-#endif /* NO_CFUSERNOTIFICATION */
-}
-
-// Returns true if it is an AppleTV based hardware running iOS, false otherwise
-mDNSlocal mDNSBool IsAppleTV(void)
-{
-#if TARGET_OS_EMBEDDED
-    static mDNSBool sInitialized = mDNSfalse;
-    static mDNSBool sIsAppleTV   = mDNSfalse;
-    CFStringRef deviceClass = NULL;
-
-    if(!sInitialized)
-    {
-        deviceClass = (CFStringRef) MGCopyAnswer(kMGQDeviceClass, NULL);
-        if(deviceClass)
-        {
-            if(CFEqual(deviceClass, kMGDeviceClassAppleTV))
-                sIsAppleTV = mDNStrue;
-            CFRelease(deviceClass);
-        }
-        sInitialized = mDNStrue;
-    }
-    return(sIsAppleTV);
-#else 
-    return mDNSfalse;
-#endif // TARGET_OS_EMBEDDED
-}
-
-mDNSlocal struct ifaddrs *myGetIfAddrs(int refresh)
-{
-    static struct ifaddrs *ifa = NULL;
-
-    if (refresh && ifa)
-    {
-        freeifaddrs(ifa);
-        ifa = NULL;
-    }
-
-    if (ifa == NULL) 
-        getifaddrs(&ifa);
-    return ifa;
-}
-
-mDNSlocal void DynamicStoreWrite(int key, const char* subkey, uintptr_t value, signed long valueCnt)
-{
-    CFStringRef sckey       = NULL;
-    Boolean release_sckey   = FALSE;
-    CFDataRef bytes         = NULL;
-    CFPropertyListRef plist = NULL;
-    SCDynamicStoreRef store = NULL;
-
-    switch ((enum mDNSDynamicStoreSetConfigKey)key)
-    {
-        case kmDNSMulticastConfig:
-            sckey = CFSTR("State:/Network/" kDNSServiceCompMulticastDNS);
-            break;
-        case kmDNSDynamicConfig:
-            sckey = CFSTR("State:/Network/DynamicDNS");
-            break;
-        case kmDNSPrivateConfig:
-            sckey = CFSTR("State:/Network/" kDNSServiceCompPrivateDNS);
-            break;
-        case kmDNSBackToMyMacConfig:
-            sckey = CFSTR("State:/Network/BackToMyMac");
-            break;
-        case kmDNSSleepProxyServersState:
-        {
-            CFMutableStringRef tmp = CFStringCreateMutable(kCFAllocatorDefault, 0);
-            CFStringAppend(tmp, CFSTR("State:/Network/Interface/"));
-            CFStringAppendCString(tmp, subkey, kCFStringEncodingUTF8);
-            CFStringAppend(tmp, CFSTR("/SleepProxyServers"));
-            sckey = CFStringCreateCopy(kCFAllocatorDefault, tmp);
-            release_sckey = TRUE;
-            CFRelease(tmp);
-            break;
-        }
-        case kmDNSDebugState:
-            sckey = CFSTR("State:/Network/mDNSResponder/DebugState");
-            break;
-        default:
-            LogMsg("unrecognized key %d", key);
-            goto fin;
-    }
-    if (NULL == (bytes = CFDataCreateWithBytesNoCopy(NULL, (void *)value,
-                                                     valueCnt, kCFAllocatorNull)))
-    {
-        LogMsg("CFDataCreateWithBytesNoCopy of value failed");
-        goto fin;
-    }
-    if (NULL == (plist = CFPropertyListCreateFromXMLData(NULL, bytes,
-                                                         kCFPropertyListImmutable, NULL)))
-    {
-        LogMsg("CFPropertyListCreateFromXMLData of bytes failed");
-        goto fin;
-    }
-    CFRelease(bytes);
-    bytes = NULL;
-    if (NULL == (store = SCDynamicStoreCreate(NULL,
-                                              CFSTR(kmDNSResponderServName), NULL, NULL)))
-    {
-        LogMsg("SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
-        goto fin;
-    }
-    SCDynamicStoreSetValue(store, sckey, plist);
-
-fin:
-    if (NULL != bytes)
-        CFRelease(bytes);
-    if (NULL != plist)
-        CFRelease(plist);
-    if (NULL != store)
-        CFRelease(store);
-    if (release_sckey && sckey)
-        CFRelease(sckey);
-}
-
-mDNSexport void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropertyListRef value)
-{
-    CFPropertyListRef valueCopy;
-    char *subkeyCopy  = NULL;
-    if (!value)
-        return;
-
-    // We need to copy the key and value before we dispatch off the block below as the
-    // caller will free the memory once we return from this function.
-    valueCopy = CFPropertyListCreateDeepCopy(NULL, value, kCFPropertyListImmutable);
-    if (!valueCopy)
-    {   
-        LogMsg("mDNSDynamicStoreSetConfig: ERROR valueCopy NULL");
-        return;
-    }
-    if (subkey)
-    {
-        int len    = strlen(subkey);
-        subkeyCopy = mDNSPlatformMemAllocate(len + 1);
-        if (!subkeyCopy)
-        {
-            LogMsg("mDNSDynamicStoreSetConfig: ERROR subkeyCopy NULL");
-            return;
-        }
-        mDNSPlatformMemCopy(subkeyCopy, subkey, len);
-        subkeyCopy[len] = 0;
-    }
-
-    dispatch_async(DynamicStoreQueue, ^{
-        CFWriteStreamRef stream = NULL;
-        CFDataRef bytes = NULL;
-        CFStringRef error;
-        CFIndex ret;
-
-        if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(NULL, NULL)))
-        {
-            LogMsg("mDNSDynamicStoreSetConfig : CFWriteStreamCreateWithAllocatedBuffers failed (Object creation failed)");
-            goto END;
-        }
-        CFWriteStreamOpen(stream);
-        ret = CFPropertyListWriteToStream(valueCopy, stream, kCFPropertyListBinaryFormat_v1_0, &error);
-        if (ret == 0)
-        {
-            LogMsg("mDNSDynamicStoreSetConfig : CFPropertyListWriteToStream failed (Could not write property list to stream)");
-            goto END;
-        }
-        if (NULL == (bytes = CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten)))
-        {
-            LogMsg("mDNSDynamicStoreSetConfig : CFWriteStreamCopyProperty failed (Object creation failed) ");
-            goto END;
-        }
-        CFWriteStreamClose(stream);
-        CFRelease(stream);
-        stream = NULL;
-        LogInfo("mDNSDynamicStoreSetConfig: key %d subkey %s", key, subkeyCopy);
-        DynamicStoreWrite(key, subkeyCopy ? subkeyCopy : "", (uintptr_t)CFDataGetBytePtr(bytes), CFDataGetLength(bytes));
-
-    END:
-        CFRelease(valueCopy);
-        if (NULL != stream)
-        {
-            CFWriteStreamClose(stream);
-            CFRelease(stream);
-        }
-        if (NULL != bytes)
-            CFRelease(bytes); 
-        if (subkeyCopy)
-            mDNSPlatformMemFree(subkeyCopy);
-    });
-}
-
-// 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)
-{
-    NetworkInterfaceInfoOSX *i;
-    for (i = m->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) ||
-             (type == AF_INET6 && i->ifinfo.ip.type == mDNSAddrType_IPv6))) return(i);
-    return(NULL);
-}
-
-#if TARGET_OS_EMBEDDED
-mDNSlocal SCPreferencesRef mDNSManagedPrefsGet(void)
-{
-    SCPreferencesRef smDNSManagedPrefs = NULL;
-    smDNSManagedPrefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("mDNSManagedPrefs"), kmDNSResponderManagedPrefsID);
-
-    return (smDNSManagedPrefs);
-}
-
-mDNSlocal mDNSBool GetmDNSManagedPrefKeyVal(SCPreferencesRef prefs, CFStringRef key)
-{
-    mDNSBool val = mDNSfalse;
-    CFBooleanRef val_cf = NULL;
- 
-    if (prefs != NULL)
-    {
-        val_cf = SCPreferencesGetValue(prefs, key);
-        if (isA_CFBoolean(val_cf) != NULL)
-            val = CFBooleanGetValue(val_cf); //When mDNSResponder-Debug-profile is Installed
-        else
-            val = mDNSfalse; //When mDNSResponder-Debug-profile is Uninstalled
-    }
-    else 
-    {
-        LogMsg("GetmDNSManagedPrefKeyVal: mDNSManagedPrefs are NULL!");
-        val = mDNSfalse;
-    }
-    if (val_cf)
-        CFRelease(val_cf);
-    return (val);
-}
-
-mDNSexport mDNSBool GetmDNSManagedPref(CFStringRef key)
-{
-    SCPreferencesRef  managed = NULL;
-    mDNSBool ret_value;
-     
-    managed = mDNSManagedPrefsGet();
-    ret_value = GetmDNSManagedPrefKeyVal(managed, key);
-    
-    if (managed)
-        CFRelease(managed);
-    return (ret_value);
-}
-#endif //TARGET_OS_EMBEDDED
-
-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 (((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)
-{
-    mDNSu32 scope_id = (mDNSu32)(uintptr_t)ifindex;
-    NetworkInterfaceInfoOSX *i;
-
-    // Don't get tricked by inactive interfaces
-    for (i = m->p->InterfaceList; i; i = i->next)
-        if (i->Registered && i->scope_id == scope_id) return(i);
-
-    return mDNSNULL;
-}
-
-mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex)
-{
-    if (ifindex == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
-    if (ifindex == kDNSServiceInterfaceIndexP2P      ) return(mDNSInterface_P2P);
-    if (ifindex == kDNSServiceInterfaceIndexAny      ) return(mDNSNULL);
-
-    NetworkInterfaceInfoOSX* ifi = IfindexToInterfaceInfoOSX(m, (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);
-    }
-
-    if (!ifi) return(mDNSNULL);
-
-    return(ifi->ifinfo.InterfaceID);
-}
-
-
-mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange)
-{
-    NetworkInterfaceInfoOSX *i;
-    if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
-    if (id == mDNSInterface_P2P      ) return(kDNSServiceInterfaceIndexP2P);
-    if (id == mDNSInterface_Any      ) return(0);
-
-    mDNSu32 scope_id = (mDNSu32)(uintptr_t)id;
-
-    // Don't use i->Registered here, because we DO want to find inactive interfaces, which have no Registered set
-    for (i = m->p->InterfaceList; i; i = i->next)
-        if (i->scope_id == scope_id) return(i->scope_id);
-
-    // If we are supposed to suppress network change, return "id" back
-    if (suppressNetworkChange) return scope_id;
-
-    // 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);
-    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
-#endif
-
-mDNSlocal mDNSBool AddrRequiresPPPConnection(const struct sockaddr *addr)
-{
-    mDNSBool result = mDNSfalse;
-    SCNetworkConnectionFlags flags;
-    CFDataRef remote_addr;
-    CFMutableDictionaryRef options;
-    SCNetworkReachabilityRef ReachRef = NULL;
-
-    options = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-    remote_addr = CFDataCreate(NULL, (const UInt8 *)addr, addr->sa_len);
-    CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, remote_addr);
-    CFDictionarySetValue(options, kSCNetworkReachabilityOptionServerBypass, kCFBooleanTrue);
-    ReachRef = SCNetworkReachabilityCreateWithOptions(kCFAllocatorDefault, options);
-    CFRelease(options);
-    CFRelease(remote_addr);
-
-    if (!ReachRef) 
-    { 
-        LogMsg("ERROR: RequiresConnection - SCNetworkReachabilityCreateWithOptions"); 
-        goto end; 
-    }
-    if (!SCNetworkReachabilityGetFlags(ReachRef, &flags)) 
-    { 
-        LogMsg("ERROR: AddrRequiresPPPConnection - SCNetworkReachabilityGetFlags"); 
-        goto end; 
-    }
-    result = flags & kSCNetworkFlagsConnectionRequired;
-
-end:
-    if (ReachRef) 
-        CFRelease(ReachRef);
-    return result;
-}
-
-// Set traffic class for socket
-mDNSlocal void setTrafficClass(int socketfd, mDNSBool useBackgroundTrafficClass)
-{
-    int traffic_class;
-
-    if (useBackgroundTrafficClass)
-        traffic_class = SO_TC_BK_SYS;
-    else
-        traffic_class = SO_TC_CTL;
-
-    (void) setsockopt(socketfd, SOL_SOCKET, SO_TRAFFIC_CLASS, (void *)&traffic_class, sizeof(traffic_class));
-}
-
-mDNSexport void mDNSPlatformSetDelegatePID(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q)
-{
-    if (src)
-    {
-        int s;
-
-        if (dst->type == mDNSAddrType_IPv4)
-        {
-            s = src->ss.sktv4;
-        }
-        else
-        {
-            s = src->ss.sktv6;
-        }
-
-        if (q->pid)
-        {
-            if (setsockopt(s, SOL_SOCKET, SO_DELEGATED, &q->pid, sizeof(q->pid)) == -1)
-            {
-                LogInfo("mDNSPlatformSetDelegatePID: Delegate PID failed %s for PID %d", strerror(errno), q->pid);
-            }
-        }
-        else
-        {
-            if (setsockopt(s, SOL_SOCKET, SO_DELEGATED_UUID, &q->uuid, sizeof(q->uuid)) == -1)
-            {
-                LogInfo("mDNSPlatformSetDelegatePID: Delegate UUID failed %s", strerror(errno));
-            }
-        }
-    }
-}
-
-// 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"
-// OR send via our primary v4 unicast socket
-// UPDATE: The UDPSocket *src parameter now allows the caller to specify the source socket
-mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
-                                       mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, 
-                                       mDNSIPPort dstPort, mDNSBool useBackgroundTrafficClass)
-{
-    NetworkInterfaceInfoOSX *info = mDNSNULL;
-    struct sockaddr_storage to;
-    int s = -1, err;
-    mStatus result = mStatus_NoError;
-
-    if (InterfaceID)
-    {
-        info = IfindexToInterfaceInfoOSX(m, InterfaceID);
-        if (info == NULL)
-        {
-            // We may not have registered interfaces with the "core" as we may not have
-            // seen any interface notifications yet. This typically happens during wakeup
-            // where we might try to send DNS requests (non-SuppressUnusable questions internal
-            // to mDNSResponder) before we receive network notifications.
-            LogInfo("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
-            return mStatus_BadParamErr;
-        }
-    }
-
-    char *ifa_name = InterfaceID ? info->ifinfo.ifname : "unicast";
-
-    if (dst->type == mDNSAddrType_IPv4)
-    {
-        struct sockaddr_in *sin_to = (struct sockaddr_in*)&to;
-        sin_to->sin_len            = sizeof(*sin_to);
-        sin_to->sin_family         = AF_INET;
-        sin_to->sin_port           = dstPort.NotAnInteger;
-        sin_to->sin_addr.s_addr    = dst->ip.v4.NotAnInteger;
-        s = (src ? src->ss : m->p->permanentsockets).sktv4;
-
-        if (info)   // Specify outgoing interface
-        {
-            if (!mDNSAddrIsDNSMulticast(dst))
-            {
-                #ifdef IP_BOUND_IF
-                if (info->scope_id == 0)
-                    LogInfo("IP_BOUND_IF socket option not set -- info %p (%s) scope_id is zero", info, ifa_name);
-                else
-                    setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
-                #else
-                {
-                    static int displayed = 0;
-                    if (displayed < 1000)
-                    {
-                        displayed++;
-                        LogInfo("IP_BOUND_IF socket option not defined -- cannot specify interface for unicast packets");
-                    }
-                }
-                #endif
-            }
-            else
-                #ifdef IP_MULTICAST_IFINDEX
-            {
-                err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IFINDEX, &info->scope_id, sizeof(info->scope_id));
-                // We get an error when we compile on a machine that supports this option and run the binary on
-                // a different machine that does not support it
-                if (err < 0)
-                {
-                    if (errno != ENOPROTOOPT) LogInfo("mDNSPlatformSendUDP: setsockopt: IP_MUTLTICAST_IFINDEX returned %d", errno);
-                    err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &info->ifa_v4addr, sizeof(info->ifa_v4addr));
-                    if (err < 0 && !m->p->NetworkChanged)
-                        LogMsg("setsockopt - IP_MULTICAST_IF error %.4a %d errno %d (%s)", &info->ifa_v4addr, err, errno, strerror(errno));
-                }
-            }
-                #else
-            {
-                err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &info->ifa_v4addr, sizeof(info->ifa_v4addr));
-                if (err < 0 && !m->p->NetworkChanged)
-                    LogMsg("setsockopt - IP_MULTICAST_IF error %.4a %d errno %d (%s)", &info->ifa_v4addr, err, errno, strerror(errno));
-
-            }
-                #endif
-        }
-    }
-
-    else if (dst->type == mDNSAddrType_IPv6)
-    {
-        struct sockaddr_in6 *sin6_to = (struct sockaddr_in6*)&to;
-        sin6_to->sin6_len            = sizeof(*sin6_to);
-        sin6_to->sin6_family         = AF_INET6;
-        sin6_to->sin6_port           = dstPort.NotAnInteger;
-        sin6_to->sin6_flowinfo       = 0;
-        sin6_to->sin6_addr           = *(struct in6_addr*)&dst->ip.v6;
-        sin6_to->sin6_scope_id       = info ? info->scope_id : 0;
-        s = (src ? src->ss : m->p->permanentsockets).sktv6;
-        if (info && mDNSAddrIsDNSMulticast(dst))    // Specify outgoing interface
-        {
-            err = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &info->scope_id, sizeof(info->scope_id));
-            if (err < 0)
-            {
-                char name[IFNAMSIZ];
-                if (if_indextoname(info->scope_id, name) != NULL)
-                    LogMsg("setsockopt - IPV6_MULTICAST_IF error %d errno %d (%s)", err, errno, strerror(errno));
-                else
-                    LogInfo("setsockopt - IPV6_MUTLICAST_IF scopeid %d, not a valid interface", info->scope_id);
-            }
-        }
-    }
-
-    else
-    {
-        LogMsg("mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!");
-#if ForceAlerts
-        *(long*)0 = 0;
-#endif
-        return mStatus_BadParamErr;
-    }
-
-    if (s >= 0)
-        verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %p %5s/%ld to %#a:%d skt %d",
-                      InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s);
-    else
-        verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %p %5s/%ld (socket of this type not available)",
-                      InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort));
-
-    // Note: When sending, mDNSCore may often ask us to send both a v4 multicast packet and then a v6 multicast packet
-    // If we don't have the corresponding type of socket available, then return mStatus_Invalid
-    if (s < 0) return(mStatus_Invalid);
-
-    // switch to background traffic class for this message if requested
-    if (useBackgroundTrafficClass)
-        setTrafficClass(s, useBackgroundTrafficClass);
-
-    err = sendto(s, msg, (UInt8*)end - (UInt8*)msg, 0, (struct sockaddr *)&to, to.ss_len);
-
-    // set traffic class back to default value
-    if (useBackgroundTrafficClass)
-        setTrafficClass(s, mDNSfalse);
-
-    if (err < 0)
-    {
-        static int MessageCount = 0;
-        // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
-        if (!mDNSAddressIsAllDNSLinkGroup(dst))
-            if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
-        // Don't report EHOSTUNREACH in the first three minutes after boot
-        // This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
-        // but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
-        if (errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(mStatus_TransientErr);
-        // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
-        if (errno == EADDRNOTAVAIL && m->p->NetworkChanged) return(mStatus_TransientErr);
-        if (errno == EHOSTUNREACH || errno == EADDRNOTAVAIL || errno == ENETDOWN)
-            LogInfo("mDNSPlatformSendUDP sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu",
-                    s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow));
-        else
-        {
-            MessageCount++;
-            if (MessageCount < 50)  // Cap and ensure NO spamming of LogMsgs
-                LogMsg("mDNSPlatformSendUDP: sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu MessageCount is %d",
-                       s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow), MessageCount);
-            else  // If logging is enabled, remove the cap and log aggressively
-                LogInfo("mDNSPlatformSendUDP: sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu MessageCount is %d",
-                        s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow), MessageCount);
-        }
-
-        result = mStatus_UnknownErr;
-    }
-
-#ifdef IP_BOUND_IF
-    if (dst->type == mDNSAddrType_IPv4 && info && !mDNSAddrIsDNSMulticast(dst))
-    {
-        static const mDNSu32 ifindex = 0;
-        setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex));
-    }
-#endif
-
-    return(result);
-}
-
-mDNSexport 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[IF_NAMESIZE], mDNSu8 *ttl)
-{
-    static unsigned int numLogMessages = 0;
-    struct iovec databuffers = { (char *)buffer, max };
-    struct msghdr msg;
-    ssize_t n;
-    struct cmsghdr *cmPtr;
-    char ancillary[1024];
-
-    *ttl = 255;  // If kernel fails to provide TTL data (e.g. Jaguar doesn't) then assume the TTL was 255 as it should be
-
-    // Set up the message
-    msg.msg_name       = (caddr_t)from;
-    msg.msg_namelen    = *fromlen;
-    msg.msg_iov        = &databuffers;
-    msg.msg_iovlen     = 1;
-    msg.msg_control    = (caddr_t)&ancillary;
-    msg.msg_controllen = sizeof(ancillary);
-    msg.msg_flags      = 0;
-
-    // Receive the data
-    n = recvmsg(s, &msg, 0);
-    if (n<0)
-    {
-        if (errno != EWOULDBLOCK && numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned error %d errno %d", s, n, errno);
-        return(-1);
-    }
-    if (msg.msg_controllen < (int)sizeof(struct cmsghdr))
-    {
-        if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned %d msg.msg_controllen %d < sizeof(struct cmsghdr) %lu, errno %d",
-                                           s, n, msg.msg_controllen, sizeof(struct cmsghdr), errno);
-        return(-1);
-    }
-    if (msg.msg_flags & MSG_CTRUNC)
-    {
-        if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s);
-        return(-1);
-    }
-
-    *fromlen = msg.msg_namelen;
-
-    // Parse each option out of the ancillary data.
-    for (cmPtr = CMSG_FIRSTHDR(&msg); cmPtr; cmPtr = CMSG_NXTHDR(&msg, cmPtr))
-    {
-        // debugf("myrecvfrom cmsg_level %d cmsg_type %d", cmPtr->cmsg_level, cmPtr->cmsg_type);
-        if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVDSTADDR)
-        {
-            dstaddr->type = mDNSAddrType_IPv4;
-            dstaddr->ip.v4 = *(mDNSv4Addr*)CMSG_DATA(cmPtr);
-            //LogMsg("mDNSMacOSX.c: recvmsg IP_RECVDSTADDR %.4a", &dstaddr->ip.v4);
-        }
-        if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVIF)
-        {
-            struct sockaddr_dl *sdl = (struct sockaddr_dl *)CMSG_DATA(cmPtr);
-            if (sdl->sdl_nlen < IF_NAMESIZE)
-            {
-                mDNSPlatformMemCopy(ifname, sdl->sdl_data, sdl->sdl_nlen);
-                ifname[sdl->sdl_nlen] = 0;
-                // debugf("IP_RECVIF sdl_index %d, sdl_data %s len %d", sdl->sdl_index, ifname, sdl->sdl_nlen);
-            }
-        }
-        if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVTTL)
-            *ttl = *(u_char*)CMSG_DATA(cmPtr);
-        if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_PKTINFO)
-        {
-            struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmPtr);
-            dstaddr->type = mDNSAddrType_IPv6;
-            dstaddr->ip.v6 = *(mDNSv6Addr*)&ip6_info->ipi6_addr;
-            myIfIndexToName(ip6_info->ipi6_ifindex, ifname);
-        }
-        if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_HOPLIMIT)
-            *ttl = *(int*)CMSG_DATA(cmPtr);
-    }
-
-    return(n);
-}
-
-mDNSlocal mDNSInterfaceID FindMyInterface(mDNS *const m, const mDNSAddr *addr)
-{
-    NetworkInterfaceInfo *intf;
-
-    if (addr->type == mDNSAddrType_IPv4)
-    {
-        for (intf = m->HostInterfaces; intf; intf = intf->next)
-        {
-            if (intf->ip.type == addr->type && intf->McastTxRx)
-            {
-                if ((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) == 0)
-                {
-                    return(intf->InterfaceID);
-                }
-            }
-        }
-    }
-
-    if (addr->type == mDNSAddrType_IPv6)
-    {
-        for (intf = m->HostInterfaces; intf; intf = intf->next)
-        {
-            if (intf->ip.type == addr->type && intf->McastTxRx)
-            {
-                if (((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) == 0) &&
-                    ((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) == 0) &&
-                    ((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) == 0) &&
-                    (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) == 0)))
-                    {
-                        return(intf->InterfaceID);
-                    }
-            }
-        }
-    }
-    return(mDNSInterface_Any);
-}
-
-mDNSexport mDNSBool mDNSPlatformPeekUDP(mDNS *const m, UDPSocket *src)
-{
-    // We should have a DNSMessage header followed by the question and an answer
-    // which also includes a CNAME (that's when this function is called).  To keep it
-    // simple, we expect at least the size of DNSMessage header(12) and size of "A"
-    // record (14 bytes).
-    char buffer[26];
-    int ret;
-
-    (void) m;
-
-    if (!src)
-        return mDNSfalse;
-
-    ret = recv(src->ss.sktv4, buffer, sizeof(buffer), MSG_PEEK);
-    if (ret > 0)
-        return mDNStrue;
-    else
-        return mDNSfalse;
-}
-
-mDNSexport void myKQSocketCallBack(int s1, short filter, void *context)
-{
-    KQSocketSet *const ss = (KQSocketSet *)context;
-    mDNS *const m = ss->m;
-    int err = 0, count = 0, closed = 0;
-
-    if (filter != EVFILT_READ)
-        LogMsg("myKQSocketCallBack: Why is filter %d not EVFILT_READ (%d)?", filter, EVFILT_READ);
-
-    if (s1 != ss->sktv4 && s1 != ss->sktv6)
-    {
-        LogMsg("myKQSocketCallBack: native socket %d", s1);
-        LogMsg("myKQSocketCallBack: sktv4 %d sktv6 %d", ss->sktv4, ss->sktv6);
-    }
-
-    while (!closed)
-    {
-        mDNSAddr senderAddr, destAddr;
-        mDNSIPPort senderPort;
-        struct sockaddr_storage from;
-        size_t fromlen = sizeof(from);
-        char packetifname[IF_NAMESIZE] = "";
-        mDNSu8 ttl;
-        err = myrecvfrom(s1, &m->imsg, sizeof(m->imsg), (struct sockaddr *)&from, &fromlen, &destAddr, packetifname, &ttl);
-        if (err < 0) break;
-
-        count++;
-        if (from.ss_family == AF_INET)
-        {
-            struct sockaddr_in *s = (struct sockaddr_in*)&from;
-            senderAddr.type = mDNSAddrType_IPv4;
-            senderAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
-            senderPort.NotAnInteger = s->sin_port;
-            //LogInfo("myKQSocketCallBack received IPv4 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
-        }
-        else if (from.ss_family == AF_INET6)
-        {
-            struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&from;
-            senderAddr.type = mDNSAddrType_IPv6;
-            senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
-            senderPort.NotAnInteger = sin6->sin6_port;
-            //LogInfo("myKQSocketCallBack received IPv6 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
-        }
-        else
-        {
-            LogMsg("myKQSocketCallBack from is unknown address family %d", from.ss_family);
-            return;
-        }
-
-        // Note: When handling multiple packets in a batch, MUST reset InterfaceID before handling each packet
-        mDNSInterfaceID InterfaceID = mDNSNULL;
-        NetworkInterfaceInfoOSX *intf = m->p->InterfaceList;
-        while (intf) 
-        {
-            if (intf->Exists && !strcmp(intf->ifinfo.ifname, packetifname))
-                break;
-            intf = intf->next;
-        }
-
-        // When going to sleep we deregister all our interfaces, but if the machine
-        // takes a few seconds to sleep we may continue to receive multicasts
-        // during that time, which would confuse mDNSCoreReceive, because as far
-        // as it's concerned, we should have no active interfaces any more.
-        // Hence we ignore multicasts for which we can find no matching InterfaceID.
-        if (intf)
-            InterfaceID = intf->ifinfo.InterfaceID;
-        else if (mDNSAddrIsDNSMulticast(&destAddr))
-            continue;
-
-        if (!InterfaceID)
-        {
-            InterfaceID = FindMyInterface(m, &destAddr);
-        }
-
-//		LogMsg("myKQSocketCallBack got packet from %#a to %#a on interface %#a/%s",
-//			&senderAddr, &destAddr, &ss->info->ifinfo.ip, ss->info->ifinfo.ifname);
-
-        // mDNSCoreReceive may close the socket we're reading from.  We must break out of our
-        // loop when that happens, or we may try to read from an invalid FD.  We do this by
-        // setting the closeFlag pointer in the socketset, so CloseSocketSet can inform us
-        // if it closes the socketset.
-        ss->closeFlag = &closed;
-
-        if (ss->proxy)
-        {
-            m->p->UDPProxyCallback(m, &m->p->UDPProxy, (unsigned char *)&m->imsg, (unsigned char*)&m->imsg + err, &senderAddr,
-                senderPort, &destAddr, ss->port, InterfaceID, NULL);
-        }
-        else
-        {
-            mDNSCoreReceive(m, &m->imsg, (unsigned char*)&m->imsg + err, &senderAddr, senderPort, &destAddr, ss->port, InterfaceID);
-        }
-
-        // if we didn't close, we can safely dereference the socketset, and should to
-        // reset the closeFlag, since it points to something on the stack
-        if (!closed) ss->closeFlag = mDNSNULL;
-    }
-
-    if (err < 0 && (errno != EWOULDBLOCK || count == 0))
-    {
-        // Something is busted here.
-        // kqueue says there is a packet, but myrecvfrom says there is not.
-        // Try calling select() to get another opinion.
-        // Find out about other socket parameter that can help understand why select() says the socket is ready for read
-        // All of this is racy, as data may have arrived after the call to select()
-        static unsigned int numLogMessages = 0;
-        int save_errno = errno;
-        int so_error = -1;
-        int so_nread = -1;
-        int fionread = -1;
-        socklen_t solen = sizeof(int);
-        fd_set readfds;
-        struct timeval timeout;
-        int selectresult;
-        FD_ZERO(&readfds);
-        FD_SET(s1, &readfds);
-        timeout.tv_sec  = 0;
-        timeout.tv_usec = 0;
-        selectresult = select(s1+1, &readfds, NULL, NULL, &timeout);
-        if (getsockopt(s1, SOL_SOCKET, SO_ERROR, &so_error, &solen) == -1)
-            LogMsg("myKQSocketCallBack getsockopt(SO_ERROR) error %d", errno);
-        if (getsockopt(s1, SOL_SOCKET, SO_NREAD, &so_nread, &solen) == -1)
-            LogMsg("myKQSocketCallBack getsockopt(SO_NREAD) error %d", errno);
-        if (ioctl(s1, FIONREAD, &fionread) == -1)
-            LogMsg("myKQSocketCallBack ioctl(FIONREAD) error %d", errno);
-        if (numLogMessages++ < 100)
-            LogMsg("myKQSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d",
-                   s1, err, save_errno, strerror(save_errno), selectresult, FD_ISSET(s1, &readfds) ? "" : "*NO* ", so_error, so_nread, fionread, count);
-        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 at group.apple.com. (Note number is different.)\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
-    }
-}
-
-mDNSlocal void doTcpSocketCallback(TCPSocket *sock)
-{
-    mDNSBool c = !sock->connected;
-    sock->connected = mDNStrue;
-    sock->callback(sock, sock->context, c, sock->err);
-    // Note: the callback may call CloseConnection here, which frees the context structure!
-}
-
-#ifndef NO_SECURITYFRAMEWORK
-
-mDNSlocal OSStatus tlsWriteSock(SSLConnectionRef connection, const void *data, size_t *dataLength)
-{
-    int ret = send(((TCPSocket *)connection)->fd, data, *dataLength, 0);
-    if (ret >= 0 && (size_t)ret < *dataLength) { *dataLength = ret; return(errSSLWouldBlock); }
-    if (ret >= 0)                              { *dataLength = ret; return(noErr); }
-    *dataLength = 0;
-    if (errno == EAGAIN                      ) return(errSSLWouldBlock);
-    if (errno == ENOENT                      ) return(errSSLClosedGraceful);
-    if (errno == EPIPE || errno == ECONNRESET) return(errSSLClosedAbort);
-    LogMsg("ERROR: tlsWriteSock: %d error %d (%s)\n", ((TCPSocket *)connection)->fd, errno, strerror(errno));
-    return(errSSLClosedAbort);
-}
-
-mDNSlocal OSStatus tlsReadSock(SSLConnectionRef connection, void *data, size_t *dataLength)
-{
-    int ret = recv(((TCPSocket *)connection)->fd, data, *dataLength, 0);
-    if (ret > 0 && (size_t)ret < *dataLength) { *dataLength = ret; return(errSSLWouldBlock); }
-    if (ret > 0)                              { *dataLength = ret; return(noErr); }
-    *dataLength = 0;
-    if (ret == 0 || errno == ENOENT    ) return(errSSLClosedGraceful);
-    if (            errno == EAGAIN    ) return(errSSLWouldBlock);
-    if (            errno == ECONNRESET) return(errSSLClosedAbort);
-    LogMsg("ERROR: tlsSockRead: error %d (%s)\n", errno, strerror(errno));
-    return(errSSLClosedAbort);
-}
-
-mDNSlocal OSStatus tlsSetupSock(TCPSocket *sock, SSLProtocolSide pside, SSLConnectionType ctype)
-{
-    char domname_cstr[MAX_ESCAPED_DOMAIN_NAME];
-
-    sock->tlsContext = SSLCreateContext(kCFAllocatorDefault, pside, ctype);
-    if (!sock->tlsContext) 
-    { 
-        LogMsg("ERROR: tlsSetupSock: SSLCreateContext failed"); 
-        return(mStatus_UnknownErr); 
-    }
-
-    mStatus err = SSLSetIOFuncs(sock->tlsContext, tlsReadSock, tlsWriteSock);
-    if (err) 
-    { 
-        LogMsg("ERROR: tlsSetupSock: SSLSetIOFuncs failed with error code: %d", err); 
-        goto fail; 
-    }
-
-    err = SSLSetConnection(sock->tlsContext, (SSLConnectionRef) sock);
-    if (err) 
-    { 
-        LogMsg("ERROR: tlsSetupSock: SSLSetConnection failed with error code: %d", err); 
-        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);
-    if (err) 
-    { 
-        LogMsg("ERROR: tlsSetupSock: SSLSetAllowAnonymousCiphers failed with error code: %d", err); 
-        goto fail; 
-    }
-
-    // We already checked for NULL in hostname and this should never happen. Hence, returning -1
-    // (error not in OSStatus space) is okay.
-    if (!sock->hostname.c[0]) 
-    {
-        LogMsg("ERROR: tlsSetupSock: hostname NULL"); 
-        err = -1;
-        goto fail;
-    }
-
-    ConvertDomainNameToCString(&sock->hostname, domname_cstr);
-    err = SSLSetPeerDomainName(sock->tlsContext, domname_cstr, strlen(domname_cstr));
-    if (err) 
-    { 
-        LogMsg("ERROR: tlsSetupSock: SSLSetPeerDomainname: %s failed with error code: %d", domname_cstr, err); 
-        goto fail; 
-    }
-
-    return(err);
-
-fail:
-    if (sock->tlsContext)
-        CFRelease(sock->tlsContext);
-    return(err);
-}
-
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-mDNSlocal void doSSLHandshake(TCPSocket *sock)
-{
-    mStatus err = SSLHandshake(sock->tlsContext);
-
-    //Can't have multiple threads in mDNS core. When MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM is
-    //defined, KQueueLock is a noop. Hence we need to serialize here
-    //
-    //NOTE: We just can't serialize doTcpSocketCallback alone on the main queue.
-    //We need the rest of the logic also. Otherwise, we can enable the READ
-    //events below, dispatch a doTcpSocketCallback on the main queue. Assume it is
-    //ConnFailed which means we are going to free the tcpInfo. While it
-    //is waiting to be dispatched, another read event can come into tcpKQSocketCallback
-    //and potentially call doTCPCallback with error which can close the fd and free the
-    //tcpInfo. Later when the thread gets dispatched it will crash because the tcpInfo
-    //is already freed.
-
-    dispatch_async(dispatch_get_main_queue(), ^{
-
-                       LogInfo("doSSLHandshake %p: got lock", sock); // Log *after* we get the lock
-
-                       if (sock->handshake == handshake_to_be_closed)
-                       {
-                           LogInfo("SSLHandshake completed after close");
-                           mDNSPlatformTCPCloseConnection(sock);
-                       }
-                       else
-                       {
-                           if (sock->fd != -1) KQueueSet(sock->fd, EV_ADD, EVFILT_READ, sock->kqEntry);
-                           else LogMsg("doSSLHandshake: sock->fd is -1");
-
-                           if (err == errSSLWouldBlock)
-                               sock->handshake = handshake_required;
-                           else
-                           {
-                               if (err)
-                               {
-                                   LogMsg("SSLHandshake failed: %d%s", err, err == errSSLPeerInternalError ? " (server busy)" : "");
-                                   CFRelease(sock->tlsContext);
-                                   sock->tlsContext = NULL;
-                               }
-
-                               sock->err = err ? mStatus_ConnFailed : 0;
-                               sock->handshake = handshake_completed;
-
-                               LogInfo("doSSLHandshake: %p calling doTcpSocketCallback fd %d", sock, sock->fd);
-                               doTcpSocketCallback(sock);
-                           }
-                       }
-
-                       LogInfo("SSLHandshake %p: dropping lock for fd %d", sock, sock->fd);
-                       return;
-                   });
-}
-#else // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-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);
-    debugf("doSSLHandshake %p: got lock", sock); // Log *after* we get the lock
-
-    if (sock->handshake == handshake_to_be_closed)
-    {
-        LogInfo("SSLHandshake completed after close");
-        mDNSPlatformTCPCloseConnection(sock);
-    }
-    else
-    {
-        if (sock->fd != -1) KQueueSet(sock->fd, EV_ADD, EVFILT_READ, sock->kqEntry);
-        else LogMsg("doSSLHandshake: sock->fd is -1");
-
-        if (err == errSSLWouldBlock)
-            sock->handshake = handshake_required;
-        else
-        {
-            if (err)
-            {
-                LogMsg("SSLHandshake failed: %d%s", err, err == errSSLPeerInternalError ? " (server busy)" : "");
-                CFRelease(sock->tlsContext);
-                sock->tlsContext = NULL;
-            }
-
-            sock->err = err ? mStatus_ConnFailed : 0;
-            sock->handshake = handshake_completed;
-
-            debugf("doSSLHandshake: %p calling doTcpSocketCallback fd %d", sock, sock->fd);
-            doTcpSocketCallback(sock);
-        }
-    }
-
-    debugf("SSLHandshake %p: dropping lock for fd %d", sock, sock->fd);
-    KQueueUnlock(m, "doSSLHandshake");
-    return NULL;
-}
-#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-
-mDNSlocal void spawnSSLHandshake(TCPSocket* sock)
-{
-    debugf("spawnSSLHandshake %p: entry", sock);
-
-    if (sock->handshake != handshake_required) LogMsg("spawnSSLHandshake: handshake status not required: %d", sock->handshake);
-    sock->handshake = handshake_in_progress;
-    KQueueSet(sock->fd, EV_DELETE, EVFILT_READ, sock->kqEntry);
-
-    // Dispatch it on a separate queue to help avoid blocking other threads/queues, and
-    // to limit the number of threads used for SSLHandshake
-    dispatch_async(SSLqueue, ^{doSSLHandshake(sock);});
-
-    debugf("spawnSSLHandshake %p: done for %d", sock, sock->fd);
-}
-
-#endif /* NO_SECURITYFRAMEWORK */
-
-mDNSlocal void tcpKQSocketCallback(__unused int fd, short filter, void *context)
-{
-    TCPSocket *sock = context;
-    sock->err = mStatus_NoError;
-
-    //if (filter == EVFILT_READ ) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_READ", filter);
-    //if (filter == EVFILT_WRITE) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_WRITE", filter);
-    // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it here with EV_DELETE
-    if (filter == EVFILT_WRITE) 
-        KQueueSet(sock->fd, EV_DELETE, EVFILT_WRITE, sock->kqEntry);
-
-    if (sock->flags & kTCPSocketFlags_UseTLS)
-    {
-#ifndef NO_SECURITYFRAMEWORK
-        if (!sock->setup) 
-        { 
-            sock->setup = mDNStrue; 
-            sock->err = tlsSetupSock(sock, kSSLClientSide, kSSLStreamType);
-            if (sock->err)
-            {
-                LogMsg("ERROR: tcpKQSocketCallback: tlsSetupSock failed with error code: %d", sock->err);
-                return;
-            }
-        }
-        if (sock->handshake == handshake_required) 
-        { 
-            spawnSSLHandshake(sock); 
-            return;
-        }
-        else if (sock->handshake == handshake_in_progress || sock->handshake == handshake_to_be_closed)
-        {
-            return;
-        }
-        else if (sock->handshake != handshake_completed)
-        {
-            if (!sock->err) 
-                sock->err = mStatus_UnknownErr;
-            LogMsg("tcpKQSocketCallback called with unexpected SSLHandshake status: %d", sock->handshake);
-        }
-#else  /* NO_SECURITYFRAMEWORK */ 
-        sock->err = mStatus_UnsupportedErr;
-#endif /* NO_SECURITYFRAMEWORK */
-    }
-
-    doTcpSocketCallback(sock);
-}
-
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-mDNSexport int KQueueSet(int fd, u_short flags, short filter, KQueueEntry *const entryRef)
-{
-    dispatch_queue_t queue = dispatch_get_main_queue();
-    dispatch_source_t source;
-    if (flags == EV_DELETE)
-    {
-        if (filter == EVFILT_READ)
-        {
-            dispatch_source_cancel(entryRef->readSource);
-            dispatch_release(entryRef->readSource);
-            entryRef->readSource = mDNSNULL;
-            debugf("KQueueSet: source cancel for read %p, %p", entryRef->readSource, entryRef->writeSource);
-        }
-        else if (filter == EVFILT_WRITE)
-        {
-            dispatch_source_cancel(entryRef->writeSource);
-            dispatch_release(entryRef->writeSource);
-            entryRef->writeSource = mDNSNULL;
-            debugf("KQueueSet: source cancel for write %p, %p", entryRef->readSource, entryRef->writeSource);
-        }
-        else
-            LogMsg("KQueueSet: ERROR: Wrong filter value %d for EV_DELETE", filter);
-        return 0;
-    }
-    if (flags != EV_ADD) LogMsg("KQueueSet: Invalid flags %d", flags);
-
-    if (filter == EVFILT_READ)
-    {
-        source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, queue);
-    }
-    else if (filter == EVFILT_WRITE)
-    {
-        source = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, fd, 0, queue);
-    }
-    else
-    {
-        LogMsg("KQueueSet: ERROR: Wrong filter value %d for EV_ADD", filter);
-        return -1;
-    }
-    if (!source) return -1;
-    dispatch_source_set_event_handler(source, ^{
-
-                                          mDNSs32 stime = mDNSPlatformRawTime();
-                                          entryRef->KQcallback(fd, filter, entryRef->KQcontext);
-                                          mDNSs32 etime = mDNSPlatformRawTime();
-                                          if (etime - stime >= WatchDogReportingThreshold)
-                                              LogInfo("KQEntryCallback Block: WARNING: took %dms to complete", etime - stime);
-
-                                          // Trigger the event delivery to the application. Even though we trigger the
-                                          // event completion after handling every event source, these all will hopefully
-                                          // get merged
-                                          TriggerEventCompletion();
-
-                                      });
-    dispatch_source_set_cancel_handler(source, ^{
-                                           if (entryRef->fdClosed)
-                                           {
-                                               //LogMsg("CancelHandler: closing fd %d", fd);
-                                               close(fd);
-                                           }
-                                       });
-    dispatch_resume(source);
-    if (filter == EVFILT_READ)
-        entryRef->readSource = source;
-    else
-        entryRef->writeSource = source;
-
-    return 0;
-}
-
-mDNSexport void KQueueLock(mDNS *const m)
-{
-    (void)m; //unused
-}
-mDNSexport void KQueueUnlock(mDNS *const m, const char const *task)
-{
-    (void)m; //unused
-    (void)task; //unused
-}
-#else
-mDNSexport int KQueueSet(int fd, u_short flags, short filter, const KQueueEntry *const entryRef)
-{
-    struct kevent new_event;
-    EV_SET(&new_event, fd, filter, flags, 0, 0, (void*)entryRef);
-    return (kevent(KQueueFD, &new_event, 1, NULL, 0, NULL) < 0) ? errno : 0;
-}
-
-mDNSexport void KQueueLock(mDNS *const m)
-{
-    pthread_mutex_lock(&m->p->BigMutex);
-    m->p->BigMutexStartTime = mDNSPlatformRawTime();
-}
-
-mDNSexport void KQueueUnlock(mDNS *const m, const char* task)
-{
-    mDNSs32 end = mDNSPlatformRawTime();
-    (void)task;
-    if (end - m->p->BigMutexStartTime >= WatchDogReportingThreshold)
-        LogInfo("WARNING: %s took %dms to complete", task, end - m->p->BigMutexStartTime);
-
-    pthread_mutex_unlock(&m->p->BigMutex);
-
-    char wake = 1;
-    if (send(m->p->WakeKQueueLoopFD, &wake, sizeof(wake), 0) == -1)
-        LogMsg("ERROR: KQueueWake: send failed with error code: %d (%s)", errno, strerror(errno));
-}
-#endif
-
-mDNSexport void mDNSPlatformCloseFD(KQueueEntry *kq, int fd)
-{
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-        (void) fd; //unused
-    if (kq->readSource)
-    {
-        dispatch_source_cancel(kq->readSource);
-        kq->readSource = mDNSNULL;
-    }
-    if (kq->writeSource)
-    {
-        dispatch_source_cancel(kq->writeSource);
-        kq->writeSource = mDNSNULL;
-    }
-    // Close happens in the cancellation handler
-    debugf("mDNSPlatformCloseFD: resetting sources for %d", fd);
-    kq->fdClosed = mDNStrue;
-#else
-    (void)kq; //unused
-    close(fd);
-#endif
-}
-
-mDNSlocal mStatus SetupTCPSocket(TCPSocket *sock, u_short sa_family, mDNSIPPort *port, mDNSBool useBackgroundTrafficClass)
-{
-    KQSocketSet *cp = &sock->ss;
-    int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
-    KQueueEntry *k        = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
-    const int on = 1;  // "on" for setsockopt
-    mStatus err;
-
-    int skt = socket(sa_family, SOCK_STREAM, IPPROTO_TCP);
-    if (skt < 3) { if (errno != EAFNOSUPPORT) LogMsg("SetupTCPSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno));return(skt); }
-
-    // for TCP sockets, the traffic class is set once and not changed
-    setTrafficClass(skt, useBackgroundTrafficClass);
-
-    if (sa_family == AF_INET)
-    {
-        // Bind it
-        struct sockaddr_in addr;
-        mDNSPlatformMemZero(&addr, sizeof(addr));
-        addr.sin_family = AF_INET;
-        addr.sin_port = port->NotAnInteger;
-        err = bind(skt, (struct sockaddr*) &addr, sizeof(addr));
-        if (err < 0) { LogMsg("ERROR: bind %s", strerror(errno)); return err; }
-
-        // Receive interface identifiers
-        err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
-        if (err < 0) { LogMsg("setsockopt IP_RECVIF - %s", strerror(errno)); return err; }
-
-        mDNSPlatformMemZero(&addr, sizeof(addr));
-        socklen_t len = sizeof(addr);
-        err = getsockname(skt, (struct sockaddr*) &addr, &len);
-        if (err < 0) { LogMsg("getsockname - %s", strerror(errno)); return err; }
-
-        port->NotAnInteger = addr.sin_port;
-    }
-    else
-    {
-        // Bind it
-        struct sockaddr_in6 addr6;
-        mDNSPlatformMemZero(&addr6, sizeof(addr6));
-        addr6.sin6_family = AF_INET6;
-        addr6.sin6_port = port->NotAnInteger;
-        err = bind(skt, (struct sockaddr*) &addr6, sizeof(addr6));
-        if (err < 0) { LogMsg("ERROR: bind6 %s", strerror(errno)); return err; }
-
-        // We want to receive destination addresses and receive interface identifiers
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
-        if (err < 0) { LogMsg("ERROR: setsockopt IPV6_RECVPKTINFO %s", strerror(errno)); return err; }
-
-        mDNSPlatformMemZero(&addr6, sizeof(addr6));
-        socklen_t len = sizeof(addr6);
-        err = getsockname(skt, (struct sockaddr *) &addr6, &len);
-        if (err < 0) { LogMsg("getsockname6 - %s", strerror(errno)); return err; }
-
-        port->NotAnInteger = addr6.sin6_port;
-
-    }
-    *s = skt;
-    k->KQcallback = tcpKQSocketCallback;
-    k->KQcontext  = sock;
-    k->KQtask     = "mDNSPlatformTCPSocket";
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    k->readSource = mDNSNULL;
-    k->writeSource = mDNSNULL;
-    k->fdClosed = mDNSfalse;
-#endif
-    return mStatus_NoError;
-}
-
-mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, 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.sktv4 = -1;
-    sock->ss.sktv6 = -1;
-    err = SetupTCPSocket(sock, AF_INET, port, useBackgroundTrafficClass);
-
-    if (!err)
-    {
-        err = SetupTCPSocket(sock, AF_INET6, port, useBackgroundTrafficClass);
-        if (err) { mDNSPlatformCloseFD(&sock->ss.kqsv4, sock->ss.sktv4); sock->ss.sktv4 = -1; }
-    }
-    if (err)
-    {
-        LogMsg("mDNSPlatformTCPSocket: socket error %d errno %d (%s)", sock->fd, errno, strerror(errno));
-        freeL("TCPSocket/mDNSPlatformTCPSocket", sock);
-        return(mDNSNULL);
-    }
-    // sock->fd is used as the default fd  if the caller does not call mDNSPlatformTCPConnect
-    sock->fd                = sock->ss.sktv4;
-    sock->callback          = mDNSNULL;
-    sock->flags             = flags;
-    sock->context           = mDNSNULL;
-    sock->setup             = mDNSfalse;
-    sock->connected         = mDNSfalse;
-    sock->handshake         = handshake_required;
-    sock->m                 = m;
-    sock->err               = mStatus_NoError;
-
-    return sock;
-}
-
-mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname, mDNSInterfaceID InterfaceID, TCPConnectionCallback callback, void *context)
-{
-    KQSocketSet *cp = &sock->ss;
-    int         *s        = (dst->type == mDNSAddrType_IPv4) ? &cp->sktv4 : &cp->sktv6;
-    KQueueEntry *k        = (dst->type == mDNSAddrType_IPv4) ? &cp->kqsv4 : &cp->kqsv6;
-    mStatus err = mStatus_NoError;
-    struct sockaddr_storage ss;
-
-    sock->callback          = callback;
-    sock->context           = context;
-    sock->setup             = mDNSfalse;
-    sock->connected         = mDNSfalse;
-    sock->handshake         = handshake_required;
-    sock->err               = mStatus_NoError;
-
-    if (hostname) { debugf("mDNSPlatformTCPConnect: hostname %##s", hostname->c); AssignDomainName(&sock->hostname, hostname); }
-
-    if (dst->type == mDNSAddrType_IPv4)
-    {
-        struct sockaddr_in *saddr = (struct sockaddr_in *)&ss;
-        mDNSPlatformMemZero(saddr, sizeof(*saddr));
-        saddr->sin_family      = AF_INET;
-        saddr->sin_port        = dstport.NotAnInteger;
-        saddr->sin_len         = sizeof(*saddr);
-        saddr->sin_addr.s_addr = dst->ip.v4.NotAnInteger;
-    }
-    else
-    {
-        struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&ss;
-        mDNSPlatformMemZero(saddr6, sizeof(*saddr6));
-        saddr6->sin6_family      = AF_INET6;
-        saddr6->sin6_port        = dstport.NotAnInteger;
-        saddr6->sin6_len         = sizeof(*saddr6);
-        saddr6->sin6_addr        = *(struct in6_addr *)&dst->ip.v6;
-    }
-
-    // Watch for connect complete (write is ready)
-    // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it in tcpKQSocketCallback using EV_DELETE
-    if (KQueueSet(*s, EV_ADD /* | EV_ONESHOT */, EVFILT_WRITE, k))
-    {
-        LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
-        return errno;
-    }
-
-    // Watch for incoming data
-    if (KQueueSet(*s, EV_ADD, EVFILT_READ, k))
-    {
-        LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
-        return errno;
-    }
-
-    if (fcntl(*s, F_SETFL, fcntl(*s, F_GETFL, 0) | O_NONBLOCK) < 0) // set non-blocking
-    {
-        LogMsg("ERROR: setsockopt O_NONBLOCK - %s", strerror(errno));
-        return mStatus_UnknownErr;
-    }
-
-    // We bind to the interface and all subsequent packets including the SYN will be sent out
-    // on this interface
-    //
-    // Note: If we are in Active Directory domain, we may try TCP (if the response can't fit in
-    // UDP). mDNSInterface_Unicast indicates this case and not a valid interface.
-    if (InterfaceID && InterfaceID != mDNSInterface_Unicast)
-    {
-        NetworkInterfaceInfoOSX *info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
-        if (dst->type == mDNSAddrType_IPv4)
-        {
-        #ifdef IP_BOUND_IF
-            if (info) setsockopt(*s, IPPROTO_IP, IP_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
-            else { LogMsg("mDNSPlatformTCPConnect: Invalid interface index %p", InterfaceID); return mStatus_BadParamErr; }
-        #else
-            (void)InterfaceID; // Unused
-            (void)info; // Unused
-        #endif
-        }
-        else
-        {
-        #ifdef IPV6_BOUND_IF
-            if (info) setsockopt(*s, IPPROTO_IPV6, IPV6_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
-            else { LogMsg("mDNSPlatformTCPConnect: Invalid interface index %p", InterfaceID); return mStatus_BadParamErr; }
-        #else
-            (void)InterfaceID; // Unused
-            (void)info; // Unused
-        #endif
-        }
-    }
-
-    // mDNSPlatformReadTCP/WriteTCP (unlike the UDP counterpart) does not provide the destination address
-    // from which we can infer the destination address family. Hence we need to remember that here.
-    // Instead of remembering the address family, we remember the right fd.
-    sock->fd = *s;
-    sock->kqEntry = k;
-    // initiate connection wth peer
-    if (connect(*s, (struct sockaddr *)&ss, ss.ss_len) < 0)
-    {
-        if (errno == EINPROGRESS) return mStatus_ConnPending;
-        if (errno == EHOSTUNREACH || errno == EADDRNOTAVAIL || errno == ENETDOWN)
-            LogInfo("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s)", sock->fd, errno, strerror(errno));
-        else
-            LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s) length %d", sock->fd, errno, strerror(errno), ss.ss_len);
-        return mStatus_ConnFailed;
-    }
-
-    LogMsg("NOTE: mDNSPlatformTCPConnect completed synchronously");
-    // kQueue should notify us, but this LogMsg is to help track down if it doesn't
-    return err;
-}
-
-// Why doesn't mDNSPlatformTCPAccept actually call accept() ?
-mDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int fd)
-{
-    mStatus err = mStatus_NoError;
-
-    TCPSocket *sock = mallocL("TCPSocket/mDNSPlatformTCPAccept", sizeof(TCPSocket));
-    if (!sock) return(mDNSNULL);
-
-    mDNSPlatformMemZero(sock, sizeof(*sock));
-    sock->fd = fd;
-    sock->flags = flags;
-
-    if (flags & kTCPSocketFlags_UseTLS)
-    {
-#ifndef NO_SECURITYFRAMEWORK
-        if (!ServerCerts) { LogMsg("ERROR: mDNSPlatformTCPAccept: unable to find TLS certificates"); err = mStatus_UnknownErr; goto exit; }
-
-        err = tlsSetupSock(sock, kSSLServerSide, kSSLStreamType);
-        if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: tlsSetupSock failed with error code: %d", err); goto exit; }
-
-        err = SSLSetCertificate(sock->tlsContext, ServerCerts);
-        if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: SSLSetCertificate failed with error code: %d", err); goto exit; }
-#else
-        err = mStatus_UnsupportedErr;
-#endif /* NO_SECURITYFRAMEWORK */
-    }
-#ifndef NO_SECURITYFRAMEWORK
-exit:
-#endif
-
-    if (err) { freeL("TCPSocket/mDNSPlatformTCPAccept", sock); return(mDNSNULL); }
-    return(sock);
-}
-
-mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
-{
-    mDNSu16 port;
-
-    port = -1;
-    if (sock)
-    {
-        port = sock->ss.port.NotAnInteger;
-    }
-    return port;
-}
-
-mDNSlocal void CloseSocketSet(KQSocketSet *ss)
-{
-    if (ss->sktv4 != -1)
-    {
-        mDNSPlatformCloseFD(&ss->kqsv4,  ss->sktv4);
-        ss->sktv4 = -1;
-    }
-    if (ss->sktv6 != -1)
-    {
-        mDNSPlatformCloseFD(&ss->kqsv6,  ss->sktv6);
-        ss->sktv6 = -1;
-    }
-    if (ss->closeFlag) *ss->closeFlag = 1;
-}
-
-mDNSexport void mDNSPlatformTCPCloseConnection(TCPSocket *sock)
-{
-    if (sock)
-    {
-#ifndef NO_SECURITYFRAMEWORK
-        if (sock->tlsContext)
-        {
-            if (sock->handshake == handshake_in_progress) // SSLHandshake thread using this sock (esp. tlsContext)
-            {
-                LogInfo("mDNSPlatformTCPCloseConnection: called while handshake in progress");
-                // When we come back from SSLHandshake, we will notice that a close was here and
-                // call this function again which will do the cleanup then.
-                sock->handshake = handshake_to_be_closed;
-                return;
-            }
-
-            SSLClose(sock->tlsContext);
-            CFRelease(sock->tlsContext);
-            sock->tlsContext = NULL;
-        }
-#endif /* NO_SECURITYFRAMEWORK */
-        if (sock->ss.sktv4 != -1) 
-            shutdown(sock->ss.sktv4, 2);
-        if (sock->ss.sktv6 != -1) 
-            shutdown(sock->ss.sktv6, 2);
-        CloseSocketSet(&sock->ss);
-        sock->fd = -1;
-
-        freeL("TCPSocket/mDNSPlatformTCPCloseConnection", sock);
-    }
-}
-
-mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed)
-{
-    ssize_t nread = 0;
-    *closed = mDNSfalse;
-
-    if (sock->flags & kTCPSocketFlags_UseTLS)
-    {
-#ifndef NO_SECURITYFRAMEWORK
-        if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformReadTCP called while handshake required"); return 0; }
-        else if (sock->handshake == handshake_in_progress) return 0;
-        else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformReadTCP called with unexpected SSLHandshake status: %d", sock->handshake);
-
-        //LogMsg("Starting SSLRead %d %X", sock->fd, fcntl(sock->fd, F_GETFL, 0));
-        mStatus err = SSLRead(sock->tlsContext, buf, buflen, (size_t *)&nread);
-        //LogMsg("SSLRead returned %d (%d) nread %d buflen %d", err, errSSLWouldBlock, nread, buflen);
-        if (err == errSSLClosedGraceful) { nread = 0; *closed = mDNStrue; }
-        else if (err && err != errSSLWouldBlock)
-        { LogMsg("ERROR: mDNSPlatformReadTCP - SSLRead: %d", err); nread = -1; *closed = mDNStrue; }
-#else
-        nread = -1;
-        *closed = mDNStrue;
-#endif /* NO_SECURITYFRAMEWORK */
-    }
-    else
-    {
-        static int CLOSEDcount = 0;
-        static int EAGAINcount = 0;
-        nread = recv(sock->fd, buf, buflen, 0);
-
-        if (nread > 0) 
-        { 
-            CLOSEDcount = 0; 
-            EAGAINcount = 0; 
-        } // On success, clear our error counters
-        else if (nread == 0)
-        {
-            *closed = mDNStrue;
-            if ((++CLOSEDcount % 1000) == 0) 
-            { 
-                LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got CLOSED %d times", sock->fd, CLOSEDcount); 
-                assert(CLOSEDcount < 1000);
-                // Recovery Mechanism to bail mDNSResponder out of trouble: Instead of logging the same error msg multiple times,
-                // crash mDNSResponder using assert() and restart fresh. See advantages below:
-                // 1.Better User Experience 
-                // 2.CrashLogs frequency can be monitored 
-                // 3.StackTrace can be used for more info
-            }
-        }
-        // else nread is negative -- see what kind of error we got
-        else if (errno == ECONNRESET) { nread = 0; *closed = mDNStrue; }
-        else if (errno != EAGAIN) { LogMsg("ERROR: mDNSPlatformReadTCP - recv: %d (%s)", errno, strerror(errno)); nread = -1; }
-        else // errno is EAGAIN (EWOULDBLOCK) -- no data available
-        {
-            nread = 0;
-            if ((++EAGAINcount % 1000) == 0) { LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got EAGAIN %d times", sock->fd, EAGAINcount); sleep(1); }
-        }
-    }
-
-    return nread;
-}
-
-mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len)
-{
-    int nsent;
-
-    if (sock->flags & kTCPSocketFlags_UseTLS)
-    {
-#ifndef NO_SECURITYFRAMEWORK
-        size_t processed;
-        if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformWriteTCP called while handshake required"); return 0; }
-        if (sock->handshake == handshake_in_progress) return 0;
-        else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformWriteTCP called with unexpected SSLHandshake status: %d", sock->handshake);
-
-        mStatus err = SSLWrite(sock->tlsContext, msg, len, &processed);
-
-        if (!err) nsent = (int) processed;
-        else if (err == errSSLWouldBlock) nsent = 0;
-        else { LogMsg("ERROR: mDNSPlatformWriteTCP - SSLWrite returned %d", err); nsent = -1; }
-#else
-        nsent = -1;
-#endif /* NO_SECURITYFRAMEWORK */
-    }
-    else
-    {
-        nsent = send(sock->fd, msg, len, 0);
-        if (nsent < 0)
-        {
-            if (errno == EAGAIN) nsent = 0;
-            else { LogMsg("ERROR: mDNSPlatformWriteTCP - send %s", strerror(errno)); nsent = -1; }
-        }
-    }
-
-    return nsent;
-}
-
-mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
-{
-    return sock->fd;
-}
-
-// If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
-// If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
-mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa_family, mDNSIPPort *const outport)
-{
-    int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
-    KQueueEntry *k        = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
-    const int on = 1;
-    const int twofivefive = 255;
-    mStatus err = mStatus_NoError;
-    char *errstr = mDNSNULL;
-    const int mtu = 0;
-
-    cp->closeFlag = mDNSNULL;
-
-    int skt = socket(sa_family, SOCK_DGRAM, IPPROTO_UDP);
-    if (skt < 3) { if (errno != EAFNOSUPPORT) LogMsg("SetupSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno));return(skt); }
-
-    // set default traffic class
-    setTrafficClass(skt, mDNSfalse);
-
-#ifdef SO_RECV_ANYIF
-    // Enable inbound packets on IFEF_AWDL interface.
-    // Only done for multicast sockets, since we don't expect unicast socket operations
-    // on the IFEF_AWDL interface. Operation is a no-op for other interface types.
-    if (mDNSSameIPPort(port, MulticastDNSPort)) 
-    {
-        err = setsockopt(skt, SOL_SOCKET, SO_RECV_ANYIF, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - SO_RECV_ANYIF"; goto fail; }
-    }
-#endif // SO_RECV_ANYIF
-
-    // ... with a shared UDP port, if it's for multicast receiving
-    if (mDNSSameIPPort(port, MulticastDNSPort) || mDNSSameIPPort(port, NATPMPAnnouncementPort)) err = setsockopt(skt, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
-    if (err < 0) { errstr = "setsockopt - SO_REUSEPORT"; goto fail; }
-
-    if (sa_family == AF_INET)
-    {
-        // We want to receive destination addresses
-        err = setsockopt(skt, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IP_RECVDSTADDR"; goto fail; }
-
-        // We want to receive interface identifiers
-        err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IP_RECVIF"; goto fail; }
-
-        // We want to receive packet TTL value so we can check it
-        err = setsockopt(skt, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
-        // We ignore errors here -- we already know Jaguar doesn't support this, but we can get by without it
-
-        // Send unicast packets with TTL 255
-        err = setsockopt(skt, IPPROTO_IP, IP_TTL, &twofivefive, sizeof(twofivefive));
-        if (err < 0) { errstr = "setsockopt - IP_TTL"; goto fail; }
-
-        // And multicast packets with TTL 255 too
-        err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive));
-        if (err < 0) { errstr = "setsockopt - IP_MULTICAST_TTL"; goto fail; }
-
-        // And start listening for packets
-        struct sockaddr_in listening_sockaddr;
-        listening_sockaddr.sin_family      = AF_INET;
-        listening_sockaddr.sin_port        = port.NotAnInteger;     // Pass in opaque ID without any byte swapping
-        listening_sockaddr.sin_addr.s_addr = mDNSSameIPPort(port, NATPMPAnnouncementPort) ? AllHosts_v4.NotAnInteger : 0;
-        err = bind(skt, (struct sockaddr *) &listening_sockaddr, sizeof(listening_sockaddr));
-        if (err) { errstr = "bind"; goto fail; }
-        if (outport) outport->NotAnInteger = listening_sockaddr.sin_port;
-    }
-    else if (sa_family == AF_INET6)
-    {
-        // NAT-PMP Announcements make no sense on IPv6, and we don't support IPv6 for PCP, so bail early w/o error
-        if (mDNSSameIPPort(port, NATPMPAnnouncementPort)) { if (outport) *outport = zeroIPPort;return mStatus_NoError; }
-
-        // We want to receive destination addresses and receive interface identifiers
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IPV6_RECVPKTINFO"; goto fail; }
-
-        // We want to receive packet hop count value so we can check it
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IPV6_RECVHOPLIMIT"; goto fail; }
-
-        // We want to receive only IPv6 packets. Without this option we get IPv4 packets too,
-        // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IPV6_V6ONLY"; goto fail; }
-
-        // Send unicast packets with TTL 255
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &twofivefive, sizeof(twofivefive));
-        if (err < 0) { errstr = "setsockopt - IPV6_UNICAST_HOPS"; goto fail; }
-
-        // And multicast packets with TTL 255 too
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &twofivefive, sizeof(twofivefive));
-        if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_HOPS"; goto fail; }
-
-        // Want to receive our own packets
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on, sizeof(on));
-        if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_LOOP"; goto fail; }
-
-        // Disable default option to send mDNSv6 packets at min IPv6 MTU: RFC 3542, Sec 11
-        err = setsockopt(skt, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &mtu, sizeof(mtu));
-        if (err < 0) // Since it is an optimization if we fail just log the err, no need to close the skt
-            LogMsg("SetupSocket: setsockopt - IPV6_USE_MIN_MTU: IP6PO_MINMTU_DISABLE socket %d err %d errno %d (%s)", 
-                    skt, err, errno, strerror(errno));
-        
-        // And start listening for packets
-        struct sockaddr_in6 listening_sockaddr6;
-        mDNSPlatformMemZero(&listening_sockaddr6, sizeof(listening_sockaddr6));
-        listening_sockaddr6.sin6_len         = sizeof(listening_sockaddr6);
-        listening_sockaddr6.sin6_family      = AF_INET6;
-        listening_sockaddr6.sin6_port        = port.NotAnInteger;       // Pass in opaque ID without any byte swapping
-        listening_sockaddr6.sin6_flowinfo    = 0;
-        listening_sockaddr6.sin6_addr        = in6addr_any; // Want to receive multicasts AND unicasts on this socket
-        listening_sockaddr6.sin6_scope_id    = 0;
-        err = bind(skt, (struct sockaddr *) &listening_sockaddr6, sizeof(listening_sockaddr6));
-        if (err) { errstr = "bind"; goto fail; }
-        if (outport) outport->NotAnInteger = listening_sockaddr6.sin6_port;
-    }
-
-    fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
-    fcntl(skt, F_SETFD, 1); // set close-on-exec
-    *s = skt;
-    k->KQcallback = myKQSocketCallBack;
-    k->KQcontext  = cp;
-    k->KQtask     = "UDP packet reception";
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    k->readSource = mDNSNULL;
-    k->writeSource = mDNSNULL;
-    k->fdClosed = mDNSfalse;
-#endif
-    KQueueSet(*s, EV_ADD, EVFILT_READ, k);
-
-    return(err);
-
-fail:
-    // For "bind" failures, only write log messages for our shared mDNS port, or for binding to zero
-    if (strcmp(errstr, "bind") || mDNSSameIPPort(port, MulticastDNSPort) || mDNSIPPortIsZero(port))
-        LogMsg("%s skt %d port %d error %d errno %d (%s)", errstr, skt, mDNSVal16(port), err, errno, strerror(errno));
-
-    // If we got a "bind" failure of EADDRINUSE, inform the caller as it might need to try another random port
-    if (!strcmp(errstr, "bind") && errno == EADDRINUSE)
-    {
-        err = EADDRINUSE;
-        if (mDNSSameIPPort(port, MulticastDNSPort))
-            NotifyOfElusiveBug("Setsockopt SO_REUSEPORT failed",
-                               "Congratulations, you've reproduced an elusive bug.\r"
-                               "Please contact the current assignee of <rdar://problem/3814904>.\r"
-                               "Alternatively, you can send email to radar-3387020 at group.apple.com. (Note number is different.)\r"
-                               "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
-    }
-
-    mDNSPlatformCloseFD(k, skt);
-    return(err);
-}
-
-mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
-{
-    mStatus err;
-    mDNSIPPort port = requestedport;
-    mDNSBool randomizePort = mDNSIPPortIsZero(requestedport);
-    int i = 10000; // Try at most 10000 times to get a unique random port
-    UDPSocket *p = mallocL("UDPSocket", sizeof(UDPSocket));
-    if (!p) { LogMsg("mDNSPlatformUDPSocket: memory exhausted"); return(mDNSNULL); }
-    mDNSPlatformMemZero(p, sizeof(UDPSocket));
-    p->ss.port  = zeroIPPort;
-    p->ss.m     = m;
-    p->ss.sktv4 = -1;
-    p->ss.sktv6 = -1;
-    p->ss.proxy = mDNSfalse;
-
-    do
-    {
-        // The kernel doesn't do cryptographically strong random port allocation, so we do it ourselves here
-        if (randomizePort) port = mDNSOpaque16fromIntVal(0xC000 + mDNSRandom(0x3FFF));
-        err = SetupSocket(&p->ss, port, AF_INET, &p->ss.port);
-        if (!err)
-        {
-            err = SetupSocket(&p->ss, port, AF_INET6, &p->ss.port);
-            if (err) { mDNSPlatformCloseFD(&p->ss.kqsv4, p->ss.sktv4); p->ss.sktv4 = -1; }
-        }
-        i--;
-    } while (err == EADDRINUSE && randomizePort && i);
-
-    if (err)
-    {
-        // In customer builds we don't want to log failures with port 5351, because this is a known issue
-        // of failing to bind to this port when Internet Sharing has already bound to it
-        // We also don't want to log about port 5350, due to a known bug when some other
-        // process is bound to it.
-        if (mDNSSameIPPort(requestedport, NATPMPPort) || mDNSSameIPPort(requestedport, NATPMPAnnouncementPort))
-            LogInfo("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
-        else LogMsg("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
-        freeL("UDPSocket", p);
-        return(mDNSNULL);
-    }
-    return(p);
-}
-
-mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock)
-{
-    CloseSocketSet(&sock->ss);
-    freeL("UDPSocket", sock);
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - BPF Raw packet sending/receiving
-#endif
-
-#if APPLE_OSX_mDNSResponder
-
-mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
-{
-    if (!InterfaceID) { LogMsg("mDNSPlatformSendRawPacket: No InterfaceID specified"); return; }
-    NetworkInterfaceInfoOSX *info;
-
-    info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
-    if (info == NULL)
-    {
-        LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
-        return;
-    }
-    if (info->BPF_fd < 0)
-        LogMsg("mDNSPlatformSendRawPacket: %s BPF_fd %d not ready", info->ifinfo.ifname, info->BPF_fd);
-    else
-    {
-        //LogMsg("mDNSPlatformSendRawPacket %d bytes on %s", end - (mDNSu8 *)msg, info->ifinfo.ifname);
-        if (write(info->BPF_fd, msg, end - (mDNSu8 *)msg) < 0)
-            LogMsg("mDNSPlatformSendRawPacket: BPF write(%d) failed %d (%s)", info->BPF_fd, errno, strerror(errno));
-    }
-}
-
-mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
-{
-    if (!InterfaceID) { LogMsg("mDNSPlatformSetLocalAddressCacheEntry: No InterfaceID specified"); return; }
-    NetworkInterfaceInfoOSX *info;
-    info = IfindexToInterfaceInfoOSX(m, 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, mDNSNULL))
-        LogSPS("Don't need address cache entry for %s %#a %.6a",            info->ifinfo.ifname, tpa, tha);
-    else
-    {
-        int result = mDNSSetLocalAddressCacheEntry(info->scope_id, tpa->type, tpa->ip.v6.b, tha->b);
-        if (result) LogMsg("Set local address cache entry for %s %#a %.6a failed: %d", info->ifinfo.ifname, tpa, tha, result);
-        else LogSPS("Set local address cache entry for %s %#a %.6a",            info->ifinfo.ifname, tpa, tha);
-    }
-}
-
-mDNSlocal void CloseBPF(NetworkInterfaceInfoOSX *const i)
-{
-    LogSPS("%s closing BPF fd %d", i->ifinfo.ifname, i->BPF_fd);
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    // close will happen in the cancel handler
-    dispatch_source_cancel(i->BPF_source);
-#else
-
-    // Note: MUST NOT close() the underlying native BSD sockets.
-    // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately, because
-    // it first has to unhook the sockets from its select() call on its other thread, before it can safely close them.
-    CFRunLoopRemoveSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode);
-    CFRelease(i->BPF_rls);
-    CFSocketInvalidate(i->BPF_cfs);
-    CFRelease(i->BPF_cfs);
-#endif
-    i->BPF_fd = -1;
-    if (i->BPF_mcfd >= 0) { close(i->BPF_mcfd); i->BPF_mcfd = -1; }
-}
-
-mDNSlocal void bpf_callback_common(NetworkInterfaceInfoOSX *info)
-{
-    KQueueLock(info->m);
-
-    // 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).
-    if (info->BPF_fd < 0) goto exit;
-
-    ssize_t n = read(info->BPF_fd, &info->m->imsg, info->BPF_len);
-    const mDNSu8 *ptr = (const mDNSu8 *)&info->m->imsg;
-    const mDNSu8 *end = (const mDNSu8 *)&info->m->imsg + n;
-    debugf("%3d: bpf_callback got %d bytes on %s", info->BPF_fd, n, info->ifinfo.ifname);
-
-    if (n<0)
-    {
-        /* <rdar://problem/10287386>
-         * sometimes there can be a race condition btw when the bpf socket
-         * gets data and the callback get scheduled and when we call BIOCSETF (which
-         * clears the socket).  this can cause the read to hang for a really long time
-         * and effectively prevent us from responding to requests for long periods of time.
-         * to prevent this make the socket non blocking and just bail if we dont get anything
-         */
-        if (errno == EAGAIN)
-        {
-            LogMsg("bpf_callback got EAGAIN bailing");
-            goto exit;
-        }
-        LogMsg("Closing %s BPF fd %d due to error %d (%s)", info->ifinfo.ifname, info->BPF_fd, errno, strerror(errno));
-        CloseBPF(info);
-        goto exit;
-    }
-
-    while (ptr < end)
-    {
-        const struct bpf_hdr *const bh = (const struct bpf_hdr *)ptr;
-        debugf("%3d: bpf_callback ptr %p bh_hdrlen %d data %p bh_caplen %4d bh_datalen %4d next %p remaining %4d",
-               info->BPF_fd, ptr, bh->bh_hdrlen, ptr + bh->bh_hdrlen, bh->bh_caplen, bh->bh_datalen,
-               ptr + BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen), end - (ptr + BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen)));
-        // Note that BPF guarantees that the NETWORK LAYER header will be word aligned, not the link-layer header.
-        // Given that An Ethernet header is 14 bytes, this means that if the network layer header (e.g. IP header,
-        // ARP message, etc.) is 4-byte aligned, then necessarily the Ethernet header will be NOT be 4-byte aligned.
-        mDNSCoreReceiveRawPacket(info->m, ptr + bh->bh_hdrlen, ptr + bh->bh_hdrlen + bh->bh_caplen, info->ifinfo.InterfaceID);
-        ptr += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen);
-    }
-exit:
-    KQueueUnlock(info->m, "bpf_callback");
-}
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-mDNSlocal void bpf_callback_dispatch(NetworkInterfaceInfoOSX *const info)
-{
-    bpf_callback_common(info);
-}
-#else
-mDNSlocal void bpf_callback(const CFSocketRef cfs, const CFSocketCallBackType CallBackType, const CFDataRef address, const void *const data, void *const context)
-{
-    (void)cfs;
-    (void)CallBackType;
-    (void)address;
-    (void)data;
-    bpf_callback_common((NetworkInterfaceInfoOSX *)context);
-}
-#endif
-
-mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win)
-{
-    LogMsg("mDNSPlatformSendKeepalive called\n");
-    mDNSSendKeepalive(sadd->ip.v6.b, dadd->ip.v6.b, lport->NotAnInteger, rport->NotAnInteger, seq, ack, win);
-}
-
-mDNSexport mStatus  mDNSPlatformClearSPSMACAddr(void)
-{
-    SCDynamicStoreRef store = NULL;
-    CFStringRef  entityname = NULL;
-
-    if ((store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:ClearSPSMACAddress"), NULL, NULL)))
-    {
-        if ((entityname = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", "[^/]", "/BonjourSleepProxyAddress")))
-        {
-            if (SCDynamicStoreRemoveValue(store, entityname) == false)
-                LogMsg("mDNSPlatformClearSPSMACAddr: Unable to remove key");
-        }
-    }
-
-    if (entityname) CFRelease(entityname);
-    if (store)      CFRelease(store);
-    return KERN_SUCCESS;
-}
-
-mDNSexport mStatus mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname)
-{
-    int family = (spsaddr->type == mDNSAddrType_IPv4) ? AF_INET : AF_INET6;
-    LogSPS("mDNSPlatformStoreSPSMACAddr : Storing %#a on interface %s", spsaddr, ifname);
-    mDNSStoreSPSMACAddress(family, spsaddr->ip.v6.b, ifname);
-    return KERN_SUCCESS;
-}
-
-mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr)
-{
-    int family = (raddr->type == mDNSAddrType_IPv4) ? AF_INET : AF_INET6;
-
-    mDNSGetRemoteMAC(m, family, raddr->ip.v6.b);
-    return KERN_SUCCESS;
-}
-
-mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti)
-{
-    mDNSs32 intfid;
-    mDNSs32 error  = 0;
-    int     family = (laddr->type == mDNSAddrType_IPv4) ? AF_INET : AF_INET6;
-
-    error = mDNSRetrieveTCPInfo(family, laddr->ip.v6.b, lport->NotAnInteger, raddr->ip.v6.b, rport->NotAnInteger, (uint32_t *)&(mti->seq), (uint32_t *)&(mti->ack), (uint16_t *)&(mti->window), (int32_t*)&intfid);
-    if (error != KERN_SUCCESS)
-    {
-        LogMsg("%s: mDNSRetrieveTCPInfo returned : %d", __func__, error);
-        return error;
-    }
-    mti->IntfId = mDNSPlatformInterfaceIDfromInterfaceIndex(m, 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)
-{
-    int numv4 = 0, numv6 = 0;
-    AuthRecord *rr;
-
-    for (rr = m->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)
-        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);
-            numv6++;
-        }
-
-    if (p4) *p4 = numv4;
-    if (p6) *p6 = numv6;
-    return(numv4 + numv6);
-}
-
-mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
-{
-    NetworkInterfaceInfoOSX *x;
-
-    // Note: We can't use IfIndexToInterfaceInfoOSX because that looks for Registered also.
-    for (x = m->p->InterfaceList; x; x = x->next) if (x->ifinfo.InterfaceID == InterfaceID) break;
-
-    if (!x) { LogMsg("mDNSPlatformUpdateProxyList: ERROR InterfaceID %p not found", InterfaceID); return; }
-
-    #define MAX_BPF_ADDRS 250
-    int numv4 = 0, numv6 = 0;
-
-    if (CountProxyTargets(m, 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;
-        numv6 = MAX_BPF_ADDRS - numv4;
-    }
-
-    LogSPS("mDNSPlatformUpdateProxyList: fd %d %-7s MAC  %.6a %d v4 %d v6", x->BPF_fd, x->ifinfo.ifname, &x->ifinfo.MAC, numv4, numv6);
-
-    // Caution: This is a static structure, so we need to be careful that any modifications we make to it
-    // are done in such a way that they work correctly when mDNSPlatformUpdateProxyList is called multiple times
-    static struct bpf_insn filter[17 + MAX_BPF_ADDRS] =
-    {
-        BPF_STMT(BPF_LD  + BPF_H   + BPF_ABS, 12),              // 0 Read Ethertype (bytes 12,13)
-
-        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0806, 0, 1),      // 1 If Ethertype == ARP goto next, else 3
-        BPF_STMT(BPF_RET + BPF_K,             42),              // 2 Return 42-byte ARP
-
-        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0800, 4, 0),      // 3 If Ethertype == IPv4 goto 8 (IPv4 address list check) else next
-
-        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x86DD, 0, 9),      // 4 If Ethertype == IPv6 goto next, else exit
-        BPF_STMT(BPF_LD  + BPF_H   + BPF_ABS, 20),              // 5 Read Protocol and Hop Limit (bytes 20,21)
-        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x3AFF, 0, 9),      // 6 If (Prot,TTL) == (3A,FF) goto next, else IPv6 address list check
-        BPF_STMT(BPF_RET + BPF_K,             86),              // 7 Return 86-byte ND
-
-        // Is IPv4 packet; check if it's addressed to any IPv4 address we're proxying for
-        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
-
-    // 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);
-
-    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 != fail) LogMsg("mDNSPlatformUpdateProxyList: pc %p != fail %p", pc, fail);
-    *pc++ = rf;     // fail points here
-
-    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
-
-    struct bpf_program prog = { pc - filter, filter };
-
-#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);
-#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->p->NetworkChanged) m->p->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
-    }
-    
-    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)
-{
-    mDNS_Lock(m);
-
-    NetworkInterfaceInfoOSX *i;
-    for (i = m->p->InterfaceList; i; i = i->next) if (i->BPF_fd == -2) break;
-    if (!i) { LogSPS("mDNSPlatformReceiveBPF_fd: No Interfaces awaiting BPF fd %d; closing", fd); close(fd); }
-    else
-    {
-        LogSPS("%s using   BPF fd %d", i->ifinfo.ifname, fd);
-
-        struct bpf_version v;
-        if (ioctl(fd, BIOCVERSION, &v) < 0)
-            LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCVERSION failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
-        else if (BPF_MAJOR_VERSION != v.bv_major || BPF_MINOR_VERSION != v.bv_minor)
-            LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCVERSION header %d.%d kernel %d.%d",
-                   fd, i->ifinfo.ifname, BPF_MAJOR_VERSION, BPF_MINOR_VERSION, v.bv_major, v.bv_minor);
-
-        if (ioctl(fd, BIOCGBLEN, &i->BPF_len) < 0)
-            LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCGBLEN failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
-
-        if (i->BPF_len > sizeof(m->imsg))
-        {
-            i->BPF_len = sizeof(m->imsg);
-            if (ioctl(fd, BIOCSBLEN, &i->BPF_len) < 0)
-                LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSBLEN failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
-            else
-                LogSPS("mDNSPlatformReceiveBPF_fd: %d %s BIOCSBLEN %d", fd, i->ifinfo.ifname, i->BPF_len);
-        }
-
-        static const u_int opt_one = 1;
-        if (ioctl(fd, BIOCIMMEDIATE, &opt_one) < 0)
-            LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCIMMEDIATE failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
-
-        //if (ioctl(fd, BIOCPROMISC, &opt_one) < 0)
-        //	LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCPROMISC failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
-
-        //if (ioctl(fd, BIOCSHDRCMPLT, &opt_one) < 0)
-        //	LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSHDRCMPLT failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
-
-        /*  <rdar://problem/10287386>
-         *  make socket non blocking see comments in bpf_callback_common for more info
-         */
-        if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) < 0) // set non-blocking
-        {
-            LogMsg("mDNSPlatformReceiveBPF_fd: %d %s O_NONBLOCK failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
-        }
-
-        struct ifreq ifr;
-        mDNSPlatformMemZero(&ifr, sizeof(ifr));
-        strlcpy(ifr.ifr_name, i->ifinfo.ifname, sizeof(ifr.ifr_name));
-        if (ioctl(fd, BIOCSETIF, &ifr) < 0)
-        { LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSETIF failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno)); i->BPF_fd = -3; }
-        else
-        {
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-            i->BPF_fd  = fd;
-            i->BPF_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, dispatch_get_main_queue());
-            if (!i->BPF_source) {LogMsg("mDNSPlatformReceiveBPF_fd: dispatch source create failed"); return;}
-            dispatch_source_set_event_handler(i->BPF_source, ^{bpf_callback_dispatch(i);});
-            dispatch_source_set_cancel_handler(i->BPF_source, ^{close(fd);});
-            dispatch_resume(i->BPF_source);
-#else
-            CFSocketContext myCFSocketContext = { 0, i, NULL, NULL, NULL };
-            i->BPF_fd  = fd;
-            i->BPF_cfs = CFSocketCreateWithNative(kCFAllocatorDefault, fd, kCFSocketReadCallBack, bpf_callback, &myCFSocketContext);
-            i->BPF_rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, i->BPF_cfs, 0);
-            CFRunLoopAddSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode);
-#endif
-            mDNSPlatformUpdateProxyList(m, i->ifinfo.InterfaceID);
-        }
-    }
-
-    mDNS_Unlock(m);
-}
-
-#endif // APPLE_OSX_mDNSResponder
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Key Management
-#endif
-
-#ifndef NO_SECURITYFRAMEWORK
-mDNSlocal CFArrayRef GetCertChain(SecIdentityRef identity)
-{
-    CFMutableArrayRef certChain = NULL;
-    if (!identity) { LogMsg("getCertChain: identity is NULL"); return(NULL); }
-    SecCertificateRef cert;
-    OSStatus err = SecIdentityCopyCertificate(identity, &cert);
-    if (err || !cert) LogMsg("getCertChain: SecIdentityCopyCertificate() returned %d", (int) err);
-    else
-    {
-        SecPolicySearchRef searchRef;
-        err = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &searchRef);
-        if (err || !searchRef) LogMsg("getCertChain: SecPolicySearchCreate() returned %d", (int) err);
-        else
-        {
-            SecPolicyRef policy;
-            err = SecPolicySearchCopyNext(searchRef, &policy);
-            if (err || !policy) LogMsg("getCertChain: SecPolicySearchCopyNext() returned %d", (int) err);
-            else
-            {
-                CFArrayRef wrappedCert = CFArrayCreate(NULL, (const void**) &cert, 1, &kCFTypeArrayCallBacks);
-                if (!wrappedCert) LogMsg("getCertChain: wrappedCert is NULL");
-                else
-                {
-                    SecTrustRef trust;
-                    err = SecTrustCreateWithCertificates(wrappedCert, policy, &trust);
-                    if (err || !trust) LogMsg("getCertChain: SecTrustCreateWithCertificates() returned %d", (int) err);
-                    else
-                    {
-                        err = SecTrustEvaluate(trust, NULL);
-                        if (err) LogMsg("getCertChain: SecTrustEvaluate() returned %d", (int) err);
-                        else
-                        {
-                            CFArrayRef rawCertChain;
-                            CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
-                            err = SecTrustGetResult(trust, NULL, &rawCertChain, &statusChain);
-                            if (err || !rawCertChain || !statusChain) LogMsg("getCertChain: SecTrustGetResult() returned %d", (int) err);
-                            else
-                            {
-                                certChain = CFArrayCreateMutableCopy(NULL, 0, rawCertChain);
-                                if (!certChain) LogMsg("getCertChain: certChain is NULL");
-                                else
-                                {
-                                    // Replace the SecCertificateRef at certChain[0] with a SecIdentityRef per documentation for SSLSetCertificate:
-                                    // <http://devworld.apple.com/documentation/Security/Reference/secureTransportRef/index.html>
-                                    CFArraySetValueAtIndex(certChain, 0, identity);
-                                    // Remove root from cert chain, but keep any and all intermediate certificates that have been signed by the root certificate
-                                    if (CFArrayGetCount(certChain) > 1) CFArrayRemoveValueAtIndex(certChain, CFArrayGetCount(certChain) - 1);
-                                }
-                                CFRelease(rawCertChain);
-                                // Do not free statusChain:
-                                // <http://developer.apple.com/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html> says:
-                                // certChain: Call the CFRelease function to release this object when you are finished with it.
-                                // statusChain: Do not attempt to free this pointer; it remains valid until the trust management object is released...
-                            }
-                        }
-                        CFRelease(trust);
-                    }
-                    CFRelease(wrappedCert);
-                }
-                CFRelease(policy);
-            }
-            CFRelease(searchRef);
-        }
-        CFRelease(cert);
-    }
-    return certChain;
-}
-#endif /* NO_SECURITYFRAMEWORK */
-
-mDNSexport mStatus mDNSPlatformTLSSetupCerts(void)
-{
-#ifdef NO_SECURITYFRAMEWORK
-    return mStatus_UnsupportedErr;
-#else
-    SecIdentityRef identity = nil;
-    SecIdentitySearchRef srchRef = nil;
-    OSStatus err;
-
-    // search for "any" identity matching specified key use
-    // In this app, we expect there to be exactly one
-    err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_DECRYPT, &srchRef);
-    if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCreate returned %d", (int) err); return err; }
-
-    err = SecIdentitySearchCopyNext(srchRef, &identity);
-    if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext returned %d", (int) err); return err; }
-
-    if (CFGetTypeID(identity) != SecIdentityGetTypeID())
-    { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext CFTypeID failure"); return mStatus_UnknownErr; }
-
-    // Found one. Call getCertChain to create the correct certificate chain.
-    ServerCerts = GetCertChain(identity);
-    if (ServerCerts == nil) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: getCertChain error"); return mStatus_UnknownErr; }
-
-    return mStatus_NoError;
-#endif /* NO_SECURITYFRAMEWORK */
-}
-
-mDNSexport void  mDNSPlatformTLSTearDownCerts(void)
-{
-#ifndef NO_SECURITYFRAMEWORK
-    if (ServerCerts) { CFRelease(ServerCerts); ServerCerts = NULL; }
-#endif /* NO_SECURITYFRAMEWORK */
-}
-
-// This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel
-mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
-{
-    CFStringEncoding encoding = kCFStringEncodingUTF8;
-    CFStringRef cfs = SCDynamicStoreCopyComputerName(NULL, &encoding);
-    if (cfs)
-    {
-        CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
-        CFRelease(cfs);
-    }
-}
-
-// This gets the text of the field currently labelled "Local Hostname" in the Sharing Prefs Control Panel
-mDNSlocal void GetUserSpecifiedLocalHostName(domainlabel *const namelabel)
-{
-    CFStringRef cfs = SCDynamicStoreCopyLocalHostName(NULL);
-    if (cfs)
-    {
-        CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
-        CFRelease(cfs);
-    }
-}
-
-mDNSexport mDNSBool DictionaryIsEnabled(CFDictionaryRef dict)
-{
-    mDNSs32 val;
-    CFNumberRef state = (CFNumberRef)CFDictionaryGetValue(dict, CFSTR("Enabled"));
-    if (!state) return mDNSfalse;
-    if (!CFNumberGetValue(state, kCFNumberSInt32Type, &val))
-    { LogMsg("ERROR: DictionaryIsEnabled - CFNumberGetValue"); return mDNSfalse; }
-    return val ? mDNStrue : mDNSfalse;
-}
-
-mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
-{
-    if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
-
-    if (sa->sa_family == AF_INET)
-    {
-        struct sockaddr_in *ifa_addr = (struct sockaddr_in *)sa;
-        ip->type = mDNSAddrType_IPv4;
-        ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr;
-        return(mStatus_NoError);
-    }
-
-    if (sa->sa_family == AF_INET6)
-    {
-        struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
-        // Inside the BSD kernel they use a hack where they stuff the sin6->sin6_scope_id
-        // value into the second word of the IPv6 link-local address, so they can just
-        // pass around IPv6 address structures instead of full sockaddr_in6 structures.
-        // Those hacked IPv6 addresses aren't supposed to escape the kernel in that form, but they do.
-        // To work around this we always whack the second word of any IPv6 link-local address back to zero.
-        if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
-        ip->type = mDNSAddrType_IPv6;
-        ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
-        return(mStatus_NoError);
-    }
-
-    LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
-    return(mStatus_Invalid);
-}
-
-mDNSlocal mDNSEthAddr GetBSSID(char *ifa_name)
-{
-    mDNSEthAddr eth = zeroEthAddr;
-    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetBSSID"), NULL, NULL);
-    if (!store)
-        LogMsg("GetBSSID: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
-    else
-    {
-        CFStringRef entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/AirPort"), ifa_name);
-        if (entityname)
-        {
-            CFDictionaryRef dict = SCDynamicStoreCopyValue(store, entityname);
-            if (dict)
-            {
-                CFRange range = { 0, 6 };       // Offset, length
-                CFDataRef data = CFDictionaryGetValue(dict, CFSTR("BSSID"));
-                if (data && CFDataGetLength(data) == 6) CFDataGetBytes(data, range, eth.b);
-                CFRelease(dict);
-            }
-            CFRelease(entityname);
-        }
-        CFRelease(store);
-    }
-    return(eth);
-}
-
-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)
-        {
-            const struct sockaddr_dl *const sdl = (const struct sockaddr_dl *)ifa->ifa_addr;
-            if (sdl->sdl_index == ifindex)
-            { mDNSPlatformMemCopy(eth->b, sdl->sdl_data + sdl->sdl_nlen, 6); return 0; }
-        }
-    *eth = zeroEthAddr;
-    return -1;
-}
-
-#ifndef SIOCGIFWAKEFLAGS
-#define SIOCGIFWAKEFLAGS _IOWR('i', 136, struct ifreq) /* get interface wake property flags */
-#endif
-
-#ifndef IF_WAKE_ON_MAGIC_PACKET
-#define IF_WAKE_ON_MAGIC_PACKET 0x01
-#endif
-
-#ifndef ifr_wake_flags
-#define ifr_wake_flags ifr_ifru.ifru_intval
-#endif
-
-mDNSlocal mDNSBool  CheckInterfaceSupport(NetworkInterfaceInfo *const intf, const char *key)
-{
-    io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOBSDNameMatching(kIOMasterPortDefault, 0, intf->ifname));
-    if (!service)
-    {
-        LogSPS("CheckInterfaceSupport: No service for interface %s", intf->ifname);
-        return mDNSfalse;
-    }
-
-    io_name_t n1, n2;
-    IOObjectGetClass(service, n1);
-    io_object_t parent;
-    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);
-        if (!ref)
-        {
-            LogSPS("CheckInterfaceSupport: No mDNS_IOREG_KEY for interface %s/%s/%s", intf->ifname, n1, n2);
-            ret = mDNSfalse;
-        }
-        else
-        {
-            ret = mDNStrue;
-            CFRelease(ref);
-        }
-        IOObjectRelease(parent);
-        CFRelease(keystr);
-    }
-    else
-    {
-        LogSPS("CheckInterfaceSupport: IORegistryEntryGetParentEntry for %s/%s failed %d", intf->ifname, n1, kr);
-        ret = mDNSfalse;
-    }
-    IOObjectRelease(service);
-    return ret;
-}
-
-
-mDNSlocal  mDNSBool InterfaceSupportsKeepAlive(NetworkInterfaceInfo *const intf)
-{
-    return CheckInterfaceSupport(intf, mDNS_IOREG_KA_KEY);
-}
-
-mDNSlocal mDNSBool NetWakeInterface(NetworkInterfaceInfoOSX *i)
-{
-    if (!MulticastInterface(i)     ) return(mDNSfalse); // We only use Sleep Proxy Service on multicast-capable interfaces
-    if (i->ifa_flags & IFF_LOOPBACK) return(mDNSfalse); // except loopback
-
-    // If the interface supports TCPKeepalive, it is capable of waking up for a magic packet
-    // This check is needed since the SIOCGIFWAKEFLAGS ioctl returns wrong values for WOMP capability
-    // when the power source is not AC Power.
-    if (InterfaceSupportsKeepAlive(&i->ifinfo))
-    {
-        LogSPS("NetWakeInterface: %s supports TCP Keepalive returning true", i->ifinfo.ifname);
-        return mDNStrue;
-    }
-
-    int s = socket(AF_INET, SOCK_DGRAM, 0);
-    if (s < 0) { LogMsg("NetWakeInterface socket failed %s error %d errno %d (%s)", i->ifinfo.ifname, s, errno, strerror(errno)); return(mDNSfalse); }
-
-    struct ifreq ifr;
-    strlcpy(ifr.ifr_name, i->ifinfo.ifname, sizeof(ifr.ifr_name));
-    if (ioctl(s, SIOCGIFWAKEFLAGS, &ifr) < 0)
-    {
-        // For some strange reason, in /usr/include/sys/errno.h, EOPNOTSUPP is defined to be
-        // 102 when compiling kernel code, and 45 when compiling user-level code. Since this
-        // error code is being returned from the kernel, we need to use the kernel version.
-        #define KERNEL_EOPNOTSUPP 102
-        if (errno != KERNEL_EOPNOTSUPP) // "Operation not supported on socket", the expected result on Leopard and earlier
-            LogMsg("NetWakeInterface SIOCGIFWAKEFLAGS %s errno %d (%s)", i->ifinfo.ifname, errno, strerror(errno));
-        // If on Leopard or earlier, we get EOPNOTSUPP, so in that case
-        // we enable WOL if this interface is not AirPort and "Wake for Network access" is turned on.
-        ifr.ifr_wake_flags = (errno == KERNEL_EOPNOTSUPP && !(i)->BSSID.l[0] && i->m->SystemWakeOnLANEnabled) ? IF_WAKE_ON_MAGIC_PACKET : 0;
-    }
-
-    close(s);
-
-    // 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");
-
-    return((ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) != 0);
-}
-
-mDNSlocal u_int64_t getExtendedFlags(char * ifa_name)
-{
-    int sockFD;
-    struct ifreq ifr;
-
-    sockFD = socket(AF_INET, SOCK_DGRAM, 0);
-    if (sockFD < 0)
-    {
-        LogMsg("getExtendedFlags: socket() call failed, errno = %d (%s)", errno, strerror(errno));
-        return 0;
-    }
-
-    ifr.ifr_addr.sa_family = AF_INET;
-    strlcpy(ifr.ifr_name, ifa_name, sizeof(ifr.ifr_name));
-
-    if (ioctl(sockFD, SIOCGIFEFLAGS, (caddr_t)&ifr) == -1)
-    {
-        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;
-}
-
-// Returns pointer to newly created NetworkInterfaceInfoOSX object, or
-// 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)
-{
-    mDNSu32 scope_id  = if_nametoindex(ifa->ifa_name);
-    mDNSEthAddr bssid = GetBSSID(ifa->ifa_name);
-    u_int64_t   eflags = getExtendedFlags(ifa->ifa_name);
-
-    mDNSAddr ip, mask;
-    if (SetupAddr(&ip,   ifa->ifa_addr   ) != mStatus_NoError) return(NULL);
-    if (SetupAddr(&mask, ifa->ifa_netmask) != mStatus_NoError) return(NULL);
-
-    NetworkInterfaceInfoOSX **p;
-    for (p = &m->p->InterfaceList; *p; p = &(*p)->next)
-        if (scope_id == (*p)->scope_id &&
-            mDNSSameAddress(&ip, &(*p)->ifinfo.ip) &&
-            mDNSSameEthAddress(&bssid, &(*p)->BSSID))
-        {
-            debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p, ifname before %s, after %s", scope_id, &bssid, &ip, *p, (*p)->ifinfo.ifname, ifa->ifa_name);
-            // The name should be updated to the new name so that we don't report a wrong name in our SIGINFO output.
-            // When interfaces are created with same MAC address, kernel resurrects the old interface.
-            // Even though the interface index is the same (which should be sufficient), when we receive a UDP packet
-            // we get the corresponding name for the interface index on which the packet was received and check against
-            // the InterfaceList for a matching name. So, keep the name in sync
-            strlcpy((*p)->ifinfo.ifname, ifa->ifa_name, sizeof((*p)->ifinfo.ifname));
-            (*p)->Exists = mDNStrue;
-            // If interface was not in getifaddrs list last time we looked, but it is now, update 'AppearanceTime' for this record
-            if ((*p)->LastSeen != utc) (*p)->AppearanceTime = utc;
-
-            // If Wake-on-LAN capability of this interface has changed (e.g. because power cable on laptop has been disconnected)
-            // we may need to start or stop or sleep proxy browse operation
-            const mDNSBool NetWake = NetWakeInterface(*p);
-            if ((*p)->ifinfo.NetWake != NetWake)
-            {
-                (*p)->ifinfo.NetWake = NetWake;
-                // If this interface is already registered with mDNSCore, then we need to start or stop its NetWake browse on-the-fly.
-                // If this interface is not already registered (i.e. it's a dormant interface we had in our list
-                // from when we previously saw it) then we mustn't do that, because mDNSCore doesn't know about it yet.
-                // In this case, the mDNS_RegisterInterface() call will take care of starting the NetWake browse if necessary.
-                if ((*p)->Registered)
-                {
-                    mDNS_Lock(m);
-                    if (NetWake) mDNS_ActivateNetWake_internal  (m, &(*p)->ifinfo);
-                    else mDNS_DeactivateNetWake_internal(m, &(*p)->ifinfo);
-                    mDNS_Unlock(m);
-                }
-            }
-            // Reset the flag if it has changed this time.
-            (*p)->ifinfo.IgnoreIPv4LL = ((eflags & IFEF_ARPLL) != 0) ? mDNSfalse : mDNStrue;
-
-            return(*p);
-        }
-
-    NetworkInterfaceInfoOSX *i = (NetworkInterfaceInfoOSX *)mallocL("NetworkInterfaceInfoOSX", sizeof(*i));
-    debugf("AddInterfaceToList: Making   new   interface %lu %.6a with address %#a at %p", scope_id, &bssid, &ip, i);
-    if (!i) return(mDNSNULL);
-    mDNSPlatformMemZero(i, sizeof(NetworkInterfaceInfoOSX));
-    i->ifinfo.InterfaceID = (mDNSInterfaceID)(uintptr_t)scope_id;
-    i->ifinfo.ip          = ip;
-    i->ifinfo.mask        = mask;
-    strlcpy(i->ifinfo.ifname, ifa->ifa_name, sizeof(i->ifinfo.ifname));
-    i->ifinfo.ifname[sizeof(i->ifinfo.ifname)-1] = 0;
-    // We can be configured to disable multicast advertisement, but we want to to support
-    // local-only services, which need a loopback address record.
-    i->ifinfo.Advertise   = m->DivertMulticastAdvertisements ? ((ifa->ifa_flags & IFF_LOOPBACK) ? mDNStrue : mDNSfalse) : m->AdvertiseLocalAddresses;
-    i->ifinfo.McastTxRx   = mDNSfalse; // For now; will be set up later at the end of UpdateInterfaceList
-    i->ifinfo.Loopback    = ((ifa->ifa_flags & IFF_LOOPBACK) != 0) ? mDNStrue : mDNSfalse;
-    i->ifinfo.IgnoreIPv4LL = ((eflags & IFEF_ARPLL) != 0) ? mDNSfalse : mDNStrue;
-    i->ifinfo.DirectLink  = (eflags & IFEF_DIRECTLINK) ? mDNStrue: mDNSfalse;
-
-    i->next            = mDNSNULL;
-    i->m               = m;
-    i->Exists          = mDNStrue;
-    i->Flashing        = mDNSfalse;
-    i->Occulting       = mDNSfalse;
-    i->D2DInterface    = (eflags & IFEF_LOCALNET_PRIVATE) ? mDNStrue: mDNSfalse;
-    if (eflags & IFEF_AWDL)
-    {
-        AWDLInterfaceID = i->ifinfo.InterfaceID;
-        LogInfo("AddInterfaceToList: AWDLInterfaceID = %d", (int) AWDLInterfaceID);
-    }
-    i->AppearanceTime  = utc;       // Brand new interface; AppearanceTime is now
-    i->LastSeen        = utc;
-    i->ifa_flags       = ifa->ifa_flags;
-    i->scope_id        = scope_id;
-    i->BSSID           = bssid;
-    i->sa_family       = ifa->ifa_addr->sa_family;
-    i->BPF_fd          = -1;
-    i->BPF_mcfd        = -1;
-    i->BPF_len         = 0;
-    i->Registered      = mDNSNULL;
-
-    // Do this AFTER i->BSSID has been set up
-    i->ifinfo.NetWake  = NetWakeInterface(i);
-    GetMAC(&i->ifinfo.MAC, scope_id);
-    if (i->ifinfo.NetWake && !i->ifinfo.MAC.l[0])
-        LogMsg("AddInterfaceToList: Bad MAC address %.6a for %d %s %#a", &i->ifinfo.MAC, scope_id, i->ifinfo.ifname, &ip);
-
-    *p = i;
-    return(i);
-}
-
-#if APPLE_OSX_mDNSResponder
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - AutoTunnel
-#endif
-
-#define kRacoonPort 4500
-
-static DomainAuthInfo* AnonymousRacoonConfig = mDNSNULL;
-
-#ifndef NO_SECURITYFRAMEWORK
-
-static CFMutableDictionaryRef domainStatusDict = NULL;
-
-mDNSlocal mStatus CheckQuestionForStatus(const DNSQuestion *const q)
-{
-    if (q->LongLived)
-    {
-        if (q->servAddr.type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsOnes(q->servAddr.ip.v4))
-            return mStatus_NoSuchRecord;
-        else if (q->state == LLQ_Poll)
-            return mStatus_PollingMode;
-        else if (q->state != LLQ_Established && !q->DuplicateOf)
-            return mStatus_TransientErr;
-    }
-
-    return mStatus_NoError;
-}
-
-mDNSlocal mStatus UpdateLLQStatus(const mDNS *const m, 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)
-        if (q->AuthInfo == info)
-        {
-            mStatus newStatus = CheckQuestionForStatus(q);
-            if      (newStatus == mStatus_NoSuchRecord) { status = newStatus; worst_q = q; break; }
-            else if (newStatus == mStatus_PollingMode)  { status = newStatus; worst_q = q; }
-            else if (newStatus == mStatus_TransientErr && status == mStatus_NoError) { status = newStatus; worst_q = q; }
-        }
-
-    if      (status == mStatus_NoError) mDNS_snprintf(buffer, bufsz, "Success");
-    else if (status == mStatus_NoSuchRecord) mDNS_snprintf(buffer, bufsz, "GetZoneData %s: %##s", worst_q->nta ? "not yet complete" : "failed", worst_q->qname.c);
-    else if (status == mStatus_PollingMode) mDNS_snprintf(buffer, bufsz, "Query polling %##s", worst_q->qname.c);
-    else if (status == mStatus_TransientErr) mDNS_snprintf(buffer, bufsz, "Query not yet established %##s", worst_q->qname.c);
-    return status;
-}
-
-mDNSlocal mStatus UpdateRRStatus(const mDNS *const m, char *buffer, int bufsz, const DomainAuthInfo *const info)
-{
-    AuthRecord *r;
-
-    if (info->deltime) return mStatus_NoError;
-    for (r = m->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),
-        // hence we inline the code here. We just need the lock to walk the list of AuthInfos which the caller
-        // has already checked
-        const domainname *n = r->resrec.name;
-        while (n->c[0])
-        {
-            DomainAuthInfo *ptr;
-            for (ptr = m->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))
-                    {
-                        mDNS_snprintf(buffer, bufsz, "Resource record update failed for %##s", r->resrec.name);
-                        return r->updateError;
-                    }
-                }
-            n = (const domainname *)(n->c + 1 + n->c[0]);
-        }
-    }
-    return mStatus_NoError;
-}
-
-#endif // ndef NO_SECURITYFRAMEWORK
-
-// MUST be called with lock held
-mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, 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
-    const NATTraversalInfo *const llq = m->LLQNAT.clientCallback ? &m->LLQNAT : mDNSNULL;
-    const NATTraversalInfo *const tun = m->AutoTunnelNAT.clientContext ? &m->AutoTunnelNAT : mDNSNULL;
-    char buffer[1024];
-    mDNSu32 buflen = 0;
-    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-    CFStringRef domain = NULL;
-    CFStringRef tmp = NULL;
-    CFNumberRef num = NULL;
-    mStatus status = mStatus_NoError;
-    mStatus llqStatus = mStatus_NoError;
-    char llqBuffer[1024];
-
-    mDNS_CheckLock(m);
-
-    if (!domainStatusDict)
-    {
-        domainStatusDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-        if (!domainStatusDict) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFDictionary domainStatusDict"); return; }
-    }
-
-    if (!dict) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFDictionary dict"); return; }
-
-    buflen = mDNS_snprintf(buffer, sizeof(buffer), "%##s", info->domain.c);
-    domain = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
-    if (!domain) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString domain"); return; }
-
-    if (info->deltime)
-    {
-        if (CFDictionaryContainsKey(domainStatusDict, domain))
-        {
-            CFDictionaryRemoveValue(domainStatusDict, domain);
-            if (!m->ShutdownTime) mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, mDNSNULL, domainStatusDict);
-        }
-        CFRelease(domain);
-        CFRelease(dict);
-
-        return;
-    }
-
-    mDNS_snprintf(buffer, sizeof(buffer), "%#a", &m->Router);
-    tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
-    if (!tmp)
-        LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString RouterAddress");
-    else
-    {
-        CFDictionarySetValue(dict, CFSTR("RouterAddress"), tmp);
-        CFRelease(tmp);
-    }
-
-    if (llq)
-    {
-        mDNSu32 port = mDNSVal16(llq->ExternalPort);
-
-        num = CFNumberCreate(NULL, kCFNumberSInt32Type, &port);
-        if (!num)
-            LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LLQExternalPort");
-        else
-        {
-            CFDictionarySetValue(dict, CFSTR("LLQExternalPort"), num);
-            CFRelease(num);
-        }
-
-        if (llq->Result)
-        {
-            num = CFNumberCreate(NULL, kCFNumberSInt32Type, &llq->Result);
-            if (!num)
-                LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LLQNPMStatus");
-            else
-            {
-                CFDictionarySetValue(dict, CFSTR("LLQNPMStatus"), num);
-                CFRelease(num);
-            }
-        }
-    }
-
-    if (tun)
-    {
-        mDNSu32 port = mDNSVal16(tun->ExternalPort);
-
-        num = CFNumberCreate(NULL, kCFNumberSInt32Type, &port);
-        if (!num)
-            LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber AutoTunnelExternalPort");
-        else
-        {
-            CFDictionarySetValue(dict, CFSTR("AutoTunnelExternalPort"), num);
-            CFRelease(num);
-        }
-
-        mDNS_snprintf(buffer, sizeof(buffer), "%.4a", &tun->ExternalAddress);
-        tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
-        if (!tmp)
-            LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString ExternalAddress");
-        else
-        {
-            CFDictionarySetValue(dict, CFSTR("ExternalAddress"), tmp);
-            CFRelease(tmp);
-        }
-
-        if (tun->Result)
-        {
-            num = CFNumberCreate(NULL, kCFNumberSInt32Type, &tun->Result);
-            if (!num)
-                LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber AutoTunnelNPMStatus");
-            else
-            {
-                CFDictionarySetValue(dict, CFSTR("AutoTunnelNPMStatus"), num);
-                CFRelease(num);
-            }
-        }
-    }
-    if (tun || llq)
-    {
-        mDNSu32 code = m->LastNATMapResultCode;
-
-        num = CFNumberCreate(NULL, kCFNumberSInt32Type, &code);
-        if (!num)
-            LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LastNATMapResultCode");
-        else
-        {
-            CFDictionarySetValue(dict, CFSTR("LastNATMapResultCode"), num);
-            CFRelease(num);
-        }
-    }
-
-    mDNS_snprintf(buffer, sizeof(buffer), "Success");
-    llqStatus = UpdateLLQStatus(m, llqBuffer, sizeof(llqBuffer), info);
-    status = UpdateRRStatus(m, 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)
-    if (status != mStatus_NoError)
-    {
-        LogInfo("UpdateAutoTunnelDomainStatus: RR Status %d, %s", status, buffer);
-    }
-    else if (m->Router.type == mDNSAddrType_None)
-    {
-        status = mStatus_NoRouter;
-        mDNS_snprintf(buffer, sizeof(buffer), "No network connection - none");
-    }
-    else if (m->Router.type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsZero(m->Router.ip.v4))
-    {
-        status = mStatus_NoRouter;
-        mDNS_snprintf(buffer, sizeof(buffer), "No network connection - v4 zero");
-    }
-    else if (mDNSIPv6AddressIsZero(info->AutoTunnelInnerAddress))
-    {
-        status = mStatus_ServiceNotRunning;
-        mDNS_snprintf(buffer, sizeof(buffer), "No inner address");
-    }
-    else if (!llq && !tun)
-    {
-        status = mStatus_NotInitializedErr;
-        mDNS_snprintf(buffer, sizeof(buffer), "Neither LLQ nor AutoTunnel NAT port mapping is currently active");
-    }
-    else if (llqStatus == mStatus_NoSuchRecord)
-    {
-        status = llqStatus;
-        mDNS_snprintf(buffer, sizeof(buffer), llqBuffer);
-    }
-    else if ((llq && llq->Result == mStatus_DoubleNAT) || (tun && tun->Result == mStatus_DoubleNAT))
-    {
-        status = mStatus_DoubleNAT;
-        mDNS_snprintf(buffer, sizeof(buffer), "Double NAT: Router is reporting a private address");
-    }
-    else if ((llq && llq->Result == mStatus_NATPortMappingDisabled) ||
-             (tun && tun->Result == mStatus_NATPortMappingDisabled) ||
-             (m->LastNATMapResultCode == NATErr_Refused && ((llq && !llq->Result && mDNSIPPortIsZero(llq->ExternalPort)) || (tun && !tun->Result && mDNSIPPortIsZero(tun->ExternalPort)))))
-    {
-        status = mStatus_NATPortMappingDisabled;
-        mDNS_snprintf(buffer, sizeof(buffer), "PCP/NAT-PMP is disabled on the router");
-    }
-    else if ((llq && llq->Result) || (tun && tun->Result))
-    {
-        status = mStatus_NATTraversal;
-        mDNS_snprintf(buffer, sizeof(buffer), "Error obtaining NAT port mapping from router");
-    }
-    else if ((llq && mDNSIPPortIsZero(llq->ExternalPort)) || (tun && mDNSIPPortIsZero(tun->ExternalPort)))
-    {
-        status = mStatus_NATTraversal;
-        mDNS_snprintf(buffer, sizeof(buffer), "Unable to obtain NAT port mapping from router");
-    }
-    else
-    {
-        status = llqStatus;
-        mDNS_snprintf(buffer, sizeof(buffer), llqBuffer);
-        LogInfo("UpdateAutoTunnelDomainStatus: LLQ Status %d, %s", status, buffer);
-    }
-
-    num = CFNumberCreate(NULL, kCFNumberSInt32Type, &status);
-    if (!num)
-        LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber StatusCode");
-    else
-    {
-        CFDictionarySetValue(dict, CFSTR("StatusCode"), num);
-        CFRelease(num);
-    }
-
-    tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
-    if (!tmp)
-        LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString StatusMessage");
-    else
-    {
-        CFDictionarySetValue(dict, CFSTR("StatusMessage"), tmp);
-        CFRelease(tmp);
-    }
-
-    if (!CFDictionaryContainsKey(domainStatusDict, domain) ||
-        !CFEqual(dict, (CFMutableDictionaryRef)CFDictionaryGetValue(domainStatusDict, domain)))
-    {
-        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, "");
-            mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, mDNSNULL, domainStatusDict);
-        }
-    }
-
-    CFRelease(domain);
-    CFRelease(dict);
-
-    debugf("UpdateAutoTunnelDomainStatus: %s", buffer);
-#endif // def NO_SECURITYFRAMEWORK
-}
-
-// MUST be called with lock held
-mDNSexport void UpdateAutoTunnelDomainStatuses(const mDNS *const m)
-{
-#ifdef NO_SECURITYFRAMEWORK
-        (void) m;
-#else
-    mDNS_CheckLock(m);
-    DomainAuthInfo* info;
-    for (info = m->AuthInfoList; info; info = info->next)
-        if (info->AutoTunnel && !info->deltime)
-            UpdateAutoTunnelDomainStatus(m, info);
-#endif // def NO_SECURITYFRAMEWORK
-}
-
-mDNSlocal void UpdateAnonymousRacoonConfig(mDNS *m)     // Determine whether we need racoon to accept incoming connections
-{
-    DomainAuthInfo *info;
-
-    for (info = m->AuthInfoList; info; info = info->next)
-        if (info->AutoTunnel && !info->deltime && (!mDNSIPPortIsZero(m->AutoTunnelNAT.ExternalPort) || !mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr)))
-            break;
-
-    if (info != AnonymousRacoonConfig)
-    {
-        AnonymousRacoonConfig = info;
-        // Create or revert configuration file, and start (or SIGHUP) Racoon
-        (void)mDNSConfigureServer(AnonymousRacoonConfig ? kmDNSUp : kmDNSDown, AnonymousRacoonConfig ? btmmprefix : mDNSNULL, AnonymousRacoonConfig ? &AnonymousRacoonConfig->domain : mDNSNULL);
-    }
-}
-
-mDNSlocal void AutoTunnelRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
-
-// Caller must hold the lock
-mDNSlocal mDNSBool DeregisterAutoTunnelRecord(mDNS *m, DomainAuthInfo *info, AuthRecord* record)
-{
-    mDNS_CheckLock(m);
-
-    LogInfo("DeregisterAutoTunnelRecord %##s %##s", &info->domain.c, record->namestorage.c);
-
-    if (record->resrec.RecordType > kDNSRecordTypeDeregistering)
-    {
-        mStatus err = mDNS_Deregister_internal(m, record, mDNS_Dereg_normal);
-        if (err)
-        {
-            record->resrec.RecordType = kDNSRecordTypeUnregistered;
-            LogMsg("DeregisterAutoTunnelRecord error %d deregistering %##s %##s", err, info->domain.c, record->namestorage.c);
-            return mDNSfalse;
-        }
-        else LogInfo("DeregisterAutoTunnelRecord: Deregistered");
-    }
-    else LogInfo("DeregisterAutoTunnelRecord: Not deregistering, state:%d", record->resrec.RecordType);
-
-    return mDNStrue;
-}
-
-// Caller must hold the lock
-mDNSlocal void DeregisterAutoTunnelHostRecord(mDNS *m, DomainAuthInfo *info)
-{
-    if (!DeregisterAutoTunnelRecord(m, info, &info->AutoTunnelHostRecord))
-    {
-        info->AutoTunnelHostRecord.namestorage.c[0] = 0;
-        m->NextSRVUpdate = NonZeroTime(m->timenow);
-    }
-}
-
-// Caller must hold the lock
-mDNSlocal void UpdateAutoTunnelHostRecord(mDNS *m, DomainAuthInfo *info)
-{
-    mStatus err;
-    mDNSBool NATProblem = mDNSIPPortIsZero(m->AutoTunnelNAT.ExternalPort) || m->AutoTunnelNAT.Result;
-
-    mDNS_CheckLock(m);
-
-    if (!info->AutoTunnelServiceStarted || info->deltime || m->ShutdownTime || mDNSIPv6AddressIsZero(info->AutoTunnelInnerAddress) || (m->SleepState != SleepState_Awake && NATProblem))
-    {
-        LogInfo("UpdateAutoTunnelHostRecord: Dereg %##s : AutoTunnelServiceStarted(%d) deltime(%d) address(%.16a) sleepstate(%d)",
-                info->domain.c, info->AutoTunnelServiceStarted, info->deltime, &info->AutoTunnelInnerAddress, m->SleepState);
-        DeregisterAutoTunnelHostRecord(m, info);
-    }
-    else if (info->AutoTunnelHostRecord.resrec.RecordType == kDNSRecordTypeUnregistered)
-    {
-        mDNS_SetupResourceRecord(&info->AutoTunnelHostRecord, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL,
-                                 kDNSRecordTypeUnregistered, AuthRecordAny, AutoTunnelRecordCallback, info);
-        info->AutoTunnelHostRecord.namestorage.c[0] = 0;
-        AppendDomainLabel(&info->AutoTunnelHostRecord.namestorage, &m->hostlabel);
-        AppendDomainName (&info->AutoTunnelHostRecord.namestorage, &info->domain);
-        info->AutoTunnelHostRecord.resrec.rdata->u.ipv6 = info->AutoTunnelInnerAddress;
-        info->AutoTunnelHostRecord.resrec.RecordType = kDNSRecordTypeKnownUnique;
-
-        err = mDNS_Register_internal(m, &info->AutoTunnelHostRecord);
-        if (err) LogMsg("UpdateAutoTunnelHostRecord error %d registering %##s", err, info->AutoTunnelHostRecord.namestorage.c);
-        else
-        {
-            // Make sure we trigger the registration of all SRV records in regState_NoTarget again
-            m->NextSRVUpdate = NonZeroTime(m->timenow);
-            LogInfo("UpdateAutoTunnelHostRecord registering %##s", info->AutoTunnelHostRecord.namestorage.c);
-        }
-    }
-    else LogInfo("UpdateAutoTunnelHostRecord: Type %d", info->AutoTunnelHostRecord.resrec.RecordType);
-}
-
-// Caller must hold the lock
-mDNSlocal void DeregisterAutoTunnelServiceRecords(mDNS *m, DomainAuthInfo *info)
-{
-    LogInfo("DeregisterAutoTunnelServiceRecords %##s", info->domain.c);
-
-    DeregisterAutoTunnelRecord(m, info, &info->AutoTunnelTarget);
-    DeregisterAutoTunnelRecord(m, info, &info->AutoTunnelService);
-    UpdateAutoTunnelHostRecord(m, info);
-}
-
-// Caller must hold the lock
-mDNSlocal void UpdateAutoTunnelServiceRecords(mDNS *m, DomainAuthInfo *info)
-{
-    mDNS_CheckLock(m);
-
-    if (!info->AutoTunnelServiceStarted || info->deltime || m->ShutdownTime || mDNSIPPortIsZero(m->AutoTunnelNAT.ExternalPort) || m->AutoTunnelNAT.Result)
-    {
-        LogInfo("UpdateAutoTunnelServiceRecords: Dereg %##s : AutoTunnelServiceStarted(%d) deltime(%d) ExtPort(%d) NATResult(%d)", info->domain.c, info->AutoTunnelServiceStarted, info->deltime, mDNSVal16(m->AutoTunnelNAT.ExternalPort), m->AutoTunnelNAT.Result);
-        DeregisterAutoTunnelServiceRecords(m, info);
-    }
-    else
-    {
-        if (info->AutoTunnelTarget.resrec.RecordType == kDNSRecordTypeUnregistered)
-        {
-            // 1. Set up our address record for the external tunnel address
-            // (Constructed name, not generally user-visible, used as target in IKE tunnel's SRV record)
-            mDNS_SetupResourceRecord(&info->AutoTunnelTarget, mDNSNULL, mDNSInterface_Any, kDNSType_A, kHostNameTTL,
-                                     kDNSRecordTypeUnregistered, AuthRecordAny, AutoTunnelRecordCallback, info);
-            AssignDomainName (&info->AutoTunnelTarget.namestorage, (const domainname*) "\x0B" "_autotunnel");
-            AppendDomainLabel(&info->AutoTunnelTarget.namestorage, &m->hostlabel);
-            AppendDomainName (&info->AutoTunnelTarget.namestorage, &info->domain);
-            info->AutoTunnelTarget.resrec.rdata->u.ipv4 = m->AutoTunnelNAT.ExternalAddress;
-            info->AutoTunnelTarget.resrec.RecordType = kDNSRecordTypeKnownUnique;
-
-            mStatus err = mDNS_Register_internal(m, &info->AutoTunnelTarget);
-            if (err) LogMsg("UpdateAutoTunnelServiceRecords error %d registering %##s", err, info->AutoTunnelTarget.namestorage.c);
-            else LogInfo("UpdateAutoTunnelServiceRecords registering %##s", info->AutoTunnelTarget.namestorage.c);
-        }
-        else LogInfo("UpdateAutoTunnelServiceRecords: NOOP Target state(%d)", info->AutoTunnelTarget.resrec.RecordType);
-
-        if (info->AutoTunnelService.resrec.RecordType == kDNSRecordTypeUnregistered)
-        {
-            // 2. Set up IKE tunnel's SRV record: _autotunnel._udp.AutoTunnelHost SRV 0 0 port AutoTunnelTarget
-            mDNS_SetupResourceRecord(&info->AutoTunnelService, mDNSNULL, mDNSInterface_Any, kDNSType_SRV,  kHostNameTTL,
-                                     kDNSRecordTypeUnregistered, AuthRecordAny, AutoTunnelRecordCallback, info);
-            AssignDomainName (&info->AutoTunnelService.namestorage, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
-            AppendDomainLabel(&info->AutoTunnelService.namestorage, &m->hostlabel);
-            AppendDomainName (&info->AutoTunnelService.namestorage, &info->domain);
-            info->AutoTunnelService.resrec.rdata->u.srv.priority = 0;
-            info->AutoTunnelService.resrec.rdata->u.srv.weight   = 0;
-            info->AutoTunnelService.resrec.rdata->u.srv.port     = m->AutoTunnelNAT.ExternalPort;
-            AssignDomainName(&info->AutoTunnelService.resrec.rdata->u.srv.target, &info->AutoTunnelTarget.namestorage);
-            info->AutoTunnelService.resrec.RecordType = kDNSRecordTypeKnownUnique;
-
-            mStatus err = mDNS_Register_internal(m, &info->AutoTunnelService);
-            if (err) LogMsg("UpdateAutoTunnelServiceRecords error %d registering %##s", err, info->AutoTunnelService.namestorage.c);
-            else LogInfo("UpdateAutoTunnelServiceRecords registering %##s", info->AutoTunnelService.namestorage.c);
-        }
-        else LogInfo("UpdateAutoTunnelServiceRecords: NOOP Service state(%d)", info->AutoTunnelService.resrec.RecordType);
-
-        UpdateAutoTunnelHostRecord(m, info);
-
-        LogInfo("AutoTunnel server listening for connections on %##s[%.4a]:%d:%##s[%.16a]",
-                info->AutoTunnelTarget.namestorage.c,     &m->AdvertisedV4.ip.v4, mDNSVal16(m->AutoTunnelNAT.IntPort),
-                info->AutoTunnelHostRecord.namestorage.c, &info->AutoTunnelInnerAddress);
-
-    }
-}
-
-// Caller must hold the lock
-mDNSlocal void DeregisterAutoTunnelDeviceInfoRecord(mDNS *m, DomainAuthInfo *info)
-{
-    DeregisterAutoTunnelRecord(m, info, &info->AutoTunnelDeviceInfo);
-}
-
-// Caller must hold the lock
-mDNSlocal void UpdateAutoTunnelDeviceInfoRecord(mDNS *m, DomainAuthInfo *info)
-{
-    mDNS_CheckLock(m);
-
-    if (!info->AutoTunnelServiceStarted || info->deltime || m->ShutdownTime)
-        DeregisterAutoTunnelDeviceInfoRecord(m, info);
-    else if (info->AutoTunnelDeviceInfo.resrec.RecordType == kDNSRecordTypeUnregistered)
-    {
-        mDNS_SetupResourceRecord(&info->AutoTunnelDeviceInfo, mDNSNULL, mDNSInterface_Any, kDNSType_TXT,  kStandardTTL, kDNSRecordTypeUnregistered, AuthRecordAny, AutoTunnelRecordCallback, info);
-        ConstructServiceName(&info->AutoTunnelDeviceInfo.namestorage, &m->nicelabel, &DeviceInfoName, &info->domain);
-
-        info->AutoTunnelDeviceInfo.resrec.rdlength = initializeDeviceInfoTXT(m, info->AutoTunnelDeviceInfo.resrec.rdata->u.data);
-        info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeKnownUnique;
-
-        mStatus err = mDNS_Register_internal(m, &info->AutoTunnelDeviceInfo);
-        if (err) LogMsg("UpdateAutoTunnelDeviceInfoRecord error %d registering %##s", err, info->AutoTunnelDeviceInfo.namestorage.c);
-        else LogInfo("UpdateAutoTunnelDeviceInfoRecord registering %##s", info->AutoTunnelDeviceInfo.namestorage.c);
-    }
-    else
-        LogInfo("UpdateAutoTunnelDeviceInfoRecord: not in Unregistered state: %d",info->AutoTunnelDeviceInfo.resrec.RecordType);
-}
-
-// Caller must hold the lock
-mDNSlocal void DeregisterAutoTunnel6Record(mDNS *m, DomainAuthInfo *info)
-{
-    LogInfo("DeregisterAutoTunnel6Record %##s", info->domain.c);
-
-    DeregisterAutoTunnelRecord(m, info, &info->AutoTunnel6Record);
-    UpdateAutoTunnelHostRecord(m, info);
-    UpdateAutoTunnelDomainStatus(m, info);
-}
-
-// Caller must hold the lock
-mDNSlocal void UpdateAutoTunnel6Record(mDNS *m, DomainAuthInfo *info)
-{
-    mDNS_CheckLock(m);
-
-    if (!info->AutoTunnelServiceStarted || info->deltime || m->ShutdownTime || mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr) || m->SleepState != SleepState_Awake)
-        DeregisterAutoTunnel6Record(m, info);
-    else if (info->AutoTunnel6Record.resrec.RecordType == kDNSRecordTypeUnregistered)
-    {
-        mDNS_SetupResourceRecord(&info->AutoTunnel6Record, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL,
-                                 kDNSRecordTypeUnregistered, AuthRecordAny, AutoTunnelRecordCallback, info);
-        AssignDomainName (&info->AutoTunnel6Record.namestorage, (const domainname*) "\x0C" "_autotunnel6");
-        AppendDomainLabel(&info->AutoTunnel6Record.namestorage, &m->hostlabel);
-        AppendDomainName (&info->AutoTunnel6Record.namestorage, &info->domain);
-        info->AutoTunnel6Record.resrec.rdata->u.ipv6 = m->AutoTunnelRelayAddr;
-        info->AutoTunnel6Record.resrec.RecordType = kDNSRecordTypeKnownUnique;
-
-        mStatus err = mDNS_Register_internal(m, &info->AutoTunnel6Record);
-        if (err) LogMsg("UpdateAutoTunnel6Record error %d registering %##s", err, info->AutoTunnel6Record.namestorage.c);
-        else LogInfo("UpdateAutoTunnel6Record registering %##s", info->AutoTunnel6Record.namestorage.c);
-
-        UpdateAutoTunnelHostRecord(m, info);
-
-        LogInfo("AutoTunnel6 server listening for connections on %##s[%.16a] :%##s[%.16a]",
-                info->AutoTunnel6Record.namestorage.c,    &m->AutoTunnelRelayAddr,
-                info->AutoTunnelHostRecord.namestorage.c, &info->AutoTunnelInnerAddress);
-
-    }
-    else LogInfo("UpdateAutoTunnel6Record NOOP state(%d)",info->AutoTunnel6Record.resrec.RecordType);
-}
-
-mDNSlocal void AutoTunnelRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    DomainAuthInfo *info = (DomainAuthInfo *)rr->RecordContext;
-    if (result == mStatus_MemFree)
-    {
-        LogInfo("AutoTunnelRecordCallback MemFree %s", ARDisplayString(m, rr));
-        
-        mDNS_Lock(m);
-        
-        // Reset the host record namestorage to force high-level PTR/SRV/TXT to deregister
-        if (rr == &info->AutoTunnelHostRecord)
-        {
-            rr->namestorage.c[0] = 0;
-            m->NextSRVUpdate = NonZeroTime(m->timenow);
-            LogInfo("AutoTunnelRecordCallback: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
-        }
-        if (m->ShutdownTime)
-        {
-            LogInfo("AutoTunnelRecordCallback: Shutdown, returning");
-            mDNS_Unlock(m);        
-            return;
-        }
-        if (rr == &info->AutoTunnelHostRecord)
-        {
-            LogInfo("AutoTunnelRecordCallback: calling UpdateAutoTunnelHostRecord");
-            UpdateAutoTunnelHostRecord(m,info);
-        }
-        else if (rr == &info->AutoTunnelDeviceInfo)
-        {
-            LogInfo("AutoTunnelRecordCallback: Calling UpdateAutoTunnelDeviceInfoRecord");
-            UpdateAutoTunnelDeviceInfoRecord(m,info);
-        }
-        else if (rr == &info->AutoTunnelService || rr == &info->AutoTunnelTarget)
-        {
-            LogInfo("AutoTunnelRecordCallback: Calling UpdateAutoTunnelServiceRecords");
-            UpdateAutoTunnelServiceRecords(m,info);
-        }
-        else if (rr == &info->AutoTunnel6Record)
-        {
-            LogInfo("AutoTunnelRecordCallback: Calling UpdateAutoTunnel6Record");
-            UpdateAutoTunnel6Record(m,info);
-        }
-
-        mDNS_Unlock(m);        
-    }
-}
-
-mDNSlocal void AutoTunnelNATCallback(mDNS *m, NATTraversalInfo *n)
-{
-    DomainAuthInfo *info;
-
-    LogInfo("AutoTunnelNATCallback Result %d %.4a Internal %d External %d",
-            n->Result, &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort));
-
-    mDNS_Lock(m);
-    
-    m->NextSRVUpdate = NonZeroTime(m->timenow);
-    LogInfo("AutoTunnelNATCallback: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
-
-    for (info = m->AuthInfoList; info; info = info->next)
-        if (info->AutoTunnel)
-            UpdateAutoTunnelServiceRecords(m, info);
-
-    UpdateAnonymousRacoonConfig(m);     // Determine whether we need racoon to accept incoming connections
-
-    UpdateAutoTunnelDomainStatuses(m);
-
-    mDNS_Unlock(m);
-}
-
-mDNSlocal void AutoTunnelHostNameChanged(mDNS *m, DomainAuthInfo *info)
-{
-    LogInfo("AutoTunnelHostNameChanged %#s.%##s", m->hostlabel.c, info->domain.c);
-
-    mDNS_Lock(m);
-    // We forcibly deregister the records that are based on the hostname.
-    // When deregistration of each completes, the MemFree callback will make the
-    // appropriate Update* call to use the new name to reregister.
-    DeregisterAutoTunnelHostRecord(m, info);
-    DeregisterAutoTunnelDeviceInfoRecord(m, info);
-    DeregisterAutoTunnelServiceRecords(m, info);
-    DeregisterAutoTunnel6Record(m, info);
-    m->NextSRVUpdate = NonZeroTime(m->timenow);
-    mDNS_Unlock(m);
-}
-
-// Must be called with the lock held
-mDNSexport void StartServerTunnel(mDNS *const m, DomainAuthInfo *const info)
-{
-    if (info->deltime) return;
-    
-    if (info->AutoTunnelServiceStarted)
-    {
-        // On wake from sleep, this function will be called when determining SRV targets,
-        // and needs to re-register the host record for the target to be set correctly
-        UpdateAutoTunnelHostRecord(m, info);
-        return;
-    }
-    
-    info->AutoTunnelServiceStarted = mDNStrue;
-
-    // Now that we have a service in this domain, we need to try to register the
-    // AutoTunnel records, because the relay connection & NAT-T may have already been
-    // started for another domain. If the relay connection is not up or the NAT-T has not
-    // yet succeeded, the Update* functions are smart enough to not register the records.
-    // Note: This should be done after we set AutoTunnelServiceStarted, as that variable is used to
-    // decide whether to register the AutoTunnel records in the calls below.
-    UpdateAutoTunnelServiceRecords(m, info);
-    UpdateAutoTunnel6Record(m, info);
-    UpdateAutoTunnelDeviceInfoRecord(m, info);
-    UpdateAutoTunnelHostRecord(m, info);
-
-    // If the global AutoTunnel NAT-T is not yet started, start it.
-    if (!m->AutoTunnelNAT.clientContext)
-    {
-        m->AutoTunnelNAT.clientCallback   = AutoTunnelNATCallback;
-        m->AutoTunnelNAT.clientContext    = (void*)1; // Means AutoTunnelNAT Traversal is active;
-        m->AutoTunnelNAT.Protocol         = NATOp_MapUDP;
-        m->AutoTunnelNAT.IntPort          = IPSECPort;
-        m->AutoTunnelNAT.RequestedPort    = IPSECPort;
-        m->AutoTunnelNAT.NATLease         = 0;
-        mStatus err = mDNS_StartNATOperation_internal(m, &m->AutoTunnelNAT);
-        if (err) LogMsg("StartServerTunnel: error %d starting NAT mapping", err);
-    }
-}
-
-mDNSlocal mStatus AutoTunnelSetKeys(ClientTunnel *tun, mDNSBool AddNew)
-{
-    mDNSv6Addr loc_outer6;
-    mDNSv6Addr rmt_outer6;
-
-    // When we are tunneling over IPv6 Relay address, the port number is zero
-    if (mDNSIPPortIsZero(tun->rmt_outer_port))
-    {
-        loc_outer6 = tun->loc_outer6;
-        rmt_outer6 = tun->rmt_outer6;
-    }
-    else
-    {
-        loc_outer6 = zerov6Addr;
-        loc_outer6.b[0] = tun->loc_outer.b[0];
-        loc_outer6.b[1] = tun->loc_outer.b[1];
-        loc_outer6.b[2] = tun->loc_outer.b[2];
-        loc_outer6.b[3] = tun->loc_outer.b[3];
-
-        rmt_outer6 = zerov6Addr;
-        rmt_outer6.b[0] = tun->rmt_outer.b[0];
-        rmt_outer6.b[1] = tun->rmt_outer.b[1];
-        rmt_outer6.b[2] = tun->rmt_outer.b[2];
-        rmt_outer6.b[3] = tun->rmt_outer.b[3];
-    }
-
-    return(mDNSAutoTunnelSetKeys(AddNew ? kmDNSAutoTunnelSetKeysReplace : kmDNSAutoTunnelSetKeysDelete, tun->loc_inner.b, loc_outer6.b, kRacoonPort, tun->rmt_inner.b, rmt_outer6.b, mDNSVal16(tun->rmt_outer_port), btmmprefix, SkipLeadingLabels(&tun->dstname, 1)));
-}
-
-// 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)
-{
-    DNSQuestion *q = m->Questions;
-    while (q)
-    {
-        if (q->NoAnswer == NoAnswer_Suspended && q->qtype == qtype && q->AuthInfo && q->AuthInfo->AutoTunnel && SameDomainName(&q->qname, d))
-        {
-            LogInfo("Restart %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-            mDNSQuestionCallback *tmp = q->QuestionCallback;
-            q->QuestionCallback = AutoTunnelCallback;   // Set QuestionCallback to suppress another call back to AddNewClientTunnel
-            mDNS_StopQuery(m, q);
-            mDNS_StartQuery(m, q);
-            q->QuestionCallback = tmp;                  // Restore QuestionCallback back to the real value
-            if (!success) q->NoAnswer = NoAnswer_Fail;
-            // When we call mDNS_StopQuery, it's possible for other subordinate questions like the GetZoneData query to be cancelled too.
-            // In general we have to assume that the question list might have changed in arbitrary ways.
-            // This code is itself called from a question callback, so the m->CurrentQuestion mechanism is
-            // already in use. The safest solution is just to go back to the start of the list and start again.
-            // In principle this sounds like an n^2 algorithm, but in practice we almost always activate
-            // just one suspended question, so it's really a 2n algorithm.
-            q = m->Questions;
-        }
-        else
-            q = q->next;
-    }
-}
-
-mDNSlocal void ReissueBlockedQuestions(mDNS *const m, 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);
-}
-
-mDNSlocal void UnlinkAndReissueBlockedQuestions(mDNS *const m, ClientTunnel *tun, mDNSBool success)
-{
-    ClientTunnel **p = &m->TunnelClients;
-    while (*p != tun && *p) p = &(*p)->next;
-    if (*p) *p = tun->next;
-    ReissueBlockedQuestions(m, &tun->dstname, success);
-    LogInfo("UnlinkAndReissueBlockedQuestions: Disposing ClientTunnel %p", tun);
-    freeL("ClientTunnel", tun);
-}
-
-mDNSlocal mDNSBool TunnelClientDeleteMatching(mDNS *const m, ClientTunnel *tun, mDNSBool v6Tunnel)
-{
-    ClientTunnel **p;
-    mDNSBool needSetKeys = mDNStrue;
-
-    p = &tun->next;
-    while (*p)
-    {
-        // Is this a tunnel to the same host that we are trying to setup now?
-        if (!mDNSSameClientTunnel(&(*p)->rmt_inner, &tun->rmt_inner)) p = &(*p)->next;
-        else
-        {
-            ClientTunnel *old = *p;
-            if (v6Tunnel)
-            {
-                if (!mDNSIPPortIsZero(old->rmt_outer_port)) { p = &old->next; continue; }
-                LogInfo("TunnelClientDeleteMatching: Found existing IPv6 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
-                if (old->q.ThisQInterval >= 0)
-                {
-                    LogInfo("TunnelClientDeleteMatching: Stopping query on IPv6 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
-                    mDNS_StopQuery(m, &old->q);
-                }
-                else if (!mDNSSameIPv6Address((*p)->rmt_inner, tun->rmt_inner) ||
-                         !mDNSSameIPv6Address(old->loc_inner, tun->loc_inner)   ||
-                         !mDNSSameIPv6Address(old->loc_outer6, tun->loc_outer6) ||
-                         !mDNSSameIPv6Address(old->rmt_outer6, tun->rmt_outer6))
-                {
-                    // Delete the old tunnel if the current tunnel to the same host does not have the same ULA or
-                    // the other parameters of the tunnel are different
-                    LogInfo("TunnelClientDeleteMatching: Deleting existing IPv6 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
-                    AutoTunnelSetKeys(old, mDNSfalse);
-                }
-                else
-                {
-                    // Reusing the existing tunnel means that we reuse the IPsec SAs and the policies. We delete the old
-                    // as "tun" and "old" are identical
-                    LogInfo("TunnelClientDeleteMatching: Reusing the existing IPv6 AutoTunnel for %##s %.16a", old->dstname.c,
-                            &old->rmt_inner);
-                    needSetKeys = mDNSfalse;
-                }
-            }
-            else
-            {
-                if (mDNSIPPortIsZero(old->rmt_outer_port)) { p = &old->next; continue; }
-                LogInfo("TunnelClientDeleteMatching: Found existing IPv4 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
-                if (old->q.ThisQInterval >= 0)
-                {
-                    LogInfo("TunnelClientDeleteMatching: Stopping query on IPv4 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
-                    mDNS_StopQuery(m, &old->q);
-                }
-                else if (!mDNSSameIPv6Address((*p)->rmt_inner, tun->rmt_inner) ||
-                         !mDNSSameIPv6Address(old->loc_inner, tun->loc_inner)   ||
-                         !mDNSSameIPv4Address(old->loc_outer, tun->loc_outer)   ||
-                         !mDNSSameIPv4Address(old->rmt_outer, tun->rmt_outer)   ||
-                         !mDNSSameIPPort(old->rmt_outer_port, tun->rmt_outer_port))
-                {
-                    // Delete the old tunnel if the current tunnel to the same host does not have the same ULA or
-                    // the other parameters of the tunnel are different
-                    LogInfo("TunnelClientDeleteMatching: Deleting existing IPv4 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
-                    AutoTunnelSetKeys(old, mDNSfalse);
-                }
-                else
-                {
-                    // Reusing the existing tunnel means that we reuse the IPsec SAs and the policies. We delete the old
-                    // as "tun" and "old" are identical
-                    LogInfo("TunnelClientDeleteMatching: Reusing the existing IPv4 AutoTunnel for %##s %.16a", old->dstname.c,
-                            &old->rmt_inner);
-                    needSetKeys = mDNSfalse;
-                }
-            }
-
-            *p = old->next;
-            LogInfo("TunnelClientDeleteMatching: Disposing ClientTunnel %p", old);
-            freeL("ClientTunnel", old);
-        }
-    }
-    return needSetKeys;
-}
-
-// 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)
-{
-    ClientTunnel **p;
-
-    p = &tun->next;
-    while (*p)
-    {
-        // If there is more than one client tunnel to the same host, delete all of them.
-        // We do this by just checking against the EUI64 rather than the full address
-        if (!mDNSSameClientTunnel(&(*p)->rmt_inner, &tun->rmt_inner)) p = &(*p)->next;
-        else
-        {
-            ClientTunnel *old = *p;
-            if (v6Tunnel)
-            {
-                if (!mDNSIPPortIsZero(old->rmt_outer_port)) { p = &old->next; continue;}
-                LogInfo("TunnelClientDeleteAny: Found existing IPv6 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
-            }
-            else
-            {
-                if (mDNSIPPortIsZero(old->rmt_outer_port)) { p = &old->next; continue;}
-                LogInfo("TunnelClientDeleteAny: Found existing IPv4 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
-            }
-            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);
-            }
-            else
-            {
-                LogInfo("TunnelClientDeleteAny: Deleting existing AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
-                AutoTunnelSetKeys(old, mDNSfalse);
-            }
-            *p = old->next;
-            LogInfo("TunnelClientDeleteAny: Disposing ClientTunnel %p", old);
-            freeL("ClientTunnel", old);
-        }
-    }
-}
-
-mDNSlocal void TunnelClientFinish(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer)
-{
-    mDNSBool needSetKeys = mDNStrue;
-    ClientTunnel *tun = (ClientTunnel *)question->QuestionContext;
-    mDNSBool v6Tunnel = mDNSfalse;
-    DomainAuthInfo *info;
-
-    // If the port is zero, then we have a relay address of the peer
-    if (mDNSIPPortIsZero(tun->rmt_outer_port))
-        v6Tunnel = mDNStrue;
-
-    if (v6Tunnel)
-    {
-        LogInfo("TunnelClientFinish: Relay address %.16a", &answer->rdata->u.ipv6);
-        tun->rmt_outer6 = answer->rdata->u.ipv6;
-        tun->loc_outer6 = m->AutoTunnelRelayAddr;
-    }
-    else
-    {
-        LogInfo("TunnelClientFinish: SRV target address %.4a", &answer->rdata->u.ipv4);
-        tun->rmt_outer = answer->rdata->u.ipv4;
-        mDNSAddr tmpDst = { mDNSAddrType_IPv4, {{{0}}} };
-        tmpDst.ip.v4 = tun->rmt_outer;
-        mDNSAddr tmpSrc = zeroAddr;
-        mDNSPlatformSourceAddrForDest(&tmpSrc, &tmpDst);
-        if (tmpSrc.type == mDNSAddrType_IPv4) tun->loc_outer = tmpSrc.ip.v4;
-        else tun->loc_outer = m->AdvertisedV4.ip.v4;
-    }
-
-    question->ThisQInterval = -1;       // So we know this tunnel setup has completed
-
-    info = GetAuthInfoForName(m, &tun->dstname);
-    if (!info)
-    {
-        LogMsg("TunnelClientFinish: Could not get AuthInfo for %##s", tun->dstname.c);
-        ReissueBlockedQuestions(m, &tun->dstname, mDNSfalse);
-        return;
-    }
-    
-    tun->loc_inner = info->AutoTunnelInnerAddress;
-
-    // If we found a v6Relay address for our peer, delete all the v4Tunnels for our peer and
-    // 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);
-
-    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, "");
-    // Kick off any questions that were held pending this tunnel setup
-    ReissueBlockedQuestions(m, &tun->dstname, (result == mStatus_NoError) ? mDNStrue : mDNSfalse);
-}
-
-mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    ClientTunnel *tun = (ClientTunnel *)question->QuestionContext;
-    DomainAuthInfo *info;
-
-    LogInfo("AutoTunnelCallback tun %p AddRecord %d rdlength %d qtype %d", tun, AddRecord, answer->rdlength, question->qtype);
-
-    if (!AddRecord) return;
-    mDNS_StopQuery(m, question);
-
-    // If we are looking up the AAAA record for _autotunnel6, don't consider it as failure.
-    // The code below will look for _autotunnel._udp SRV record followed by A record
-    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);
-        return;
-    }
-
-    switch (tun->tc_state)
-    {
-    case TC_STATE_AAAA_PEER:
-        if (question->qtype != kDNSType_AAAA)
-        {
-            LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_AAAA_PEER", question->qtype);
-        }
-        info = GetAuthInfoForName(m, &tun->dstname);
-        if (!info)
-        {
-            LogMsg("AutoTunnelCallback: Could not get AuthInfo for %##s", tun->dstname.c);
-            UnlinkAndReissueBlockedQuestions(m, 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);
-            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);
-            return;
-        }
-        tun->rmt_inner = answer->rdata->u.ipv6;
-        LogInfo("AutoTunnelCallback:TC_STATE_AAAA_PEER: dst host %.16a", &tun->rmt_inner);
-        if (!mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr))
-        {
-            LogInfo("AutoTunnelCallback: Looking up _autotunnel6 AAAA");
-            tun->tc_state = TC_STATE_AAAA_PEER_RELAY;
-            question->qtype = kDNSType_AAAA;
-            AssignDomainName(&question->qname, (const domainname*) "\x0C" "_autotunnel6");
-        }
-        else
-        {
-            LogInfo("AutoTunnelCallback: Looking up _autotunnel._udp SRV");
-            tun->tc_state = TC_STATE_SRV_PEER;
-            question->qtype = kDNSType_SRV;
-            AssignDomainName(&question->qname, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
-        }
-        AppendDomainName(&question->qname, &tun->dstname);
-        mDNS_StartQuery(m, &tun->q);
-        return;
-    case TC_STATE_AAAA_PEER_RELAY:
-        if (question->qtype != kDNSType_AAAA)
-        {
-            LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_AAAA_PEER_RELAY", question->qtype);
-        }
-        // If it failed, look for the SRV record.
-        if (!answer->rdlength)
-        {
-            LogInfo("AutoTunnelCallback: Looking up _autotunnel6 AAAA failed, trying SRV");
-            tun->tc_state = TC_STATE_SRV_PEER;
-            AssignDomainName(&question->qname, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
-            AppendDomainName(&question->qname, &tun->dstname);
-            question->qtype = kDNSType_SRV;
-            mDNS_StartQuery(m, &tun->q);
-            return;
-        }
-        TunnelClientFinish(m, question, answer);
-        return;
-    case TC_STATE_SRV_PEER:
-        if (question->qtype != kDNSType_SRV)
-        {
-            LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_SRV_PEER", question->qtype);
-        }
-        LogInfo("AutoTunnelCallback: SRV target name %##s", answer->rdata->u.srv.target.c);
-        tun->tc_state = TC_STATE_ADDR_PEER;
-        AssignDomainName(&tun->q.qname, &answer->rdata->u.srv.target);
-        tun->rmt_outer_port = answer->rdata->u.srv.port;
-        question->qtype = kDNSType_A;
-        mDNS_StartQuery(m, &tun->q);
-        return;
-    case TC_STATE_ADDR_PEER:
-        if (question->qtype != kDNSType_A)
-        {
-            LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_ADDR_PEER", question->qtype);
-        }
-        TunnelClientFinish(m, question, answer);
-        return;
-    default:
-        LogMsg("AutoTunnelCallback: Unknown question %p", question);
-    }
-}
-
-// Must be called with the lock held
-mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
-{
-    ClientTunnel *p = mallocL("ClientTunnel", sizeof(ClientTunnel));
-    if (!p) return;
-    AssignDomainName(&p->dstname, &q->qname);
-    p->MarkedForDeletion = mDNSfalse;
-    p->loc_inner      = zerov6Addr;
-    p->loc_outer      = zerov4Addr;
-    p->loc_outer6     = zerov6Addr;
-    p->rmt_inner      = zerov6Addr;
-    p->rmt_outer      = zerov4Addr;
-    p->rmt_outer6     = zerov6Addr;
-    p->rmt_outer_port = zeroIPPort;
-    p->tc_state = TC_STATE_AAAA_PEER;
-    p->next = m->TunnelClients;
-    m->TunnelClients = p;       // We intentionally build list in reverse order
-
-    p->q.InterfaceID      = mDNSInterface_Any;
-    p->q.flags            = 0;
-    p->q.Target           = zeroAddr;
-    AssignDomainName(&p->q.qname, &q->qname);
-    p->q.qtype            = kDNSType_AAAA;
-    p->q.qclass           = kDNSClass_IN;
-    p->q.LongLived        = mDNSfalse;
-    p->q.ExpectUnique     = mDNStrue;
-    p->q.ForceMCast       = mDNSfalse;
-    p->q.ReturnIntermed   = mDNStrue;
-    p->q.SuppressUnusable = mDNSfalse;
-    p->q.SearchListIndex  = 0;
-    p->q.AppendSearchDomains = 0;
-    p->q.RetryWithSearchDomains = mDNSfalse;
-    p->q.TimeoutQuestion  = 0;
-    p->q.WakeOnResolve    = 0;
-    p->q.UseBackgroundTrafficClass = mDNSfalse;
-    p->q.ValidationRequired = 0;
-    p->q.ValidatingResponse = 0;
-    p->q.ProxyQuestion      = 0;
-    p->q.qnameOrig        = mDNSNULL;
-    p->q.AnonInfo         = mDNSNULL;
-    p->q.pid              = mDNSPlatformGetPID();
-    p->q.QuestionCallback = AutoTunnelCallback;
-    p->q.QuestionContext  = p;
-
-    LogInfo("AddNewClientTunnel start tun %p %##s (%s)%s", p, &q->qname.c, DNSTypeName(q->qtype), q->LongLived ? " LongLived" : "");
-    mDNS_StartQuery_internal(m, &p->q);
-}
-
-#endif // APPLE_OSX_mDNSResponder
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Power State & Configuration Change Management
-#endif
-
-mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
-{
-    mDNSBool foundav4           = mDNSfalse;
-    mDNSBool foundav6           = mDNSfalse;
-    struct ifaddrs *ifa         = myGetIfAddrs(1);
-    struct ifaddrs *v4Loopback  = NULL;
-    struct ifaddrs *v6Loopback  = NULL;
-    char defaultname[64];
-    int InfoSocket              = socket(AF_INET6, SOCK_DGRAM, 0);
-    if (InfoSocket < 3 && errno != EAFNOSUPPORT) 
-        LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket, errno, strerror(errno));
-
-    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_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);
-        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);
-        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);
-        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);
-#endif
-
-        if (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))
-                mDNSPlatformMemCopy(m->PrimaryMAC.b, sdl->sdl_data + sdl->sdl_nlen, 6);
-        }
-
-        if (ifa->ifa_flags & IFF_UP && ifa->ifa_addr)
-            if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6)
-            {
-                if (!ifa->ifa_netmask)
-                {
-                    mDNSAddr ip;
-                    SetupAddr(&ip, ifa->ifa_addr);
-                    LogMsg("getifaddrs: ifa_netmask is NULL for %5s(%d) Flags %04X Family %2d %#a",
-                           ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip);
-                }
-                // Apparently it's normal for the sa_family of an ifa_netmask to sometimes be zero, so we don't complain about that
-                // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
-                else if (ifa->ifa_netmask->sa_family != ifa->ifa_addr->sa_family && ifa->ifa_netmask->sa_family != 0)
-                {
-                    mDNSAddr ip;
-                    SetupAddr(&ip, ifa->ifa_addr);
-                    LogMsg("getifaddrs ifa_netmask for %5s(%d) Flags %04X Family %2d %#a has different family: %d",
-                           ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip, ifa->ifa_netmask->sa_family);
-                }
-                // Currently we use a few internal ones like mDNSInterfaceID_LocalOnly etc. that are negative values (0, -1, -2).
-                else if ((int)if_nametoindex(ifa->ifa_name) <= 0)
-                {
-                    LogMsg("UpdateInterfaceList: if_nametoindex returned zero/negative value for %5s(%d)", ifa->ifa_name, if_nametoindex(ifa->ifa_name));
-                }
-                else
-                {
-                    // Make sure ifa_netmask->sa_family is set correctly
-                    // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
-                    ifa->ifa_netmask->sa_family = ifa->ifa_addr->sa_family;
-                    int ifru_flags6 = 0;
-
-                    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
-                    if (ifa->ifa_addr->sa_family == AF_INET6 && InfoSocket >= 0)
-                    {
-                        struct in6_ifreq ifr6;
-                        mDNSPlatformMemZero((char *)&ifr6, sizeof(ifr6));
-                        strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
-                        ifr6.ifr_addr = *sin6;
-                        if (ioctl(InfoSocket, SIOCGIFAFLAG_IN6, &ifr6) != -1)
-                            ifru_flags6 = ifr6.ifr_ifru.ifru_flags6;
-                        verbosedebugf("%s %.16a %04X %04X", ifa->ifa_name, &sin6->sin6_addr, ifa->ifa_flags, ifru_flags6);
-                    }
-
-                    if (!(ifru_flags6 & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY)))
-                    {
-                        if (ifa->ifa_flags & IFF_LOOPBACK)
-                        {
-                            if (ifa->ifa_addr->sa_family == AF_INET) 
-                                v4Loopback = ifa;
-                            else if (sin6->sin6_addr.s6_addr[0] != 0xFD) 
-                                v6Loopback = ifa;
-                        }
-                        else
-                        {
-                            NetworkInterfaceInfoOSX *i = AddInterfaceToList(m, ifa, utc);
-                            if (i && MulticastInterface(i) && i->ifinfo.Advertise)
-                            {
-                                if (ifa->ifa_addr->sa_family == AF_INET) 
-                                    foundav4 = mDNStrue;
-                                else 
-                                    foundav6 = mDNStrue;
-                            }
-                        }
-                    }
-                }
-            }
-        ifa = ifa->ifa_next;
-    }
-
-    // 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);
-
-    // Now the list is complete, set the McastTxRx setting for each interface.
-    NetworkInterfaceInfoOSX *i;
-    for (i = m->p->InterfaceList; i; i = i->next)
-        if (i->Exists)
-        {
-            mDNSBool txrx = MulticastInterface(i);
-            if (i->ifinfo.McastTxRx != txrx)
-            {
-                i->ifinfo.McastTxRx = txrx;
-                i->Exists = 2; // State change; need to deregister and reregister this interface
-            }
-        }
-
-    if (InfoSocket >= 0) 
-        close(InfoSocket);
-
-    mDNS_snprintf(defaultname, sizeof(defaultname), "%.*s-%02X%02X%02X%02X%02X%02X", HINFO_HWstring_prefixlen, HINFO_HWstring,
-                  m->PrimaryMAC.b[0], m->PrimaryMAC.b[1], m->PrimaryMAC.b[2], m->PrimaryMAC.b[3], m->PrimaryMAC.b[4], m->PrimaryMAC.b[5]);
-
-    // Set up the nice label
-    domainlabel nicelabel;
-    nicelabel.c[0] = 0;
-    GetUserSpecifiedFriendlyComputerName(&nicelabel);
-    if (nicelabel.c[0] == 0)
-    {
-        debugf("Couldn’t read user-specified Computer Name; using default “%s” instead", defaultname);
-        MakeDomainLabelFromLiteralString(&nicelabel, defaultname);
-    }
-
-    // Set up the RFC 1034-compliant label
-    domainlabel hostlabel;
-    hostlabel.c[0] = 0;
-    GetUserSpecifiedLocalHostName(&hostlabel);
-    if (hostlabel.c[0] == 0)
-    {
-        debugf("Couldn’t read user-specified Local Hostname; using default “%s.local” instead", defaultname);
-        MakeDomainLabelFromLiteralString(&hostlabel, defaultname);
-    }
-
-    mDNSBool namechange = mDNSfalse;
-
-    // We use a case-sensitive comparison here because even though changing the capitalization
-    // of the name alone is not significant to DNS, it's still a change from the user's point of view
-    if (SameDomainLabelCS(m->p->usernicelabel.c, nicelabel.c))
-        debugf("Usernicelabel (%#s) unchanged since last time; not changing m->nicelabel (%#s)", m->p->usernicelabel.c, m->nicelabel.c);
-    else
-    {
-        if (m->p->usernicelabel.c[0])   // Don't show message first time through, when we first read name from prefs on boot
-            LogMsg("User updated Computer Name from “%#s” to “%#s”", m->p->usernicelabel.c, nicelabel.c);
-        m->p->usernicelabel = m->nicelabel = nicelabel;
-        namechange = mDNStrue;
-    }
-
-    if (SameDomainLabelCS(m->p->userhostlabel.c, hostlabel.c))
-        debugf("Userhostlabel (%#s) unchanged since last time; not changing m->hostlabel (%#s)", m->p->userhostlabel.c, m->hostlabel.c);
-    else
-    {
-        if (m->p->userhostlabel.c[0])   // Don't show message first time through, when we first read name from prefs on boot
-            LogMsg("User updated Local Hostname from “%#s” to “%#s”", m->p->userhostlabel.c, hostlabel.c);
-        m->p->userhostlabel = m->hostlabel = hostlabel;
-        mDNS_SetFQDN(m);
-        namechange = mDNStrue;
-    }
-
-#if APPLE_OSX_mDNSResponder
-    if (namechange)     // If either name has changed, we need to tickle our AutoTunnel state machine to update its registered records
-    {
-        DomainAuthInfo *info;
-        for (info = m->AuthInfoList; info; info = info->next)
-            if (info->AutoTunnel) AutoTunnelHostNameChanged(m, info);
-    }
-#endif // APPLE_OSX_mDNSResponder
-
-    return(mStatus_NoError);
-}
-
-// Returns number of leading one-bits in mask: 0-32 for IPv4, 0-128 for IPv6
-// Returns -1 if all the one-bits are not contiguous
-mDNSlocal int CountMaskBits(mDNSAddr *mask)
-{
-    int i = 0, bits = 0;
-    int bytes = mask->type == mDNSAddrType_IPv4 ? 4 : mask->type == mDNSAddrType_IPv6 ? 16 : 0;
-    while (i < bytes)
-    {
-        mDNSu8 b = mask->ip.v6.b[i++];
-        while (b & 0x80) { bits++; b <<= 1; }
-        if (b) return(-1);
-    }
-    while (i < bytes) if (mask->ip.v6.b[i++]) return(-1);
-    return(bits);
-}
-
-// returns count of non-link local V4 addresses registered
-mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
-{
-    NetworkInterfaceInfoOSX *i;
-    int count = 0;
-    for (i = m->p->InterfaceList; i; i = i->next)
-        if (i->Exists)
-        {
-            NetworkInterfaceInfo *const n = &i->ifinfo;
-            NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, 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
-            {
-                LogMsg("SetupActiveInterfaces ERROR! n->Registered %p != primary %p", i->Registered, primary);
-                i->Registered = mDNSNULL;
-            }
-
-            if (!i->Registered)
-            {
-                // 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
-                //
-
-                i->Registered = primary;
-
-                // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
-                // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
-                // 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
-                // everytime it creates a new interface. 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.
-                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);
-                }
-                else
-                {
-                    mDNS_RegisterInterface(m, n, i->Flashing && i->Occulting);
-                }
-
-                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),
-                        i->Flashing        ? " (Flashing)"  : "",
-                        i->Occulting       ? " (Occulting)" : "",
-                        n->InterfaceActive ? " (Primary)"   : "");
-
-                if (!n->McastTxRx)
-                    debugf("SetupActiveInterfaces:   No Tx/Rx on   %5s(%lu) %.6a InterfaceID %p %#a", i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, &n->ip);
-                else
-                {
-                    if (i->sa_family == AF_INET)
-                    {
-                        struct ip_mreq imr;
-                        primary->ifa_v4addr.s_addr = n->ip.ip.v4.NotAnInteger;
-                        imr.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
-                        imr.imr_interface        = primary->ifa_v4addr;
-
-                        // If this is our *first* IPv4 instance for this interface name, we need to do a IP_DROP_MEMBERSHIP first,
-                        // before trying to join the group, to clear out stale kernel state which may be lingering.
-                        // In particular, this happens with removable network interfaces like USB Ethernet adapters -- the kernel has stale state
-                        // from the last time the USB Ethernet adapter was connected, and part of the kernel thinks we've already joined the group
-                        // on that interface (so we get EADDRINUSE when we try to join again) but a different part of the kernel thinks we haven't
-                        // joined the group (so we receive no multicasts). Doing an IP_DROP_MEMBERSHIP before joining seems to flush the stale state.
-                        // Also, trying to make the code leave the group when the adapter is removed doesn't work either,
-                        // 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)
-                        {
-                            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));
-                            if (err < 0 && (errno != EADDRNOTAVAIL))
-                                LogMsg("setsockopt - IP_DROP_MEMBERSHIP error %d errno %d (%s)", err, errno, strerror(errno));
-                        }
-
-                        LogInfo("SetupActiveInterfaces: %5s(%lu) joining IPv4 mcast group %.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_ADD_MEMBERSHIP, &imr, sizeof(imr));
-                        // Joining same group twice can give "Address already in use" error -- no need to report that
-                        if (err < 0 && (errno != EADDRINUSE))
-                            LogMsg("setsockopt - IP_ADD_MEMBERSHIP error %d errno %d (%s) group %.4a on %.4a", err, errno, strerror(errno), &imr.imr_multiaddr, &imr.imr_interface);
-                    }
-                    if (i->sa_family == AF_INET6)
-                    {
-                        struct ipv6_mreq i6mr;
-                        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)
-                        {
-                            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));
-                            if (err < 0 && (errno != EADDRNOTAVAIL))
-                                LogMsg("setsockopt - IPV6_LEAVE_GROUP error %d errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
-                        }
-
-                        LogInfo("SetupActiveInterfaces: %5s(%lu) joining IPv6 mcast group %.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_JOIN_GROUP, &i6mr, sizeof(i6mr));
-                        // Joining same group twice can give "Address already in use" error -- no need to report that
-                        if (err < 0 && (errno != EADDRINUSE))
-                            LogMsg("setsockopt - IPV6_JOIN_GROUP error %d errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
-                    }
-                }
-            }
-        }
-
-    return count;
-}
-
-mDNSlocal void MarkAllInterfacesInactive(mDNS *const m, mDNSs32 utc)
-{
-    NetworkInterfaceInfoOSX *i;
-    for (i = m->p->InterfaceList; i; i = i->next)
-    {
-        if (i->Exists) i->LastSeen = utc;
-        i->Exists = mDNSfalse;
-    }
-}
-
-// returns count of non-link local V4 addresses deregistered
-mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
-{
-    // 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.
-    // We have to do this because mDNSCore will use that InterfaceID when sending packets, and if the memory
-    // it refers to has gone away we'll crash.
-    NetworkInterfaceInfoOSX *i;
-    int count = 0;
-    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);
-        if (i->Registered)
-            if (i->Exists == 0 || i->Exists == 2 || i->Registered != primary)
-            {
-                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,
-                        &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask),
-                        i->Flashing               ? " (Flashing)"  : "",
-                        i->Occulting              ? " (Occulting)" : "",
-                        i->ifinfo.InterfaceActive ? " (Primary)"   : "");
-
-                // Temporary fix to handle P2P flapping. P2P reuses the scope-id, mac address and the IP address
-                // everytime 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.
-                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);
-                }
-                else
-                {
-                    mDNS_DeregisterInterface(m, &i->ifinfo, i->Flashing && i->Occulting);
-                }
-                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,
-                // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
-                // If i->Registered is NOT set, then it's not registered and we should not call mDNS_DeregisterInterface() on it.
-
-                // Caution: If we ever decide to add code here to leave the multicast group, we need to make sure that this
-                // is the LAST representative of this physical interface, or we'll unsubscribe from the group prematurely.
-            }
-    }
-
-    // Second pass:
-    // Now that everything that's going to deregister has done so, we can clean up and free the memory
-    NetworkInterfaceInfoOSX **p = &m->p->InterfaceList;
-    while (*p)
-    {
-        i = *p;
-        // If no longer active, delete interface from list and free memory
-        if (!i->Exists)
-        {
-            if (i->LastSeen == utc) i->LastSeen = utc - 1;
-            mDNSBool delete = (NumCacheRecordsForInterfaceID(m, i->ifinfo.InterfaceID) == 0) && (utc - i->LastSeen >= 60);
-            LogInfo("ClearInactiveInterfaces: %-13s %5s(%lu) %.6a InterfaceID %p(%p) %#a/%d Age %d%s", delete ? "Deleting" : "Holding",
-                    i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, i,
-                    &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask), utc - i->LastSeen,
-                    i->ifinfo.InterfaceActive ? " (Primary)" : "");
-#if APPLE_OSX_mDNSResponder
-            if (i->BPF_fd >= 0) CloseBPF(i);
-#endif // APPLE_OSX_mDNSResponder
-            if (delete)
-            {
-                *p = i->next;
-                freeL("NetworkInterfaceInfoOSX", i);
-                continue;   // After deleting this object, don't want to do the "p = &i->next;" thing at the end of the loop
-            }
-        }
-        p = &i->next;
-    }
-    return count;
-}
-
-mDNSlocal void AppendDNameListElem(DNameListElem ***List, mDNSu32 uid, domainname *name)
-{
-    DNameListElem *dnle = (DNameListElem*) mallocL("DNameListElem/AppendDNameListElem", sizeof(DNameListElem));
-    if (!dnle) LogMsg("ERROR: AppendDNameListElem: memory exhausted");
-    else
-    {
-        dnle->next = mDNSNULL;
-        dnle->uid  = uid;
-        AssignDomainName(&dnle->name, name);
-        **List = dnle;
-        *List = &dnle->next;
-    }
-}
-
-mDNSlocal int compare_dns_configs(const void *aa, const void *bb)
-{
-    dns_resolver_t *a = *(dns_resolver_t**)aa;
-    dns_resolver_t *b = *(dns_resolver_t**)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)
-{
-    char *buf = ".";
-    mDNSu32 scopeid = 0;
-    char ifid_buf[16];
-
-    if (domain)
-        buf = domain;
-    //
-    // Hash the search domain name followed by the InterfaceID.
-    // As we have scoped search domains, we also included InterfaceID. If either of them change,
-    // we will detect it. Even if the order of them change, we will detect it.
-    //
-    // Note: We have to handle a few of these tricky cases.
-    //
-    // 1) Current: com, apple.com Changing to: comapple.com
-    // 2) Current: a.com,b.com Changing to a.comb.com
-    // 3) Current: a.com,b.com (ifid 8), Changing to a.com8b.com (ifid 8)
-    // 4) Current: a.com (ifid 12), Changing to a.com1 (ifid: 2)
-    //
-    // There are more variants of the above. The key thing is if we include the null in each case
-    // at the end of name and the InterfaceID, it will prevent a new name (which can't include
-    // NULL as part of the name) to be mistakenly thought of as a old name.
-
-    scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNStrue);
-    // mDNS_snprintf always null terminates
-    if (mDNS_snprintf(ifid_buf, sizeof(ifid_buf), "%u", scopeid) >= sizeof(ifid_buf))
-        LogMsg("UpdateSearchDomainHash: mDNS_snprintf failed for scopeid %u", scopeid);
-
-    LogInfo("UpdateSearchDomainHash: buf %s, ifid_buf %s", buf, ifid_buf);
-    MD5_Update(sdc, buf, strlen(buf) + 1);
-    MD5_Update(sdc, ifid_buf, strlen(ifid_buf) + 1);
-}
-
-mDNSlocal void FinalizeSearchDomainHash(mDNS *const m, MD5_CTX *sdc)
-{
-    mDNSu8 md5_hash[MD5_LEN];
-
-    MD5_Final(md5_hash, sdc);
-
-    if (memcmp(md5_hash, m->SearchDomainsHash, MD5_LEN))
-    {
-        // If the hash is different, either the search domains have changed or
-        // the ordering between them has changed. Restart the questions that
-        // would be affected by this.
-        LogInfo("FinalizeSearchDomains: The hash is different");
-        memcpy(m->SearchDomainsHash, md5_hash, MD5_LEN);
-        RetrySearchDomainQuestions(m);
-    }
-    else { LogInfo("FinalizeSearchDomains: The hash is same"); }
-}
-
-mDNSexport const char *DNSScopeToString(mDNSu32 scope)
-{
-    switch (scope)
-    {
-        case kScopeNone:
-            return "Unscoped";
-        case kScopeInterfaceID:
-            return "InterfaceScoped";
-        case kScopeServiceID:
-            return "ServiceScoped";
-        default:
-            return "Unknown";
-    }
-}
-
-mDNSlocal void ConfigSearchDomains(mDNS *const m, dns_resolver_t *resolver, mDNSInterfaceID interface, mDNSu32 scope, MD5_CTX *sdc)
-{
-    const char *scopeString = DNSScopeToString(scope);
-    int j;
-
-    if (scope != kScopeNone)
-    {
-        LogInfo("ConfigSearchDomains: (%s) Ignoring search domain for Interface %p", scopeString, interface);
-        return;
-    }
-    for (j = 0; j < resolver->n_search; j++)
-    {
-        LogInfo("ConfigSearchDomains: (%s) configuring search list %s", scopeString, resolver->search[j]);
-        UpdateSearchDomainHash(m, sdc, resolver->search[j], NULL);
-        mDNS_AddSearchDomain_CString(resolver->search[j], NULL);
-    }
-}
-
-mDNSlocal mDNSInterfaceID ConfigParseInterfaceID(mDNS *const m, mDNSu32 ifindex)
-{
-    NetworkInterfaceInfoOSX *ni;
-    mDNSInterfaceID interface;
-
-    for (ni = m->p->InterfaceList; ni; ni = ni->next)
-    {
-        if (ni->ifinfo.InterfaceID && ni->scope_id == ifindex) 
-            break;
-    }
-    if (ni != NULL) 
-    {
-        interface = ni->ifinfo.InterfaceID;
-    }
-    else
-    {
-        // In rare circumstances, we could potentially hit this case where we cannot parse the InterfaceID
-        // (see <rdar://problem/13214785>). At this point, we still accept the DNS Config from configd 
-        // Note: We currently ack the whole dns configuration and not individual resolvers or DNS servers. 
-        // As the caller is going to ack the configuration always, we have to add all the DNS servers 
-        // in the configuration. Otherwise, we won't have any DNS servers up until the network change.
-
-        LogMsg("ConfigParseInterfaceID: interface specific index %d not found (interface may not be UP)",ifindex);
-
-        // Set the correct interface from configd before passing this to mDNS_AddDNSServer() below
-        interface = (mDNSInterfaceID)(unsigned long)ifindex;
-    }
-    return interface;
-}
-
-mDNSlocal void ConfigNonUnicastResolver(mDNS *const m, dns_resolver_t *r)
-{
-    char *opt = r->options;
-    domainname d; 
-
-    if (opt && !strncmp(opt, "mdns", strlen(opt)))
-    {
-        if (!MakeDomainNameFromDNSNameString(&d, r->domain))
-        { 
-            LogMsg("ConfigNonUnicastResolver: config->resolver bad domain %s", r->domain); 
-            return;
-        }
-        mDNS_AddMcastResolver(m, &d, mDNSInterface_Any, r->timeout);
-    }
-}
-
-mDNSlocal void ConfigDNSServers(mDNS *const m, dns_resolver_t *r, mDNSInterfaceID interface, mDNSu32 scope, mDNSu16 resGroupID)
-{
-    int n;
-    domainname d;
-    int serviceID = 0;
-    mDNSBool cellIntf = mDNSfalse;
-    mDNSBool scopedDNS = mDNSfalse;
-    mDNSBool reqA, reqAAAA;
-
-    if (!r->domain || !*r->domain) 
-    {
-        d.c[0] = 0;
-    }
-    else if (!MakeDomainNameFromDNSNameString(&d, r->domain))
-    { 
-        LogMsg("ConfigDNSServers: bad domain %s", r->domain); 
-        return;
-    }
-    // Parse the resolver specific attributes that affects all the DNS servers.
-    if (scope == kScopeInterfaceID)
-    {
-        scopedDNS = mDNStrue;
-    }
-    else if (scope == kScopeServiceID)
-    {
-        serviceID = r->service_identifier;
-    }
-
-#if TARGET_OS_IPHONE
-    cellIntf = (r->reach_flags & kSCNetworkReachabilityFlagsIsWWAN) ? mDNStrue : mDNSfalse;
-#endif
-    reqA = (r->flags & DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS ? mDNStrue : mDNSfalse);
-    reqAAAA = (r->flags & DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS ? mDNStrue : mDNSfalse);
-
-    for (n = 0; n < r->n_nameserver; n++)
-    {
-        mDNSAddr saddr;
-        DNSServer *s;
-
-        if (r->nameserver[n]->sa_family != AF_INET && r->nameserver[n]->sa_family != AF_INET6)
-            continue;
-        
-        if (SetupAddr(&saddr, r->nameserver[n]))
-        {
-            LogMsg("ConfigDNSServers: Bad address");
-            continue;
-        }
-        
-        // The timeout value is for all the DNS servers in a given resolver, hence we pass
-        // the timeout value only for the first DNSServer. If we don't have a value in the
-        // resolver, then use the core's default value
-        //
-        // 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);
-        if (s)
-        {
-            LogInfo("ConfigDNSServers(%s): DNS server %#a:%d for domain %##s", DNSScopeToString(scope), &s->addr, mDNSVal16(s->port), d.c);
-        }
-    }
-}
-
-// ConfigResolvers is called for different types of resolvers: Unscoped resolver, Interface scope resolver and
-// Service scope resolvers. This is indicated by the scope argument.
-//
-// "resolver" has entries that should only be used for unscoped questions.
-//
-// "scoped_resolver" has entries that should only be used for Interface scoped question i.e., questions that specify an
-// interface index (q->InterfaceID)
-//
-// "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)
-{
-    int i;
-    dns_resolver_t **resolver;
-    int nresolvers;
-    const char *scopeString = DNSScopeToString(scope);
-    mDNSInterfaceID interface;
-
-    switch (scope)
-    {
-        case kScopeNone:
-            resolver = config->resolver;
-            nresolvers = config->n_resolver;
-            break;
-        case kScopeInterfaceID:
-            resolver = config->scoped_resolver;
-            nresolvers = config->n_scoped_resolver;
-            break;
-        case kScopeServiceID:
-            resolver = config->service_specific_resolver;
-            nresolvers = config->n_service_specific_resolver;
-            break;
-        default:
-            return;
-    }
-    qsort(resolver, nresolvers, sizeof(dns_resolver_t*), compare_dns_configs);
-
-    for (i = 0; i < nresolvers; i++)
-    {
-        dns_resolver_t *r = resolver[i];
-
-        LogInfo("ConfigResolvers: %s resolver[%d] domain %s n_nameserver %d", scopeString, i, r->domain, r->n_nameserver);
-
-        interface = mDNSInterface_Any;
-
-        // Parse the interface index 
-        if (r->if_index != 0)
-        {
-            interface = ConfigParseInterfaceID(m, r->if_index);
-        }
-
-        if (setsearch)
-        {
-            ConfigSearchDomains(m, resolver[i], interface, scope, sdc);
-            // Parse other scoped resolvers for search lists
-            if (!setservers) 
-                continue;
-        }
-
-        if (r->port == 5353 || r->n_nameserver == 0)
-        {
-            ConfigNonUnicastResolver(m, r);
-        }
-        else
-        {
-            // Each scoped resolver gets its own ID (i.e., they are in their own group) so that responses from the
-            // scoped resolver are not used by other non-scoped or scoped resolvers.
-            if (scope != kScopeNone) 
-                resGroupID++;
-
-            ConfigDNSServers(m, r, interface, scope, resGroupID);
-        }
-    }
-}
-
-#if APPLE_OSX_mDNSResponder
-mDNSlocal mDNSBool QuestionValidForDNSTrigger(DNSQuestion *q)
-{
-    if (QuerySuppressed(q))
-    {
-        debugf("QuestionValidForDNSTrigger: Suppressed: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-        return mDNSfalse;
-    }
-    if (mDNSOpaque16IsZero(q->TargetQID))
-    {
-        debugf("QuestionValidForDNSTrigger: Multicast: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-        return mDNSfalse;
-    }
-    // If we answered using LocalOnly records e.g., /etc/hosts, don't consider that a valid response
-    // for trigger.
-    if (q->LOAddressAnswers)
-    {
-        debugf("QuestionValidForDNSTrigger: LocalOnly answers: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-        return mDNSfalse;
-    }
-    return mDNStrue;
-}
-#endif
-
-// This function is called if we are not delivering unicast answers to "A" or "AAAA" questions.
-// 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)
-{
-    if (!QuestionValidForDNSTrigger(q))
-        return;
-
-    // Ignore applications that start and stop queries for no reason before we ever talk
-    // to any DNS server.
-    if (!q->triedAllServersOnce)
-    {
-        LogInfo("QuestionValidForDNSTrigger: question %##s (%s) stopped too soon", q->qname.c, DNSTypeName(q->qtype));
-        return;
-    }
-    if (q->qtype == kDNSType_A)
-        m->p->v4answers = 0;
-    if (q->qtype == kDNSType_AAAA)
-        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,
-            DNSTypeName(q->qtype));
-    }
-}
-#endif
-
-mDNSlocal void AckConfigd(mDNS *const m, dns_config_t *config)
-{
-    mDNS_CheckLock(m);
-
-    // Acking the configuration triggers configd to reissue the reachability queries
-    m->p->DNSTrigger = NonZeroTime(m->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)
-{
-    mDNSBool trigger = mDNSfalse;
-    mDNSs32 timenow;
-
-    // Don't send triggers too often.
-    // If we have started delivering answers to questions, we should send a trigger
-    // if the time permits. If we are delivering answers, we should set the state
-    // of v4answers/v6answers to 1 and avoid sending a trigger.  But, we don't know
-    // whether the answers that are being delivered currently is for configd or some
-    // other application. If we set the v4answers/v6answers to 1 and not deliver a trigger,
-    // then we won't deliver the trigger later when it is okay to send one as the
-    // "answers" are already set to 1. Hence, don't affect the state of v4answers and
-    // v6answers if we are not delivering triggers.
-    mDNS_Lock(m);
-    timenow = m->timenow;
-    if (m->p->DNSTrigger && (timenow - m->p->DNSTrigger) < DNS_TRIGGER_INTERVAL)
-    {
-        if (!m->p->v4answers || !m->p->v6answers)
-        {
-            debugf("mDNSPlatformTriggerDNSRetry: not triggering, time since last trigger %d ms, v4ans %d, v6ans %d",
-                (timenow - m->p->DNSTrigger), m->p->v4answers, m->p->v6answers);
-        }
-        mDNS_Unlock(m);
-        return;
-    }
-    mDNS_Unlock(m);
-    if (v4q != NULL && QuestionValidForDNSTrigger(v4q))
-    {
-        int old = m->p->v4answers;
-
-        m->p->v4answers = 1;
-
-        // If there are IPv4 answers now and previously we did not have
-        // any answers, trigger a DNS change so that reachability
-        // can retry the queries again.
-        if (!old)
-        {
-            LogInfo("mDNSPlatformTriggerDNSRetry: Triggering because of IPv4, last trigger %d ms, %##s (%s)", (timenow - m->p->DNSTrigger),
-                v4q->qname.c, DNSTypeName(v4q->qtype));
-            trigger = mDNStrue;
-        }
-    }
-    if (v6q != NULL && QuestionValidForDNSTrigger(v6q))
-    {
-        int old = m->p->v6answers;
-
-        m->p->v6answers = 1;
-        // If there are IPv6 answers now and previously we did not have
-        // any answers, trigger a DNS change so that reachability
-        // can retry the queries again.
-        if (!old)
-        {
-            LogInfo("mDNSPlatformTriggerDNSRetry: Triggering because of IPv6, last trigger %d ms, %##s (%s)", (timenow - m->p->DNSTrigger),
-                v6q->qname.c, DNSTypeName(v6q->qtype));
-            trigger = mDNStrue;
-        }
-    }
-    if (trigger)
-    {
-        dns_config_t *config = dns_configuration_copy();
-        if (config)
-        {
-            mDNS_Lock(m);
-            AckConfigd(m, config);
-            mDNS_Unlock(m);
-            dns_configuration_free(config);
-        }
-        else
-        {
-            LogMsg("mDNSPlatformTriggerDNSRetry: ERROR!! configd did not return config");
-        }
-    }
-}
-
-mDNSlocal void SetupActiveDirectoryDomain(dns_config_t *config)
-{
-    // Record the so-called "primary" domain, which we use as a hint to tell if the user is on a network set up
-    // by someone using Microsoft Active Directory using "local" as a private internal top-level domain
-    if (config->n_resolver && config->resolver[0]->domain && config->resolver[0]->n_nameserver &&
-        config->resolver[0]->nameserver[0])
-    {
-        MakeDomainNameFromDNSNameString(&ActiveDirectoryPrimaryDomain, config->resolver[0]->domain);
-    }
-    else
-    {
-         ActiveDirectoryPrimaryDomain.c[0] = 0;
-    }
-
-    //MakeDomainNameFromDNSNameString(&ActiveDirectoryPrimaryDomain, "test.local");
-    ActiveDirectoryPrimaryDomainLabelCount = CountLabels(&ActiveDirectoryPrimaryDomain);
-    if (config->n_resolver && config->resolver[0]->n_nameserver &&
-        SameDomainName(SkipLeadingLabels(&ActiveDirectoryPrimaryDomain, ActiveDirectoryPrimaryDomainLabelCount - 1), &localdomain))
-    {
-        SetupAddr(&ActiveDirectoryPrimaryDomainServer, config->resolver[0]->nameserver[0]);
-    }
-    else
-    {
-        AssignDomainName(&ActiveDirectoryPrimaryDomain, (const domainname *)"");
-        ActiveDirectoryPrimaryDomainLabelCount = 0;
-        ActiveDirectoryPrimaryDomainServer = zeroAddr;
-    }
-}
-#endif
-
-mDNSlocal void SetupDDNSDomains(domainname *const fqdn, DNameListElem **RegDomains, DNameListElem **BrowseDomains)
-{
-    int i;
-    char buf[MAX_ESCAPED_DOMAIN_NAME];  // Max legal C-string name, including terminating NUL
-    domainname d;
-
-    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:mDNSPlatformSetDNSConfig"), NULL, NULL);
-    if (!store)
-    {
-        LogMsg("SetupDDNSDomains: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
-    }
-    else
-    {
-        CFDictionaryRef ddnsdict = SCDynamicStoreCopyValue(store, NetworkChangedKey_DynamicDNS);
-        if (ddnsdict)
-        {
-            if (fqdn)
-            {
-                CFArrayRef fqdnArray = CFDictionaryGetValue(ddnsdict, CFSTR("HostNames"));
-                if (fqdnArray && CFArrayGetCount(fqdnArray) > 0)
-                {
-                    // for now, we only look at the first array element.  if we ever support multiple configurations, we will walk the list
-                    CFDictionaryRef fqdnDict = CFArrayGetValueAtIndex(fqdnArray, 0);
-                    if (fqdnDict && DictionaryIsEnabled(fqdnDict))
-                    {
-                        CFStringRef name = CFDictionaryGetValue(fqdnDict, CFSTR("Domain"));
-                        if (name)
-                        {
-                            if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
-                                !MakeDomainNameFromDNSNameString(fqdn, buf) || !fqdn->c[0])
-                                LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS host name: %s", buf[0] ? buf : "(unknown)");
-                            else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS host name: %s", buf);
-                        }
-                    }
-                }
-            }
-
-            if (RegDomains)
-            {
-                CFArrayRef regArray = CFDictionaryGetValue(ddnsdict, CFSTR("RegistrationDomains"));
-                if (regArray && CFArrayGetCount(regArray) > 0)
-                {
-                    CFDictionaryRef regDict = CFArrayGetValueAtIndex(regArray, 0);
-                    if (regDict && DictionaryIsEnabled(regDict))
-                    {
-                        CFStringRef name = CFDictionaryGetValue(regDict, CFSTR("Domain"));
-                        if (name)
-                        {
-                            if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
-                                !MakeDomainNameFromDNSNameString(&d, buf) || !d.c[0])
-                                LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS registration domain: %s", buf[0] ? buf : "(unknown)");
-                            else
-                            {
-                                debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS registration domain: %s", buf);
-                                AppendDNameListElem(&RegDomains, 0, &d);
-                            }
-                        }
-                    }
-                }
-            }
-
-            if (BrowseDomains)
-            {
-                CFArrayRef browseArray = CFDictionaryGetValue(ddnsdict, CFSTR("BrowseDomains"));
-                if (browseArray)
-                {
-                    for (i = 0; i < CFArrayGetCount(browseArray); i++)
-                    {
-                        CFDictionaryRef browseDict = CFArrayGetValueAtIndex(browseArray, i);
-                        if (browseDict && DictionaryIsEnabled(browseDict))
-                        {
-                            CFStringRef name = CFDictionaryGetValue(browseDict, CFSTR("Domain"));
-                            if (name)
-                            {
-                                if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
-                                    !MakeDomainNameFromDNSNameString(&d, buf) || !d.c[0])
-                                    LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS browsing domain: %s", buf[0] ? buf : "(unknown)");
-                                else
-                                {
-                                    debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS browsing domain: %s", buf);
-                                    AppendDNameListElem(&BrowseDomains, 0, &d);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            CFRelease(ddnsdict);
-        }
-
-        if (RegDomains)
-        {
-            CFDictionaryRef btmm = SCDynamicStoreCopyValue(store, NetworkChangedKey_BackToMyMac);
-            if (btmm)
-            {
-                CFIndex size = CFDictionaryGetCount(btmm);
-                const void *key[size];
-                const void *val[size];
-                CFDictionaryGetKeysAndValues(btmm, key, val);
-                for (i = 0; i < size; i++)
-                {
-                    LogInfo("BackToMyMac %d", i);
-                    if (!CFStringGetCString(key[i], buf, sizeof(buf), kCFStringEncodingUTF8))
-                        LogMsg("Can't read BackToMyMac %d key %s", i, buf);
-                    else
-                    {
-                        mDNSu32 uid = atoi(buf);
-                        if (!CFStringGetCString(val[i], buf, sizeof(buf), kCFStringEncodingUTF8))
-                            LogMsg("Can't read BackToMyMac %d val %s", i, buf);
-                        else if (MakeDomainNameFromDNSNameString(&d, buf) && d.c[0])
-                        {
-                            LogInfo("BackToMyMac %d %d %##s", i, uid, d.c);
-                            AppendDNameListElem(&RegDomains, uid, &d);
-                        }
-                    }
-                }
-                CFRelease(btmm);
-            }
-        }
-        CFRelease(store);
-    }
-}
-
-// 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,
-    DNameListElem **RegDomains, DNameListElem **BrowseDomains, mDNSBool ackConfig)
-{
-    MD5_CTX sdc;    // search domain context
-    static mDNSu16 resolverGroupID = 0;
-
-    // Need to set these here because we need to do this even if SCDynamicStoreCreate() or SCDynamicStoreCopyValue() below don't succeed
-    if (fqdn) fqdn->c[0]      = 0;
-    if (RegDomains   ) *RegDomains     = NULL;
-    if (BrowseDomains) *BrowseDomains  = NULL;
-
-    LogInfo("mDNSPlatformSetDNSConfig:%s%s%s%s%s",
-            setservers    ? " setservers"    : "",
-            setsearch     ? " setsearch"     : "",
-            fqdn          ? " fqdn"          : "",
-            RegDomains    ? " RegDomains"    : "",
-            BrowseDomains ? " BrowseDomains" : "");
-
-    if (setsearch) MD5_Init(&sdc);
-
-    // Add the inferred address-based configuration discovery domains
-    // (should really be in core code I think, not platform-specific)
-    if (setsearch)
-    {
-        struct ifaddrs *ifa = mDNSNULL;
-        struct sockaddr_in saddr;
-        mDNSPlatformMemZero(&saddr, sizeof(saddr));
-        saddr.sin_len = sizeof(saddr);
-        saddr.sin_family = AF_INET;
-        saddr.sin_port = 0;
-        saddr.sin_addr.s_addr = *(in_addr_t *)&m->Router.ip.v4;
-
-        // Don't add any reverse-IP search domains if doing the WAB bootstrap queries would cause dial-on-demand connection initiation
-        if (!AddrRequiresPPPConnection((struct sockaddr *)&saddr)) ifa =  myGetIfAddrs(1);
-
-        while (ifa)
-        {
-            mDNSAddr a, n;
-            char buf[64];
-
-            if (ifa->ifa_addr->sa_family == AF_INET &&
-                ifa->ifa_netmask                    &&
-                !(ifa->ifa_flags & IFF_LOOPBACK)    &&
-                !SetupAddr(&a, ifa->ifa_addr)       &&
-                !mDNSv4AddressIsLinkLocal(&a.ip.v4)  )
-            {
-                // Apparently it's normal for the sa_family of an ifa_netmask to sometimes be incorrect, so we explicitly fix it here before calling SetupAddr
-                // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
-                ifa->ifa_netmask->sa_family = ifa->ifa_addr->sa_family;     // Make sure ifa_netmask->sa_family is set correctly
-                SetupAddr(&n, ifa->ifa_netmask);
-                // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
-                mDNS_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa.", a.ip.v4.b[3] & n.ip.v4.b[3],
-                              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);
-                mDNS_AddSearchDomain_CString(buf, mDNSNULL);
-            }
-            ifa = ifa->ifa_next;
-        }
-    }
-
-#ifndef MDNS_NO_DNSINFO
-    if (setservers || setsearch)
-    {
-        dns_config_t *config = dns_configuration_copy();
-        if (!config)
-        {
-            // When running on 10.3 (build 7xxx) and earlier, we don't expect dns_configuration_copy() to succeed
-            // On 10.4, calls to dns_configuration_copy() early in the boot process often fail.
-            // Apparently this is expected behaviour -- "not a bug".
-            // Accordingly, we suppress syslog messages for the first three minutes after boot.
-            // If we are still getting failures after three minutes, then we log them.
-            if ((mDNSu32)mDNSPlatformRawTime() > (mDNSu32)(mDNSPlatformOneSecond * 180))
-                LogMsg("mDNSPlatformSetDNSConfig: Error: dns_configuration_copy returned NULL");
-        }
-        else
-        {
-            LogInfo("mDNSPlatformSetDNSConfig: config->n_resolver = %d, generation %llu", config->n_resolver, config->generation);
-            if (m->p->LastConfigGeneration == config->generation)
-            {
-                LogInfo("mDNSPlatformSetDNSConfig: generation number %llu same, not processing", config->generation);
-                dns_configuration_free(config);
-                SetupDDNSDomains(fqdn, RegDomains, BrowseDomains);
-                return mDNSfalse;
-            }
-#if APPLE_OSX_mDNSResponder
-            SetupActiveDirectoryDomain(config);
-#endif
-
-            // With scoped DNS, we don't want to answer a non-scoped question using a scoped cache entry
-            // and vice-versa. As we compare resolverGroupID for matching cache entry with question, we need
-            // to make sure that they don't match. We ensure this by always bumping up resolverGroupID between
-            // the two calls to ConfigResolvers DNSServers for scoped and non-scoped can never have the
-            // 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);
-            resolverGroupID += config->n_resolver;
-
-            ConfigResolvers(m, config, kScopeInterfaceID, setsearch, setservers, &sdc, resolverGroupID);
-            resolverGroupID += config->n_scoped_resolver;
-
-            ConfigResolvers(m, config, kScopeServiceID, setsearch, setservers, &sdc, resolverGroupID);
-
-            // Acking provides a hint that we processed this current configuration and
-            // we will use that from now on, assuming we don't get another one immediately
-            // after we return from here.
-            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);
-            }
-            dns_configuration_free(config);
-            if (setsearch) FinalizeSearchDomainHash(m, &sdc);
-            setservers = mDNSfalse;  // Done these now -- no need to fetch the same data from SCDynamicStore
-            setsearch  = mDNSfalse;
-        }
-    }
-#endif // MDNS_NO_DNSINFO
-    SetupDDNSDomains(fqdn, RegDomains, BrowseDomains);
-    return mDNStrue;
-}
-
-
-mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *r)
-{
-    char buf[256];
-    (void)m; // Unused
-
-    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:mDNSPlatformGetPrimaryInterface"), NULL, NULL);
-    if (!store)
-        LogMsg("mDNSPlatformGetPrimaryInterface: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
-    else
-    {
-        CFDictionaryRef dict = SCDynamicStoreCopyValue(store, NetworkChangedKey_IPv4);
-        if (dict)
-        {
-            r->type  = mDNSAddrType_IPv4;
-            r->ip.v4 = zerov4Addr;
-            CFStringRef string = CFDictionaryGetValue(dict, kSCPropNetIPv4Router);
-            if (string)
-            {
-                if (!CFStringGetCString(string, buf, 256, kCFStringEncodingUTF8))
-                    LogMsg("Could not convert router to CString");
-                else
-                {
-                    struct sockaddr_in saddr;
-                    saddr.sin_len = sizeof(saddr);
-                    saddr.sin_family = AF_INET;
-                    saddr.sin_port = 0;
-                    inet_aton(buf, &saddr.sin_addr);
-
-                    *(in_addr_t *)&r->ip.v4 = saddr.sin_addr.s_addr;
-                }
-            }
-
-            string = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface);
-            if (string)
-            {
-                mDNSBool HavePrimaryGlobalv6 = mDNSfalse;  // does the primary interface have a global v6 address?
-                struct ifaddrs *ifa = myGetIfAddrs(1);
-
-                *v4 = *v6 = zeroAddr;
-
-                if (!CFStringGetCString(string, buf, 256, kCFStringEncodingUTF8)) { LogMsg("Could not convert router to CString"); goto exit; }
-
-                // find primary interface in list
-                while (ifa && (mDNSIPv4AddressIsZero(v4->ip.v4) || mDNSv4AddressIsLinkLocal(&v4->ip.v4) || !HavePrimaryGlobalv6))
-                {
-                    mDNSAddr tmp6 = zeroAddr;
-                    if (!strcmp(buf, ifa->ifa_name))
-                    {
-                        if (ifa->ifa_addr->sa_family == AF_INET)
-                        {
-                            if (mDNSIPv4AddressIsZero(v4->ip.v4) || mDNSv4AddressIsLinkLocal(&v4->ip.v4)) SetupAddr(v4, ifa->ifa_addr);
-                        }
-                        else if (ifa->ifa_addr->sa_family == AF_INET6)
-                        {
-                            SetupAddr(&tmp6, ifa->ifa_addr);
-                            if (tmp6.ip.v6.b[0] >> 5 == 1)   // global prefix: 001
-                            { HavePrimaryGlobalv6 = mDNStrue; *v6 = tmp6; }
-                        }
-                    }
-                    else
-                    {
-                        // We'll take a V6 address from the non-primary interface if the primary interface doesn't have a global V6 address
-                        if (!HavePrimaryGlobalv6 && ifa->ifa_addr->sa_family == AF_INET6 && !v6->ip.v6.b[0])
-                        {
-                            SetupAddr(&tmp6, ifa->ifa_addr);
-                            if (tmp6.ip.v6.b[0] >> 5 == 1) *v6 = tmp6;
-                        }
-                    }
-                    ifa = ifa->ifa_next;
-                }
-
-                // Note that while we advertise v6, we still require v4 (possibly NAT'd, but not link-local) because we must use
-                // V4 to communicate w/ our DNS server
-            }
-
-exit:
-            CFRelease(dict);
-        }
-        CFRelease(store);
-    }
-    return mStatus_NoError;
-}
-
-mDNSexport void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
-{
-    LogInfo("mDNSPlatformDynDNSHostNameStatusChanged %d %##s", status, dname->c);
-    char uname[MAX_ESCAPED_DOMAIN_NAME];    // Max legal C-string name, including terminating NUL
-    ConvertDomainNameToCString(dname, uname);
-
-    char *p = uname;
-    while (*p)
-    {
-        *p = tolower(*p);
-        if (!(*(p+1)) && *p == '.') *p = 0; // if last character, strip trailing dot
-        p++;
-    }
-
-    // We need to make a CFDictionary called "State:/Network/DynamicDNS" containing (at present) a single entity.
-    // That single entity is a CFDictionary with name "HostNames".
-    // The "HostNames" CFDictionary contains a set of name/value pairs, where the each name is the FQDN
-    // in question, and the corresponding value is a CFDictionary giving the state for that FQDN.
-    // (At present we only support a single FQDN, so this dictionary holds just a single name/value pair.)
-    // The CFDictionary for each FQDN holds (at present) a single name/value pair,
-    // where the name is "Status" and the value is a CFNumber giving an errror code (with zero meaning success).
-
-    const CFStringRef StateKeys [1] = { CFSTR("HostNames") };
-    const CFStringRef HostKeys  [1] = { CFStringCreateWithCString(NULL, uname, kCFStringEncodingUTF8) };
-    const CFStringRef StatusKeys[1] = { CFSTR("Status") };
-    if (!HostKeys[0]) LogMsg("SetDDNSNameStatus: CFStringCreateWithCString(%s) failed", uname);
-    else
-    {
-        const CFNumberRef StatusVals[1] = { CFNumberCreate(NULL, kCFNumberSInt32Type, &status) };
-        if (!StatusVals[0]) LogMsg("SetDDNSNameStatus: CFNumberCreate(%d) failed", status);
-        else
-        {
-            const CFDictionaryRef HostVals[1] = { CFDictionaryCreate(NULL, (void*)StatusKeys, (void*)StatusVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
-            if (HostVals[0])
-            {
-                const CFDictionaryRef StateVals[1] = { CFDictionaryCreate(NULL, (void*)HostKeys, (void*)HostVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
-                if (StateVals[0])
-                {
-                    CFDictionaryRef StateDict = CFDictionaryCreate(NULL, (void*)StateKeys, (void*)StateVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-                    if (StateDict)
-                    {
-                        mDNSDynamicStoreSetConfig(kmDNSDynamicConfig, mDNSNULL, StateDict);
-                        CFRelease(StateDict);
-                    }
-                    CFRelease(StateVals[0]);
-                }
-                CFRelease(HostVals[0]);
-            }
-            CFRelease(StatusVals[0]);
-        }
-        CFRelease(HostKeys[0]);
-    }
-}
-
-#if APPLE_OSX_mDNSResponder
-#if !NO_AWACS
-
-// checks whether a domain is present in Setup:/Network/BackToMyMac. Just because there is a key in the
-// keychain for a domain, it does not become a valid BTMM domain. If things get inconsistent, this will
-// help catch it
-mDNSlocal mDNSBool IsBTMMDomain(domainname *d)
-{
-    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:IsBTMMDomain"), NULL, NULL);
-    if (!store)
-    {
-        LogMsg("IsBTMMDomain: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
-        return mDNSfalse;
-    }
-    CFDictionaryRef btmm = SCDynamicStoreCopyValue(store, NetworkChangedKey_BackToMyMac);
-    if (btmm)
-    {
-        CFIndex size = CFDictionaryGetCount(btmm);
-        char buf[MAX_ESCAPED_DOMAIN_NAME];  // Max legal C-string name, including terminating NUL
-        const void *key[size];
-        const void *val[size];
-        domainname dom;
-        int i;
-        CFDictionaryGetKeysAndValues(btmm, key, val);
-        for (i = 0; i < size; i++)
-        {
-            LogInfo("BackToMyMac %d", i);
-            if (!CFStringGetCString(key[i], buf, sizeof(buf), kCFStringEncodingUTF8))
-                LogMsg("IsBTMMDomain: ERROR!! Can't read BackToMyMac %d key %s", i, buf);
-            else
-            {
-                mDNSu32 uid = atoi(buf);
-                if (!CFStringGetCString(val[i], buf, sizeof(buf), kCFStringEncodingUTF8))
-                    LogMsg("IsBTMMDomain: Can't read BackToMyMac %d val %s", i, buf);
-                else if (MakeDomainNameFromDNSNameString(&dom, buf) && dom.c[0])
-                {
-                    if (SameDomainName(&dom, d))
-                    {
-                        LogInfo("IsBTMMDomain: Domain %##s is a btmm domain, uid %u", d->c, uid);
-                        CFRelease(btmm);
-                        CFRelease(store);
-                        return mDNStrue;
-                    }
-                }
-            }
-        }
-        CFRelease(btmm);
-    }
-    CFRelease(store);
-    LogInfo("IsBTMMDomain: Domain %##s not a btmm domain", d->c);
-    return mDNSfalse;
-}
-
-// Appends data to the buffer
-mDNSlocal int AddOneItem(char *buf, int bufsz, char *data, int *currlen)
-{
-    int len;
-
-    len = strlcpy(buf + *currlen, data, bufsz - *currlen);
-    if (len >= (bufsz - *currlen))
-    {
-        // if we have exceeded the space in buf, it has already been NULL terminated
-        // and we have nothing more to do. Set currlen to the last byte so that the caller
-        // knows to do the right thing
-        LogMsg("AddOneItem: Exceeded the max buffer size currlen %d, len %d", *currlen, len);
-        *currlen = bufsz - 1;
-        return -1;
-    }
-    else { (*currlen) += len; }
-
-    buf[*currlen] = ',';
-    if (*currlen >= bufsz)
-    {
-        LogMsg("AddOneItem: ERROR!! How can currlen be %d", *currlen);
-        *currlen = bufsz - 1;
-        buf[*currlen] = 0;
-        return -1;
-    }
-    // if we have filled up the buffer exactly, then there is no more work to do
-    if (*currlen == bufsz - 1) { buf[*currlen] = 0; return -1; }
-    (*currlen)++;
-    return *currlen;
-}
-
-// If we have at least one BTMM domain, then trigger the connection to the relay. If we have no
-// BTMM domains, then bring down the connection to the relay.
-mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m)
-{
-    DomainAuthInfo *BTMMDomain = mDNSNULL;
-    DomainAuthInfo *FoundInList;
-    static mDNSBool AWACSDConnected = mDNSfalse;
-    char AllUsers[1024];    // maximum size of mach message
-    char AllPass[1024];     // maximum size of mach message
-    char username[MAX_DOMAIN_LABEL + 1];
-    int currulen = 0;
-    int currplen = 0;
-
-    // if a domain is being deleted, we want to send a disconnect. If we send a disconnect now,
-    // we may not be able to send the dns queries over the relay connection which may be needed
-    // for sending the deregistrations. Hence, we need to delay sending the disconnect. But we
-    // need to make sure that we send the disconnect before attempting the next connect as the
-    // awacs connections are redirected based on usernames.
-    //
-    // For now we send a disconnect immediately. When we start sending dns queries over the relay
-    // connection, we will need to fix this.
-
-    for (FoundInList = m->AuthInfoList; FoundInList; FoundInList = FoundInList->next)
-        if (!FoundInList->deltime && FoundInList->AutoTunnel && IsBTMMDomain(&FoundInList->domain))
-        {
-            // We need the passwd from the first domain.
-            BTMMDomain = FoundInList;
-            ConvertDomainLabelToCString_unescaped((domainlabel *)BTMMDomain->domain.c, username);
-            LogInfo("UpdateBTMMRelayConnection: user %s for domain %##s", username, BTMMDomain->domain.c);
-            if (AddOneItem(AllUsers, sizeof(AllUsers), username, &currulen) == -1) break;
-            if (AddOneItem(AllPass, sizeof(AllPass), BTMMDomain->b64keydata, &currplen) == -1) break;
-        }
-
-    if (BTMMDomain)
-    {
-        // In the normal case (where we neither exceed the buffer size nor write bytes that
-        // fit exactly into the buffer), currulen/currplen should be a different size than
-        // (AllUsers - 1) / (AllPass - 1). In that case, we need to override the "," with a NULL byte.
-
-        if (currulen != (int)(sizeof(AllUsers) - 1)) AllUsers[currulen - 1] = 0;
-        if (currplen != (int)(sizeof(AllPass) - 1)) AllPass[currplen - 1] = 0;
-
-        LogInfo("UpdateBTMMRelayConnection: AWS_Connect for user %s", AllUsers);
-        AWACS_Connect(AllUsers, AllPass, "hello.connectivity.me.com");
-        AWACSDConnected = mDNStrue;
-    }
-    else
-    {
-        // Disconnect only if we connected previously
-        if (AWACSDConnected)
-        {
-            LogInfo("UpdateBTMMRelayConnection: AWS_Disconnect");
-            AWACS_Disconnect();
-            AWACSDConnected = mDNSfalse;
-        }
-        else LogInfo("UpdateBTMMRelayConnection: Not calling AWS_Disconnect");
-    }
-}
-#else
-mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m)
-{
-    (void) m; // Unused
-    LogInfo("UpdateBTMMRelayConnection: AWACS connection not started, no AWACS library");
-}
-#endif // ! NO_AWACS
-
-mDNSlocal void ProcessConndConfigChanges(mDNS *const m);
-
-#endif // APPLE_OSX_mDNSResponder
-
-// MUST be called holding the lock
-mDNSexport void SetDomainSecrets(mDNS *m)
-{
-#ifdef NO_SECURITYFRAMEWORK
-        (void) m;
-    LogMsg("Note: SetDomainSecrets: no keychain support");
-#else
-    mDNSBool haveAutoTunnels = mDNSfalse;
-
-    LogInfo("SetDomainSecrets");
-
-    // Rather than immediately deleting all keys now, we mark them for deletion in ten seconds.
-    // In the case where the user simultaneously removes their DDNS host name and the key
-    // for it, this gives mDNSResponder ten seconds to gracefully delete the name from the
-    // server before it loses access to the necessary key. Otherwise, we'd leave orphaned
-    // address records behind that we no longer have permission to delete.
-    DomainAuthInfo *ptr;
-    for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
-        ptr->deltime = NonZeroTime(m->timenow + mDNSPlatformOneSecond*10);
-
-#if APPLE_OSX_mDNSResponder
-    {
-        // Mark all TunnelClients for deletion
-        ClientTunnel *client;
-        for (client = m->TunnelClients; client; client = client->next)
-        {
-            LogInfo("SetDomainSecrets: tunnel to %##s marked for deletion", client->dstname.c);
-            client->MarkedForDeletion = mDNStrue;
-        }
-    }
-#endif // APPLE_OSX_mDNSResponder
-
-    // String Array used to write list of private domains to Dynamic Store
-    CFMutableArrayRef sa = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    if (!sa) { LogMsg("SetDomainSecrets: CFArrayCreateMutable failed"); return; }
-    CFIndex i;
-    CFDataRef data = NULL;
-    const int itemsPerEntry = 4; // domain name, key name, key value, Name value
-    CFArrayRef secrets = NULL;
-    int err = mDNSKeychainGetSecrets(&secrets);
-    if (err || !secrets)
-        LogMsg("SetDomainSecrets: mDNSKeychainGetSecrets failed error %d CFArrayRef %p", err, secrets);
-    else
-    {
-        CFIndex ArrayCount = CFArrayGetCount(secrets);
-        // Iterate through the secrets
-        for (i = 0; i < ArrayCount; ++i)
-        {
-            mDNSBool AutoTunnel;
-            int j, offset;
-            CFArrayRef entry = CFArrayGetValueAtIndex(secrets, i);
-            if (CFArrayGetTypeID() != CFGetTypeID(entry) || itemsPerEntry != CFArrayGetCount(entry))
-            { LogMsg("SetDomainSecrets: malformed entry %d, itemsPerEntry %d", i, itemsPerEntry); continue; }
-            for (j = 0; j < CFArrayGetCount(entry); ++j)
-                if (CFDataGetTypeID() != CFGetTypeID(CFArrayGetValueAtIndex(entry, j)))
-                { LogMsg("SetDomainSecrets: malformed entry item %d", j); continue; }
-
-            // The names have already been vetted by the helper, but checking them again here helps humans and automated tools verify correctness
-
-            // Max legal domainname as C-string, including space for btmmprefix and terminating NUL
-            // Get DNS domain this key is for (kmDNSKcWhere)
-            char stringbuf[MAX_ESCAPED_DOMAIN_NAME + sizeof(btmmprefix)];
-            data = CFArrayGetValueAtIndex(entry, kmDNSKcWhere);
-            if (CFDataGetLength(data) >= (int)sizeof(stringbuf))
-            { LogMsg("SetDomainSecrets: Bad kSecServiceItemAttr length %d", CFDataGetLength(data)); continue; }
-            CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), (UInt8 *)stringbuf);
-            stringbuf[CFDataGetLength(data)] = '\0';
-
-            AutoTunnel = mDNSfalse;
-            offset = 0;
-            if (!strncmp(stringbuf, dnsprefix, strlen(dnsprefix)))
-                offset = strlen(dnsprefix);
-            else if (!strncmp(stringbuf, btmmprefix, strlen(btmmprefix)))
-            {
-                AutoTunnel = mDNStrue;
-                offset = strlen(btmmprefix);
-            }
-            domainname domain;
-            if (!MakeDomainNameFromDNSNameString(&domain, stringbuf + offset)) { LogMsg("SetDomainSecrets: bad key domain %s", stringbuf); continue; }
-
-            // Get key name (kmDNSKcAccount)
-            data = CFArrayGetValueAtIndex(entry, kmDNSKcAccount);
-            if (CFDataGetLength(data) >= (int)sizeof(stringbuf))
-            { LogMsg("SetDomainSecrets: Bad kSecAccountItemAttr length %d", CFDataGetLength(data)); continue; }
-            CFDataGetBytes(data, CFRangeMake(0,CFDataGetLength(data)), (UInt8 *)stringbuf);
-            stringbuf[CFDataGetLength(data)] = '\0';
-
-            domainname keyname;
-            if (!MakeDomainNameFromDNSNameString(&keyname, stringbuf)) { LogMsg("SetDomainSecrets: bad key name %s", stringbuf); continue; }
-
-            // Get key data (kmDNSKcKey)
-            data = CFArrayGetValueAtIndex(entry, kmDNSKcKey);
-            if (CFDataGetLength(data) >= (int)sizeof(stringbuf))
-            { 
-                LogMsg("SetDomainSecrets: Shared secret too long: %d", CFDataGetLength(data));
-                continue;
-            }
-            CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), (UInt8 *)stringbuf);
-            stringbuf[CFDataGetLength(data)] = '\0';    // mDNS_SetSecretForDomain requires NULL-terminated C string for key
-
-            // Get the Name of the keychain entry (kmDNSKcName) host or host:port
-            // The hostname also has the port number and ":". It should take a maximum of 6 bytes.
-            char hostbuf[MAX_ESCAPED_DOMAIN_NAME + 6];  // Max legal domainname as C-string, including terminating NUL
-            data = CFArrayGetValueAtIndex(entry, kmDNSKcName);
-            if (CFDataGetLength(data) >= (int)sizeof(hostbuf))
-            { 
-                LogMsg("SetDomainSecrets: host:port data too long: %d", CFDataGetLength(data));
-                continue;
-            }
-            CFDataGetBytes(data, CFRangeMake(0,CFDataGetLength(data)), (UInt8 *)hostbuf);
-            hostbuf[CFDataGetLength(data)] = '\0';
-
-            domainname hostname;
-            mDNSIPPort port;
-            char *hptr;
-            hptr = strchr(hostbuf, ':');
-
-            port.NotAnInteger = 0;
-            if (hptr)
-            {
-                mDNSu8 *p;
-                mDNSu16 val = 0;
-
-                *hptr++ = '\0';
-                while(hptr && *hptr != 0)
-                {
-                    if (*hptr < '0' || *hptr > '9')
-                    { LogMsg("SetDomainSecrets: Malformed Port number %d, val %d", *hptr, val); val = 0; break;}
-                    val = val * 10 + *hptr - '0';
-                    hptr++;
-                }
-                if (!val) continue;
-                p = (mDNSu8 *)&val;
-                port.NotAnInteger = p[0] << 8 | p[1];
-            }
-            // The hostbuf is of the format dsid at hostname:port. We don't care about the dsid.
-            hptr = strchr(hostbuf, '@');
-            if (hptr)
-                hptr++;
-            else
-                hptr = hostbuf;
-            if (!MakeDomainNameFromDNSNameString(&hostname, hptr)) { LogMsg("SetDomainSecrets: bad host name %s", hptr); continue; }
-
-            DomainAuthInfo *FoundInList;
-            for (FoundInList = m->AuthInfoList; FoundInList; FoundInList = FoundInList->next)
-                if (SameDomainName(&FoundInList->domain, &domain)) break;
-
-#if APPLE_OSX_mDNSResponder
-            if (FoundInList)
-            {
-                // If any client tunnel destination is in this domain, set deletion flag to false
-                ClientTunnel *client;
-                for (client = m->TunnelClients; client; client = client->next)
-                    if (FoundInList == GetAuthInfoForName_internal(m, &client->dstname))
-                    {
-                        LogInfo("SetDomainSecrets: tunnel to %##s no longer marked for deletion", client->dstname.c);
-                        client->MarkedForDeletion = mDNSfalse;
-                    }
-            }
-
-#endif // APPLE_OSX_mDNSResponder
-
-            // Uncomment the line below to view the keys as they're read out of the system keychain
-            // DO NOT SHIP CODE THIS WAY OR YOU'LL LEAK SECRET DATA INTO A PUBLICLY READABLE FILE!
-            //LogInfo("SetDomainSecrets: domain %##s keyname %##s key %s hostname %##s port %d", &domain.c, &keyname.c, stringbuf, hostname.c, (port.b[0] << 8 | port.b[1]));
-            LogInfo("SetDomainSecrets: domain %##s keyname %##s hostname %##s port %d", &domain.c, &keyname.c, hostname.c, (port.b[0] << 8 | port.b[1]));
-
-            // If didn't find desired domain in the list, make a new entry
-            ptr = FoundInList;
-            if (FoundInList && FoundInList->AutoTunnel && haveAutoTunnels == mDNSfalse) haveAutoTunnels = mDNStrue;
-            if (!FoundInList)
-            {
-                ptr = (DomainAuthInfo*)mallocL("DomainAuthInfo", sizeof(*ptr));
-                if (!ptr) { LogMsg("SetDomainSecrets: No memory"); continue; }
-            }
-
-            //LogInfo("SetDomainSecrets: %d of %d %##s", i, ArrayCount, &domain);
-
-            // It is an AutoTunnel if the keychains tells us so (with btmm prefix) or if it is a TunnelModeDomain
-            if (mDNS_SetSecretForDomain(m, ptr, &domain, &keyname, stringbuf, &hostname, &port, AutoTunnel) == mStatus_BadParamErr)
-            {
-                if (!FoundInList) mDNSPlatformMemFree(ptr);     // If we made a new DomainAuthInfo here, and it turned out bad, dispose it immediately
-                continue;
-            }
-
-            ConvertDomainNameToCString(&domain, stringbuf);
-            CFStringRef cfs = CFStringCreateWithCString(NULL, stringbuf, kCFStringEncodingUTF8);
-            if (cfs) { CFArrayAppendValue(sa, cfs); CFRelease(cfs); }
-        }
-        CFRelease(secrets);
-    }
-
-    if (!privateDnsArray || !CFEqual(privateDnsArray, sa))
-    {
-        if (privateDnsArray)
-            CFRelease(privateDnsArray);
-        
-        privateDnsArray = sa;
-        CFRetain(privateDnsArray);
-        mDNSDynamicStoreSetConfig(kmDNSPrivateConfig, mDNSNULL, privateDnsArray);
-    }
-    CFRelease(sa);
-
-#if APPLE_OSX_mDNSResponder
-    {
-        // clean up ClientTunnels
-        ClientTunnel **pp = &m->TunnelClients;
-        while (*pp)
-        {
-            if ((*pp)->MarkedForDeletion)
-            {
-                ClientTunnel *cur = *pp;
-                LogInfo("SetDomainSecrets: removing client %p %##s from list", cur, cur->dstname.c);
-                if (cur->q.ThisQInterval >= 0) mDNS_StopQuery(m, &cur->q);
-                AutoTunnelSetKeys(cur, mDNSfalse);
-                *pp = cur->next;
-                freeL("ClientTunnel", cur);
-            }
-            else
-                pp = &(*pp)->next;
-        }
-
-        mDNSBool needAutoTunnelNAT = mDNSfalse;
-        DomainAuthInfo *info;
-        for (info = m->AuthInfoList; info; info = info->next)
-        {
-            if (info->AutoTunnel)
-            {
-                UpdateAutoTunnelDeviceInfoRecord(m, info);
-                UpdateAutoTunnelHostRecord(m, info);
-                UpdateAutoTunnelServiceRecords(m, info);
-                UpdateAutoTunnel6Record(m, info);
-                if (info->deltime)
-                {
-                    if (info->AutoTunnelServiceStarted) info->AutoTunnelServiceStarted = mDNSfalse;
-                }
-                else if (info->AutoTunnelServiceStarted)
-                    needAutoTunnelNAT = true;
-
-	            UpdateAutoTunnelDomainStatus(m, info);
-            }
-        }
-
-        // If the AutoTunnel NAT-T is no longer needed (& is currently running), stop it
-        if (!needAutoTunnelNAT && m->AutoTunnelNAT.clientContext)
-        {
-            // stop the NAT operation, reset port, cleanup state
-            mDNS_StopNATOperation_internal(m, &m->AutoTunnelNAT);
-            m->AutoTunnelNAT.ExternalAddress = zerov4Addr;
-            m->AutoTunnelNAT.NewAddress      = zerov4Addr;
-            m->AutoTunnelNAT.ExternalPort    = zeroIPPort;
-            m->AutoTunnelNAT.RequestedPort   = zeroIPPort;
-            m->AutoTunnelNAT.Lifetime        = 0;
-            m->AutoTunnelNAT.Result          = mStatus_NoError;
-            m->AutoTunnelNAT.clientContext   = mDNSNULL;
-        }
-
-        UpdateAnonymousRacoonConfig(m);     // Determine whether we need racoon to accept incoming connections
-        ProcessConndConfigChanges(m);       // Update AutoTunnelInnerAddress values and default ipsec policies as necessary
-    }
-#endif // APPLE_OSX_mDNSResponder
-
-    CheckSuppressUnusableQuestions(m);
-
-#endif /* NO_SECURITYFRAMEWORK */
-}
-
-mDNSlocal void SetLocalDomains(void)
-{
-    CFMutableArrayRef sa = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    if (!sa) { LogMsg("SetLocalDomains: CFArrayCreateMutable failed"); return; }
-
-    CFArrayAppendValue(sa, CFSTR("local"));
-    CFArrayAppendValue(sa, CFSTR("254.169.in-addr.arpa"));
-    CFArrayAppendValue(sa, CFSTR("8.e.f.ip6.arpa"));
-    CFArrayAppendValue(sa, CFSTR("9.e.f.ip6.arpa"));
-    CFArrayAppendValue(sa, CFSTR("a.e.f.ip6.arpa"));
-    CFArrayAppendValue(sa, CFSTR("b.e.f.ip6.arpa"));
-
-    mDNSDynamicStoreSetConfig(kmDNSMulticastConfig, mDNSNULL, sa);
-    CFRelease(sa);
-}
-
-mDNSlocal void GetCurrentPMSetting(const CFStringRef name, mDNSs32 *val)
-{
-#if USE_IOPMCOPYACTIVEPMPREFERENCES
-    CFTypeRef blob = NULL;
-    CFStringRef str = NULL;
-    CFDictionaryRef odict = NULL;
-    CFDictionaryRef idict = NULL;
-    CFNumberRef number = NULL;
-
-    blob = IOPSCopyPowerSourcesInfo();
-    if (!blob) { LogMsg("GetCurrentPMSetting: IOPSCopyPowerSourcesInfo failed!"); goto end; }
-
-    odict = IOPMCopyActivePMPreferences();
-    if (!odict) { LogMsg("GetCurrentPMSetting: IOPMCopyActivePMPreferences failed!"); goto end; }
-
-    str = IOPSGetProvidingPowerSourceType(blob);
-    if (!str) { LogMsg("GetCurrentPMSetting: IOPSGetProvidingPowerSourceType failed!"); goto end; }
-
-    idict = CFDictionaryGetValue(odict, str);
-    if (!idict)
-    {
-        char buf[256];
-        if (!CFStringGetCString(str, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
-        LogMsg("GetCurrentPMSetting: CFDictionaryGetValue (%s) failed!", buf);
-        goto end;
-    }
-
-    number = CFDictionaryGetValue(idict, name);
-    if (!number || CFGetTypeID(number) != CFNumberGetTypeID() || !CFNumberGetValue(number, kCFNumberSInt32Type, val))
-        *val = 0;
-end:
-    if (blob) CFRelease(blob);
-    if (odict) CFRelease(odict);
-
-#else
-
-    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetCurrentPMSetting"), NULL, NULL);
-    if (!store) LogMsg("GetCurrentPMSetting: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
-    else
-    {
-        CFDictionaryRef dict = SCDynamicStoreCopyValue(store, NetworkChangedKey_PowerSettings);
-        if (!dict) LogSPS("GetCurrentPMSetting: Could not get IOPM CurrentSettings dict");
-        else
-        {
-            CFNumberRef number = CFDictionaryGetValue(dict, name);
-            if (!number || CFGetTypeID(number) != CFNumberGetTypeID() || !CFNumberGetValue(number, kCFNumberSInt32Type, val))
-                *val = 0;
-            CFRelease(dict);
-        }
-        CFRelease(store);
-    }
-
-#endif
-}
-
-#if APPLE_OSX_mDNSResponder
-
-static CFMutableDictionaryRef spsStatusDict = NULL;
-static const CFStringRef kMetricRef = CFSTR("Metric");
-
-mDNSlocal void SPSStatusPutNumber(CFMutableDictionaryRef dict, const mDNSu8* const ptr, CFStringRef key)
-{
-    mDNSu8 tmp = (ptr[0] - '0') * 10 + ptr[1] - '0';
-    CFNumberRef num = CFNumberCreate(NULL, kCFNumberSInt8Type, &tmp);
-    if (!num)
-        LogMsg("SPSStatusPutNumber: Could not create CFNumber");
-    else
-    {
-        CFDictionarySetValue(dict, key, num);
-        CFRelease(num);
-    }
-}
-
-mDNSlocal CFMutableDictionaryRef SPSCreateDict(const mDNSu8* const ptr)
-{
-    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-    if (!dict) { LogMsg("SPSCreateDict: Could not create CFDictionary dict"); return dict; }
-
-    char buffer[1024];
-    buffer[mDNS_snprintf(buffer, sizeof(buffer), "%##s", ptr) - 1] = 0;
-    CFStringRef spsname = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
-    if (!spsname) { LogMsg("SPSCreateDict: Could not create CFString spsname full"); CFRelease(dict); return NULL; }
-    CFDictionarySetValue(dict, CFSTR("FullName"), spsname);
-    CFRelease(spsname);
-
-    if (ptr[0] >=  2) SPSStatusPutNumber(dict, ptr + 1, CFSTR("Type"));
-    if (ptr[0] >=  5) SPSStatusPutNumber(dict, ptr + 4, CFSTR("Portability"));
-    if (ptr[0] >=  8) SPSStatusPutNumber(dict, ptr + 7, CFSTR("MarginalPower"));
-    if (ptr[0] >= 11) SPSStatusPutNumber(dict, ptr +10, CFSTR("TotalPower"));
-
-    mDNSu32 tmp = SPSMetric(ptr);
-    CFNumberRef num = CFNumberCreate(NULL, kCFNumberSInt32Type, &tmp);
-    if (!num)
-        LogMsg("SPSCreateDict: Could not create CFNumber");
-    else
-    {
-        CFDictionarySetValue(dict, kMetricRef, num);
-        CFRelease(num);
-    }
-
-    if (ptr[0] >= 12)
-    {
-        memcpy(buffer, ptr + 13, ptr[0] - 12);
-        buffer[ptr[0] - 12] = 0;
-        spsname = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
-        if (!spsname) { LogMsg("SPSCreateDict: Could not create CFString spsname"); CFRelease(dict); return NULL; }
-        else
-        {
-            CFDictionarySetValue(dict, CFSTR("PrettyName"), spsname);
-            CFRelease(spsname);
-        }
-    }
-
-    return dict;
-}
-
-mDNSlocal CFComparisonResult CompareSPSEntries(const void *val1, const void *val2, void *context)
-{
-    (void)context;
-    return CFNumberCompare((CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)val1, kMetricRef),
-                           (CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)val2, kMetricRef),
-                           NULL);
-}
-
-mDNSlocal void UpdateSPSStatus(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
-{
-    NetworkInterfaceInfo* info = (NetworkInterfaceInfo*)question->QuestionContext;
-    debugf("UpdateSPSStatus: %s %##s %s %s", info->ifname, question->qname.c, AddRecord ? "Add" : "Rmv", answer ? RRDisplayString(m, answer) : "<null>");
-
-    mDNS_Lock(m);
-    mDNS_UpdateAllowSleep(m);
-    mDNS_Unlock(m);
-
-    if (answer && SPSMetric(answer->rdata->u.name.c) > 999999) return;  // Ignore instances with invalid names
-
-    if (!spsStatusDict)
-    {
-        spsStatusDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-        if (!spsStatusDict) { LogMsg("UpdateSPSStatus: Could not create CFDictionary spsStatusDict"); return; }
-    }
-
-    CFStringRef ifname = CFStringCreateWithCString(NULL, info->ifname, kCFStringEncodingUTF8);
-    if (!ifname) { LogMsg("UpdateSPSStatus: Could not create CFString ifname"); return; }
-
-    CFMutableArrayRef array = NULL;
-
-    if (!CFDictionaryGetValueIfPresent(spsStatusDict, ifname, (const void**) &array))
-    {
-        array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-        if (!array) { LogMsg("UpdateSPSStatus: Could not create CFMutableArray"); CFRelease(ifname); return; }
-        CFDictionarySetValue(spsStatusDict, ifname, array);
-        CFRelease(array); // let go of our reference, now that the dict has one
-    }
-    else
-    if (!array) { LogMsg("UpdateSPSStatus: Could not get CFMutableArray for %s", info->ifname); CFRelease(ifname); return; }
-
-    if (!answer) // special call that means the question has been stopped (because the interface is going away)
-        CFArrayRemoveAllValues(array);
-    else
-    {
-        CFMutableDictionaryRef dict = SPSCreateDict(answer->rdata->u.name.c);
-        if (!dict) { CFRelease(ifname); return; }
-
-        if (AddRecord)
-        {
-            if (!CFArrayContainsValue(array, CFRangeMake(0, CFArrayGetCount(array)), dict))
-            {
-                int i=0;
-                for (i=0; i<CFArrayGetCount(array); i++)
-                    if (CompareSPSEntries(CFArrayGetValueAtIndex(array, i), dict, NULL) != kCFCompareLessThan)
-                        break;
-                CFArrayInsertValueAtIndex(array, i, dict);
-            }
-            else LogMsg("UpdateSPSStatus: %s array already contains %##s", info->ifname, answer->rdata->u.name.c);
-        }
-        else
-        {
-            CFIndex i = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), dict);
-            if (i != -1) CFArrayRemoveValueAtIndex(array, i);
-            else LogMsg("UpdateSPSStatus: %s array does not contain %##s", info->ifname, answer->rdata->u.name.c);
-        }
-
-        CFRelease(dict);
-    }
-
-    if (!m->ShutdownTime) mDNSDynamicStoreSetConfig(kmDNSSleepProxyServersState, info->ifname, array);
-
-    CFRelease(ifname);
-}
-
-mDNSlocal mDNSs32 GetSystemSleepTimerSetting(void)
-{
-    mDNSs32 val = -1;
-    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetSystemSleepTimerSetting"), NULL, NULL);
-    if (!store)
-        LogMsg("GetSystemSleepTimerSetting: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
-    else
-    {
-        CFDictionaryRef dict = SCDynamicStoreCopyValue(store, NetworkChangedKey_PowerSettings);
-        if (dict)
-        {
-            CFNumberRef number = CFDictionaryGetValue(dict, CFSTR("System Sleep Timer"));
-            if (number) CFNumberGetValue(number, kCFNumberSInt32Type, &val);
-            CFRelease(dict);
-        }
-        CFRelease(store);
-    }
-    return val;
-}
-
-mDNSlocal void SetSPS(mDNS *const m)
-{
-    
-    // If we ever want to know InternetSharing status in the future, use DNSXEnableProxy()
-    mDNSu8 sps = (OfferSleepProxyService && GetSystemSleepTimerSetting() == 0) ? mDNSSleepProxyMetric_IncidentalSoftware : 0;
-
-    // For devices that are not running NAT, but are set to never sleep, we may choose to act
-    // as a Sleep Proxy, but only for non-portable Macs (Portability > 35 means nominal weight < 3kg)
-    //if (sps > mDNSSleepProxyMetric_PrimarySoftware && SPMetricPortability > 35) sps = 0;
-
-    // If we decide to let laptops act as Sleep Proxy, we should do it only when running on AC power, not on battery
-
-    // For devices that are unable to sleep at all to save power, or save 1W or less by sleeping,
-    // it makes sense for them to offer low-priority Sleep Proxy service on the network.
-    // We rate such a device as metric 70 ("Incidentally Available Hardware")
-    if (SPMetricMarginalPower <= 60 && !sps) sps = mDNSSleepProxyMetric_IncidentalHardware;
-
-    // If the launchd plist specifies an explicit value for the Intent Metric, then use that instead of the
-    // computed value (currently 40 "Primary Network Infrastructure Software" or 80 "Incidentally Available Software")
-    if (sps && OfferSleepProxyService && OfferSleepProxyService < 100) sps = OfferSleepProxyService;
-
-#ifdef NO_APPLETV_SLEEP_PROXY_ON_WIFI
-    // AppleTVs are not reliable sleep proxy servers on WiFi. Do not offer to be a BSP if the WiFi interface is active.
-    if (IsAppleTV())
-    {
-        NetworkInterfaceInfo *intf  = mDNSNULL;
-        mDNSEthAddr           bssid = zeroEthAddr;
-        for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
-        {
-            bssid = GetBSSID(intf->ifname);
-            if (!mDNSSameEthAddress(&bssid, &zeroEthAddr))
-            {
-                LogMsg("SetSPS: AppleTV on WiFi - not advertising BSP services");
-                sps = 0;
-                break;
-            }
-        }
-    }
-#endif  //  NO_APPLETV_SLEEP_PROXY_ON_WIFI
-
-    mDNSCoreBeSleepProxyServer(m, sps, SPMetricPortability, SPMetricMarginalPower, SPMetricTotalPower, SPMetricFeatures);
-}
-
-// The definitions below should eventually come from some externally-supplied header file.
-// However, since these definitions can't really be changed without breaking binary compatibility,
-// they should never change, so in practice it should not be a big problem to have them defined here.
-
-enum
-{                               // commands from the daemon to the driver
-    cmd_mDNSOffloadRR = 21,     // give the mdns update buffer to the driver
-};
-
-typedef union { void *ptr; mDNSOpaque64 sixtyfourbits; } FatPtr;
-
-typedef struct
-{                                       // cmd_mDNSOffloadRR structure
-    uint32_t command;                 // set to OffloadRR
-    uint32_t rrBufferSize;            // number of bytes of RR records
-    uint32_t numUDPPorts;             // number of SRV UDP ports
-    uint32_t numTCPPorts;             // number of SRV TCP ports
-    uint32_t numRRRecords;            // number of RR records
-    uint32_t compression;             // rrRecords - compression is base for compressed strings
-    FatPtr rrRecords;                 // address of array of pointers to the rr records
-    FatPtr udpPorts;                  // address of udp port list (SRV)
-    FatPtr tcpPorts;                  // address of tcp port list (SRV)
-} mDNSOffloadCmd;
-
-#include <IOKit/IOKitLib.h>
-#include <dns_util.h>
-
-mDNSlocal mDNSu16 GetPortArray(mDNS *const m, int trans, mDNSIPPort *portarray)
-{
-    const domainlabel *const tp = (trans == mDNSTransport_UDP) ? (const domainlabel *)"\x4_udp" : (const domainlabel *)"\x4_tcp";
-    int count = 0;
-    AuthRecord *rr;
-    for (rr = m->ResourceRecords; rr; rr=rr->next)
-        if (rr->resrec.rrtype == kDNSType_SRV && SameDomainLabel(ThirdLabel(rr->resrec.name)->c, tp->c))
-        {
-            if (portarray) portarray[count] = rr->resrec.rdata->u.srv.port;
-            count++;
-        }
-
-    // If Back to My Mac is on, also wake for packets to the IPSEC UDP port (4500)
-    if (trans == mDNSTransport_UDP && m->AutoTunnelNAT.clientContext)
-    {
-        LogSPS("GetPortArray Back to My Mac at %d", count);
-        if (portarray) portarray[count] = IPSECPort;
-        count++;
-    }
-    return(count);
-}
-
-#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
-mDNSlocal mDNSBool SupportsTCPKeepAlive()
-{
-    IOReturn  ret      = kIOReturnSuccess;
-    CFTypeRef obj      = NULL;
-    mDNSBool  supports = mDNSfalse;
-
-    ret = IOPlatformCopyFeatureActive(CFSTR("TCPKeepAliveDuringSleep"), &obj);
-    if ((kIOReturnSuccess == ret) && (obj != NULL))
-    {
-        supports = (obj ==  kCFBooleanTrue)? mDNStrue : mDNSfalse;
-        CFRelease(obj);
-    }
-    LogSPS("%s: The hardware %s TCP Keep Alive", __func__, (supports ? "supports" : "does not support"));
-    return supports;
-}
-
-mDNSlocal mDNSBool OnBattery(void)
-{
-    CFTypeRef powerInfo = IOPSCopyPowerSourcesInfo();
-    CFTypeRef powerSrc  = IOPSGetProvidingPowerSourceType(powerInfo);
-    mDNSBool  result    = mDNSfalse;
-
-    if (powerInfo != NULL)
-    {
-        result = CFEqual(CFSTR(kIOPSBatteryPowerValue), powerSrc);
-        CFRelease(powerInfo);
-    }
-    LogSPS("%s: The system is on %s", __func__, (result)? "Battery" : "AC Power");
-    return result;
-}
-
-#endif // !TARGET_OS_EMBEDDED
-
-#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)
-{
-    *numbytes = 0;
-    int count = 0;
-
-    AuthRecord *rr;
-
-    for (rr = m->ResourceRecords; rr; rr=rr->next)
-    {
-        if (!(rr->AuthFlags & AuthFlagsWakeOnly) && rr->resrec.RecordType > kDNSRecordTypeDeregistering)
-        {
-#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
-            mDNSBool   isKeepAliveRecord = mDNS_KeepaliveRecord(&rr->resrec);
-            // Skip over all other records if we are registering TCP KeepAlive records only
-            // Skip over TCP KeepAlive records if the policy prohibits it or if the interface does not support TCP Keepalive.
-            if ((TCPKAOnly && !isKeepAliveRecord) || (isKeepAliveRecord && !supportsTCPKA))
-                continue;
-
-            // Update the record before calculating the number of bytes required
-            // We offload the TCP Keepalive record even if the update fails. When the driver gets the record, it will
-            // attempt to update the record again.
-            if (isKeepAliveRecord && (UpdateKeepaliveRData(m, rr, intf, mDNSfalse, mDNSNULL) != mStatus_NoError))
-                LogSPS("CountProxyRecords: Failed to update keepalive record - %s", ARDisplayString(m, rr));
-#else
-            (void) TCPKAOnly;     // unused
-            (void) supportsTCPKA; // unused
-            (void) intf;          // unused
-#endif // APPLE_OSX_mDNSResponder
-            if (TfrRecordToNIC(rr))
-            {
-                *numbytes += DomainNameLength(rr->resrec.name) + 10 + rr->resrec.rdestimate;
-                LogSPS("CountProxyRecords: %3d size %5d total %5d %s",
-                       count, DomainNameLength(rr->resrec.name) + 10 + rr->resrec.rdestimate, *numbytes, ARDisplayString(m,rr));
-                count++;
-            }
-        }
-    }
-    return(count);
-}
-
-mDNSlocal void GetProxyRecords(mDNS *const m, DNSMessage *const msg, uint32_t *const numbytes, FatPtr *const records, mDNSBool TCPKAOnly, mDNSBool supportsTCPKA)
-{
-    mDNSu8 *p = msg->data;
-    const mDNSu8 *const limit = p + *numbytes;
-    InitializeDNSMessage(&msg->h, zeroID, zeroID);
-
-    int count = 0;
-    AuthRecord *rr;
-
-    for (rr = m->ResourceRecords; rr; rr=rr->next)
-    {
-        if (!(rr->AuthFlags & AuthFlagsWakeOnly) && rr->resrec.RecordType > kDNSRecordTypeDeregistering)
-        {
-#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
-            mDNSBool   isKeepAliveRecord = mDNS_KeepaliveRecord(&rr->resrec);
-
-            // Skip over all other records if we are registering TCP KeepAlive records only
-            // Skip over TCP KeepAlive records if the policy prohibits it or if the interface does not support TCP Keepalive
-            if ((TCPKAOnly && !isKeepAliveRecord) || (isKeepAliveRecord && !supportsTCPKA))
-                continue;
-#else
-            (void) TCPKAOnly;     // unused
-            (void) supportsTCPKA; // unused
-#endif // APPLE_OSX_mDNSResponder
-
-            if (TfrRecordToNIC(rr))
-            {
-                records[count].sixtyfourbits = zeroOpaque64;
-                records[count].ptr = p;
-                if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
-                    rr->resrec.rrclass |= kDNSClass_UniqueRRSet;    // Temporarily set the 'unique' bit so PutResourceRecord will set it
-                p = PutResourceRecordTTLWithLimit(msg, p, &msg->h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl, limit);
-                rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;       // Make sure to clear 'unique' bit back to normal state
-                LogSPS("GetProxyRecords: %3d start %p end %p size %5d total %5d %s",
-                       count, records[count].ptr, p, p - (mDNSu8 *)records[count].ptr, p - msg->data, ARDisplayString(m,rr));
-                count++;
-            }
-        }
-    }
-    *numbytes = p - msg->data;
-}
-
-// If compiling with old headers and libraries (pre 10.5) that don't include IOConnectCallStructMethod
-// then we declare a dummy version here so that the code at least compiles
-#ifndef AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER
-static kern_return_t
-IOConnectCallStructMethod(
-    mach_port_t connection,         // In
-    uint32_t selector,              // In
-    const void  *inputStruct,       // In
-    size_t inputStructCnt,          // In
-    void        *outputStruct,      // Out
-    size_t      *outputStructCnt)   // In/Out
-{
-    (void)connection;
-    (void)selector;
-    (void)inputStruct;
-    (void)inputStructCnt;
-    (void)outputStruct;
-    (void)outputStructCnt;
-    LogMsg("Compiled without IOConnectCallStructMethod");
-    return(KERN_FAILURE);
-}
-#endif
-
-mDNSexport mDNSBool SupportsInNICProxy(NetworkInterfaceInfo *const intf)
-{
-    if(!UseInternalSleepProxy)
-    {
-        LogSPS("SupportsInNICProxy: Internal Sleep Proxy is disabled");
-        return mDNSfalse;
-    }
-    return CheckInterfaceSupport(intf, mDNS_IOREG_KEY);
-}
-
-mDNSexport mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const intf)  // Called with the lock held
-{
-    mStatus      result        = mStatus_UnknownErr;
-    mDNSBool     TCPKAOnly     = mDNSfalse;
-    mDNSBool     supportsTCPKA = mDNSfalse;
-    mDNSBool     onbattery     = mDNSfalse; 
-    io_service_t service       = IOServiceGetMatchingService(kIOMasterPortDefault, IOBSDNameMatching(kIOMasterPortDefault, 0, intf->ifname));
-
-#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
-    onbattery = OnBattery();
-    // Check if the interface supports TCP Keepalives and the system policy says it is ok to offload TCP Keepalive records
-    supportsTCPKA = (InterfaceSupportsKeepAlive(intf) && SupportsTCPKeepAlive());
-
-    // 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);
-#else
-    (void) onbattery; // unused;
-#endif
-    if (!service) { LogMsg("ActivateLocalProxy: No service for interface %s", intf->ifname); return(mStatus_UnknownErr); }
-
-    io_name_t n1, n2;
-    IOObjectGetClass(service, n1);
-    io_object_t parent;
-    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);
-        else
-        {
-            if (CFGetTypeID(ref) != CFStringGetTypeID() || !CFEqual(ref, CFSTR(mDNS_IOREG_VALUE)))
-                LogMsg("ActivateLocalProxy: mDNS_IOREG_KEY for interface %s/%s/%s value %s != %s",
-                       intf->ifname, n1, n2, CFStringGetCStringPtr(ref, mDNSNULL), mDNS_IOREG_VALUE);
-            else if (!UseInternalSleepProxy)
-                LogSPS("ActivateLocalProxy: Not using internal (NIC) sleep proxy for interface %s", intf->ifname);
-            else
-            {
-                io_connect_t conObj;
-                kr = IOServiceOpen(parent, mach_task_self(), mDNS_USER_CLIENT_CREATE_TYPE, &conObj);
-                if (kr != KERN_SUCCESS) LogMsg("ActivateLocalProxy: IOServiceOpen for %s/%s/%s failed %d", intf->ifname, n1, n2, kr);
-                else
-                {
-                    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.compression   = sizeof(DNSMessageHeader);
-
-                    DNSMessage *msg = (DNSMessage *)mallocL("mDNSOffloadCmd msg", sizeof(DNSMessageHeader) + cmd.rrBufferSize);
-                    cmd.rrRecords.ptr = mallocL("mDNSOffloadCmd rrRecords", cmd.numRRRecords * sizeof(FatPtr));
-                    cmd.udpPorts.ptr = mallocL("mDNSOffloadCmd udpPorts",  cmd.numUDPPorts  * sizeof(mDNSIPPort));
-                    cmd.tcpPorts.ptr = mallocL("mDNSOffloadCmd tcpPorts",  cmd.numTCPPorts  * sizeof(mDNSIPPort));
-
-                    LogSPS("ActivateLocalProxy: msg %p %d RR %p %d, UDP %p %d, TCP %p %d",
-                           msg, cmd.rrBufferSize,
-                           cmd.rrRecords.ptr, cmd.numRRRecords,
-                           cmd.udpPorts.ptr, cmd.numUDPPorts,
-                           cmd.tcpPorts.ptr, cmd.numTCPPorts);
-
-                    if (!msg || !cmd.rrRecords.ptr || !cmd.udpPorts.ptr || !cmd.tcpPorts.ptr)
-                        LogMsg("ActivateLocalProxy: Failed to allocate memory: msg %p %d RR %p %d, UDP %p %d, TCP %p %d",
-                               msg, cmd.rrBufferSize,
-                               cmd.rrRecords.ptr, cmd.numRRRecords,
-                               cmd.udpPorts.ptr, cmd.numUDPPorts,
-                               cmd.tcpPorts.ptr, cmd.numTCPPorts);
-                    else
-                    {
-                        GetProxyRecords(m, msg, &cmd.rrBufferSize, cmd.rrRecords.ptr, TCPKAOnly, supportsTCPKA);
-                        GetPortArray(m, mDNSTransport_UDP, cmd.udpPorts.ptr);
-                        GetPortArray(m, mDNSTransport_TCP, cmd.tcpPorts.ptr);
-                        char outputData[2];
-                        size_t outputDataSize = sizeof(outputData);
-                        kr = IOConnectCallStructMethod(conObj, 0, &cmd, sizeof(cmd), outputData, &outputDataSize);
-                        LogSPS("ActivateLocalProxy: IOConnectCallStructMethod for %s/%s/%s %d", intf->ifname, n1, n2, kr);
-                        if (kr == KERN_SUCCESS) result = mStatus_NoError;
-                    }
-
-                    if (cmd.tcpPorts.ptr) freeL("mDNSOffloadCmd udpPorts",  cmd.tcpPorts.ptr);
-                    if (cmd.udpPorts.ptr) freeL("mDNSOffloadCmd tcpPorts",  cmd.udpPorts.ptr);
-                    if (cmd.rrRecords.ptr) freeL("mDNSOffloadCmd rrRecords", cmd.rrRecords.ptr);
-                    if (msg) freeL("mDNSOffloadCmd msg",       msg);
-                    IOServiceClose(conObj);
-                }
-            }
-            CFRelease(ref);
-        }
-        IOObjectRelease(parent);
-    }
-    IOObjectRelease(service);
-    return result;
-}
-
-#endif // APPLE_OSX_mDNSResponder
-
-mDNSlocal mDNSu8 SystemWakeForNetworkAccess(void)
-{
-    mDNSs32 val = 0;
-    mDNSu8  ret = (mDNSu8)mDNS_NoWake;
-
-    if (DisableSleepProxyClient)
-    {
-       LogSPS("SystemWakeForNetworkAccess: Sleep Proxy Client disabled by command-line option");
-       return mDNSfalse;
-    }
-
-    GetCurrentPMSetting(CFSTR("Wake On LAN"), &val);
-
-    ret = (mDNSu8)(val != 0) ? mDNS_WakeOnAC : mDNS_NoWake;
-
-#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
-    // If we have TCP Keepalive support, system is capable of registering for TCP Keepalives.
-    // Further policy decisions on whether to offload the records is handled during sleep processing.
-    if ((ret == mDNS_NoWake) && SupportsTCPKeepAlive())
-        ret = (mDNSu8)mDNS_WakeOnBattery;
-#endif // APPLE_OSX_mDNSResponder
-
-    LogSPS("SystemWakeForNetworkAccess: Wake On LAN: %d", ret);
-    return ret;
-}
-
-mDNSlocal mDNSBool SystemSleepOnlyIfWakeOnLAN(void)
-{
-    mDNSs32 val = 0;
-    GetCurrentPMSetting(CFSTR("PrioritizeNetworkReachabilityOverSleep"), &val);
-    return val != 0 ? mDNStrue : mDNSfalse;
-}
-
-#if APPLE_OSX_mDNSResponder
-// When sleeping, we always ensure that the _autotunnel6 record (if connected to RR relay)
-// gets deregistered, so that older peers are forced to connect over direct UDP instead of
-// the RR relay.
-//
-// When sleeping w/o a successful AutoTunnel NAT Mapping, we ensure that all our BTMM
-// service records are deregistered, so they do not appear in peers' Finder sidebars.
-// We do this by checking for the (non-autotunnel) SRV records, as the PTR and TXT records
-// depend on their associated SRV record and therefore will be deregistered together in a
-// single update with the SRV record.
-//
-// Also, the per-zone _kerberos TXT record is always there, including while sleeping, so
-// its presence shouldn't delay sleep.
-//
-// Note that the order of record deregistration is: first _autotunnel6 (if connected to RR
-// 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)
-{
-    if (!AuthRecord_uDNS(rr)) return mDNStrue;
-    
-    if ((rr->resrec.rrtype == kDNSType_AAAA) && SameDomainLabel(rr->namestorage.c, (const mDNSu8 *)"\x0c_autotunnel6"))
-    {
-        LogInfo("RecordReadyForSleep: %s not ready for sleep", ARDisplayString(m, rr));
-        return mDNSfalse;
-    }
-    
-    if ((mDNSIPPortIsZero(m->AutoTunnelNAT.ExternalPort) || m->AutoTunnelNAT.Result))
-    {
-        if (rr->resrec.rrtype == kDNSType_SRV && rr->state != regState_NoTarget && rr->zone
-            && !SameDomainLabel(rr->namestorage.c, (const mDNSu8 *)"\x0b_autotunnel"))
-        {
-            DomainAuthInfo *info = GetAuthInfoForName_internal(m, rr->zone);
-            if (info && info->AutoTunnel)
-            {
-                LogInfo("RecordReadyForSleep: %s not ready for sleep", ARDisplayString(m, rr));
-                return mDNSfalse;
-            }
-        }
-    }
-    
-    return mDNStrue;
-}
-
-// Caller must hold the lock
-mDNSexport void RemoveAutoTunnel6Record(mDNS *const m)
-{
-    DomainAuthInfo *info;
-    // Set the address to zero before calling UpdateAutoTunnel6Record, so that it will
-    // deregister the record, and the MemFree callback won't re-register.
-    m->AutoTunnelRelayAddr = zerov6Addr;
-    for (info = m->AuthInfoList; info; info = info->next)
-        if (info->AutoTunnel)
-            UpdateAutoTunnel6Record(m, info);
-}
-
-mDNSlocal mDNSBool IPv6AddressIsOnInterface(mDNSv6Addr ipv6Addr, char *ifname)
-{
-    struct ifaddrs  *ifa;
-    struct ifaddrs  *ifaddrs;
-    mDNSAddr addr;
-
-    if (if_nametoindex(ifname) == 0) {LogInfo("IPv6AddressIsOnInterface: Invalid name %s", ifname); return mDNSfalse;}
-
-    if (getifaddrs(&ifaddrs) < 0) {LogInfo("IPv6AddressIsOnInterface: getifaddrs failed"); return mDNSfalse;}
-
-    for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next)
-    {
-        if (strncmp(ifa->ifa_name, ifname, IFNAMSIZ) != 0)
-            continue;
-        if ((ifa->ifa_flags & IFF_UP) == 0 || !ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET6)
-            continue;
-        if (SetupAddr(&addr, ifa->ifa_addr) != mStatus_NoError)
-        {
-            LogInfo("IPv6AddressIsOnInterface: SetupAddr error, continuing to the next address");
-            continue;
-        }
-        if (mDNSSameIPv6Address(ipv6Addr, *(mDNSv6Addr*)&addr.ip.v6))
-        {
-            LogInfo("IPv6AddressIsOnInterface: found %.16a", &ipv6Addr);
-            break;
-        }
-    }
-    freeifaddrs(ifaddrs);
-    return ifa != NULL;
-}
-
-mDNSlocal mDNSv6Addr IPv6AddressFromString(char* buf)
-{
-    mDNSv6Addr retVal;
-    struct addrinfo hints;
-    struct addrinfo *res0;
-
-    memset(&hints, 0, sizeof(hints));
-    hints.ai_family = AF_INET6;
-    hints.ai_flags = AI_NUMERICHOST;
-
-    int err = getaddrinfo(buf, NULL, &hints, &res0);
-    if (err)
-        return zerov6Addr;
-
-    retVal = *(mDNSv6Addr*)&((struct sockaddr_in6*)res0->ai_addr)->sin6_addr;
-
-    freeaddrinfo(res0);
-
-    return retVal;
-}
-
-mDNSlocal CFDictionaryRef CopyConnectivityBackToMyMacDict()
-{
-    SCDynamicStoreRef store = NULL;
-    CFDictionaryRef connd = NULL;
-    CFDictionaryRef BTMMDict = NULL;
-
-    store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:CopyConnectivityBackToMyMacDict"), NULL, NULL);
-    if (!store)
-    {
-        LogMsg("CopyConnectivityBackToMyMacDict: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
-        goto end;
-    }
-
-    connd = SCDynamicStoreCopyValue(store, NetworkChangedKey_BTMMConnectivity);
-    if (!connd)
-    {
-        LogInfo("CopyConnectivityBackToMyMacDict: SCDynamicStoreCopyValue failed: %s", SCErrorString(SCError()));
-        goto end;
-    }
-
-    BTMMDict = CFDictionaryGetValue(connd, CFSTR("BackToMyMac"));
-    if (!BTMMDict)
-    {
-        LogInfo("CopyConnectivityBackToMyMacDict: CFDictionaryGetValue: No value for BackToMyMac");
-        goto end;
-    }
-
-    // Non-dictionary is treated as non-existent dictionary
-    if (CFGetTypeID(BTMMDict) != CFDictionaryGetTypeID())
-    {
-        BTMMDict = NULL;
-        LogMsg("CopyConnectivityBackToMyMacDict: BackToMyMac not a dictionary");
-        goto end;
-    }
-
-    CFRetain(BTMMDict);
-
-end:
-    if (connd) CFRelease(connd);
-    if (store) CFRelease(store);
-
-    return BTMMDict;
-}
-
-#define MAX_IPV6_TEXTUAL 40
-
-mDNSlocal mDNSv6Addr ParseBackToMyMacAddr(CFDictionaryRef BTMMDict, CFStringRef ifKey, CFStringRef addrKey)
-{
-    mDNSv6Addr retVal = zerov6Addr;
-    CFTypeRef string = NULL;
-    char ifname[IFNAMSIZ];
-    char address[MAX_IPV6_TEXTUAL];
-
-    if (!BTMMDict)
-        return zerov6Addr;
-
-    if (!CFDictionaryGetValueIfPresent(BTMMDict, ifKey, &string))
-    {
-        LogInfo("ParseBackToMyMacAddr: interface key does not exist");
-        return zerov6Addr;
-    }
-
-    if (!CFStringGetCString(string, ifname, IFNAMSIZ, kCFStringEncodingUTF8))
-    {
-        LogMsg("ParseBackToMyMacAddr: Could not convert interface to CString");
-        return zerov6Addr;
-    }
-
-    if (!CFDictionaryGetValueIfPresent(BTMMDict, addrKey, &string))
-    {
-        LogMsg("ParseBackToMyMacAddr: address key does not exist, but interface key does");
-        return zerov6Addr;
-    }
-
-    if (!CFStringGetCString(string, address, sizeof(address), kCFStringEncodingUTF8))
-    {
-        LogMsg("ParseBackToMyMacAddr: Could not convert address to CString");
-        return zerov6Addr;
-    }
-
-    retVal = IPv6AddressFromString(address);
-    LogInfo("ParseBackToMyMacAddr: %s (%s) %.16a", ifname, address, &retVal);
-
-    if (mDNSIPv6AddressIsZero(retVal))
-        return zerov6Addr;
-
-    if (!IPv6AddressIsOnInterface(retVal, ifname))
-    {
-        LogMsg("ParseBackToMyMacAddr: %.16a is not on %s", &retVal, ifname);
-        return zerov6Addr;
-    }
-
-    return retVal;
-}
-
-mDNSlocal CFDictionaryRef GetBackToMyMacZones(CFDictionaryRef BTMMDict)
-{
-    CFTypeRef zones = NULL;
-
-    if (!BTMMDict)
-        return NULL;
-
-    if (!CFDictionaryGetValueIfPresent(BTMMDict, CFSTR("Zones"), &zones))
-    {
-        LogInfo("CopyBTMMZones: Zones key does not exist");
-        return NULL;
-    }
-
-    return zones;
-}
-
-mDNSlocal mDNSv6Addr ParseBackToMyMacZone(CFDictionaryRef zones, DomainAuthInfo* info)
-{
-    mDNSv6Addr addr = zerov6Addr;
-    char buffer[MAX_ESCAPED_DOMAIN_NAME];
-    CFStringRef domain = NULL;
-    CFTypeRef theZone = NULL;
-
-    if (!zones)
-        return addr;
-
-    ConvertDomainNameToCString(&info->domain, buffer);
-    domain = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
-    if (!domain)
-        return addr;
-
-    if (CFDictionaryGetValueIfPresent(zones, domain, &theZone))
-        addr = ParseBackToMyMacAddr(theZone, CFSTR("Interface"), CFSTR("Address"));
-
-    CFRelease(domain);
-
-    return addr;
-}
-
-mDNSlocal void SetupBackToMyMacInnerAddresses(mDNS *const m, CFDictionaryRef BTMMDict)
-{
-    DomainAuthInfo* info;
-    CFDictionaryRef zones = GetBackToMyMacZones(BTMMDict);
-    mDNSv6Addr newAddr;
-
-    for (info = m->AuthInfoList; info; info = info->next)
-    {
-        if (!info->AutoTunnel)
-            continue;
-
-        newAddr = ParseBackToMyMacZone(zones, info);
-
-        if (mDNSSameIPv6Address(newAddr, info->AutoTunnelInnerAddress))
-            continue;
-
-        info->AutoTunnelInnerAddress = newAddr;
-        DeregisterAutoTunnelHostRecord(m, info);
-        UpdateAutoTunnelHostRecord(m, info);
-        UpdateAutoTunnelDomainStatus(m, info);
-    }
-}
-
-// MUST be called holding the lock
-mDNSlocal void ProcessConndConfigChanges(mDNS *const m)
-{
-    CFDictionaryRef dict = CopyConnectivityBackToMyMacDict();
-    if (!dict)
-        LogInfo("ProcessConndConfigChanges: No BTMM dictionary");
-    mDNSv6Addr relayAddr = ParseBackToMyMacAddr(dict, CFSTR("RelayInterface"), CFSTR("RelayAddress"));
-
-    LogInfo("ProcessConndConfigChanges: relay %.16a", &relayAddr);
-
-    SetupBackToMyMacInnerAddresses(m, dict);
-
-    if (dict) CFRelease(dict);
-
-    if (!mDNSSameIPv6Address(relayAddr, m->AutoTunnelRelayAddr))
-    {
-        m->AutoTunnelRelayAddr = relayAddr;
-
-        DomainAuthInfo* info;
-        for (info = m->AuthInfoList; info; info = info->next)
-            if (info->AutoTunnel)
-            {
-                DeregisterAutoTunnel6Record(m, info);
-                UpdateAutoTunnel6Record(m, info);
-                UpdateAutoTunnelDomainStatus(m, info);
-            }
-
-        // Determine whether we need racoon to accept incoming connections
-        UpdateAnonymousRacoonConfig(m);
-    }
-
-    // If awacsd crashes or exits for some reason, restart it
-    UpdateBTMMRelayConnection(m);
-}
-#endif /* APPLE_OSX_mDNSResponder */
-
-mDNSlocal mDNSBool IsAppleNetwork(mDNS *const m)
-{
-    DNSServer *s;
-    // Determine if we're on AppleNW based on DNSServer having 17.x.y.z IPv4 addr
-    for (s = m->DNSServers; s; s = s->next)
-    {
-        if (s->addr.ip.v4.b[0] == 17)
-        {     
-            LogInfo("IsAppleNetwork: Found 17.x.y.z DNSServer concluding that we are on AppleNW: %##s %#a", s->domain.c, &s->addr);
-            return mDNStrue;
-        }     
-    }
-    return mDNSfalse;
-}
-
-mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
-{
-    LogInfo("***   Network Configuration Change   ***  (%d)%s",
-            m->p->NetworkChanged ? mDNS_TimeNow(m) - m->p->NetworkChanged : 0,
-            m->p->NetworkChanged ? "" : " (no scheduled configuration change)");
-    m->p->NetworkChanged = 0;       // If we received a network change event and deferred processing, we're now dealing with it
-    mDNSs32 utc = mDNSPlatformUTC();
-    m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
-    m->SystemSleepOnlyIfWakeOnLAN = SystemSleepOnlyIfWakeOnLAN();
-    MarkAllInterfacesInactive(m, utc);
-    UpdateInterfaceList(m, utc);
-    ClearInactiveInterfaces(m, utc);
-    SetupActiveInterfaces(m, utc);
-
-#if APPLE_OSX_mDNSResponder
-
-    mDNS_Lock(m);
-    ProcessConndConfigChanges(m);
-    mDNS_Unlock(m);
-
-    // Scan to find client tunnels whose questions have completed,
-    // but whose local inner/outer addresses have changed since the tunnel was set up
-    ClientTunnel *p;
-    for (p = m->TunnelClients; p; p = p->next)
-        if (p->q.ThisQInterval < 0)
-        {
-            DomainAuthInfo* info = GetAuthInfoForName(m, &p->dstname);
-            if (!info)
-            {
-                LogMsg("mDNSMacOSXNetworkChanged: Could not get AuthInfo for %##s, removing tunnel keys", p->dstname.c);
-                AutoTunnelSetKeys(p, mDNSfalse);
-            }
-            else
-            {
-                mDNSv6Addr inner = info->AutoTunnelInnerAddress;
-
-                if (!mDNSIPPortIsZero(p->rmt_outer_port))
-                {
-                    mDNSAddr tmpSrc = zeroAddr;
-                    mDNSAddr tmpDst = { mDNSAddrType_IPv4, {{{0}}} };
-                    tmpDst.ip.v4 = p->rmt_outer;
-                    mDNSPlatformSourceAddrForDest(&tmpSrc, &tmpDst);
-                    if (!mDNSSameIPv6Address(p->loc_inner, inner) ||
-                        !mDNSSameIPv4Address(p->loc_outer, tmpSrc.ip.v4))
-                    {
-                        AutoTunnelSetKeys(p, mDNSfalse);
-                        p->loc_inner = inner;
-                        p->loc_outer = tmpSrc.ip.v4;
-                        AutoTunnelSetKeys(p, mDNStrue);
-                    }
-                }
-                else
-                {
-                    if (!mDNSSameIPv6Address(p->loc_inner, inner) ||
-                        !mDNSSameIPv6Address(p->loc_outer6, m->AutoTunnelRelayAddr))
-                    {
-                        AutoTunnelSetKeys(p, mDNSfalse);
-                        p->loc_inner = inner;
-                        p->loc_outer6 = m->AutoTunnelRelayAddr;
-                        AutoTunnelSetKeys(p, mDNStrue);
-                    }
-                }
-            }
-        }
-
-    SetSPS(m);
-
-    NetworkInterfaceInfoOSX *i;
-    for (i = m->p->InterfaceList; i; i = i->next)
-    {
-        if (!m->SPSSocket)      // Not being Sleep Proxy Server; close any open BPF fds
-        {
-            if (i->BPF_fd >= 0 && CountProxyTargets(m, i, mDNSNULL, mDNSNULL) == 0) CloseBPF(i);
-        }
-        else                                // else, we're Sleep Proxy Server; open BPF fds
-        {
-            if (i->Exists && i->Registered == i && i->ifinfo.McastTxRx && !(i->ifa_flags & IFF_LOOPBACK) && i->BPF_fd == -1)
-            { LogSPS("%s requesting BPF", i->ifinfo.ifname); i->BPF_fd = -2; mDNSRequestBPF(); }
-        }
-    }
-
-#endif // APPLE_OSX_mDNSResponder
-
-    uDNS_SetupDNSConfig(m);
-    mDNS_ConfigChanged(m);
-
-    if (IsAppleNetwork(m) != mDNS_McastTracingEnabled)
-    {
-        mDNS_McastTracingEnabled = mDNS_McastTracingEnabled ? mDNSfalse : mDNStrue; 
-        LogMsg("mDNSMacOSXNetworkChanged: Multicast Tracing %s", mDNS_McastTracingEnabled ? "Enabled" : "Disabled");
-        UpdateDebugState();
-    }
-
-}
-
-// Called with KQueueLock & mDNS lock
-mDNSlocal void SetNetworkChanged(mDNS *const m, mDNSs32 delay)
-{
-    if (!m->p->NetworkChanged || m->p->NetworkChanged - NonZeroTime(m->timenow + delay) < 0)
-    {
-        m->p->NetworkChanged = NonZeroTime(m->timenow + delay);
-        LogInfo("SetNetworkChanged: scheduling in %d msec", delay);
-    }
-}
-
-// Called with KQueueLock & mDNS lock
-mDNSlocal void SetKeyChainTimer(mDNS *const m, mDNSs32 delay)
-{
-    // 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)
-    {
-        m->p->KeyChainTimer = NonZeroTime(m->timenow + delay);
-        LogInfo("SetKeyChainTimer: %d", delay);
-    }
-}
-
-// Copy the fourth slash-delimited element from either:
-//   State:/Network/Interface/<bsdname>/IPv4
-// or
-//   Setup:/Network/Service/<servicename>/Interface
-mDNSlocal CFStringRef CopyNameFromKey(CFStringRef key)
-{
-    CFArrayRef a;
-    CFStringRef name = NULL;
-
-    a = CFStringCreateArrayBySeparatingStrings(NULL, key, CFSTR("/"));
-    if (a && CFArrayGetCount(a) == 5) name = CFRetain(CFArrayGetValueAtIndex(a, 3));
-    if (a != NULL) CFRelease(a);
-
-    return name;
-}
-
-// Whether a key from a network change notification corresponds to
-// an IP service that is explicitly configured for IPv4 Link Local
-mDNSlocal mDNSBool ChangedKeysHaveIPv4LL(CFArrayRef inkeys)
-{
-    SCDynamicStoreRef store = NULL;
-    CFDictionaryRef dict = NULL;
-    CFMutableArrayRef a;
-    const void **keys = NULL, **vals = NULL;
-    CFStringRef pattern = NULL;
-    int i, ic, j, jc;
-    mDNSBool found = mDNSfalse;
-
-    jc = CFArrayGetCount(inkeys);
-    if (!jc) goto done;
-
-    store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:ChangedKeysHaveIPv4LL"), NULL, NULL);
-    if (store == NULL) goto done;
-
-    a = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    if (a == NULL) goto done;
-
-    // Setup:/Network/Service/[^/]+/Interface
-    pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetInterface);
-    if (pattern == NULL) goto done;
-    CFArrayAppendValue(a, pattern);
-    CFRelease(pattern);
-
-    // Setup:/Network/Service/[^/]+/IPv4
-    pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetIPv4);
-    if (pattern == NULL) goto done;
-    CFArrayAppendValue(a, pattern);
-    CFRelease(pattern);
-
-    dict = SCDynamicStoreCopyMultiple(store, NULL, a);
-    CFRelease(a);
-
-    if (!dict)
-    {
-        LogMsg("ChangedKeysHaveIPv4LL: Empty dictionary");
-        goto done;
-    }
-
-    ic = CFDictionaryGetCount(dict);
-    vals = mDNSPlatformMemAllocate(sizeof (void *) * ic);
-    keys = mDNSPlatformMemAllocate(sizeof (void *) * ic);
-    CFDictionaryGetKeysAndValues(dict, keys, vals);
-
-    for (j = 0; j < jc && !found; j++)
-    {
-        CFStringRef key = CFArrayGetValueAtIndex(inkeys, j);
-        CFStringRef ifname = NULL;
-
-        char buf[256];
-
-        // It would be nice to use a regex here
-        if (!CFStringHasPrefix(key, CFSTR("State:/Network/Interface/")) || !CFStringHasSuffix(key, kSCEntNetIPv4)) continue;
-
-        if ((ifname = CopyNameFromKey(key)) == NULL) continue;
-        if (mDNS_LoggingEnabled)
-        {
-            if (!CFStringGetCString(ifname, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
-            LogInfo("ChangedKeysHaveIPv4LL: potential ifname %s", buf);
-        }
-
-        for (i = 0; i < ic; i++)
-        {
-            CFDictionaryRef ipv4dict;
-            CFStringRef name;
-            CFStringRef serviceid;
-            CFStringRef configmethod;
-
-            if (!CFStringHasSuffix(keys[i], kSCEntNetInterface)) continue;
-
-            if (CFDictionaryGetTypeID() != CFGetTypeID(vals[i])) continue;
-
-            if ((name = CFDictionaryGetValue(vals[i], kSCPropNetInterfaceDeviceName)) == NULL) continue;
-
-            if (!CFEqual(ifname, name)) continue;
-
-            if ((serviceid = CopyNameFromKey(keys[i])) == NULL) continue;
-            if (mDNS_LoggingEnabled)
-            {
-                if (!CFStringGetCString(serviceid, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
-                LogInfo("ChangedKeysHaveIPv4LL: found serviceid %s", buf);
-            }
-
-            pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceid, kSCEntNetIPv4);
-            CFRelease(serviceid);
-            if (pattern == NULL) continue;
-
-            ipv4dict = CFDictionaryGetValue(dict, pattern);
-            CFRelease(pattern);
-            if (!ipv4dict || CFDictionaryGetTypeID() != CFGetTypeID(ipv4dict)) continue;
-
-            configmethod = CFDictionaryGetValue(ipv4dict, kSCPropNetIPv4ConfigMethod);
-            if (!configmethod) continue;
-
-            if (mDNS_LoggingEnabled)
-            {
-                if (!CFStringGetCString(configmethod, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
-                LogInfo("ChangedKeysHaveIPv4LL: configmethod %s", buf);
-            }
-
-            if (CFEqual(configmethod, kSCValNetIPv4ConfigMethodLinkLocal)) { found = mDNStrue; break; }
-        }
-
-        CFRelease(ifname);
-    }
-
-done:
-    if (vals != NULL) mDNSPlatformMemFree(vals);
-    if (keys != NULL) mDNSPlatformMemFree(keys);
-    if (dict != NULL) CFRelease(dict);
-    if (store != NULL) CFRelease(store);
-
-    return found;
-}
-
-mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context)
-{
-    (void)store;        // Parameter not used
-    mDNSBool changeNow = mDNSfalse;
-    mDNS *const m = (mDNS *const)context;
-    KQueueLock(m);
-    mDNS_Lock(m);
-
-    mDNSs32 delay = mDNSPlatformOneSecond * 2;              // Start off assuming a two-second delay
-
-    int c = CFArrayGetCount(changedKeys);                   // Count changes
-    CFRange range = { 0, c };
-    int c1 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_Hostnames   ) != 0);
-    int c2 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_Computername) != 0);
-    int c3 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DynamicDNS  ) != 0);
-    int c4 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DNS         ) != 0);
-    if (c && c - c1 - c2 - c3 - c4 == 0)
-        delay = mDNSPlatformOneSecond/10;  // If these were the only changes, shorten delay
-
-    // Do immediate network changed processing for "p2p*" interfaces and
-    // for interfaces with the IFEF_DIRECTLINK flag set.
-    {
-        CFArrayRef  labels;
-        CFIndex     n;
-        for (int i = 0; i < c; i++)
-        {
-            CFStringRef key = CFArrayGetValueAtIndex(changedKeys, i);
-
-            // Only look at keys with prefix "State:/Network/Interface/"
-            if (!CFStringHasPrefix(key, NetworkChangedKey_StateInterfacePrefix))
-                continue;
-
-            // And suffix "IPv6" or "IPv4".
-            if (!CFStringHasSuffix(key, kSCEntNetIPv6) && !CFStringHasSuffix(key, kSCEntNetIPv4))
-                continue;
-
-            labels = CFStringCreateArrayBySeparatingStrings(NULL, key, CFSTR("/"));
-            if (labels == NULL)
-                break;
-            n = CFArrayGetCount(labels);
-
-            // Interface changes will have keys of the form: 
-            //     State:/Network/Interface/<interfaceName>/IPv6
-            // Thus five '/' seperated fields, the 4th one being the <interfaceName> string.
-            if (n == 5)
-            {
-                char buf[256];
-
-                // 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)))
-                {
-                    LogInfo("NetworkChanged: interface %s, not delaying network change", buf);
-                    changeNow = mDNStrue;
-                    CFRelease(labels);
-                    break;
-                }
-            }
-            CFRelease(labels);
-        }
-    }
-
-    mDNSBool btmmChanged = CFArrayContainsValue(changedKeys, range, NetworkChangedKey_BackToMyMac);
-    if (btmmChanged) delay = 0;
-
-    if (mDNS_LoggingEnabled)
-    {
-        int i;
-        for (i=0; i<c; i++)
-        {
-            char buf[256];
-            if (!CFStringGetCString(CFArrayGetValueAtIndex(changedKeys, i), buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
-            LogInfo("***   NetworkChanged SC key: %s", buf);
-        }
-        LogInfo("***   NetworkChanged   *** %d change%s %s%s%s%sdelay %d",
-                c, c>1 ? "s" : "",
-                c1 ? "(Local Hostname) " : "",
-                c2 ? "(Computer Name) "  : "",
-                c3 ? "(DynamicDNS) "     : "",
-                c4 ? "(DNS) "            : "",
-                changeNow ? 0 : delay);
-    }
-
-    if (!changeNow)
-        SetNetworkChanged(m, delay);
-
-    // Other software might pick up these changes to register or browse in WAB or BTMM domains,
-    // so in order for secure updates to be made to the server, make sure to read the keychain and
-    // setup the DomainAuthInfo before handing the network change.
-    // If we don't, then we will first try to register services in the clear, then later setup the
-    // DomainAuthInfo, which is incorrect.
-    if (c3 || btmmChanged)
-        SetKeyChainTimer(m, delay);
-
-    mDNS_Unlock(m);
-
-    // If DNS settings changed, immediately force a reconfig (esp. cache flush)
-    // Similarly, if an interface changed that is explicitly IPv4 link local, immediately force a reconfig
-    if (c4 || ChangedKeysHaveIPv4LL(changedKeys) || changeNow) mDNSMacOSXNetworkChanged(m);
-
-    KQueueUnlock(m, "NetworkChanged");
-}
-
-#if APPLE_OSX_mDNSResponder
-mDNSlocal void RefreshSPSStatus(const void *key, const void *value, void *context)
-{
-    (void)context;
-    char buf[IFNAMSIZ];
-
-    CFStringRef ifnameStr = (CFStringRef)key;
-    CFArrayRef array = (CFArrayRef)value;
-    if (!CFStringGetCString(ifnameStr, buf, sizeof(buf), kCFStringEncodingUTF8)) 
-        buf[0] = 0;
-
-    LogInfo("RefreshSPSStatus: Updating SPS state for key %s, array count %d", buf, CFArrayGetCount(array));
-    mDNSDynamicStoreSetConfig(kmDNSSleepProxyServersState, buf, value);
-}
-#endif
-
-mDNSlocal void DynamicStoreReconnected(SCDynamicStoreRef store, void *info)
-{
-    mDNS *const m = (mDNS *const)info;
-    (void)store;
-
-    LogInfo("DynamicStoreReconnected: Reconnected");
-
-    // State:/Network/MulticastDNS
-    SetLocalDomains();
-
-    // State:/Network/DynamicDNS
-    if (m->FQDN.c[0])
-        mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1);
-
-    // Note: PrivateDNS and BackToMyMac are automatically populated when configd is restarted
-    // as we receive network change notifications and thus not necessary. But we leave it here
-    // so that if things are done differently in the future, this code still works.
-
-    // State:/Network/PrivateDNS
-    if (privateDnsArray)
-        mDNSDynamicStoreSetConfig(kmDNSPrivateConfig, mDNSNULL, privateDnsArray);
-
-#if APPLE_OSX_mDNSResponder
-    mDNS_Lock(m);
-    // State:/Network/BackToMyMac
-    UpdateAutoTunnelDomainStatuses(m);
-    mDNS_Unlock(m);
-
-    // State:/Network/Interface/en0/SleepProxyServers
-    if (spsStatusDict) 
-        CFDictionaryApplyFunction(spsStatusDict, RefreshSPSStatus, NULL);
-#endif
-}
-
-mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m)
-{
-    mStatus err = -1;
-    SCDynamicStoreContext context = { 0, m, NULL, NULL, NULL };
-    SCDynamicStoreRef store    = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:WatchForNetworkChanges"), NetworkChanged, &context);
-    CFMutableArrayRef keys     = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    CFStringRef pattern1 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4);
-    CFStringRef pattern2 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6);
-    CFMutableArrayRef patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-
-    if (!store) { LogMsg("SCDynamicStoreCreate failed: %s", SCErrorString(SCError())); goto error; }
-    if (!keys || !pattern1 || !pattern2 || !patterns) goto error;
-
-    CFArrayAppendValue(keys, NetworkChangedKey_IPv4);
-    CFArrayAppendValue(keys, NetworkChangedKey_IPv6);
-    CFArrayAppendValue(keys, NetworkChangedKey_Hostnames);
-    CFArrayAppendValue(keys, NetworkChangedKey_Computername);
-    CFArrayAppendValue(keys, NetworkChangedKey_DNS);
-    CFArrayAppendValue(keys, NetworkChangedKey_DynamicDNS);
-    CFArrayAppendValue(keys, NetworkChangedKey_BackToMyMac);
-    CFArrayAppendValue(keys, NetworkChangedKey_PowerSettings); // should remove as part of <rdar://problem/6751656>
-    CFArrayAppendValue(keys, NetworkChangedKey_BTMMConnectivity);
-    CFArrayAppendValue(patterns, pattern1);
-    CFArrayAppendValue(patterns, pattern2);
-    CFArrayAppendValue(patterns, CFSTR("State:/Network/Interface/[^/]+/AirPort"));
-    if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns))
-    { LogMsg("SCDynamicStoreSetNotificationKeys failed: %s", SCErrorString(SCError())); goto error; }
-
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-    if (!SCDynamicStoreSetDispatchQueue(store, dispatch_get_main_queue()))
-    { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error; }
-#else
-    m->p->StoreRLS = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
-    if (!m->p->StoreRLS) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error; }
-    CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode);
-#endif
-    SCDynamicStoreSetDisconnectCallBack(store, DynamicStoreReconnected);
-    m->p->Store = store;
-    err = 0;
-    goto exit;
-
-error:
-    if (store) CFRelease(store);
-
-exit:
-    if (patterns) CFRelease(patterns);
-    if (pattern2) CFRelease(pattern2);
-    if (pattern1) CFRelease(pattern1);
-    if (keys) CFRelease(keys);
-
-    return(err);
-}
-
-#if 0 // <rdar://problem/6751656>
-mDNSlocal void PMChanged(void *context)
-{
-    mDNS *const m = (mDNS *const)context;
-
-    KQueueLock(m);
-    mDNS_Lock(m);
-
-    LogSPS("PMChanged");
-
-    SetNetworkChanged(m, mDNSPlatformOneSecond * 2);
-
-    mDNS_Unlock(m);
-    KQueueUnlock(m, "PMChanged");
-}
-
-mDNSlocal mStatus WatchForPMChanges(mDNS *const m)
-{
-    m->p->PMRLS = IOPMPrefsNotificationCreateRunLoopSource(PMChanged, m);
-    if (!m->p->PMRLS) { LogMsg("IOPMPrefsNotificationCreateRunLoopSource failed!"); return mStatus_UnknownErr; }
-
-    CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->PMRLS, kCFRunLoopDefaultMode);
-
-    return mStatus_NoError;
-}
-#endif
-
-#if !TARGET_OS_EMBEDDED     // don't setup packet filter rules on embedded
-
-mDNSlocal void mDNSSetPacketFilterRules(mDNS *const m, char * ifname, const ResourceRecord *const excludeRecord)
-{
-    AuthRecord  *rr;
-    pfArray_t portArray;
-    pfArray_t protocolArray;
-    uint32_t count = 0;
-
-    for (rr = m->ResourceRecords; rr; rr=rr->next)
-    {
-        if ((rr->resrec.rrtype == kDNSServiceType_SRV) 
-            && ((rr->ARType == AuthRecordAnyIncludeP2P) || (rr->ARType == AuthRecordAnyIncludeAWDLandP2P)))
-        {
-            const mDNSu8    *p;
-
-            if (count >= PFPortArraySize)
-            {
-                LogMsg("mDNSSetPacketFilterRules: %d service limit, skipping %s", PFPortArraySize, ARDisplayString(m, rr));
-                continue;
-            }
-
-            if (excludeRecord && IdenticalResourceRecord(&rr->resrec, excludeRecord))
-            {
-                LogInfo("mDNSSetPacketFilterRules: record being removed, skipping %s", ARDisplayString(m, rr));
-                continue;
-            }
-
-            LogInfo("mDNSSetPacketFilterRules: found %s", ARDisplayString(m, rr));
-
-            portArray[count] = rr->resrec.rdata->u.srv.port.NotAnInteger;
-
-            // Assume <Service Instance>.<App Protocol>.<Transport Protocol>.<Name>
-            p = rr->resrec.name->c;
-
-            // Skip to App Protocol
-            if (p[0]) p += 1 + p[0];
-
-            // Skip to Transport Protocol
-            if (p[0]) p += 1 + p[0];
-
-            if      (SameDomainLabel(p, (mDNSu8 *)"\x4" "_tcp")) protocolArray[count] = IPPROTO_TCP;
-            else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) protocolArray[count] = IPPROTO_UDP;
-            else
-            {
-                LogMsg("mDNSSetPacketFilterRules: could not determine transport protocol of service");
-                LogMsg("mDNSSetPacketFilterRules: %s", ARDisplayString(m, rr));
-                return;
-            }
-            count++;
-        }
-    }
-    mDNSPacketFilterControl(PF_SET_RULES, ifname, count, portArray, protocolArray);
-}
-
-// If the p2p interface already exists, update the Bonjour packet filter rules for it.
-mDNSexport void mDNSUpdatePacketFilter(const ResourceRecord *const excludeRecord)
-{
-    mDNS *const m = &mDNSStorage;
-
-    NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
-    while (intf)
-    {
-        if (strncmp(intf->ifname, "p2p", 3) == 0)
-        {
-            LogInfo("mDNSInitPacketFilter: Setting rules for ifname %s", intf->ifname);
-            mDNSSetPacketFilterRules(m, intf->ifname, excludeRecord);
-            break;
-        }
-        intf = GetFirstActiveInterface(intf->next);
-    }
-}
-
-#else // !TARGET_OS_EMBEDDED
-
-// Currently no packet filter setup required on embedded platforms.
-mDNSexport void mDNSUpdatePacketFilter(const ResourceRecord *const excludeRecord)
-{
-    (void) excludeRecord; // unused
-}
-
-#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)
-{
-    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);
-
-    if (!interfaceIndex)
-    {
-        LogMsg("newMasterElected: if_nametoindex(%s) failed", ifname);
-        return;
-    }
-
-    LogInfo("newMasterElected: ifname = %s, interfaceIndex = %d", ifname, interfaceIndex);
-    infoOSX = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)interfaceIndex);
-
-    // Can get an KEV_DL_MASTER_ELECTED event prior to the interface existing
-    // when it is first brought up.
-    if (!infoOSX)
-    {
-        LogInfo("newMasterElected: interface not yet active");
-        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);
-        }
-    }
-}
-
-// An ssth array of all zeroes indicates the peer has no services registered.
-mDNSlocal mDNSBool allZeroSSTH(struct opaque_presence_indication *op)
-{
-    int i;
-    int *intp = (int *) op->ssth;
-
-    // MAX_SSTH_SIZE should always be a multiple of sizeof(int), if
-    // it's not, print an error message and return false so that
-    // corresponding peer records are not flushed when KEV_DL_NODE_PRESENCE event
-    // is received.
-    if (MAX_SSTH_SIZE % sizeof(int))
-    {
-        LogInfo("allZeroSSTH: MAX_SSTH_SIZE = %d not a multiple of sizeof(int)", MAX_SSTH_SIZE);
-        return mDNSfalse;
-    }
-
-    for (i = 0; i < (int)(MAX_SSTH_SIZE / sizeof(int)); i++, intp++)
-    {
-        if (*intp)
-            return mDNSfalse;
-    }
-    return mDNStrue;
-}
-
-// mDNS_Reconfirm_internal() adds 33% to this interval, so the records should
-// be removed in 4 seconds.
-#define kAWDLReconfirmTime ((mDNSu32)mDNSPlatformOneSecond *  3)
-
-// Mark records from this peer for deletion from the cache.
-mDNSlocal void removeCachedPeerRecords(mDNS *const m, mDNSu32 ifindex, mDNSAddr *ap)
-{
-    mDNSu32     slot;
-    CacheGroup  *cg;
-    CacheRecord *cr;
-    mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(m, ifindex);
-
-    if (!InterfaceID)
-    {
-        LogInfo("removeCachedPeerRecords: Invalid ifindex: %d", ifindex);
-        return;
-    }
-
-    FORALL_CACHERECORDS(slot, cg, cr)
-    {
-        if ((InterfaceID == cr->resrec.InterfaceID) && mDNSSameAddress(ap, & cr->sourceAddress))
-        {
-            LogInfo("removeCachedPeerRecords: %s %##s marking for deletion",
-                 DNSTypeName(cr->resrec.rrtype), cr->resrec.name->c);
-            mDNS_Reconfirm_internal(m, cr, kAWDLReconfirmTime);
-        }
-    }
-}
-
-// Handle KEV_DL_NODE_PRESENCE event.
-mDNSlocal void nodePresence(mDNS *const m, struct kev_dl_node_presence * p)
-{
-    char buf[INET6_ADDRSTRLEN];
-    struct opaque_presence_indication *op = (struct opaque_presence_indication *) p->node_service_info;
-
-    if (inet_ntop(AF_INET6, & p->sin6_node_address.sin6_addr, buf, sizeof(buf)))
-        LogInfo("nodePresence:  IPv6 address: %s, SUI %d", buf, op->SUI);
-    else
-        LogInfo("nodePresence:  inet_ntop() error");
- 
-    // AWDL will generate a KEV_DL_NODE_PRESENCE event with SSTH field of
-    // all zeroes when a node is present and has no services registered.
-    if (allZeroSSTH(op))
-    {
-        mDNSAddr    peerAddr;
-
-        peerAddr.type = mDNSAddrType_IPv6;
-        peerAddr.ip.v6 = *(mDNSv6Addr*)&p->sin6_node_address.sin6_addr;
-
-        LogInfo("nodePresence: ssth is all zeroes, delete cached records from this peer");
-        removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr);
-    }
-}
-
-// Handle KEV_DL_NODE_ABSENCE event.
-mDNSlocal void nodeAbsence(mDNS *const m, struct kev_dl_node_absence * p)
-{
-    mDNSAddr    peerAddr;
-    char buf[INET6_ADDRSTRLEN];
-
-    if (inet_ntop(AF_INET6, & p->sin6_node_address.sin6_addr, buf, sizeof(buf)))
-        LogInfo("nodeAbsence:  IPv6 address: %s", buf);
-    else
-        LogInfo("nodeAbsence:  inet_ntop() error");
-
-    peerAddr.type = mDNSAddrType_IPv6;
-    peerAddr.ip.v6 = *(mDNSv6Addr*)&p->sin6_node_address.sin6_addr;
-
-    LogInfo("nodeAbsence: delete cached records from this peer");
-    removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr);
-}
-
-mDNSlocal void SysEventCallBack(int s1, short __unused filter, void *context)
-{
-    mDNS *const m = (mDNS *const)context;
-
-    mDNS_Lock(m);
-
-    struct { struct kern_event_msg k; char extra[256]; } msg;
-    int bytes = recv(s1, &msg, sizeof(msg), 0);
-    if (bytes < 0)
-        LogMsg("SysEventCallBack: recv error %d errno %d (%s)", bytes, errno, strerror(errno));
-    else
-    {
-        LogInfo("SysEventCallBack got %d bytes size %d %X %s %X %s %X %s id %d code %d %s",
-                bytes, msg.k.total_size,
-                msg.k.vendor_code, msg.k.vendor_code  == KEV_VENDOR_APPLE  ? "KEV_VENDOR_APPLE"  : "?",
-                msg.k.kev_class, msg.k.kev_class    == KEV_NETWORK_CLASS ? "KEV_NETWORK_CLASS" : "?",
-                msg.k.kev_subclass, msg.k.kev_subclass == KEV_DL_SUBCLASS   ? "KEV_DL_SUBCLASS"   : "?",
-                msg.k.id, msg.k.event_code,
-                msg.k.event_code == KEV_DL_SIFFLAGS             ? "KEV_DL_SIFFLAGS"             :
-                msg.k.event_code == KEV_DL_SIFMETRICS           ? "KEV_DL_SIFMETRICS"           :
-                msg.k.event_code == KEV_DL_SIFMTU               ? "KEV_DL_SIFMTU"               :
-                msg.k.event_code == KEV_DL_SIFPHYS              ? "KEV_DL_SIFPHYS"              :
-                msg.k.event_code == KEV_DL_SIFMEDIA             ? "KEV_DL_SIFMEDIA"             :
-                msg.k.event_code == KEV_DL_SIFGENERIC           ? "KEV_DL_SIFGENERIC"           :
-                msg.k.event_code == KEV_DL_ADDMULTI             ? "KEV_DL_ADDMULTI"             :
-                msg.k.event_code == KEV_DL_DELMULTI             ? "KEV_DL_DELMULTI"             :
-                msg.k.event_code == KEV_DL_IF_ATTACHED          ? "KEV_DL_IF_ATTACHED"          :
-                msg.k.event_code == KEV_DL_IF_DETACHING         ? "KEV_DL_IF_DETACHING"         :
-                msg.k.event_code == KEV_DL_IF_DETACHED          ? "KEV_DL_IF_DETACHED"          :
-                msg.k.event_code == KEV_DL_LINK_OFF             ? "KEV_DL_LINK_OFF"             :
-                msg.k.event_code == KEV_DL_LINK_ON              ? "KEV_DL_LINK_ON"              :
-                msg.k.event_code == KEV_DL_PROTO_ATTACHED       ? "KEV_DL_PROTO_ATTACHED"       :
-                msg.k.event_code == KEV_DL_PROTO_DETACHED       ? "KEV_DL_PROTO_DETACHED"       :
-                msg.k.event_code == KEV_DL_LINK_ADDRESS_CHANGED ? "KEV_DL_LINK_ADDRESS_CHANGED" :
-                msg.k.event_code == KEV_DL_WAKEFLAGS_CHANGED    ? "KEV_DL_WAKEFLAGS_CHANGED"    :
-                msg.k.event_code == KEV_DL_IF_IDLE_ROUTE_REFCNT ? "KEV_DL_IF_IDLE_ROUTE_REFCNT" :
-                msg.k.event_code == KEV_DL_IFCAP_CHANGED        ? "KEV_DL_IFCAP_CHANGED"        :
-                msg.k.event_code == KEV_DL_LINK_QUALITY_METRIC_CHANGED    ? "KEV_DL_LINK_QUALITY_METRIC_CHANGED"    :
-                msg.k.event_code == KEV_DL_NODE_PRESENCE        ? "KEV_DL_NODE_PRESENCE"        :
-                msg.k.event_code == KEV_DL_NODE_ABSENCE         ? "KEV_DL_NODE_ABSENCE"         :
-                msg.k.event_code == KEV_DL_MASTER_ELECTED       ? "KEV_DL_MASTER_ELECTED"       :
-                 "?");
-
-        if (msg.k.event_code == KEV_DL_NODE_PRESENCE)
-            nodePresence(m, (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);
-
-        if (msg.k.event_code == KEV_DL_MASTER_ELECTED)
-            newMasterElected(m, (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)
-        // always during sleep/wakeup due to some race conditions (See radar:8666757). At the same time, if
-        // "Wake on Network Access" is not turned on, the notification will not have KEV_DL_WAKEFLAGS_CHANGED.
-        // 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);
-
-#if !TARGET_OS_EMBEDDED     // don't setup packet filter rules on embedded
-
-        // For p2p interfaces, need to open the advertised service port in the firewall.
-        if (msg.k.event_code == KEV_DL_IF_ATTACHED)
-        {
-            struct net_event_data   * p;
-            p = (struct net_event_data *) &msg.k.event_data;
-
-            if (strncmp(p->if_name, "p2p", 3) == 0)
-            {
-                char ifname[IFNAMSIZ];
-                snprintf(ifname, IFNAMSIZ, "%s%d", p->if_name, p->if_unit);
-
-                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);
-            }
-        }
-
-        // For p2p interfaces, need to clear the firewall rules on interface detach
-        if (msg.k.event_code == KEV_DL_IF_DETACHED)
-        {
-            struct net_event_data   * p;
-            p = (struct net_event_data *) &msg.k.event_data;
-
-            if (strncmp(p->if_name, "p2p", 3) == 0)
-            {
-                pfArray_t portArray, protocolArray; // not initialized since count is 0 for PF_CLEAR_RULES
-                char ifname[IFNAMSIZ];
-                snprintf(ifname, IFNAMSIZ, "%s%d", p->if_name, p->if_unit);
-
-                LogInfo("SysEventCallBack: KEV_DL_IF_DETACHED if_family = %d, if_unit = %d, if_name = %s", p->if_family, p->if_unit, p->if_name);
-
-                mDNSPacketFilterControl(PF_CLEAR_RULES, ifname, 0, portArray, protocolArray);
-            }
-        }
-#endif // !TARGET_OS_EMBEDDED
-
-    }
-
-    mDNS_Unlock(m);
-}
-
-mDNSlocal mStatus WatchForSysEvents(mDNS *const m)
-{
-    m->p->SysEventNotifier = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT);
-    if (m->p->SysEventNotifier < 0)
-    { LogMsg("WatchForSysEvents: socket failed error %d errno %d (%s)", m->p->SysEventNotifier, errno, strerror(errno)); return(mStatus_NoMemoryErr); }
-
-    struct kev_request kev_req = { KEV_VENDOR_APPLE, KEV_NETWORK_CLASS, KEV_DL_SUBCLASS };
-    int err = ioctl(m->p->SysEventNotifier, SIOCSKEVFILT, &kev_req);
-    if (err < 0)
-    {
-        LogMsg("WatchForSysEvents: SIOCSKEVFILT failed error %d errno %d (%s)", err, errno, strerror(errno));
-        close(m->p->SysEventNotifier);
-        m->p->SysEventNotifier = -1;
-        return(mStatus_UnknownErr);
-    }
-
-    m->p->SysEventKQueue.KQcallback = SysEventCallBack;
-    m->p->SysEventKQueue.KQcontext  = m;
-    m->p->SysEventKQueue.KQtask     = "System Event Notifier";
-    KQueueSet(m->p->SysEventNotifier, EV_ADD, EVFILT_READ, &m->p->SysEventKQueue);
-
-    return(mStatus_NoError);
-}
-
-#ifndef NO_SECURITYFRAMEWORK
-mDNSlocal OSStatus KeychainChanged(SecKeychainEvent keychainEvent, SecKeychainCallbackInfo *info, void *context)
-{
-    LogInfo("***   Keychain Changed   ***");
-    mDNS *const m = (mDNS *const)context;
-    SecKeychainRef skc;
-    OSStatus err = SecKeychainCopyDefault(&skc);
-    if (!err)
-    {
-        if (info->keychain == skc)
-        {
-            // For delete events, attempt to verify what item was deleted fail because the item is already gone, so we just assume they may be relevant
-            mDNSBool relevant = (keychainEvent == kSecDeleteEvent);
-            if (!relevant)
-            {
-                UInt32 tags[3] = { kSecTypeItemAttr, kSecServiceItemAttr, kSecAccountItemAttr };
-                SecKeychainAttributeInfo attrInfo = { 3, tags, NULL };  // Count, array of tags, array of formats
-                SecKeychainAttributeList *a = NULL;
-                err = SecKeychainItemCopyAttributesAndData(info->item, &attrInfo, NULL, &a, NULL, NULL);
-                if (!err)
-                {
-                    relevant = ((a->attr[0].length == 4 && (!strncasecmp(a->attr[0].data, "ddns", 4) || !strncasecmp(a->attr[0].data, "sndd", 4))) ||
-                                (a->attr[1].length >= mDNSPlatformStrLen(dnsprefix) && (!strncasecmp(a->attr[1].data, dnsprefix, mDNSPlatformStrLen(dnsprefix)))) ||
-                                (a->attr[1].length >= mDNSPlatformStrLen(btmmprefix) && (!strncasecmp(a->attr[1].data, btmmprefix, mDNSPlatformStrLen(btmmprefix)))));
-                    SecKeychainItemFreeAttributesAndData(a, NULL);
-                }
-            }
-            if (relevant)
-            {
-                LogInfo("***   Keychain Changed   *** KeychainEvent=%d %s",
-                        keychainEvent,
-                        keychainEvent == kSecAddEvent    ? "kSecAddEvent"    :
-                        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);
-                mDNS_Lock(m);
-
-                // To not read the keychain twice: when BTMM is enabled, changes happen to the keychain
-                // then the BTMM DynStore dictionary, so delay reading the keychain for a second.
-                // NetworkChanged() will reset the keychain timer to fire immediately when the DynStore changes.
-                //
-                // In the "fixup" case where the BTMM DNS servers aren't accepting the key mDNSResponder has,
-                // the DynStore dictionary won't change (because the BTMM zone won't change).  In that case,
-                // a one second delay is ok, as we'll still converge to correctness, and there's no race
-                // condition between the RegistrationDomain and the DomainAuthInfo.
-                //
-                // 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);
-
-                mDNS_Unlock(m);
-                KQueueUnlock(m, "KeychainChanged");
-            }
-        }
-        CFRelease(skc);
-    }
-
-    return 0;
-}
-#endif
-
-mDNSlocal void PowerOn(mDNS *const m)
-{
-    mDNSCoreMachineSleep(m, false);     // Will set m->SleepState = SleepState_Awake;
-    if (m->p->WakeAtUTC)
-    {
-        long utc = mDNSPlatformUTC();
-        mDNSPowerRequest(-1,-1);        // Need to explicitly clear any previous power requests -- they're not cleared automatically on wake
-        if (m->p->WakeAtUTC - utc > 30)
-        { 
-            LogSPS("PowerChanged PowerOn %d seconds early, assuming not maintenance wake", m->p->WakeAtUTC - utc);
-        }
-        else if (utc - m->p->WakeAtUTC > 30) 
-        {
-            LogSPS("PowerChanged PowerOn %d seconds late, assuming not maintenance wake", utc - m->p->WakeAtUTC);
-        }
-        else if (IsAppleTV())
-        { 
-            LogSPS("PowerChanged PowerOn %d seconds late, device is an AppleTV running iOS so not re-sleeping", utc - m->p->WakeAtUTC);
-        }
-        else
-        {
-            LogSPS("PowerChanged: Waking for network maintenance operations %d seconds early; re-sleeping in 20 seconds", m->p->WakeAtUTC - utc);
-            m->p->RequestReSleep = mDNS_TimeNow(m) + 20 * mDNSPlatformOneSecond;
-        }
-    }
-}
-
-mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messageType, void *messageArgument)
-{
-    mDNS *const m = (mDNS *const)refcon;
-    KQueueLock(m);
-    (void)service;    // Parameter not used
-    debugf("PowerChanged %X %lX", messageType, messageArgument);
-
-    // Make sure our m->SystemWakeOnLANEnabled value correctly reflects the current system setting
-    m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
-
-    switch(messageType)
-    {
-    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);
-        break;
-    case kIOMessageSystemWillNotPowerOff:   LogSPS("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break;          // E0000260
-    case kIOMessageCanSystemSleep:          LogSPS("PowerChanged kIOMessageCanSystemSleep        (no action)"); break;          // E0000270
-    case kIOMessageSystemWillSleep:         LogSPS("PowerChanged kIOMessageSystemWillSleep");                                   // E0000280
-        mDNSCoreMachineSleep(m, true);
-        break;
-    case kIOMessageSystemWillNotSleep:      LogSPS("PowerChanged kIOMessageSystemWillNotSleep    (no action)"); break;          // E0000290
-    case kIOMessageSystemHasPoweredOn:      LogSPS("PowerChanged kIOMessageSystemHasPoweredOn");                                // E0000300
-        // If still sleeping (didn't get 'WillPowerOn' message for some reason?) wake now
-        if (m->SleepState)
-        {
-            LogMsg("PowerChanged kIOMessageSystemHasPoweredOn: ERROR m->SleepState %d", m->SleepState);
-            PowerOn(m);
-        }
-        // Just to be safe, schedule a mDNSMacOSXNetworkChanged(), in case we never received
-        // the System Configuration Framework "network changed" event that we expect
-        // to receive some time shortly after the kIOMessageSystemWillPowerOn message
-        mDNS_Lock(m);
-        if (!m->p->NetworkChanged ||
-            m->p->NetworkChanged - NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2) < 0)
-            m->p->NetworkChanged = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2);
-        mDNS_Unlock(m);
-
-        break;
-    case kIOMessageSystemWillRestart:       LogSPS("PowerChanged kIOMessageSystemWillRestart     (no action)"); break;          // E0000310
-    case kIOMessageSystemWillPowerOn:       LogSPS("PowerChanged kIOMessageSystemWillPowerOn");                                 // E0000320
-
-        // Make sure our interface list is cleared to the empty state, then tell mDNSCore to wake
-        if (m->SleepState != SleepState_Sleeping)
-        {
-            LogMsg("kIOMessageSystemWillPowerOn: ERROR m->SleepState %d", m->SleepState);
-            m->SleepState = SleepState_Sleeping;
-            mDNSMacOSXNetworkChanged(m);
-        }
-        PowerOn(m);
-        break;
-    default:                                LogSPS("PowerChanged unknown message %X", messageType); break;
-    }
-
-    if (messageType == kIOMessageSystemWillSleep) m->p->SleepCookie = (long)messageArgument;
-    else IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
-
-    KQueueUnlock(m, "PowerChanged Sleep/Wake");
-}
-
-// iPhone OS doesn't currently have SnowLeopard's IO Power Management
-// but it does define kIOPMAcknowledgmentOptionSystemCapabilityRequirements
-#if defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements) && !TARGET_OS_EMBEDDED
-mDNSlocal void SnowLeopardPowerChanged(void *refcon, IOPMConnection connection, IOPMConnectionMessageToken token, IOPMSystemPowerStateCapabilities eventDescriptor)
-{
-    mDNS *const m = (mDNS *const)refcon;
-    KQueueLock(m);
-    LogSPS("SnowLeopardPowerChanged %X %X %X%s%s%s%s%s",
-           connection, token, eventDescriptor,
-           eventDescriptor & kIOPMSystemPowerStateCapabilityCPU     ? " CPU"     : "",
-           eventDescriptor & kIOPMSystemPowerStateCapabilityVideo   ? " Video"   : "",
-           eventDescriptor & kIOPMSystemPowerStateCapabilityAudio   ? " Audio"   : "",
-           eventDescriptor & kIOPMSystemPowerStateCapabilityNetwork ? " Network" : "",
-           eventDescriptor & kIOPMSystemPowerStateCapabilityDisk    ? " Disk"    : "");
-
-    // Make sure our m->SystemWakeOnLANEnabled value correctly reflects the current system setting
-    m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
-
-    if (eventDescriptor & kIOPMSystemPowerStateCapabilityCPU)
-    {
-        // We might be in Sleeping or Transferring state. When we go from "wakeup" to "sleep" state, we don't
-        // go directly to sleep state, but transfer in to the sleep state during which SleepState is set to
-        // SleepState_Transferring. During that time, we might get another wakeup before we transition to Sleeping
-        // state. In that case, we need to acknowledge the previous "sleep" before we acknowledge the wakeup.
-        if (m->SleepLimit)
-        {
-            LogSPS("SnowLeopardPowerChanged: Waking up, Acking old Sleep, SleepLimit %d SleepState %d", m->SleepLimit, m->SleepState);
-            IOPMConnectionAcknowledgeEvent(connection, m->p->SleepCookie);
-            m->SleepLimit = 0;
-        }
-        LogSPS("SnowLeopardPowerChanged: Waking up, Acking Wakeup, SleepLimit %d SleepState %d", m->SleepLimit, m->SleepState);
-        // If the network notifications have already come before we got the wakeup, we ignored them and
-        // in case we get no more, we need to trigger one.
-        mDNS_Lock(m);
-        SetNetworkChanged(m, 2 * mDNSPlatformOneSecond);
-        mDNS_Unlock(m);
-        // CPU Waking. Note: Can get this message repeatedly, as other subsystems power up or down.
-        if (m->SleepState != SleepState_Awake) PowerOn(m);
-        IOPMConnectionAcknowledgeEvent(connection, token);
-    }
-    else
-    {
-        // CPU sleeping. Should not get this repeatedly -- once we're told that the CPU is halting
-        // we should hear nothing more until we're told that the CPU has started executing again.
-        if (m->SleepState) LogMsg("SnowLeopardPowerChanged: Sleep Error %X m->SleepState %d", eventDescriptor, m->SleepState);
-        //sleep(5);
-        //mDNSMacOSXNetworkChanged(m);
-        mDNSCoreMachineSleep(m, true);
-        //if (m->SleepState == SleepState_Sleeping) mDNSMacOSXNetworkChanged(m);
-        m->p->SleepCookie = token;
-    }
-
-    KQueueUnlock(m, "SnowLeopardPowerChanged Sleep/Wake");
-}
-#endif
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - /etc/hosts support
-#endif
-
-// Implementation Notes
-//
-// As /etc/hosts file can be huge (1000s of entries - when this comment was written, the test file had about
-// 23000 entries with about 4000 duplicates), we can't use a linked list to store these entries. So, we parse
-// them into a hash table. The implementation need to be able to do the following things efficiently
-//
-// 1. Detect duplicates e.g., two entries with "1.2.3.4 foo"
-// 2. Detect whether /etc/hosts has changed and what has changed since the last read from the disk
-// 3. Ability to support multiple addresses per name e.g., "1.2.3.4 foo, 2.3.4.5 foo". To support this, we
-//    need to be able set the RRSet of a resource record to the first one in the list and also update when
-//    one of them go away. This is needed so that the core thinks that they are all part of the same RRSet and
-//    not a duplicate
-// 4. Don't maintain any local state about any records registered with the core to detect changes to /etc/hosts
-//
-// CFDictionary is not a suitable candidate because it does not support duplicates and even if we use a custom
-// "hash" function to solve this, the others are hard to solve. Hence, we share the hash (AuthHash) implementation
-// of the core layer which does all of the above very efficiently
-
-#define ETCHOSTS_BUFSIZE    1024    // Buffer size to parse a single line in /etc/hosts
-
-mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    (void)m;  // unused
-    (void)rr;
-    (void)result;
-    if (result == mStatus_MemFree)
-    {
-        LogInfo("FreeEtcHosts: %s", ARDisplayString(m, rr));
-        freeL("etchosts", rr);
-    }
-}
-
-// 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)
-{
-    AuthRecord *rr;
-    mDNSu32 slot;
-    mDNSu32 namehash;
-    AuthGroup *ag;
-    mDNSInterfaceID InterfaceID = mDNSInterface_LocalOnly;
-    mDNSu16 rrtype;
-
-    if (!domain)
-    {
-        LogMsg("mDNSMacOSXCreateEtcHostsEntry: ERROR!! name NULL");
-        return mDNSfalse;
-    }
-    if (!sa && !cname)
-    {
-        LogMsg("mDNSMacOSXCreateEtcHostsEntry: ERROR!! sa and cname both NULL");
-        return mDNSfalse;
-    }
-
-    if (sa && sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
-    {
-        LogMsg("mDNSMacOSXCreateEtcHostsEntry: ERROR!! sa with bad family %d", sa->sa_family);
-        return mDNSfalse;
-    }
-
-
-    if (ifname)
-    {
-        mDNSu32 ifindex = if_nametoindex(ifname);
-        if (!ifindex)
-        {
-            LogMsg("mDNSMacOSXCreateEtcHostsEntry: hosts entry %##s with invalid ifname %s", domain->c, ifname);
-            return mDNSfalse;
-        }
-        InterfaceID = (mDNSInterfaceID)(uintptr_t)ifindex;
-    }
-
-    if (sa)
-        rrtype = (sa->sa_family == AF_INET ? kDNSType_A : kDNSType_AAAA);
-    else
-        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);
-    if (ag)
-    {
-        rr = ag->members;
-        while (rr)
-        {
-            if (rr->resrec.rrtype == rrtype)
-            {
-                if (rrtype == kDNSType_A)
-                {
-                    mDNSv4Addr ip;
-                    ip.NotAnInteger = ((struct sockaddr_in*)sa)->sin_addr.s_addr;
-                    if (mDNSSameIPv4Address(rr->resrec.rdata->u.ipv4, ip))
-                    {
-                        LogInfo("mDNSMacOSXCreateEtcHostsEntry: Same IPv4 address for name %##s", domain->c);
-                        return mDNSfalse;
-                    }
-                }
-                else if (rrtype == kDNSType_AAAA)
-                {
-                    mDNSv6Addr ip6;
-                    ip6.l[0] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[0];
-                    ip6.l[1] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[1];
-                    ip6.l[2] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[2];
-                    ip6.l[3] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[3];
-                    if (mDNSSameIPv6Address(rr->resrec.rdata->u.ipv6, ip6))
-                    {
-                        LogInfo("mDNSMacOSXCreateEtcHostsEntry: Same IPv6 address for name %##s", domain->c);
-                        return mDNSfalse;
-                    }
-                }
-                else if (rrtype == kDNSType_CNAME)
-                {
-                    if (SameDomainName(&rr->resrec.rdata->u.name, cname))
-                    {
-                        LogInfo("mDNSMacOSXCreateEtcHostsEntry: Same cname %##s for name %##s", cname->c, domain->c);
-                        return mDNSfalse;
-                    }
-                }
-            }
-            rr = rr->next;
-        }
-    }
-    rr= mallocL("etchosts", sizeof(*rr));
-    if (rr == NULL) return mDNSfalse;
-    mDNSPlatformMemZero(rr, sizeof(*rr));
-    mDNS_SetupResourceRecord(rr, NULL, InterfaceID, rrtype, 1, kDNSRecordTypeKnownUnique, AuthRecordLocalOnly, FreeEtcHosts, NULL);
-    AssignDomainName(&rr->namestorage, domain);
-
-    if (sa)
-    {
-        rr->resrec.rdlength = sa->sa_family == AF_INET ? sizeof(mDNSv4Addr) : sizeof(mDNSv6Addr);
-        if (sa->sa_family == AF_INET)
-            rr->resrec.rdata->u.ipv4.NotAnInteger = ((struct sockaddr_in*)sa)->sin_addr.s_addr;
-        else
-        {
-            rr->resrec.rdata->u.ipv6.l[0] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[0];
-            rr->resrec.rdata->u.ipv6.l[1] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[1];
-            rr->resrec.rdata->u.ipv6.l[2] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[2];
-            rr->resrec.rdata->u.ipv6.l[3] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[3];
-        }
-    }
-    else
-    {
-        rr->resrec.rdlength = DomainNameLength(cname);
-        rr->resrec.rdata->u.name.c[0] = 0;
-        AssignDomainName(&rr->resrec.rdata->u.name, cname);
-    }
-    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);
-    return mDNStrue;
-}
-
-mDNSlocal int EtcHostsParseOneName(int start, int length, char *buffer, char **name)
-{
-    int i;
-
-    *name = NULL;
-    for (i = start; i < length; i++)
-    {
-        if (buffer[i] == '#')
-            return -1;
-        if (buffer[i] != ' ' && buffer[i] != ',' && buffer[i] != '\t')
-        {
-            *name = &buffer[i];
-
-            // Found the start of a name, find the end and null terminate
-            for (i++; i < length; i++)
-            {
-                if (buffer[i] == ' ' || buffer[i] == ',' || buffer[i] == '\t')
-                {
-                    buffer[i] = 0;
-                    break;
-                }
-            }
-            return i;
-        }
-    }
-    return -1;
-}
-
-mDNSlocal void mDNSMacOSXParseEtcHostsLine(mDNS *const m, char *buffer, ssize_t length, AuthHash *auth)
-{
-    int i;
-    int ifStart = 0;
-    char *ifname = NULL;
-    domainname name1d;
-    domainname name2d;
-    char *name1;
-    char *name2;
-    int aliasIndex;
-
-    //Ignore leading whitespaces and tabs
-    while (*buffer == ' ' || *buffer == '\t')
-    {
-        buffer++;
-        length--;
-    }
-
-    // Find the end of the address string
-    for (i = 0; i < length; i++)
-    {
-        if (buffer[i] == ' ' || buffer[i] == ',' || buffer[i] == '\t' || buffer[i] == '%')
-        {
-            if (buffer[i] == '%')
-                ifStart = i + 1;
-            buffer[i] = 0;
-            break;
-        }
-    }
-
-    // Convert the address string to an address
-    struct addrinfo hints;
-    bzero(&hints, sizeof(hints));
-    hints.ai_flags = AI_NUMERICHOST;
-    struct addrinfo *gairesults = NULL;
-    if (getaddrinfo(buffer, NULL, &hints, &gairesults) != 0)
-    {
-        LogInfo("mDNSMacOSXParseEtcHostsLine: getaddrinfo returning null");
-        return;
-    }
-
-    if (ifStart)
-    {
-        // Parse the interface
-        ifname = &buffer[ifStart];
-        for (i = ifStart + 1; i < length; i++)
-        {
-            if (buffer[i] == ' ' || buffer[i] == ',' || buffer[i] == '\t')
-            {
-                buffer[i] = 0;
-                break;
-            }
-        }
-    }
-
-    i = EtcHostsParseOneName(i + 1, length, buffer, &name1);
-    if (i == length)
-    {
-        // Common case (no aliases) : The entry is of the form "1.2.3.4 somehost" with no trailing white spaces/tabs etc.
-        if (!MakeDomainNameFromDNSNameString(&name1d, name1))
-        {
-            LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name1);
-            freeaddrinfo(gairesults);
-            return;
-        }
-        mDNSMacOSXCreateEtcHostsEntry(m, &name1d, gairesults->ai_addr, mDNSNULL, ifname, auth);
-    }
-    else if (i != -1)
-    {
-        domainname first;
-        // We might have some extra white spaces at the end for the common case of "1.2.3.4 somehost".
-        // When we parse again below, EtchHostsParseOneName would return -1 and we will end up
-        // doing the right thing.
-        if (!MakeDomainNameFromDNSNameString(&first, name1))
-        {
-            LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name1);
-            freeaddrinfo(gairesults);
-            return;
-        }
-        // If the /etc/hosts has an entry like this
-        //
-        // 1.2.3.4 sun star bright
-        //
-        // star and bright are aliases (gethostbyname h_alias should point to these) and sun is the canonical
-        // name (getaddrinfo ai_cannonname and gethostbyname h_name points to "sun")
-        //
-        // To achieve this, we need to add the entry like this:
-        //
-        // star CNAME bright
-        // bright CNAME sun
-        // sun A 1.2.3.4
-        //
-        // We store the first name we parsed in "first". Then we parse additional names adding CNAME records
-        // till we reach the end. When we reach the end, we wrap around and add one final CNAME with the last
-        // entry and the first entry. Finally, we add the Address (A/AAAA) record.
-        aliasIndex = 0;
-        while (i <= length)
-        {
-            // Parse a name. If there are no names, we need to know whether we
-            // parsed CNAMEs before or not. If we parsed CNAMEs before, then we
-            // add a CNAME with the last name and the first name. Otherwise, this
-            // is same as the common case above where the line has just one name
-            // but with trailing white spaces.
-            i = EtcHostsParseOneName(i + 1, length, buffer, &name2);
-            if (name2)
-            {
-                if (!MakeDomainNameFromDNSNameString(&name2d, name2))
-                {
-                    LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name2);
-                    freeaddrinfo(gairesults);
-                    return;
-                }
-                aliasIndex++;
-            }
-            else if (!aliasIndex)
-            {
-                // We have never parsed any aliases. This case happens if there
-                // is just one name and some extra white spaces at the end.
-                LogInfo("mDNSMacOSXParseEtcHostsLine: White space at the end of %##s", first.c);
-                break;
-            }
-            else
-            {
-                // We have parsed at least one alias before and we reached the end of the line.
-                // Setup a CNAME for the last name with "first" name as its RDATA
-                name2d.c[0] = 0;
-                AssignDomainName(&name2d, &first);
-            }
-
-            // Don't add a CNAME for the first alias we parse (see the example above).
-            // As we parse more, we might discover that there are no more aliases, in
-            // which case we would have set "name2d" to "first" above. We need to add
-            // the CNAME in that case.
-
-            if (aliasIndex > 1 || SameDomainName(&name2d, &first))
-            {
-                // Ignore if it points to itself
-                if (!SameDomainName(&name1d, &name2d))
-                {
-                    if (!mDNSMacOSXCreateEtcHostsEntry(m, &name1d, mDNSNULL, &name2d, ifname, auth))
-                    {
-                        freeaddrinfo(gairesults);
-                        return;
-                    }
-                }
-                else
-                    LogMsg("mDNSMacOSXParseEtcHostsLine: Ignoring entry with same names name1 %##s, name2 %##s", name1d.c, name2d.c);
-            }
-
-            // If we have already wrapped around, we just need to add the A/AAAA record alone
-            // which is done below
-            if (SameDomainName(&name2d, &first)) break;
-
-            // Remember the current name so that we can set the CNAME record if we parse one
-            // more name
-            name1d.c[0] = 0;
-            AssignDomainName(&name1d, &name2d);
-        }
-        // Added all the CNAMEs if any, add the "A/AAAA" record
-        mDNSMacOSXCreateEtcHostsEntry(m, &first, gairesults->ai_addr, mDNSNULL, ifname, auth);
-    }
-    freeaddrinfo(gairesults);
-}
-
-mDNSlocal void mDNSMacOSXParseEtcHosts(mDNS *const m, int fd, AuthHash *auth)
-{
-    mDNSBool good;
-    char buf[ETCHOSTS_BUFSIZE];
-    ssize_t len;
-    FILE *fp;
-
-    if (fd == -1) { LogInfo("mDNSMacOSXParseEtcHosts: fd is -1"); return; }
-
-    fp = fopen("/etc/hosts", "r");
-    if (!fp) { LogInfo("mDNSMacOSXParseEtcHosts: fp is NULL"); return; }
-
-    while (1)
-    {
-        good = (fgets(buf, ETCHOSTS_BUFSIZE, fp) != NULL);
-        if (!good) break;
-
-        // skip comment and empty lines
-        if (buf[0] == '#' || buf[0] == '\r' || buf[0] == '\n')
-            continue;
-
-        len = strlen(buf);
-        if (!len) break;    // sanity check
-        //Check for end of line code(mostly only \n but pre-OS X Macs could have only \r)
-        if (buf[len - 1] == '\r' || buf[len - 1] == '\n')
-        {
-            buf[len - 1] = '\0';
-            len = len - 1;
-        }
-        // fgets always null terminates and hence even if we have no
-        // newline at the end, it is null terminated. The callee
-        // (mDNSMacOSXParseEtcHostsLine) expects the length to be such that
-        // buf[length] is zero and hence we decrement len to reflect that.
-        if (len)
-        {
-            //Additional check when end of line code is 2 chars ie\r\n(DOS, other old OSes)
-            //here we need to check for just \r but taking extra caution.
-            if (buf[len - 1] == '\r' || buf[len - 1] == '\n')
-            {
-                buf[len - 1] = '\0';
-                len = len - 1;
-            }
-        }
-        if (!len) //Sanity Check: len should never be zero
-        {
-            LogMsg("mDNSMacOSXParseEtcHosts: Length is zero!");
-            continue;
-        }
-        mDNSMacOSXParseEtcHostsLine(m, buf, len, auth);
-    }
-    fclose(fp);
-}
-
-mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m);
-
-mDNSlocal int mDNSMacOSXGetEtcHostsFD(mDNS *const m)
-{
-#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;
-    static dispatch_source_t etcsrc   = 0;
-    static dispatch_source_t hostssrc = 0;
-
-    // First time through? just schedule ourselves on the main queue and we'll do the work later
-    if (!etcq)
-    {
-        etcq = dispatch_get_main_queue();
-        if (etcq)
-        {
-            // Do this work on the queue, not here - solves potential synchronization issues
-            dispatch_async(etcq, ^{mDNSMacOSXUpdateEtcHosts(m);});
-        }
-        return -1;
-    }
-
-    if (hostssrc) return dispatch_source_get_handle(hostssrc);
-#endif
-
-    int fd = open("/etc/hosts", O_RDONLY);
-
-#ifdef __DISPATCH_GROUP__
-    // Can't do this stuff to be notified of changes in /etc/hosts if we don't have libdispatch
-    if (fd == -1)
-    {
-        // If the open failed and we're already watching /etc, we're done
-        if (etcsrc) { LogInfo("mDNSMacOSXGetEtcHostsFD: Returning etcfd because no etchosts"); return fd; }
-
-        // we aren't watching /etc, we should be
-        fd = open("/etc", O_RDONLY);
-        if (fd == -1) { LogInfo("mDNSMacOSXGetEtcHostsFD: etc does not exist"); return -1; }
-        etcsrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fd, DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_RENAME, etcq);
-        if (etcsrc == NULL)
-        {
-            close(fd);
-            return -1;
-        }
-        dispatch_source_set_event_handler(etcsrc,
-                                          ^{
-                                              u_int32_t flags = dispatch_source_get_data(etcsrc);
-                                              LogMsg("mDNSMacOSXGetEtcHostsFD: /etc changed 0x%x", flags);
-                                              if ((flags & (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_RENAME)) != 0)
-                                              {
-                                                  dispatch_source_cancel(etcsrc);
-                                                  dispatch_release(etcsrc);
-                                                  etcsrc = NULL;
-                                                  dispatch_async(etcq, ^{mDNSMacOSXUpdateEtcHosts(m);});
-                                                  return;
-                                              }
-                                              if ((flags & DISPATCH_VNODE_WRITE) != 0 && hostssrc == NULL)
-                                              {
-                                                  mDNSMacOSXUpdateEtcHosts(m);
-                                              }
-                                          });
-        dispatch_source_set_cancel_handler(etcsrc, ^{close(fd);});
-        dispatch_resume(etcsrc);
-
-        // Try and open /etc/hosts once more now that we're watching /etc, in case we missed the creation
-        fd = open("/etc/hosts", O_RDONLY | O_EVTONLY);
-        if (fd == -1) { LogMsg("mDNSMacOSXGetEtcHostsFD etc hosts does not exist, watching etc"); return -1; }
-    }
-
-    // create a dispatch source to watch for changes to hosts file
-    hostssrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fd,
-                                      (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_RENAME |
-                                       DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_LINK | DISPATCH_VNODE_REVOKE), etcq);
-    if (hostssrc == NULL)
-    {
-        close(fd);
-        return -1;
-    }
-    dispatch_source_set_event_handler(hostssrc,
-                                      ^{
-                                          u_int32_t flags = dispatch_source_get_data(hostssrc);
-                                          LogInfo("mDNSMacOSXGetEtcHostsFD: /etc/hosts changed 0x%x", flags);
-                                          if ((flags & (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_RENAME)) != 0)
-                                          {
-                                              dispatch_source_cancel(hostssrc);
-                                              dispatch_release(hostssrc);
-                                              hostssrc = NULL;
-                                              // Bug in LibDispatch: wait a second before scheduling the block. If we schedule
-                                              // the block immediately, we try to open the file and the file may not exist and may
-                                              // fail to get a notification in the future. When the file does not exist and
-                                              // we start to monitor the directory, on "dispatch_resume" of that source, there
-                                              // is no guarantee that the file creation will be notified always because when
-                                              // the dispatch_resume returns, the kevent manager may not have registered the
-                                              // kevent yet but the file may have been created
-                                              usleep(1000000);
-                                              dispatch_async(etcq, ^{mDNSMacOSXUpdateEtcHosts(m);});
-                                              return;
-                                          }
-                                          if ((flags & DISPATCH_VNODE_WRITE) != 0)
-                                          {
-                                              mDNSMacOSXUpdateEtcHosts(m);
-                                          }
-                                      });
-    dispatch_source_set_cancel_handler(hostssrc, ^{LogInfo("mDNSMacOSXGetEtcHostsFD: Closing etchosts fd %d", fd); close(fd);});
-    dispatch_resume(hostssrc);
-
-    // Cleanup /etc source, no need to watch it if we already have /etc/hosts
-    if (etcsrc)
-    {
-        dispatch_source_cancel(etcsrc);
-        dispatch_release(etcsrc);
-        etcsrc = NULL;
-    }
-
-    LogInfo("mDNSMacOSXGetEtcHostsFD: /etc/hosts being monitored, and not etc");
-    return hostssrc ? (int)dispatch_source_get_handle(hostssrc) : -1;
-#else
-    (void)m;
-    return fd;
-#endif
-}
-
-// When /etc/hosts is modified, flush all the cache records as there may be local
-// authoritative answers now
-mDNSlocal void FlushAllCacheRecords(mDNS *const m)
-{
-    CacheRecord *cr;
-    mDNSu32 slot;
-    CacheGroup *cg;
-
-    FORALL_CACHERECORDS(slot, cg, cr)
-    {
-        // Skip multicast.
-        if (cr->resrec.InterfaceID) continue;
-
-        // If a resource record can answer A or AAAA, they need to be flushed so that we will
-        // never used to deliver an ADD or RMV
-        if (RRTypeAnswersQuestionType(&cr->resrec, kDNSType_A) ||
-            RRTypeAnswersQuestionType(&cr->resrec, kDNSType_AAAA))
-        {
-            LogInfo("FlushAllCacheRecords: Purging Resourcerecord %s", CRDisplayString(m, cr));
-            mDNS_PurgeCacheResourceRecord(m, cr);
-        }
-    }
-}
-
-// 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)
-{
-    AuthGroup *ag;
-    mDNSu32 slot;
-    AuthRecord *rr, *primary, *rrnext;
-    for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
-        for (ag = newhosts->rrauth_hash[slot]; ag; ag = ag->next)
-        {
-            primary = NULL;
-            for (rr = ag->members; rr; rr = rrnext)
-            {
-                rrnext = rr->next;
-                AuthGroup *ag1;
-                AuthRecord *rr1;
-                mDNSBool found = mDNSfalse;
-                ag1 = AuthGroupForRecord(&m->rrauth, slot, &rr->resrec);
-                if (ag1 && ag1->members)
-                {
-                    if (!primary) primary = ag1->members;
-                    rr1 = ag1->members;
-                    while (rr1)
-                    {
-                        // We are not using InterfaceID in checking for duplicates. This means,
-                        // if there are two addresses for a given name e.g., fe80::1%en0 and
-                        // fe80::1%en1, we only add the first one. It is not clear whether
-                        // this is a common case. To fix this, we also need to modify
-                        // mDNS_Register_internal in how it handles duplicates. If it becomes a
-                        // common case, we will fix it then.
-                        if (IdenticalResourceRecord(&rr1->resrec, &rr->resrec))
-                        {
-                            LogInfo("EtcHostsAddNewEntries: Skipping, not adding %s", ARDisplayString(m, rr1));
-                            found = mDNStrue;
-                            break;
-                        }
-                        rr1 = rr1->next;
-                    }
-                }
-                if (!found)
-                {
-                    if (justCheck)
-                    {
-                        LogInfo("EtcHostsAddNewEntries: Entry %s not registered with core yet", ARDisplayString(m, rr));
-                        return mDNStrue;
-                    }
-                    RemoveAuthRecord(m, newhosts, rr);
-                    // if there is no primary, point to self
-                    rr->RRSet = (primary ? primary : rr);
-                    rr->next = NULL;
-                    LogInfo("EtcHostsAddNewEntries: Adding %s", ARDisplayString(m, rr));
-                    if (mDNS_Register_internal(m, rr) != mStatus_NoError)
-                        LogMsg("EtcHostsAddNewEntries: mDNS_Register failed for %s", ARDisplayString(m, rr));
-                }
-            }
-        }
-    return mDNSfalse;
-}
-
-// 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)
-{
-    AuthGroup *ag;
-    mDNSu32 slot;
-    AuthRecord *rr, *primary, *rrnext;
-    for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
-        for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next)
-            for (rr = ag->members; rr; rr = rrnext)
-            {
-                mDNSBool found = mDNSfalse;
-                AuthGroup *ag1;
-                AuthRecord *rr1;
-                rrnext = rr->next;
-                if (rr->RecordCallback != FreeEtcHosts) continue;
-                ag1 = AuthGroupForRecord(newhosts, slot, &rr->resrec);
-                if (ag1)
-                {
-                    primary = rr1 = ag1->members;
-                    while (rr1)
-                    {
-                        if (IdenticalResourceRecord(&rr1->resrec, &rr->resrec))
-                        {
-                            LogInfo("EtcHostsDeleteOldEntries: Old record %s found in new, skipping", ARDisplayString(m, rr));
-                            found = mDNStrue;
-                            break;
-                        }
-                        rr1 = rr1->next;
-                    }
-                }
-                // there is no corresponding record in newhosts for the same name. This means
-                // we should delete this from the core.
-                if (!found)
-                {
-                    if (justCheck)
-                    {
-                        LogInfo("EtcHostsDeleteOldEntries: Record %s not found in new, deleting", ARDisplayString(m, rr));
-                        return mDNStrue;
-                    }
-                    // if primary is going away, make sure that the rest of the records
-                    // point to the new primary
-                    if (rr == ag->members)
-                    {
-                        AuthRecord *new_primary = rr->next;
-                        AuthRecord *r = new_primary;
-                        while (r)
-                        {
-                            if (r->RRSet == rr)
-                            {
-                                LogInfo("EtcHostsDeleteOldEntries: Updating Resource Record %s to primary", ARDisplayString(m, r));
-                                r->RRSet = new_primary;
-                            }
-                            else LogMsg("EtcHostsDeleteOldEntries: ERROR!! Resource Record %s not pointing to primary %##s", ARDisplayString(m, r), r->resrec.name);
-                            r = r->next;
-                        }
-                    }
-                    LogInfo("EtcHostsDeleteOldEntries: Deleting %s", ARDisplayString(m, rr));
-                    mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
-                }
-            }
-    return mDNSfalse;
-}
-
-mDNSlocal void UpdateEtcHosts(mDNS *const m, void *context)
-{
-    AuthHash *newhosts = (AuthHash *)context;
-
-    mDNS_CheckLock(m);
-
-    //Delete old entries from the core if they are not present in the newhosts
-    EtcHostsDeleteOldEntries(m, newhosts, mDNSfalse);
-    // Add the new entries to the core if not already present in the core
-    EtcHostsAddNewEntries(m, newhosts, mDNSfalse);
-}
-
-mDNSlocal void FreeNewHosts(AuthHash *newhosts)
-{
-    mDNSu32 slot;
-    AuthGroup *ag, *agnext;
-    AuthRecord *rr, *rrnext;
-
-    for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
-        for (ag = newhosts->rrauth_hash[slot]; ag; ag = agnext)
-        {
-            agnext = ag->next;
-            for (rr = ag->members; rr; rr = rrnext)
-            {
-                rrnext = rr->next;
-                freeL("etchosts", rr);
-            }
-            freeL("AuthGroups", ag);
-        }
-}
-
-mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m)
-{
-    AuthHash newhosts;
-
-    // As we will be modifying the core, we can only have one thread running at
-    // any point in time.
-    KQueueLock(m);
-
-    mDNSPlatformMemZero(&newhosts, sizeof(AuthHash));
-
-    // Get the file desecriptor (will trigger us to start watching for changes)
-    int fd = mDNSMacOSXGetEtcHostsFD(m);
-    if (fd != -1)
-    {
-        LogInfo("mDNSMacOSXUpdateEtcHosts: Parsing /etc/hosts fd %d", fd);
-        mDNSMacOSXParseEtcHosts(m, fd, &newhosts);
-    }
-    else LogInfo("mDNSMacOSXUpdateEtcHosts: /etc/hosts is not present");
-
-    // Optimization: Detect whether /etc/hosts changed or not.
-    //
-    // 1. Check to see if there are any new entries. We do this by seeing whether any entries in
-    //    newhosts is already registered with core.  If we find at least one entry that is not
-    //    registered with core, then it means we have work to do.
-    //
-    // 2. Next, we check to see if any of the entries that are registered with core is not present
-    //   in newhosts. If we find at least one entry that is not present, it means we have work to
-    //   do.
-    //
-    // Note: We may not have to hold the lock right here as KQueueLock is held which prevents any
-    // other thread from running. But mDNS_Lock is needed here as we will be traversing the core
-    // data structure in EtcHostsDeleteOldEntries/NewEntries which might expect the lock to be held
-    // 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))
-    {
-        // 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))
-        {
-            LogInfo("mDNSMacOSXUpdateEtcHosts: No work");
-            mDNS_Unlock(m);
-            KQueueUnlock(m, "/etc/hosts changed");
-            FreeNewHosts(&newhosts);
-            return;
-        }
-    }
-
-    // This will flush the cache, stop and start the query so that the queries
-    // can look at the /etc/hosts again
-    //
-    // Notes:
-    //
-    // We can't delete and free the records here. We wait for the mDNSCoreRestartAddressQueries to
-    // deliver RMV events. It has to be done in a deferred way because we can't deliver RMV
-    // events for local records *before* the RMV events for cache records. mDNSCoreRestartAddressQueries
-    // delivers these events in the right order and then calls us back to delete them.
-    //
-    // Similarly, we do a deferred Registration of the record because mDNSCoreRestartAddressQueries
-    // is a common function that looks at all local auth records and delivers a RMV including
-    // the records that we might add here. If we deliver a ADD here, it will get a RMV and then when
-    // the query is restarted, it will get another ADD. To avoid this (ADD-RMV-ADD), we defer registering
-    // the record until the RMVs are delivered in mDNSCoreRestartAddressQueries after which UpdateEtcHosts
-    // is called back where we do the Registration of the record. This results in RMV followed by ADD which
-    // looks normal.
-    mDNSCoreRestartAddressQueries(m, mDNSfalse, FlushAllCacheRecords, UpdateEtcHosts, &newhosts);
-    mDNS_Unlock(m);
-
-    KQueueUnlock(m, "/etc/hosts changed");
-    FreeNewHosts(&newhosts);
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Initialization & Teardown
-#endif
-
-CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
-CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey;
-CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey;
-CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey;
-
-// Major version 13 is 10.9.x 
-mDNSexport void mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring)
-{
-    int major = 0, minor = 0;
-    char letter = 0, prodname[256]="<Unknown>", prodvers[256]="<Unknown>", buildver[256]="<Unknown>";
-    CFDictionaryRef vers = _CFCopySystemVersionDictionary();
-    if (vers)
-    {
-        CFStringRef cfprodname = CFDictionaryGetValue(vers, _kCFSystemVersionProductNameKey);
-        CFStringRef cfprodvers = CFDictionaryGetValue(vers, _kCFSystemVersionProductVersionKey);
-        CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey);
-        if (cfprodname) 
-            CFStringGetCString(cfprodname, prodname, sizeof(prodname), kCFStringEncodingUTF8);
-        if (cfprodvers) 
-            CFStringGetCString(cfprodvers, prodvers, sizeof(prodvers), kCFStringEncodingUTF8);
-        if (cfbuildver && CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8))
-            sscanf(buildver, "%d%c%d", &major, &letter, &minor);
-        CFRelease(vers);
-    }
-    if (!major) 
-    { 
-        major = 13; 
-        LogMsg("Note: No Major Build Version number found; assuming 13"); 
-    }
-    if (HINFO_SWstring) 
-        mDNS_snprintf(HINFO_SWstring, 256, "%s %s (%s), %s", prodname, prodvers, buildver, STRINGIFY(mDNSResponderVersion));
-    //LogMsg("%s %s (%s), %d %c %d", prodname, prodvers, buildver, major, letter, minor);
-
-    // If product name is "Mac OS X" (or similar) we set OSXVers, else we set iOSVers;
-    if ((prodname[0] & 0xDF) == 'M') 
-        OSXVers = major;
-    else 
-        iOSVers = major;
-}
-
-// Test to see if we're the first client running on UDP port 5353, by trying to bind to 5353 without using SO_REUSEPORT.
-// If we fail, someone else got here first. That's not a big problem; we can share the port for multicast responses --
-// we just need to be aware that we shouldn't expect to successfully receive unicast UDP responses.
-mDNSlocal mDNSBool mDNSPlatformInit_CanReceiveUnicast(void)
-{
-    int err = -1;
-    int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-    if (s < 3)
-        LogMsg("mDNSPlatformInit_CanReceiveUnicast: socket error %d errno %d (%s)", s, errno, strerror(errno));
-    else
-    {
-        struct sockaddr_in s5353;
-        s5353.sin_family      = AF_INET;
-        s5353.sin_port        = MulticastDNSPort.NotAnInteger;
-        s5353.sin_addr.s_addr = 0;
-        err = bind(s, (struct sockaddr *)&s5353, sizeof(s5353));
-        close(s);
-    }
-
-    if (err) LogMsg("No unicast UDP responses");
-    else debugf("Unicast UDP responses okay");
-    return(err == 0);
-}
-
-mDNSlocal void CreatePTRRecord(mDNS *const m, const domainname *domain)
-{
-    AuthRecord *rr;
-    const domainname *pname = (domainname *)"\x9" "localhost";
-
-    rr= mallocL("localhosts", sizeof(*rr));
-    if (rr == NULL) return;
-    mDNSPlatformMemZero(rr, sizeof(*rr));
-
-    mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordLocalOnly, mDNSNULL, mDNSNULL);
-    AssignDomainName(&rr->namestorage, domain);
-
-    rr->resrec.rdlength = DomainNameLength(pname);
-    rr->resrec.rdata->u.name.c[0] = 0;
-    AssignDomainName(&rr->resrec.rdata->u.name, pname);
-
-    rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
-    SetNewRData(&rr->resrec, mDNSNULL, 0);  // Sets rr->rdatahash for us
-    mDNS_Register(m, rr);
-}
-
-// Setup PTR records for 127.0.0.1 and ::1. This helps answering them locally rather than relying
-// on the external DNS server to answer this. Sometimes, the DNS servers don't respond in a timely
-// fashion and applications depending on this e.g., telnetd, times out after 30 seconds creating
-// a bad user experience. For now, we specifically create only localhosts to handle radar://9354225
-//
-// 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)
-{
-    char buffer[MAX_REVERSE_MAPPING_NAME];
-    domainname name;
-    int i;
-    struct in6_addr addr;
-    mDNSu8 *ptr = addr.__u6_addr.__u6_addr8;
-
-    if (inet_pton(AF_INET, "127.0.0.1", &addr) == 1)
-    {
-        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);
-    }
-    else LogMsg("SetupLocalHostRecords: ERROR!! inet_pton AF_INET failed");
-
-    if (inet_pton(AF_INET6, "::1", &addr) == 1)
-    {
-        for (i = 0; i < 16; i++)
-        {
-            static const char hexValues[] = "0123456789ABCDEF";
-            buffer[i * 4    ] = hexValues[ptr[15 - i] & 0x0F];
-            buffer[i * 4 + 1] = '.';
-            buffer[i * 4 + 2] = hexValues[ptr[15 - i] >> 4];
-            buffer[i * 4 + 3] = '.';
-        }
-        mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa.");
-        MakeDomainNameFromDNSNameString(&name, buffer);
-        CreatePTRRecord(m, &name);
-    }
-    else LogMsg("SetupLocalHostRecords: ERROR!! inet_pton AF_INET6 failed");
-}
-
-// 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)
-// 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>.
-// 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result>
-// 4) result above should generate a callback from question in (1).  result added to global list
-// 5) global list delivered to client via GetSearchDomainList()
-// 6) client calls to enumerate domains now go over LocalOnly interface
-//    (!!!KRS may add outgoing interface in addition)
-
-mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
-{
-    mStatus err;
-    m->p->CFRunLoop = CFRunLoopGetCurrent();
-
-    char HINFO_SWstring[256] = "";
-    mDNSMacOSXSystemBuildNumber(HINFO_SWstring);
-
-    err = mDNSHelperInit();
-    if (err)
-        return err;
-    
-    DynamicStoreQueue = dispatch_queue_create("com.apple.mDNSResponder.DynamicStoreQueue", NULL);
-    if (DynamicStoreQueue == NULL)
-    {
-        LogMsg("dispatch_queue_create: DynamicStoreQueue NULL!");
-        return mStatus_NoMemoryErr;
-    }
-
-    // Store mDNSResponder Platform 
-    if (OSXVers)
-    {
-        m->mDNS_plat = platform_OSX;
-    }
-    else if (iOSVers)
-    {
-        if (IsAppleTV())
-            m->mDNS_plat = platform_Atv;
-        else
-            m->mDNS_plat = platform_iOS;
-    }
-    else
-    {
-        m->mDNS_plat = platform_NonApple; 
-    }   
-        
-    // In 10.4, mDNSResponder is launched very early in the boot process, while other subsystems are still in the process of starting up.
-    // If we can't read the user's preferences, then we sleep a bit and try again, for up to five seconds before we give up.
-    int i;
-    for (i=0; i<100; i++)
-    {
-        domainlabel testlabel;
-        testlabel.c[0] = 0;
-        GetUserSpecifiedLocalHostName(&testlabel);
-        if (testlabel.c[0]) break;
-        usleep(50000);
-    }
-
-    m->hostlabel.c[0]        = 0;
-
-    int get_model[2] = { CTL_HW, HW_MODEL };
-    size_t len_model = sizeof(HINFO_HWstring_buffer);
-
-    // Normal Apple model names are of the form "iPhone2,1", and
-    // internal code names are strings containing no commas, e.g. "N88AP".
-    // We used to ignore internal code names, but Apple now uses these internal code names
-    // even in released shipping products, so we no longer ignore strings containing no commas.
-//	if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0 && strchr(HINFO_HWstring_buffer, ','))
-    if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0)
-        HINFO_HWstring = HINFO_HWstring_buffer;
-
-    // For names of the form "iPhone2,1" we use "iPhone" as the prefix for automatic name generation.
-    // For names of the form "N88AP" containg no comma, we use the entire string.
-    HINFO_HWstring_prefixlen = strchr(HINFO_HWstring_buffer, ',') ? strcspn(HINFO_HWstring, "0123456789") : strlen(HINFO_HWstring);
-
-    if (mDNSPlatformInit_CanReceiveUnicast()) 
-        m->CanReceiveUnicastOn5353 = mDNStrue;
-
-    mDNSu32 hlen = mDNSPlatformStrLen(HINFO_HWstring);
-    mDNSu32 slen = mDNSPlatformStrLen(HINFO_SWstring);
-    if (hlen + slen < 254)
-    {
-        m->HIHardware.c[0] = hlen;
-        m->HISoftware.c[0] = slen;
-        mDNSPlatformMemCopy(&m->HIHardware.c[1], HINFO_HWstring, hlen);
-        mDNSPlatformMemCopy(&m->HISoftware.c[1], HINFO_SWstring, slen);
-    }
-
-    m->p->permanentsockets.port  = MulticastDNSPort;
-    m->p->permanentsockets.m     = m;
-    m->p->permanentsockets.sktv4 = -1;
-    m->p->permanentsockets.kqsv4.KQcallback = myKQSocketCallBack;
-    m->p->permanentsockets.kqsv4.KQcontext  = &m->p->permanentsockets;
-    m->p->permanentsockets.kqsv4.KQtask     = "UDP packet reception";
-    m->p->permanentsockets.sktv6 = -1;
-    m->p->permanentsockets.kqsv6.KQcallback = myKQSocketCallBack;
-    m->p->permanentsockets.kqsv6.KQcontext  = &m->p->permanentsockets;
-    m->p->permanentsockets.kqsv6.KQtask     = "UDP packet reception";
-
-    err = SetupSocket(&m->p->permanentsockets, MulticastDNSPort, AF_INET, mDNSNULL);
-    err = SetupSocket(&m->p->permanentsockets, MulticastDNSPort, AF_INET6, mDNSNULL);
-
-    struct sockaddr_in s4;
-    socklen_t n4 = sizeof(s4);
-    if (getsockname(m->p->permanentsockets.sktv4, (struct sockaddr *)&s4, &n4) < 0) 
-        LogMsg("getsockname v4 error %d (%s)", errno, strerror(errno));
-    else 
-        m->UnicastPort4.NotAnInteger = s4.sin_port;
-
-    if (m->p->permanentsockets.sktv6 >= 0)
-    {
-        struct sockaddr_in6 s6;
-        socklen_t n6 = sizeof(s6);
-        if (getsockname(m->p->permanentsockets.sktv6, (struct sockaddr *)&s6, &n6) < 0) LogMsg("getsockname v6 error %d (%s)", errno, strerror(errno));
-        else m->UnicastPort6.NotAnInteger = s6.sin6_port;
-    }
-
-    m->p->InterfaceList      = mDNSNULL;
-    m->p->userhostlabel.c[0] = 0;
-    m->p->usernicelabel.c[0] = 0;
-    m->p->prevoldnicelabel.c[0] = 0;
-    m->p->prevnewnicelabel.c[0] = 0;
-    m->p->prevoldhostlabel.c[0] = 0;
-    m->p->prevnewhostlabel.c[0] = 0;
-    m->p->NotifyUser         = 0;
-    m->p->KeyChainTimer      = 0;
-    m->p->WakeAtUTC          = 0;
-    m->p->RequestReSleep     = 0;
-    // Assume that everything is good to begin with. If something is not working,
-    // we will detect that when we start sending questions.
-    m->p->v4answers          = 1;
-    m->p->v6answers          = 1;
-    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);
-    NetworkChangedKey_IPv6         = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);
-    NetworkChangedKey_Hostnames    = SCDynamicStoreKeyCreateHostNames(NULL);
-    NetworkChangedKey_Computername = SCDynamicStoreKeyCreateComputerName(NULL);
-    NetworkChangedKey_DNS          = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
-    NetworkChangedKey_StateInterfacePrefix = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, CFSTR(""), NULL);
-    if (!NetworkChangedKey_IPv4 || !NetworkChangedKey_IPv6 || !NetworkChangedKey_Hostnames || !NetworkChangedKey_Computername || !NetworkChangedKey_DNS || !NetworkChangedKey_StateInterfacePrefix)
-    { LogMsg("SCDynamicStore string setup failed"); return(mStatus_NoMemoryErr); }
-
-    err = WatchForNetworkChanges(m);
-    if (err) { LogMsg("mDNSPlatformInit_setup: WatchForNetworkChanges failed %d", err); return(err); }
-
-#if 0 // <rdar://problem/6751656>
-    err = WatchForPMChanges(m);
-    if (err) { LogMsg("mDNSPlatformInit_setup: WatchForPMChanges failed %d", err); return(err); }
-#endif
-
-    err = WatchForSysEvents(m);
-    if (err) { LogMsg("mDNSPlatformInit_setup: WatchForSysEvents failed %d", err); return(err); }
-
-    mDNSs32 utc = mDNSPlatformUTC();
-    m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
-    UpdateInterfaceList(m, utc);
-    SetupActiveInterfaces(m, utc);
-
-    // Explicitly ensure that our Keychain operations utilize the system domain.
-#ifndef NO_SECURITYFRAMEWORK
-    SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
-#endif
-
-    mDNS_Lock(m);
-    SetDomainSecrets(m);
-    SetLocalDomains();
-    mDNS_Unlock(m);
-
-#ifndef NO_SECURITYFRAMEWORK
-    err = SecKeychainAddCallback(KeychainChanged, kSecAddEventMask|kSecDeleteEventMask|kSecUpdateEventMask, m);
-    if (err) { LogMsg("mDNSPlatformInit_setup: SecKeychainAddCallback failed %d", err); return(err); }
-#endif
-
-#if !defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements) || TARGET_OS_EMBEDDED
-    LogMsg("Note: Compiled without SnowLeopard Fine-Grained Power Management support");
-#else
-    IOPMConnection c;
-    IOReturn iopmerr = IOPMConnectionCreate(CFSTR("mDNSResponder"), kIOPMSystemPowerStateCapabilityCPU, &c);
-    if (iopmerr) LogMsg("IOPMConnectionCreate failed %d", iopmerr);
-    else
-    {
-        iopmerr = IOPMConnectionSetNotification(c, m, SnowLeopardPowerChanged);
-        if (iopmerr) LogMsg("IOPMConnectionSetNotification failed %d", iopmerr);
-        else
-        {
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-            IOPMConnectionSetDispatchQueue(c, dispatch_get_main_queue());
-            LogInfo("IOPMConnectionSetDispatchQueue is now running");
-#else
-            iopmerr = IOPMConnectionScheduleWithRunLoop(c, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
-            if (iopmerr) LogMsg("IOPMConnectionScheduleWithRunLoop failed %d", iopmerr);
-            LogInfo("IOPMConnectionScheduleWithRunLoop is now running");
-#endif /* MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM */
-        }
-    }
-    m->p->IOPMConnection = iopmerr ? mDNSNULL : c;
-    if (iopmerr) // If IOPMConnectionCreate unavailable or failed, proceed with old-style power notification code below
-#endif // kIOPMAcknowledgmentOptionSystemCapabilityRequirements
-    {
-        m->p->PowerConnection = IORegisterForSystemPower(m, &m->p->PowerPortRef, PowerChanged, &m->p->PowerNotifier);
-        if (!m->p->PowerConnection) { LogMsg("mDNSPlatformInit_setup: IORegisterForSystemPower failed"); return(-1); }
-        else
-        {
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-            IONotificationPortSetDispatchQueue(m->p->PowerPortRef, dispatch_get_main_queue());
-#else
-            CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
-#endif /* MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM */
-        }
-    }
-
-#if APPLE_OSX_mDNSResponder
-    // Note: We use SPMetricPortability > 35 to indicate a laptop of some kind
-    // SPMetricPortability <= 35 means nominally a non-portable machine (i.e. Mac mini or better)
-    // Apple TVs, AirPort base stations, and Time Capsules do not actually weigh 3kg, but we assign them
-    // higher 'nominal' masses to indicate they should be treated as being relatively less portable than a laptop
-    if      (!strncasecmp(HINFO_HWstring, "Xserve",       6)) { SPMetricPortability = 25 /* 30kg */; SPMetricMarginalPower = 84 /* 250W */; SPMetricTotalPower = 85 /* 300W */; }
-    else if (!strncasecmp(HINFO_HWstring, "RackMac",      7)) { SPMetricPortability = 25 /* 30kg */; SPMetricMarginalPower = 84 /* 250W */; SPMetricTotalPower = 85 /* 300W */; }
-    else if (!strncasecmp(HINFO_HWstring, "MacPro",       6)) { SPMetricPortability = 27 /* 20kg */; SPMetricMarginalPower = 84 /* 250W */; SPMetricTotalPower = 85 /* 300W */; }
-    else if (!strncasecmp(HINFO_HWstring, "PowerMac",     8)) { SPMetricPortability = 27 /* 20kg */; SPMetricMarginalPower = 82 /* 160W */; SPMetricTotalPower = 83 /* 200W */; }
-    else if (!strncasecmp(HINFO_HWstring, "iMac",         4)) { SPMetricPortability = 30 /* 10kg */; SPMetricMarginalPower = 77 /*  50W */; SPMetricTotalPower = 78 /*  60W */; }
-    else if (!strncasecmp(HINFO_HWstring, "Macmini",      7)) { SPMetricPortability = 33 /*  5kg */; SPMetricMarginalPower = 73 /*  20W */; SPMetricTotalPower = 74 /*  25W */; }
-    else if (!strncasecmp(HINFO_HWstring, "TimeCapsule", 11)) { SPMetricPortability = 34 /*  4kg */; SPMetricMarginalPower = 10 /*  ~0W */; SPMetricTotalPower = 70 /*  13W */; }
-    else if (!strncasecmp(HINFO_HWstring, "AirPort",      7)) { SPMetricPortability = 35 /*  3kg */; SPMetricMarginalPower = 10 /*  ~0W */; SPMetricTotalPower = 70 /*  12W */; }
-    else if (  IsAppleTV()  )                                 { SPMetricPortability = 35 /*  3kg */; SPMetricMarginalPower = 60 /*   1W */; SPMetricTotalPower = 63 /*   2W */; }
-    else if (!strncasecmp(HINFO_HWstring, "MacBook",      7)) { SPMetricPortability = 37 /*  2kg */; SPMetricMarginalPower = 71 /*  13W */; SPMetricTotalPower = 72 /*  15W */; }
-    else if (!strncasecmp(HINFO_HWstring, "PowerBook",    9)) { SPMetricPortability = 37 /*  2kg */; SPMetricMarginalPower = 71 /*  13W */; SPMetricTotalPower = 72 /*  15W */; }
-    LogSPS("HW_MODEL: %.*s (%s) Portability %d Marginal Power %d Total Power %d Features %d",
-           HINFO_HWstring_prefixlen, HINFO_HWstring, HINFO_HWstring, SPMetricPortability, SPMetricMarginalPower, SPMetricTotalPower, SPMetricFeatures);
-#endif // APPLE_OSX_mDNSResponder
-
-    // Currently this is not defined. SSL code will eventually fix this. If it becomes
-    // critical, we will define this to workaround the bug in SSL.
-#ifdef __SSL_NEEDS_SERIALIZATION__
-    SSLqueue = dispatch_queue_create("com.apple.mDNSResponder.SSLQueue", NULL);
-#else
-    SSLqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
-#endif
-    if (SSLqueue == mDNSNULL) LogMsg("dispatch_queue_create: SSL queue NULL");
-
-    mDNSMacOSXUpdateEtcHosts(m);
-    SetupLocalHostRecords(m);
-    CUPInit(m);
-
-    return(mStatus_NoError);
-}
-
-mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
-{
-#if MDNS_NO_DNSINFO
-    LogMsg("Note: Compiled without Apple-specific Split-DNS support");
-#endif
-
-    // Adding interfaces will use this flag, so set it now.
-    m->DivertMulticastAdvertisements = !m->AdvertiseLocalAddresses;
-
-#if APPLE_OSX_mDNSResponder
-    m->SPSBrowseCallback = UpdateSPSStatus;
-#endif // APPLE_OSX_mDNSResponder
-
-    mStatus result = mDNSPlatformInit_setup(m);
-
-    // We don't do asynchronous initialization on OS X, so by the time we get here the setup will already
-    // have succeeded or failed -- so if it succeeded, we should just call mDNSCoreInitComplete() immediately
-    if (result == mStatus_NoError)
-    {
-        mDNSCoreInitComplete(m, mStatus_NoError);
-
-#if !NO_D2D
-        // We only initialize if mDNSCore successfully initialized.
-        if (D2DInitialize)
-        {
-            D2DStatus ds = D2DInitialize(m->p->CFRunLoop, xD2DServiceCallback, m) ;
-            if (ds != kD2DSuccess)
-                LogMsg("D2DInitialiize failed: %d", ds);
-            else
-                LogMsg("D2DInitialize succeeded");
-        }
-#endif // ! NO_D2D
-
-    }
-    result = DNSSECCryptoInit(m);
-    return(result);
-}
-
-mDNSexport void mDNSPlatformClose(mDNS *const m)
-{
-    if (m->p->PowerConnection)
-    {
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-        IONotificationPortSetDispatchQueue(m->p->PowerPortRef, NULL);
-#else
-        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
-#endif
-        // According to <http://developer.apple.com/qa/qa2004/qa1340.html>, a single call
-        // to IORegisterForSystemPower creates *three* objects that need to be disposed individually:
-        IODeregisterForSystemPower(&m->p->PowerNotifier);
-        IOServiceClose            ( m->p->PowerConnection);
-        IONotificationPortDestroy ( m->p->PowerPortRef);
-        m->p->PowerConnection = 0;
-    }
-
-    if (m->p->Store)
-    {
-#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
-        if (!SCDynamicStoreSetDispatchQueue(m->p->Store, NULL))
-            LogMsg("mDNSPlatformClose: SCDynamicStoreSetDispatchQueue failed");
-#else
-        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode);
-        CFRunLoopSourceInvalidate(m->p->StoreRLS);
-        CFRelease(m->p->StoreRLS);
-        m->p->StoreRLS = NULL;
-#endif
-        CFRelease(m->p->Store);
-        m->p->Store    = NULL;
-    }
-
-    if (m->p->PMRLS)
-    {
-        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->PMRLS, kCFRunLoopDefaultMode);
-        CFRunLoopSourceInvalidate(m->p->PMRLS);
-        CFRelease(m->p->PMRLS);
-        m->p->PMRLS = NULL;
-    }
-
-    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
-
-    mDNSs32 utc = mDNSPlatformUTC();
-    MarkAllInterfacesInactive(m, utc);
-    ClearInactiveInterfaces(m, utc);
-    CloseSocketSet(&m->p->permanentsockets);
-
-#if APPLE_OSX_mDNSResponder
-    // clean up tunnels
-    while (m->TunnelClients)
-    {
-        ClientTunnel *cur = m->TunnelClients;
-        LogInfo("mDNSPlatformClose: removing client tunnel %p %##s from list", cur, cur->dstname.c);
-        if (cur->q.ThisQInterval >= 0) mDNS_StopQuery(m, &cur->q);
-        AutoTunnelSetKeys(cur, mDNSfalse);
-        m->TunnelClients = cur->next;
-        freeL("ClientTunnel", cur);
-    }
-
-    if (AnonymousRacoonConfig)
-    {
-        AnonymousRacoonConfig = mDNSNULL;
-        LogInfo("mDNSPlatformClose: Deconfiguring autotunnel");
-        (void)mDNSConfigureServer(kmDNSDown, mDNSNULL, mDNSNULL);
-    }
-#endif // APPLE_OSX_mDNSResponder
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - General Platform Support Layer functions
-#endif
-
-mDNSexport mDNSu32 mDNSPlatformRandomNumber(void)
-{
-    return(arc4random());
-}
-
-mDNSexport mDNSs32 mDNSPlatformOneSecond = 1000;
-mDNSexport mDNSu32 mDNSPlatformClockDivisor = 0;
-
-mDNSexport mStatus mDNSPlatformTimeInit(void)
-{
-    // Notes: Typical values for mach_timebase_info:
-    // tbi.numer = 1000 million
-    // tbi.denom =   33 million
-    // These are set such that (mach_absolute_time() * numer/denom) gives us nanoseconds;
-    //          numer  / denom = nanoseconds per hardware clock tick (e.g. 30);
-    //          denom  / numer = hardware clock ticks per nanosecond (e.g. 0.033)
-    // (denom*1000000) / numer = hardware clock ticks per millisecond (e.g. 33333)
-    // So: mach_absolute_time() / ((denom*1000000)/numer) = milliseconds
-    //
-    // Arithmetic notes:
-    // tbi.denom is at least 1, and not more than 2^32-1.
-    // Therefore (tbi.denom * 1000000) is at least one million, but cannot overflow a uint64_t.
-    // tbi.denom is at least 1, and not more than 2^32-1.
-    // Therefore clockdivisor should end up being a number roughly in the range 10^3 - 10^9.
-    // If clockdivisor is less than 10^3 then that means that the native clock frequency is less than 1MHz,
-    // which is unlikely on any current or future Macintosh.
-    // If clockdivisor is greater than 10^9 then that means the native clock frequency is greater than 1000GHz.
-    // When we ship Macs with clock frequencies above 1000GHz, we may have to update this code.
-    struct mach_timebase_info tbi;
-    kern_return_t result = mach_timebase_info(&tbi);
-    if (result == KERN_SUCCESS) mDNSPlatformClockDivisor = ((uint64_t)tbi.denom * 1000000) / tbi.numer;
-    return(result);
-}
-
-mDNSexport mDNSs32 mDNSPlatformRawTime(void)
-{
-    if (mDNSPlatformClockDivisor == 0) { LogMsg("mDNSPlatformRawTime called before mDNSPlatformTimeInit"); return(0); }
-
-    static uint64_t last_mach_absolute_time = 0;
-    //static uint64_t last_mach_absolute_time = 0x8000000000000000LL;	// Use this value for testing the alert display
-    uint64_t this_mach_absolute_time = mach_absolute_time();
-    if ((int64_t)this_mach_absolute_time - (int64_t)last_mach_absolute_time < 0)
-    {
-        LogMsg("mDNSPlatformRawTime: last_mach_absolute_time %08X%08X", last_mach_absolute_time);
-        LogMsg("mDNSPlatformRawTime: this_mach_absolute_time %08X%08X", this_mach_absolute_time);
-        // Update last_mach_absolute_time *before* calling NotifyOfElusiveBug()
-        last_mach_absolute_time = this_mach_absolute_time;
-        // Note: This bug happens all the time on 10.3
-        NotifyOfElusiveBug("mach_absolute_time went backwards!",
-                           "This error occurs from time to time, often on newly released hardware, "
-                           "and usually the exact cause is different in each instance.\r\r"
-                           "Please file a new Radar bug report with the title “mach_absolute_time went backwards” "
-                           "and assign it to Radar Component “Kernel” Version “X”.");
-    }
-    last_mach_absolute_time = this_mach_absolute_time;
-
-    return((mDNSs32)(this_mach_absolute_time / mDNSPlatformClockDivisor));
-}
-
-mDNSexport mDNSs32 mDNSPlatformUTC(void)
-{
-    return time(NULL);
-}
-
-// Locking is a no-op here, because we're single-threaded with a CFRunLoop, so we can never interrupt ourselves
-mDNSexport void     mDNSPlatformLock   (const mDNS *const m) { (void)m; }
-mDNSexport void     mDNSPlatformUnlock (const mDNS *const m) { (void)m; }
-mDNSexport void     mDNSPlatformStrCopy(      void *dst, const void *src)              { strcpy((char *)dst, (char *)src); }
-mDNSexport mDNSu32  mDNSPlatformStrLen (                 const void *src)              { return(strlen((char*)src)); }
-mDNSexport void     mDNSPlatformMemCopy(      void *dst, const void *src, mDNSu32 len) { memcpy(dst, src, len); }
-mDNSexport mDNSBool mDNSPlatformMemSame(const void *dst, const void *src, mDNSu32 len) { return(memcmp(dst, src, len) == 0); }
-mDNSexport int      mDNSPlatformMemCmp(const void *dst, const void *src, mDNSu32 len) { return(memcmp(dst, src, len)); }
-mDNSexport void     mDNSPlatformMemZero(      void *dst,                  mDNSu32 len) { memset(dst, 0, len); }
-mDNSexport void     mDNSPlatformQsort  (      void *base, int nel, int width, int (*compar)(const void *, const void *))
-{
-    return (qsort(base, nel, width, compar));
-}
-#if !(APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING)
-mDNSexport void *   mDNSPlatformMemAllocate(mDNSu32 len) { return(mallocL("mDNSPlatformMemAllocate", len)); }
-#endif
-mDNSexport void     mDNSPlatformMemFree    (void *mem)   { freeL("mDNSPlatformMemFree", mem); }
-
-mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason)
-{
-    if (allowSleep && m->p->IOPMAssertion)
-    {
-        LogInfo("%s Destroying NoIdleSleep power assertion", __FUNCTION__);
-        IOPMAssertionRelease(m->p->IOPMAssertion);
-        m->p->IOPMAssertion = 0;
-    }
-    else if (!allowSleep)
-    {
-#ifdef kIOPMAssertionTypeNoIdleSleep
-        if (m->p->IOPMAssertion)
-        {
-            IOPMAssertionRelease(m->p->IOPMAssertion);
-            m->p->IOPMAssertion = 0;
-        }
-
-        CFStringRef assertionName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s.%d %s"), getprogname(), getpid(), reason ? reason : "");
-        IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, assertionName ? assertionName : CFSTR("mDNSResponder"), &m->p->IOPMAssertion);
-        if (assertionName) CFRelease(assertionName);
-        LogInfo("%s Creating NoIdleSleep power assertion", __FUNCTION__);
-#endif
-    }
-}
-
-mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
-{
-    mDNSu32 ifindex;
-
-    // Sanity check
-    ifindex = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNStrue);
-    if (ifindex <= 0)
-    {
-        LogMsg("mDNSPlatformSendWakeupPacket: ERROR!! Invalid InterfaceID %u", ifindex);
-        return;
-    }
-    mDNSSendWakeupPacket(ifindex, EthAddr, IPAddr, iteration);
-}
-
-mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
-{
-    NetworkInterfaceInfoOSX *info;
-
-    if (InterfaceID == mDNSInterface_P2P)
-        return mDNStrue;
-
-    if (   (InterfaceID == mDNSInterface_Any) 
-        || (InterfaceID == mDNSInterfaceMark)
-        || (InterfaceID == mDNSInterface_LocalOnly)
-        || (InterfaceID == mDNSInterface_Unicast))
-        return mDNSfalse;
-
-    info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
-    if (info == NULL)
-    {
-        // this log message can print when operations are stopped on an interface that has gone away
-        LogInfo("mDNSPlatformInterfaceIsD2D: Invalid interface index %d", InterfaceID);
-        return mDNSfalse;
-    }
-
-    return (mDNSBool) info->D2DInterface;
-}
-
-// Filter records send over P2P (D2D) type interfaces
-// Note that the terms P2P and D2D are used synonymously in the current code and comments.
-mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf)
-{
-    // For an explicit match to a valid interface ID, return true. 
-    if (rr->resrec.InterfaceID == intf->InterfaceID)
-        return mDNStrue;
-
-    // Only filtering records for D2D type interfaces, return true for all other interface types.
-    if (!mDNSPlatformInterfaceIsD2D(intf->InterfaceID))
-        return mDNStrue;
-    
-    // If it's an AWDL interface the record must be explicitly marked to include AWDL.
-    if (intf->InterfaceID == AWDLInterfaceID)
-    {
-        if (rr->ARType == AuthRecordAnyIncludeAWDL || rr->ARType == AuthRecordAnyIncludeAWDLandP2P)
-            return mDNStrue;
-        else
-            return mDNSfalse;
-    }
-    
-    // Send record if it is explicitly marked to include all other P2P type interfaces.
-    if (rr->ARType == AuthRecordAnyIncludeP2P || rr->ARType == AuthRecordAnyIncludeAWDLandP2P)
-        return mDNStrue;
-
-    // Don't send the record over this interface.
-    return mDNSfalse;
-}
-
-// Filter questions send over P2P (D2D) type interfaces.
-mDNSexport mDNSBool mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf)
-{
-    // For an explicit match to a valid interface ID, return true. 
-    if (q->InterfaceID == intf->InterfaceID)
-        return mDNStrue;
-
-    // Only filtering questions for D2D type interfaces
-    if (!mDNSPlatformInterfaceIsD2D(intf->InterfaceID))
-        return mDNStrue;
-
-    // If it's an AWDL interface the question must be explicitly marked to include AWDL.
-    if (intf->InterfaceID == AWDLInterfaceID)
-    {
-        if (q->flags & kDNSServiceFlagsIncludeAWDL)
-            return mDNStrue;
-        else
-            return mDNSfalse;
-    }
-    
-    // Sent question if it is explicitly marked to include all other P2P type interfaces.
-    if (q->flags & kDNSServiceFlagsIncludeP2P)
-        return mDNStrue;
-
-    // Don't send the question over this interface.
-    return mDNSfalse;
-}
-
-// Returns true unless record was received over the AWDL interface and
-// the question was not specific to the AWDL interface or did not specify kDNSServiceInterfaceIndexAny
-// with the kDNSServiceFlagsIncludeAWDL flag set.
-mDNSexport mDNSBool   mDNSPlatformValidRecordForQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
-{
-    if (!rr->InterfaceID || (rr->InterfaceID == q->InterfaceID))
-        return mDNStrue;
-
-    if ((rr->InterfaceID == AWDLInterfaceID) && !(q->flags & kDNSServiceFlagsIncludeAWDL))
-    {
-        LogInfo("mDNSPlatformValidRecordForQuestion: Record recieved over AWDL not returned for %s %##s query",
-                DNSTypeName(q->qtype), q->qname.c);
-        return mDNSfalse;
-    }
-
-    return mDNStrue;
-}
-
-// formating time to RFC 4034 format
-mDNSexport void mDNSPlatformFormatTime(unsigned long te, mDNSu8 *buf, int bufsize)
-{
-    struct tm tmTime;
-    time_t t = (time_t)te;
-    // Time since epoch : strftime takes "tm". Convert seconds to "tm" using
-    // gmtime_r first and then use strftime
-    gmtime_r(&t, &tmTime);
-    strftime((char *)buf, bufsize, "%Y%m%d%H%M%S", &tmTime);
-}
-
-mDNSexport mDNSs32 mDNSPlatformGetPID()
-{
-    return getpid();
-}
-
-// Schedule a function asynchronously on the main queue
-mDNSexport void mDNSPlatformDispatchAsync(mDNS *const m, void *context, AsyncDispatchFunc func)
-{
-    // KQueueLock/Unlock is used for two purposes
-    //
-    // 1. We can't be running along with the KQueue thread and hence acquiring the lock
-    //    serializes the access to the "core"
-    //
-    // 2. KQueueUnlock also sends a message wake up the KQueue thread which in turn wakes
-    //    up and calls udsserver_idle which schedules the messages across the uds socket.
-    //    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);
-        func(m, context);
-        KQueueUnlock(m, "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.
-        TriggerEventCompletion();
-#endif
-    });
-}
-
-// definitions for device-info record construction
-#define DEVINFO_MODEL       "model="
-#define DEVINFO_MODEL_LEN   strlen(DEVINFO_MODEL)
-
-#define OSX_VER         "osxvers="
-#define OSX_VER_LEN     strlen(OSX_VER) 
-#define VER_NUM_LEN     2  // 2 digits of version number added to base string
-
-// Bytes available in TXT record for model name after subtracting space for other 
-// fixed size strings and their length bytes.
-#define MAX_MODEL_NAME_LEN   (256 - (DEVINFO_MODEL_LEN + 1) - (OSX_VER_LEN + VER_NUM_LEN + 1))
-
-// Initialize device-info TXT record contents and return total length of record data.
-mDNSexport mDNSu32 initializeDeviceInfoTXT(mDNS *m, mDNSu8 *ptr)
-{
-    mDNSu8 *bufferStart = ptr;
-    mDNSu8 len = m->HIHardware.c[0] < MAX_MODEL_NAME_LEN ? m->HIHardware.c[0] : MAX_MODEL_NAME_LEN;
-
-    *ptr = DEVINFO_MODEL_LEN + len; // total length of DEVINFO_MODEL string plus the hardware name string
-    ptr++;
-    mDNSPlatformMemCopy(ptr, DEVINFO_MODEL, DEVINFO_MODEL_LEN);
-    ptr += DEVINFO_MODEL_LEN;
-    mDNSPlatformMemCopy(ptr, m->HIHardware.c + 1, len);
-    ptr += len;
-
-    // only include this string for OSX
-    if (OSXVers)
-    {
-        char    ver_num[VER_NUM_LEN + 1]; // version digits + null written by snprintf
-        *ptr = OSX_VER_LEN + VER_NUM_LEN; // length byte
-        ptr++;
-        mDNSPlatformMemCopy(ptr, OSX_VER, OSX_VER_LEN);
-        ptr += OSX_VER_LEN;
-        // convert version number to ASCII, add 1 for terminating null byte written by snprintf()
-        snprintf(ver_num, VER_NUM_LEN + 1, "%d", OSXVers);
-        mDNSPlatformMemCopy(ptr, ver_num, VER_NUM_LEN);
-        ptr += VER_NUM_LEN;
-    }
-
-    return (ptr - bufferStart);
-}

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSMacOSX.c (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSMacOSX/mDNSMacOSX.c)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSMacOSX.c	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSMacOSX.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,10443 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2002-2013 Apple Computer, 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.
+ */
+
+// ***************************************************************************
+// mDNSMacOSX.c:
+// Supporting routines to run mDNS on a CFRunLoop platform
+// ***************************************************************************
+
+// For debugging, set LIST_ALL_INTERFACES to 1 to display all found interfaces,
+// including ones that mDNSResponder chooses not to use.
+#define LIST_ALL_INTERFACES 0
+
+#include "mDNSEmbeddedAPI.h"        // Defines the interface provided to the client layer above
+#include "DNSCommon.h"
+#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 "PlatformCommon.h"
+#include "uds_daemon.h"
+#include "CryptoSupport.h"
+
+#include <stdio.h>
+#include <stdarg.h>                 // For va_list support
+#include <stdlib.h>                 // For arc4random
+#include <net/if.h>
+#include <net/if_types.h>           // For IFT_ETHER
+#include <net/if_dl.h>
+#include <net/bpf.h>                // For BIOCSETIF etc.
+#include <sys/uio.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/event.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <time.h>                   // platform support for UTC time
+#include <arpa/inet.h>              // for inet_aton
+#include <pthread.h>
+#include <netdb.h>                  // for getaddrinfo
+#include <sys/sockio.h>             // for SIOCGIFEFLAGS
+#include <notify.h>
+#include <netinet/in.h>             // For IP_RECVTTL
+#ifndef IP_RECVTTL
+#define IP_RECVTTL 24               // bool; receive reception TTL w/dgram
+#endif
+
+#include <netinet/in_systm.h>       // For n_long, required by <netinet/ip.h> below
+#include <netinet/ip.h>             // For IPTOS_LOWDELAY etc.
+#include <netinet6/in6_var.h>       // For IN6_IFF_NOTREADY etc.
+#include <netinet6/nd6.h>           // For ND6_INFINITE_LIFETIME etc.
+
+#include <netinet/tcp.h>
+
+#include <DebugServices.h>
+#include "dnsinfo.h"
+
+#include <ifaddrs.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOMessage.h>
+
+#include <IOKit/ps/IOPowerSources.h>
+#include <IOKit/ps/IOPowerSourcesPrivate.h>
+#include <IOKit/ps/IOPSKeys.h>
+
+#include <mach/mach_error.h>
+#include <mach/mach_port.h>
+#include <mach/mach_time.h>
+#include "helper.h"
+#include "P2PPacketFilter.h"
+
+#include <asl.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+// Include definition of opaque_presence_indication for KEV_DL_NODE_PRESENCE handling logic.
+#include <Kernel/IOKit/apple80211/apple80211_var.h>
+
+#if APPLE_OSX_mDNSResponder
+#include <DeviceToDeviceManager/DeviceToDeviceManager.h>
+#include <AWACS.h>
+#if !NO_D2D
+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));
+
+#endif // ! NO_D2D
+
+#else
+#define NO_D2D 1
+#define NO_AWACS 1
+#endif // APPLE_OSX_mDNSResponder
+
+#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
+#include <IOKit/platform/IOPlatformSupportPrivate.h>
+#endif // APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
+
+
+#define kInterfaceSpecificOption "interface="
+
+#define mDNS_IOREG_KEY               "mDNS_KEY"
+#define mDNS_IOREG_VALUE             "2009-07-30"
+#define mDNS_IOREG_KA_KEY            "mDNS_Keepalive"
+#define mDNS_USER_CLIENT_CREATE_TYPE 'mDNS'
+
+// cache the InterfaceID of the AWDL interface 
+static mDNSInterfaceID AWDLInterfaceID;
+
+// ***************************************************************************
+// Globals
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark - Globals
+#endif
+
+// By default we don't offer sleep proxy service
+// If OfferSleepProxyService is set non-zero (typically via command-line switch),
+// then we'll offer sleep proxy service on desktop Macs that are set to never sleep.
+// We currently do not offer sleep proxy service on laptops, or on machines that are set to go to sleep.
+mDNSexport int OfferSleepProxyService = 0;
+mDNSexport int DisableSleepProxyClient = 0;
+mDNSexport int UseInternalSleepProxy = 1;       // Set to non-zero to use internal (in-NIC) Sleep Proxy
+
+mDNSexport int OSXVers, iOSVers;
+mDNSexport int KQueueFD;
+
+#ifndef NO_SECURITYFRAMEWORK
+static CFArrayRef ServerCerts;
+OSStatus SSLSetAllowAnonymousCiphers(SSLContextRef context, Boolean enable);
+#endif /* NO_SECURITYFRAMEWORK */
+
+static CFStringRef NetworkChangedKey_IPv4;
+static CFStringRef NetworkChangedKey_IPv6;
+static CFStringRef NetworkChangedKey_Hostnames;
+static CFStringRef NetworkChangedKey_Computername;
+static CFStringRef NetworkChangedKey_DNS;
+static CFStringRef NetworkChangedKey_StateInterfacePrefix;
+static CFStringRef NetworkChangedKey_DynamicDNS       = CFSTR("Setup:/Network/DynamicDNS");
+static CFStringRef NetworkChangedKey_BackToMyMac      = CFSTR("Setup:/Network/BackToMyMac");
+static CFStringRef NetworkChangedKey_BTMMConnectivity = CFSTR("State:/Network/Connectivity");
+static CFStringRef NetworkChangedKey_PowerSettings    = CFSTR("State:/IOKit/PowerManagement/CurrentSettings");
+
+static char HINFO_HWstring_buffer[32];
+static char *HINFO_HWstring = "Device";
+static int HINFO_HWstring_prefixlen = 6;
+
+mDNSexport int WatchDogReportingThreshold = 250;
+
+dispatch_queue_t SSLqueue;
+
+//To prevent blocking the main queue, all writes to DynamicStore happen on the DynamicStoreQueue
+static dispatch_queue_t DynamicStoreQueue;
+
+#if TARGET_OS_EMBEDDED
+#define kmDNSResponderManagedPrefsID CFSTR("/Library/Managed Preferences/mobile/com.apple.mDNSResponder.plist")
+#endif
+
+#if APPLE_OSX_mDNSResponder
+static mDNSu8 SPMetricPortability   = 99;
+static mDNSu8 SPMetricMarginalPower = 99;
+static mDNSu8 SPMetricTotalPower    = 99;
+static mDNSu8 SPMetricFeatures      = 1; /* The current version supports TCP Keep Alive Feature */
+mDNSexport domainname ActiveDirectoryPrimaryDomain;
+mDNSexport int ActiveDirectoryPrimaryDomainLabelCount;
+mDNSexport mDNSAddr ActiveDirectoryPrimaryDomainServer;
+#endif // APPLE_OSX_mDNSResponder
+
+// Don't send triggers too often. We arbitrarily limit it to three minutes.
+#define DNS_TRIGGER_INTERVAL (180 * mDNSPlatformOneSecond)
+
+// Used by AutoTunnel
+const char btmmprefix[] = "btmmdns:";
+const char dnsprefix[] = "dns:";
+
+// String Array used to write list of private domains to Dynamic Store
+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, NULL);
+        if (interface->RR_PTR.resrec.RecordType)
+            external_start_advertising_service(&interface->RR_PTR.resrec, NULL);
+    }
+}
+
+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, NULL);
+        if (interface->RR_PTR.resrec.RecordType)
+            external_stop_advertising_service(&interface->RR_PTR.resrec, NULL);
+    }
+}
+
+// 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 mStatus DNSNameCompressionParseBytes(mDNS *const m, const mDNSu8 *const lhs, const mDNSu16 lhs_len, const mDNSu8 *const rhs, const mDNSu16 rhs_len, AuthRecord *rr)
+{
+    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("DNSNameCompressionParseBytes: failed to get large RR"); m->rec.r.resrec.RecordType = 0; return mStatus_UnknownErr; }
+    else LogInfo("DNSNameCompressionParseBytes: got rr: %s", CRDisplayString(m, &m->rec.r));
+
+    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;
+}
+
+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))
+        {
+            mDNS_Deregister(&mDNSStorage, &ptr->ar);
+            LogInfo("xD2DClearCache: Clearing cache record and deregistering %s", ARDisplayString(&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);
+}
+
+mDNSlocal void 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; }
+
+    (*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);
+    }
+}
+
+mDNSlocal mStatus xD2DParse(mDNS *const m, const mDNSu8 * const lhs, const mDNSu16 lhs_len, const mDNSu8 * const rhs, const mDNSu16 rhs_len, AuthRecord *rr)
+{
+    if (*(lhs + (lhs_len - 1)) == compression_packet_v1)
+        return DNSNameCompressionParseBytes(m, lhs, lhs_len, rhs, rhs_len, rr);
+    else
+        return mStatus_Incompatible;
+}
+
+mDNSlocal 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 = mDNSPlatformMemAllocate(sizeof(D2DRecordListElem) + (valueSize < sizeof(RData) ? 0 : valueSize - sizeof(RData)));
+
+        if (ptr == NULL) { LogMsg("xD2DAddToCache: memory allocation failure"); return; }
+
+        err = xD2DParse(m, (const mDNSu8 * const)key, (const mDNSu16)keySize, (const mDNSu8 * const)value, (const mDNSu16)valueSize, &ptr->ar);
+        if (err)
+        {
+            LogMsg("xD2DAddToCache: xD2DParse returned error: %d", err);
+            PrintHelper(__func__, (mDNSu8 *)key, (mDNSu16)keySize, (mDNSu8 *)value, (mDNSu16)valueSize);
+            mDNSPlatformMemFree(ptr);
+            return;
+        }
+        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;
+
+    if ( key == NULL || value == NULL || keySize == 0 || valueSize == 0) { LogMsg("xD2DFindInList: NULL Byte * passed in or length == 0"); return NULL; }
+
+    arptr = mDNSPlatformMemAllocate(sizeof(D2DRecordListElem) + (valueSize < sizeof(RData) ? 0 : valueSize - sizeof(RData)));
+    if (arptr == NULL) { LogMsg("xD2DFindInList: memory allocation failure"); return NULL; }
+
+    if (xD2DParse(m, (const mDNSu8 *const)key, (const mDNSu16)keySize, (const mDNSu8 *const)value, (const mDNSu16)valueSize, &arptr->ar) != mStatus_NoError)
+    {
+        LogMsg("xD2DFindInList: xD2DParse failed for key: %p (%u) value: %p (%u)", key, keySize, value, valueSize);
+        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;
+}
+
+mDNSlocal 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;
+}
+
+mDNSexport void external_start_browsing_for_service(mDNSInterfaceID InterfaceID, const domainname *const typeDomain, DNS_TypeValues qtype, DNSServiceFlags flags)
+{
+    domainname lower;
+
+    if (qtype == kDNSServiceType_A || qtype == kDNSServiceType_AAAA)
+    {
+        LogInfo("external_start_browsing_for_service: ignoring address record");
+        return;
+    }
+
+    DomainnameToLower(typeDomain, &lower);
+
+    if (!D2DBrowseListRefCount(&lower, qtype))
+    {
+        D2DTransportType transportType, excludedTransport;
+
+        LogInfo("external_start_browsing_for_service: Starting browse for: %##s %s", 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)
+{
+    domainname lower;
+
+    if (qtype == kDNSServiceType_A || qtype == kDNSServiceType_AAAA)
+    {
+        LogInfo("external_stop_browsing_for_service: ignoring address record");
+        return;
+    }
+
+    DomainnameToLower(typeDomain, &lower);
+
+    D2DBrowseListRelease(&lower, qtype);
+    if (!D2DBrowseListRefCount(&lower, qtype))
+    {
+        D2DTransportType transportType, excludedTransport;
+
+        LogInfo("external_stop_browsing_for_service: Stopping browse for: %##s %s", 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)
+{
+    domainname lower;
+    mDNSu8 *rhs = NULL;
+    mDNSu8 *end = NULL;
+    D2DTransportType transportType, excludedTransport;
+    DomainnameToLower(resourceRecord->name, &lower);
+
+    LogInfo("external_start_advertising_service: %s", 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)
+{
+    domainname lower;
+    mDNSu8 *rhs = NULL;
+    mDNSu8 *end = NULL;
+    D2DTransportType transportType, excludedTransport;
+    DomainnameToLower(resourceRecord->name, &lower);
+
+    LogInfo("external_stop_advertising_service: %s", RRDisplayString(&mDNSStorage, resourceRecord));
+
+    // 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, NULL);
+        external_start_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_SRV, NULL);
+    }
+}
+
+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, NULL);
+        external_stop_browsing_for_service(AWDLInterfaceID, fqdn, kDNSType_SRV, NULL);
+    }
+}
+
+#elif APPLE_OSX_mDNSResponder
+
+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;}
+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
+#pragma mark -
+#pragma mark - Utility Functions
+#endif
+
+// We only attempt to send and receive multicast packets on interfaces that are
+// (a) flagged as multicast-capable
+// (b) *not* flagged as point-to-point (e.g. modem)
+// Typically point-to-point interfaces are modems (including mobile-phone pseudo-modems), and we don't want
+// to run up the user's bill sending multicast traffic over a link where there's only a single device at the
+// other end, and that device (e.g. a modem bank) is probably not answering Multicast DNS queries anyway.
+#define MulticastInterface(i) (((i)->ifa_flags & IFF_MULTICAST) && !((i)->ifa_flags & IFF_POINTOPOINT))
+
+mDNSexport void NotifyOfElusiveBug(const char *title, const char *msg)  // Both strings are UTF-8 text
+{
+    static int notifyCount = 0;
+    if (notifyCount) return;
+
+    // If we display our alert early in the boot process, then it vanishes once the desktop appears.
+    // To avoid this, we don't try to display alerts in the first three minutes after boot.
+    if ((mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return;
+
+    // Unless ForceAlerts is defined, we only show these bug report alerts on machines that have a 17.x.x.x address
+    #if !ForceAlerts
+    {
+        // Determine if we're at Apple (17.*.*.*)
+        NetworkInterfaceInfoOSX *i;
+        for (i = mDNSStorage.p->InterfaceList; i; i = i->next)
+            if (i->ifinfo.ip.type == mDNSAddrType_IPv4 && i->ifinfo.ip.ip.v4.b[0] == 17)
+                break;
+        if (!i) return; // If not at Apple, don't show the alert
+    }
+    #endif
+
+    LogMsg("%s", title);
+    LogMsg("%s", msg);
+    // Display a notification to the user
+    notifyCount++;
+
+#ifndef NO_CFUSERNOTIFICATION
+    mDNSNotify(title, msg);
+#endif /* NO_CFUSERNOTIFICATION */
+}
+
+// Returns true if it is an AppleTV based hardware running iOS, false otherwise
+mDNSlocal mDNSBool IsAppleTV(void)
+{
+#if TARGET_OS_EMBEDDED
+    static mDNSBool sInitialized = mDNSfalse;
+    static mDNSBool sIsAppleTV   = mDNSfalse;
+    CFStringRef deviceClass = NULL;
+
+    if(!sInitialized)
+    {
+        deviceClass = (CFStringRef) MGCopyAnswer(kMGQDeviceClass, NULL);
+        if(deviceClass)
+        {
+            if(CFEqual(deviceClass, kMGDeviceClassAppleTV))
+                sIsAppleTV = mDNStrue;
+            CFRelease(deviceClass);
+        }
+        sInitialized = mDNStrue;
+    }
+    return(sIsAppleTV);
+#else 
+    return mDNSfalse;
+#endif // TARGET_OS_EMBEDDED
+}
+
+mDNSlocal struct ifaddrs *myGetIfAddrs(int refresh)
+{
+    static struct ifaddrs *ifa = NULL;
+
+    if (refresh && ifa)
+    {
+        freeifaddrs(ifa);
+        ifa = NULL;
+    }
+
+    if (ifa == NULL) 
+        getifaddrs(&ifa);
+    return ifa;
+}
+
+mDNSlocal void DynamicStoreWrite(int key, const char* subkey, uintptr_t value, signed long valueCnt)
+{
+    CFStringRef sckey       = NULL;
+    Boolean release_sckey   = FALSE;
+    CFDataRef bytes         = NULL;
+    CFPropertyListRef plist = NULL;
+    SCDynamicStoreRef store = NULL;
+
+    switch ((enum mDNSDynamicStoreSetConfigKey)key)
+    {
+        case kmDNSMulticastConfig:
+            sckey = CFSTR("State:/Network/" kDNSServiceCompMulticastDNS);
+            break;
+        case kmDNSDynamicConfig:
+            sckey = CFSTR("State:/Network/DynamicDNS");
+            break;
+        case kmDNSPrivateConfig:
+            sckey = CFSTR("State:/Network/" kDNSServiceCompPrivateDNS);
+            break;
+        case kmDNSBackToMyMacConfig:
+            sckey = CFSTR("State:/Network/BackToMyMac");
+            break;
+        case kmDNSSleepProxyServersState:
+        {
+            CFMutableStringRef tmp = CFStringCreateMutable(kCFAllocatorDefault, 0);
+            CFStringAppend(tmp, CFSTR("State:/Network/Interface/"));
+            CFStringAppendCString(tmp, subkey, kCFStringEncodingUTF8);
+            CFStringAppend(tmp, CFSTR("/SleepProxyServers"));
+            sckey = CFStringCreateCopy(kCFAllocatorDefault, tmp);
+            release_sckey = TRUE;
+            CFRelease(tmp);
+            break;
+        }
+        case kmDNSDebugState:
+            sckey = CFSTR("State:/Network/mDNSResponder/DebugState");
+            break;
+        default:
+            LogMsg("unrecognized key %d", key);
+            goto fin;
+    }
+    if (NULL == (bytes = CFDataCreateWithBytesNoCopy(NULL, (void *)value,
+                                                     valueCnt, kCFAllocatorNull)))
+    {
+        LogMsg("CFDataCreateWithBytesNoCopy of value failed");
+        goto fin;
+    }
+    if (NULL == (plist = CFPropertyListCreateFromXMLData(NULL, bytes,
+                                                         kCFPropertyListImmutable, NULL)))
+    {
+        LogMsg("CFPropertyListCreateFromXMLData of bytes failed");
+        goto fin;
+    }
+    CFRelease(bytes);
+    bytes = NULL;
+    if (NULL == (store = SCDynamicStoreCreate(NULL,
+                                              CFSTR(kmDNSResponderServName), NULL, NULL)))
+    {
+        LogMsg("SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
+        goto fin;
+    }
+    SCDynamicStoreSetValue(store, sckey, plist);
+
+fin:
+    if (NULL != bytes)
+        CFRelease(bytes);
+    if (NULL != plist)
+        CFRelease(plist);
+    if (NULL != store)
+        CFRelease(store);
+    if (release_sckey && sckey)
+        CFRelease(sckey);
+}
+
+mDNSexport void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropertyListRef value)
+{
+    CFPropertyListRef valueCopy;
+    char *subkeyCopy  = NULL;
+    if (!value)
+        return;
+
+    // We need to copy the key and value before we dispatch off the block below as the
+    // caller will free the memory once we return from this function.
+    valueCopy = CFPropertyListCreateDeepCopy(NULL, value, kCFPropertyListImmutable);
+    if (!valueCopy)
+    {   
+        LogMsg("mDNSDynamicStoreSetConfig: ERROR valueCopy NULL");
+        return;
+    }
+    if (subkey)
+    {
+        int len    = strlen(subkey);
+        subkeyCopy = mDNSPlatformMemAllocate(len + 1);
+        if (!subkeyCopy)
+        {
+            LogMsg("mDNSDynamicStoreSetConfig: ERROR subkeyCopy NULL");
+            return;
+        }
+        mDNSPlatformMemCopy(subkeyCopy, subkey, len);
+        subkeyCopy[len] = 0;
+    }
+
+    dispatch_async(DynamicStoreQueue, ^{
+        CFWriteStreamRef stream = NULL;
+        CFDataRef bytes = NULL;
+        CFStringRef error;
+        CFIndex ret;
+
+        if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(NULL, NULL)))
+        {
+            LogMsg("mDNSDynamicStoreSetConfig : CFWriteStreamCreateWithAllocatedBuffers failed (Object creation failed)");
+            goto END;
+        }
+        CFWriteStreamOpen(stream);
+        ret = CFPropertyListWriteToStream(valueCopy, stream, kCFPropertyListBinaryFormat_v1_0, &error);
+        if (ret == 0)
+        {
+            LogMsg("mDNSDynamicStoreSetConfig : CFPropertyListWriteToStream failed (Could not write property list to stream)");
+            goto END;
+        }
+        if (NULL == (bytes = CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten)))
+        {
+            LogMsg("mDNSDynamicStoreSetConfig : CFWriteStreamCopyProperty failed (Object creation failed) ");
+            goto END;
+        }
+        CFWriteStreamClose(stream);
+        CFRelease(stream);
+        stream = NULL;
+        LogInfo("mDNSDynamicStoreSetConfig: key %d subkey %s", key, subkeyCopy);
+        DynamicStoreWrite(key, subkeyCopy ? subkeyCopy : "", (uintptr_t)CFDataGetBytePtr(bytes), CFDataGetLength(bytes));
+
+    END:
+        CFRelease(valueCopy);
+        if (NULL != stream)
+        {
+            CFWriteStreamClose(stream);
+            CFRelease(stream);
+        }
+        if (NULL != bytes)
+            CFRelease(bytes); 
+        if (subkeyCopy)
+            mDNSPlatformMemFree(subkeyCopy);
+    });
+}
+
+// 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)
+{
+    NetworkInterfaceInfoOSX *i;
+    for (i = m->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) ||
+             (type == AF_INET6 && i->ifinfo.ip.type == mDNSAddrType_IPv6))) return(i);
+    return(NULL);
+}
+
+#if TARGET_OS_EMBEDDED
+mDNSlocal SCPreferencesRef mDNSManagedPrefsGet(void)
+{
+    SCPreferencesRef smDNSManagedPrefs = NULL;
+    smDNSManagedPrefs = SCPreferencesCreate(kCFAllocatorDefault, CFSTR("mDNSManagedPrefs"), kmDNSResponderManagedPrefsID);
+
+    return (smDNSManagedPrefs);
+}
+
+mDNSlocal mDNSBool GetmDNSManagedPrefKeyVal(SCPreferencesRef prefs, CFStringRef key)
+{
+    mDNSBool val = mDNSfalse;
+    CFBooleanRef val_cf = NULL;
+ 
+    if (prefs != NULL)
+    {
+        val_cf = SCPreferencesGetValue(prefs, key);
+        if (isA_CFBoolean(val_cf) != NULL)
+            val = CFBooleanGetValue(val_cf); //When mDNSResponder-Debug-profile is Installed
+        else
+            val = mDNSfalse; //When mDNSResponder-Debug-profile is Uninstalled
+    }
+    else 
+    {
+        LogMsg("GetmDNSManagedPrefKeyVal: mDNSManagedPrefs are NULL!");
+        val = mDNSfalse;
+    }
+    if (val_cf)
+        CFRelease(val_cf);
+    return (val);
+}
+
+mDNSexport mDNSBool GetmDNSManagedPref(CFStringRef key)
+{
+    SCPreferencesRef  managed = NULL;
+    mDNSBool ret_value;
+     
+    managed = mDNSManagedPrefsGet();
+    ret_value = GetmDNSManagedPrefKeyVal(managed, key);
+    
+    if (managed)
+        CFRelease(managed);
+    return (ret_value);
+}
+#endif //TARGET_OS_EMBEDDED
+
+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 (((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)
+{
+    mDNSu32 scope_id = (mDNSu32)(uintptr_t)ifindex;
+    NetworkInterfaceInfoOSX *i;
+
+    // Don't get tricked by inactive interfaces
+    for (i = m->p->InterfaceList; i; i = i->next)
+        if (i->Registered && i->scope_id == scope_id) return(i);
+
+    return mDNSNULL;
+}
+
+mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex)
+{
+    if (ifindex == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
+    if (ifindex == kDNSServiceInterfaceIndexP2P      ) return(mDNSInterface_P2P);
+    if (ifindex == kDNSServiceInterfaceIndexAny      ) return(mDNSNULL);
+
+    NetworkInterfaceInfoOSX* ifi = IfindexToInterfaceInfoOSX(m, (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);
+    }
+
+    if (!ifi) return(mDNSNULL);
+
+    return(ifi->ifinfo.InterfaceID);
+}
+
+
+mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange)
+{
+    NetworkInterfaceInfoOSX *i;
+    if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
+    if (id == mDNSInterface_P2P      ) return(kDNSServiceInterfaceIndexP2P);
+    if (id == mDNSInterface_Any      ) return(0);
+
+    mDNSu32 scope_id = (mDNSu32)(uintptr_t)id;
+
+    // Don't use i->Registered here, because we DO want to find inactive interfaces, which have no Registered set
+    for (i = m->p->InterfaceList; i; i = i->next)
+        if (i->scope_id == scope_id) return(i->scope_id);
+
+    // If we are supposed to suppress network change, return "id" back
+    if (suppressNetworkChange) return scope_id;
+
+    // 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);
+    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
+#endif
+
+mDNSlocal mDNSBool AddrRequiresPPPConnection(const struct sockaddr *addr)
+{
+    mDNSBool result = mDNSfalse;
+    SCNetworkConnectionFlags flags;
+    CFDataRef remote_addr;
+    CFMutableDictionaryRef options;
+    SCNetworkReachabilityRef ReachRef = NULL;
+
+    options = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+    remote_addr = CFDataCreate(NULL, (const UInt8 *)addr, addr->sa_len);
+    CFDictionarySetValue(options, kSCNetworkReachabilityOptionRemoteAddress, remote_addr);
+    CFDictionarySetValue(options, kSCNetworkReachabilityOptionServerBypass, kCFBooleanTrue);
+    ReachRef = SCNetworkReachabilityCreateWithOptions(kCFAllocatorDefault, options);
+    CFRelease(options);
+    CFRelease(remote_addr);
+
+    if (!ReachRef) 
+    { 
+        LogMsg("ERROR: RequiresConnection - SCNetworkReachabilityCreateWithOptions"); 
+        goto end; 
+    }
+    if (!SCNetworkReachabilityGetFlags(ReachRef, &flags)) 
+    { 
+        LogMsg("ERROR: AddrRequiresPPPConnection - SCNetworkReachabilityGetFlags"); 
+        goto end; 
+    }
+    result = flags & kSCNetworkFlagsConnectionRequired;
+
+end:
+    if (ReachRef) 
+        CFRelease(ReachRef);
+    return result;
+}
+
+// Set traffic class for socket
+mDNSlocal void setTrafficClass(int socketfd, mDNSBool useBackgroundTrafficClass)
+{
+    int traffic_class;
+
+    if (useBackgroundTrafficClass)
+        traffic_class = SO_TC_BK_SYS;
+    else
+        traffic_class = SO_TC_CTL;
+
+    (void) setsockopt(socketfd, SOL_SOCKET, SO_TRAFFIC_CLASS, (void *)&traffic_class, sizeof(traffic_class));
+}
+
+mDNSexport void mDNSPlatformSetDelegatePID(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q)
+{
+    if (src)
+    {
+        int s;
+
+        if (dst->type == mDNSAddrType_IPv4)
+        {
+            s = src->ss.sktv4;
+        }
+        else
+        {
+            s = src->ss.sktv6;
+        }
+
+        if (q->pid)
+        {
+            if (setsockopt(s, SOL_SOCKET, SO_DELEGATED, &q->pid, sizeof(q->pid)) == -1)
+            {
+                LogInfo("mDNSPlatformSetDelegatePID: Delegate PID failed %s for PID %d", strerror(errno), q->pid);
+            }
+        }
+        else
+        {
+            if (setsockopt(s, SOL_SOCKET, SO_DELEGATED_UUID, &q->uuid, sizeof(q->uuid)) == -1)
+            {
+                LogInfo("mDNSPlatformSetDelegatePID: Delegate UUID failed %s", strerror(errno));
+            }
+        }
+    }
+}
+
+// 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"
+// OR send via our primary v4 unicast socket
+// UPDATE: The UDPSocket *src parameter now allows the caller to specify the source socket
+mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
+                                       mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, 
+                                       mDNSIPPort dstPort, mDNSBool useBackgroundTrafficClass)
+{
+    NetworkInterfaceInfoOSX *info = mDNSNULL;
+    struct sockaddr_storage to;
+    int s = -1, err;
+    mStatus result = mStatus_NoError;
+
+    if (InterfaceID)
+    {
+        info = IfindexToInterfaceInfoOSX(m, InterfaceID);
+        if (info == NULL)
+        {
+            // We may not have registered interfaces with the "core" as we may not have
+            // seen any interface notifications yet. This typically happens during wakeup
+            // where we might try to send DNS requests (non-SuppressUnusable questions internal
+            // to mDNSResponder) before we receive network notifications.
+            LogInfo("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
+            return mStatus_BadParamErr;
+        }
+    }
+
+    char *ifa_name = InterfaceID ? info->ifinfo.ifname : "unicast";
+
+    if (dst->type == mDNSAddrType_IPv4)
+    {
+        struct sockaddr_in *sin_to = (struct sockaddr_in*)&to;
+        sin_to->sin_len            = sizeof(*sin_to);
+        sin_to->sin_family         = AF_INET;
+        sin_to->sin_port           = dstPort.NotAnInteger;
+        sin_to->sin_addr.s_addr    = dst->ip.v4.NotAnInteger;
+        s = (src ? src->ss : m->p->permanentsockets).sktv4;
+
+        if (info)   // Specify outgoing interface
+        {
+            if (!mDNSAddrIsDNSMulticast(dst))
+            {
+                #ifdef IP_BOUND_IF
+                if (info->scope_id == 0)
+                    LogInfo("IP_BOUND_IF socket option not set -- info %p (%s) scope_id is zero", info, ifa_name);
+                else
+                    setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
+                #else
+                {
+                    static int displayed = 0;
+                    if (displayed < 1000)
+                    {
+                        displayed++;
+                        LogInfo("IP_BOUND_IF socket option not defined -- cannot specify interface for unicast packets");
+                    }
+                }
+                #endif
+            }
+            else
+                #ifdef IP_MULTICAST_IFINDEX
+            {
+                err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IFINDEX, &info->scope_id, sizeof(info->scope_id));
+                // We get an error when we compile on a machine that supports this option and run the binary on
+                // a different machine that does not support it
+                if (err < 0)
+                {
+                    if (errno != ENOPROTOOPT) LogInfo("mDNSPlatformSendUDP: setsockopt: IP_MUTLTICAST_IFINDEX returned %d", errno);
+                    err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &info->ifa_v4addr, sizeof(info->ifa_v4addr));
+                    if (err < 0 && !m->p->NetworkChanged)
+                        LogMsg("setsockopt - IP_MULTICAST_IF error %.4a %d errno %d (%s)", &info->ifa_v4addr, err, errno, strerror(errno));
+                }
+            }
+                #else
+            {
+                err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &info->ifa_v4addr, sizeof(info->ifa_v4addr));
+                if (err < 0 && !m->p->NetworkChanged)
+                    LogMsg("setsockopt - IP_MULTICAST_IF error %.4a %d errno %d (%s)", &info->ifa_v4addr, err, errno, strerror(errno));
+
+            }
+                #endif
+        }
+    }
+
+    else if (dst->type == mDNSAddrType_IPv6)
+    {
+        struct sockaddr_in6 *sin6_to = (struct sockaddr_in6*)&to;
+        sin6_to->sin6_len            = sizeof(*sin6_to);
+        sin6_to->sin6_family         = AF_INET6;
+        sin6_to->sin6_port           = dstPort.NotAnInteger;
+        sin6_to->sin6_flowinfo       = 0;
+        sin6_to->sin6_addr           = *(struct in6_addr*)&dst->ip.v6;
+        sin6_to->sin6_scope_id       = info ? info->scope_id : 0;
+        s = (src ? src->ss : m->p->permanentsockets).sktv6;
+        if (info && mDNSAddrIsDNSMulticast(dst))    // Specify outgoing interface
+        {
+            err = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &info->scope_id, sizeof(info->scope_id));
+            if (err < 0)
+            {
+                char name[IFNAMSIZ];
+                if (if_indextoname(info->scope_id, name) != NULL)
+                    LogMsg("setsockopt - IPV6_MULTICAST_IF error %d errno %d (%s)", err, errno, strerror(errno));
+                else
+                    LogInfo("setsockopt - IPV6_MUTLICAST_IF scopeid %d, not a valid interface", info->scope_id);
+            }
+        }
+    }
+
+    else
+    {
+        LogMsg("mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!");
+#if ForceAlerts
+        *(long*)0 = 0;
+#endif
+        return mStatus_BadParamErr;
+    }
+
+    if (s >= 0)
+        verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %p %5s/%ld to %#a:%d skt %d",
+                      InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s);
+    else
+        verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %p %5s/%ld (socket of this type not available)",
+                      InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort));
+
+    // Note: When sending, mDNSCore may often ask us to send both a v4 multicast packet and then a v6 multicast packet
+    // If we don't have the corresponding type of socket available, then return mStatus_Invalid
+    if (s < 0) return(mStatus_Invalid);
+
+    // switch to background traffic class for this message if requested
+    if (useBackgroundTrafficClass)
+        setTrafficClass(s, useBackgroundTrafficClass);
+
+    err = sendto(s, msg, (UInt8*)end - (UInt8*)msg, 0, (struct sockaddr *)&to, to.ss_len);
+
+    // set traffic class back to default value
+    if (useBackgroundTrafficClass)
+        setTrafficClass(s, mDNSfalse);
+
+    if (err < 0)
+    {
+        static int MessageCount = 0;
+        LogInfo("mDNSPlatformSendUDP -> sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu",
+                s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow));
+        if (!mDNSAddressIsAllDNSLinkGroup(dst))
+            if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
+        // Don't report EHOSTUNREACH in the first three minutes after boot
+        // This is because mDNSResponder intentionally starts up early in the boot process (See <rdar://problem/3409090>)
+        // but this means that sometimes it starts before configd has finished setting up the multicast routing entries.
+        if (errno == EHOSTUNREACH && (mDNSu32)(mDNSPlatformRawTime()) < (mDNSu32)(mDNSPlatformOneSecond * 180)) return(mStatus_TransientErr);
+        // Don't report EADDRNOTAVAIL ("Can't assign requested address") if we're in the middle of a network configuration change
+        if (errno == EADDRNOTAVAIL && m->p->NetworkChanged) return(mStatus_TransientErr);
+        if (errno == EHOSTUNREACH || errno == EADDRNOTAVAIL || errno == ENETDOWN)
+            LogInfo("mDNSPlatformSendUDP sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu",
+                    s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow));
+        else
+        {
+            MessageCount++;
+            if (MessageCount < 50)  // Cap and ensure NO spamming of LogMsgs
+                LogMsg("mDNSPlatformSendUDP: sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu MessageCount is %d",
+                       s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow), MessageCount);
+            else  // If logging is enabled, remove the cap and log aggressively
+                LogInfo("mDNSPlatformSendUDP: sendto(%d) failed to send packet on InterfaceID %p %5s/%d to %#a:%d skt %d error %d errno %d (%s) %lu MessageCount is %d",
+                        s, InterfaceID, ifa_name, dst->type, dst, mDNSVal16(dstPort), s, err, errno, strerror(errno), (mDNSu32)(m->timenow), MessageCount);
+        }
+
+        result = mStatus_UnknownErr;
+    }
+
+#ifdef IP_BOUND_IF
+    if (dst->type == mDNSAddrType_IPv4 && info && !mDNSAddrIsDNSMulticast(dst))
+    {
+        static const mDNSu32 ifindex = 0;
+        setsockopt(s, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex));
+    }
+#endif
+
+    return(result);
+}
+
+mDNSexport 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[IF_NAMESIZE], mDNSu8 *ttl)
+{
+    static unsigned int numLogMessages = 0;
+    struct iovec databuffers = { (char *)buffer, max };
+    struct msghdr msg;
+    ssize_t n;
+    struct cmsghdr *cmPtr;
+    char ancillary[1024];
+
+    *ttl = 255;  // If kernel fails to provide TTL data (e.g. Jaguar doesn't) then assume the TTL was 255 as it should be
+
+    // Set up the message
+    msg.msg_name       = (caddr_t)from;
+    msg.msg_namelen    = *fromlen;
+    msg.msg_iov        = &databuffers;
+    msg.msg_iovlen     = 1;
+    msg.msg_control    = (caddr_t)&ancillary;
+    msg.msg_controllen = sizeof(ancillary);
+    msg.msg_flags      = 0;
+
+    // Receive the data
+    n = recvmsg(s, &msg, 0);
+    if (n<0)
+    {
+        if (errno != EWOULDBLOCK && numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned error %d errno %d", s, n, errno);
+        return(-1);
+    }
+    if (msg.msg_controllen < (int)sizeof(struct cmsghdr))
+    {
+        if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) returned %d msg.msg_controllen %d < sizeof(struct cmsghdr) %lu, errno %d",
+                                           s, n, msg.msg_controllen, sizeof(struct cmsghdr), errno);
+        return(-1);
+    }
+    if (msg.msg_flags & MSG_CTRUNC)
+    {
+        if (numLogMessages++ < 100) LogMsg("mDNSMacOSX.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s);
+        return(-1);
+    }
+
+    *fromlen = msg.msg_namelen;
+
+    // Parse each option out of the ancillary data.
+    for (cmPtr = CMSG_FIRSTHDR(&msg); cmPtr; cmPtr = CMSG_NXTHDR(&msg, cmPtr))
+    {
+        // debugf("myrecvfrom cmsg_level %d cmsg_type %d", cmPtr->cmsg_level, cmPtr->cmsg_type);
+        if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVDSTADDR)
+        {
+            dstaddr->type = mDNSAddrType_IPv4;
+            dstaddr->ip.v4 = *(mDNSv4Addr*)CMSG_DATA(cmPtr);
+            //LogMsg("mDNSMacOSX.c: recvmsg IP_RECVDSTADDR %.4a", &dstaddr->ip.v4);
+        }
+        if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVIF)
+        {
+            struct sockaddr_dl *sdl = (struct sockaddr_dl *)CMSG_DATA(cmPtr);
+            if (sdl->sdl_nlen < IF_NAMESIZE)
+            {
+                mDNSPlatformMemCopy(ifname, sdl->sdl_data, sdl->sdl_nlen);
+                ifname[sdl->sdl_nlen] = 0;
+                // debugf("IP_RECVIF sdl_index %d, sdl_data %s len %d", sdl->sdl_index, ifname, sdl->sdl_nlen);
+            }
+        }
+        if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVTTL)
+            *ttl = *(u_char*)CMSG_DATA(cmPtr);
+        if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_PKTINFO)
+        {
+            struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmPtr);
+            dstaddr->type = mDNSAddrType_IPv6;
+            dstaddr->ip.v6 = *(mDNSv6Addr*)&ip6_info->ipi6_addr;
+            myIfIndexToName(ip6_info->ipi6_ifindex, ifname);
+        }
+        if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_HOPLIMIT)
+            *ttl = *(int*)CMSG_DATA(cmPtr);
+    }
+
+    return(n);
+}
+
+mDNSlocal mDNSInterfaceID FindMyInterface(mDNS *const m, const mDNSAddr *addr)
+{
+    NetworkInterfaceInfo *intf;
+
+    if (addr->type == mDNSAddrType_IPv4)
+    {
+        for (intf = m->HostInterfaces; intf; intf = intf->next)
+        {
+            if (intf->ip.type == addr->type && intf->McastTxRx)
+            {
+                if ((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) == 0)
+                {
+                    return(intf->InterfaceID);
+                }
+            }
+        }
+    }
+
+    if (addr->type == mDNSAddrType_IPv6)
+    {
+        for (intf = m->HostInterfaces; intf; intf = intf->next)
+        {
+            if (intf->ip.type == addr->type && intf->McastTxRx)
+            {
+                if (((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) == 0) &&
+                    ((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) == 0) &&
+                    ((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) == 0) &&
+                    (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) == 0)))
+                    {
+                        return(intf->InterfaceID);
+                    }
+            }
+        }
+    }
+    return(mDNSInterface_Any);
+}
+
+mDNSexport mDNSBool mDNSPlatformPeekUDP(mDNS *const m, UDPSocket *src)
+{
+    // We should have a DNSMessage header followed by the question and an answer
+    // which also includes a CNAME (that's when this function is called).  To keep it
+    // simple, we expect at least the size of DNSMessage header(12) and size of "A"
+    // record (14 bytes).
+    char buffer[26];
+    int ret;
+
+    (void) m;
+
+    if (!src)
+        return mDNSfalse;
+
+    ret = recv(src->ss.sktv4, buffer, sizeof(buffer), MSG_PEEK);
+    if (ret > 0)
+        return mDNStrue;
+    else
+        return mDNSfalse;
+}
+
+mDNSexport void myKQSocketCallBack(int s1, short filter, void *context)
+{
+    KQSocketSet *const ss = (KQSocketSet *)context;
+    mDNS *const m = ss->m;
+    int err = 0, count = 0, closed = 0;
+
+    if (filter != EVFILT_READ)
+        LogMsg("myKQSocketCallBack: Why is filter %d not EVFILT_READ (%d)?", filter, EVFILT_READ);
+
+    if (s1 != ss->sktv4 && s1 != ss->sktv6)
+    {
+        LogMsg("myKQSocketCallBack: native socket %d", s1);
+        LogMsg("myKQSocketCallBack: sktv4 %d sktv6 %d", ss->sktv4, ss->sktv6);
+    }
+
+    while (!closed)
+    {
+        mDNSAddr senderAddr, destAddr;
+        mDNSIPPort senderPort;
+        struct sockaddr_storage from;
+        size_t fromlen = sizeof(from);
+        char packetifname[IF_NAMESIZE] = "";
+        mDNSu8 ttl;
+        err = myrecvfrom(s1, &m->imsg, sizeof(m->imsg), (struct sockaddr *)&from, &fromlen, &destAddr, packetifname, &ttl);
+        if (err < 0) break;
+
+        count++;
+        if (from.ss_family == AF_INET)
+        {
+            struct sockaddr_in *s = (struct sockaddr_in*)&from;
+            senderAddr.type = mDNSAddrType_IPv4;
+            senderAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
+            senderPort.NotAnInteger = s->sin_port;
+            //LogInfo("myKQSocketCallBack received IPv4 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
+        }
+        else if (from.ss_family == AF_INET6)
+        {
+            struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&from;
+            senderAddr.type = mDNSAddrType_IPv6;
+            senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr;
+            senderPort.NotAnInteger = sin6->sin6_port;
+            //LogInfo("myKQSocketCallBack received IPv6 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
+        }
+        else
+        {
+            LogMsg("myKQSocketCallBack from is unknown address family %d", from.ss_family);
+            return;
+        }
+
+        // Note: When handling multiple packets in a batch, MUST reset InterfaceID before handling each packet
+        mDNSInterfaceID InterfaceID = mDNSNULL;
+        NetworkInterfaceInfoOSX *intf = m->p->InterfaceList;
+        while (intf) 
+        {
+            if (intf->Exists && !strcmp(intf->ifinfo.ifname, packetifname))
+                break;
+            intf = intf->next;
+        }
+
+        // When going to sleep we deregister all our interfaces, but if the machine
+        // takes a few seconds to sleep we may continue to receive multicasts
+        // during that time, which would confuse mDNSCoreReceive, because as far
+        // as it's concerned, we should have no active interfaces any more.
+        // Hence we ignore multicasts for which we can find no matching InterfaceID.
+        if (intf)
+            InterfaceID = intf->ifinfo.InterfaceID;
+        else if (mDNSAddrIsDNSMulticast(&destAddr))
+            continue;
+
+        if (!InterfaceID)
+        {
+            InterfaceID = FindMyInterface(m, &destAddr);
+        }
+
+//		LogMsg("myKQSocketCallBack got packet from %#a to %#a on interface %#a/%s",
+//			&senderAddr, &destAddr, &ss->info->ifinfo.ip, ss->info->ifinfo.ifname);
+
+        // mDNSCoreReceive may close the socket we're reading from.  We must break out of our
+        // loop when that happens, or we may try to read from an invalid FD.  We do this by
+        // setting the closeFlag pointer in the socketset, so CloseSocketSet can inform us
+        // if it closes the socketset.
+        ss->closeFlag = &closed;
+
+        if (ss->proxy)
+        {
+            m->p->UDPProxyCallback(m, &m->p->UDPProxy, (unsigned char *)&m->imsg, (unsigned char*)&m->imsg + err, &senderAddr,
+                senderPort, &destAddr, ss->port, InterfaceID, NULL);
+        }
+        else
+        {
+            mDNSCoreReceive(m, &m->imsg, (unsigned char*)&m->imsg + err, &senderAddr, senderPort, &destAddr, ss->port, InterfaceID);
+        }
+
+        // if we didn't close, we can safely dereference the socketset, and should to
+        // reset the closeFlag, since it points to something on the stack
+        if (!closed) ss->closeFlag = mDNSNULL;
+    }
+
+    if (err < 0 && (errno != EWOULDBLOCK || count == 0))
+    {
+        // Something is busted here.
+        // kqueue says there is a packet, but myrecvfrom says there is not.
+        // Try calling select() to get another opinion.
+        // Find out about other socket parameter that can help understand why select() says the socket is ready for read
+        // All of this is racy, as data may have arrived after the call to select()
+        static unsigned int numLogMessages = 0;
+        int save_errno = errno;
+        int so_error = -1;
+        int so_nread = -1;
+        int fionread = -1;
+        socklen_t solen = sizeof(int);
+        fd_set readfds;
+        struct timeval timeout;
+        int selectresult;
+        FD_ZERO(&readfds);
+        FD_SET(s1, &readfds);
+        timeout.tv_sec  = 0;
+        timeout.tv_usec = 0;
+        selectresult = select(s1+1, &readfds, NULL, NULL, &timeout);
+        if (getsockopt(s1, SOL_SOCKET, SO_ERROR, &so_error, &solen) == -1)
+            LogMsg("myKQSocketCallBack getsockopt(SO_ERROR) error %d", errno);
+        if (getsockopt(s1, SOL_SOCKET, SO_NREAD, &so_nread, &solen) == -1)
+            LogMsg("myKQSocketCallBack getsockopt(SO_NREAD) error %d", errno);
+        if (ioctl(s1, FIONREAD, &fionread) == -1)
+            LogMsg("myKQSocketCallBack ioctl(FIONREAD) error %d", errno);
+        if (numLogMessages++ < 100)
+            LogMsg("myKQSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d",
+                   s1, err, save_errno, strerror(save_errno), selectresult, FD_ISSET(s1, &readfds) ? "" : "*NO* ", so_error, so_nread, fionread, count);
+        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 at group.apple.com. (Note number is different.)\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
+    }
+}
+
+mDNSlocal void doTcpSocketCallback(TCPSocket *sock)
+{
+    mDNSBool c = !sock->connected;
+    sock->connected = mDNStrue;
+    sock->callback(sock, sock->context, c, sock->err);
+    // Note: the callback may call CloseConnection here, which frees the context structure!
+}
+
+#ifndef NO_SECURITYFRAMEWORK
+
+mDNSlocal OSStatus tlsWriteSock(SSLConnectionRef connection, const void *data, size_t *dataLength)
+{
+    int ret = send(((TCPSocket *)connection)->fd, data, *dataLength, 0);
+    if (ret >= 0 && (size_t)ret < *dataLength) { *dataLength = ret; return(errSSLWouldBlock); }
+    if (ret >= 0)                              { *dataLength = ret; return(noErr); }
+    *dataLength = 0;
+    if (errno == EAGAIN                      ) return(errSSLWouldBlock);
+    if (errno == ENOENT                      ) return(errSSLClosedGraceful);
+    if (errno == EPIPE || errno == ECONNRESET) return(errSSLClosedAbort);
+    LogMsg("ERROR: tlsWriteSock: %d error %d (%s)\n", ((TCPSocket *)connection)->fd, errno, strerror(errno));
+    return(errSSLClosedAbort);
+}
+
+mDNSlocal OSStatus tlsReadSock(SSLConnectionRef connection, void *data, size_t *dataLength)
+{
+    int ret = recv(((TCPSocket *)connection)->fd, data, *dataLength, 0);
+    if (ret > 0 && (size_t)ret < *dataLength) { *dataLength = ret; return(errSSLWouldBlock); }
+    if (ret > 0)                              { *dataLength = ret; return(noErr); }
+    *dataLength = 0;
+    if (ret == 0 || errno == ENOENT    ) return(errSSLClosedGraceful);
+    if (            errno == EAGAIN    ) return(errSSLWouldBlock);
+    if (            errno == ECONNRESET) return(errSSLClosedAbort);
+    LogMsg("ERROR: tlsSockRead: error %d (%s)\n", errno, strerror(errno));
+    return(errSSLClosedAbort);
+}
+
+mDNSlocal OSStatus tlsSetupSock(TCPSocket *sock, SSLProtocolSide pside, SSLConnectionType ctype)
+{
+    char domname_cstr[MAX_ESCAPED_DOMAIN_NAME];
+
+    sock->tlsContext = SSLCreateContext(kCFAllocatorDefault, pside, ctype);
+    if (!sock->tlsContext) 
+    { 
+        LogMsg("ERROR: tlsSetupSock: SSLCreateContext failed"); 
+        return(mStatus_UnknownErr); 
+    }
+
+    mStatus err = SSLSetIOFuncs(sock->tlsContext, tlsReadSock, tlsWriteSock);
+    if (err) 
+    { 
+        LogMsg("ERROR: tlsSetupSock: SSLSetIOFuncs failed with error code: %d", err); 
+        goto fail; 
+    }
+
+    err = SSLSetConnection(sock->tlsContext, (SSLConnectionRef) sock);
+    if (err) 
+    { 
+        LogMsg("ERROR: tlsSetupSock: SSLSetConnection failed with error code: %d", err); 
+        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);
+    if (err) 
+    { 
+        LogMsg("ERROR: tlsSetupSock: SSLSetAllowAnonymousCiphers failed with error code: %d", err); 
+        goto fail; 
+    }
+
+    // We already checked for NULL in hostname and this should never happen. Hence, returning -1
+    // (error not in OSStatus space) is okay.
+    if (!sock->hostname.c[0]) 
+    {
+        LogMsg("ERROR: tlsSetupSock: hostname NULL"); 
+        err = -1;
+        goto fail;
+    }
+
+    ConvertDomainNameToCString(&sock->hostname, domname_cstr);
+    err = SSLSetPeerDomainName(sock->tlsContext, domname_cstr, strlen(domname_cstr));
+    if (err) 
+    { 
+        LogMsg("ERROR: tlsSetupSock: SSLSetPeerDomainname: %s failed with error code: %d", domname_cstr, err); 
+        goto fail; 
+    }
+
+    return(err);
+
+fail:
+    if (sock->tlsContext)
+        CFRelease(sock->tlsContext);
+    return(err);
+}
+
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+mDNSlocal void doSSLHandshake(TCPSocket *sock)
+{
+    mStatus err = SSLHandshake(sock->tlsContext);
+
+    //Can't have multiple threads in mDNS core. When MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM is
+    //defined, KQueueLock is a noop. Hence we need to serialize here
+    //
+    //NOTE: We just can't serialize doTcpSocketCallback alone on the main queue.
+    //We need the rest of the logic also. Otherwise, we can enable the READ
+    //events below, dispatch a doTcpSocketCallback on the main queue. Assume it is
+    //ConnFailed which means we are going to free the tcpInfo. While it
+    //is waiting to be dispatched, another read event can come into tcpKQSocketCallback
+    //and potentially call doTCPCallback with error which can close the fd and free the
+    //tcpInfo. Later when the thread gets dispatched it will crash because the tcpInfo
+    //is already freed.
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+
+                       LogInfo("doSSLHandshake %p: got lock", sock); // Log *after* we get the lock
+
+                       if (sock->handshake == handshake_to_be_closed)
+                       {
+                           LogInfo("SSLHandshake completed after close");
+                           mDNSPlatformTCPCloseConnection(sock);
+                       }
+                       else
+                       {
+                           if (sock->fd != -1) KQueueSet(sock->fd, EV_ADD, EVFILT_READ, sock->kqEntry);
+                           else LogMsg("doSSLHandshake: sock->fd is -1");
+
+                           if (err == errSSLWouldBlock)
+                               sock->handshake = handshake_required;
+                           else
+                           {
+                               if (err)
+                               {
+                                   LogMsg("SSLHandshake failed: %d%s", err, err == errSSLPeerInternalError ? " (server busy)" : "");
+                                   CFRelease(sock->tlsContext);
+                                   sock->tlsContext = NULL;
+                               }
+
+                               sock->err = err ? mStatus_ConnFailed : 0;
+                               sock->handshake = handshake_completed;
+
+                               LogInfo("doSSLHandshake: %p calling doTcpSocketCallback fd %d", sock, sock->fd);
+                               doTcpSocketCallback(sock);
+                           }
+                       }
+
+                       LogInfo("SSLHandshake %p: dropping lock for fd %d", sock, sock->fd);
+                       return;
+                   });
+}
+#else // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+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);
+    debugf("doSSLHandshake %p: got lock", sock); // Log *after* we get the lock
+
+    if (sock->handshake == handshake_to_be_closed)
+    {
+        LogInfo("SSLHandshake completed after close");
+        mDNSPlatformTCPCloseConnection(sock);
+    }
+    else
+    {
+        if (sock->fd != -1) KQueueSet(sock->fd, EV_ADD, EVFILT_READ, sock->kqEntry);
+        else LogMsg("doSSLHandshake: sock->fd is -1");
+
+        if (err == errSSLWouldBlock)
+            sock->handshake = handshake_required;
+        else
+        {
+            if (err)
+            {
+                LogMsg("SSLHandshake failed: %d%s", err, err == errSSLPeerInternalError ? " (server busy)" : "");
+                CFRelease(sock->tlsContext);
+                sock->tlsContext = NULL;
+            }
+
+            sock->err = err ? mStatus_ConnFailed : 0;
+            sock->handshake = handshake_completed;
+
+            debugf("doSSLHandshake: %p calling doTcpSocketCallback fd %d", sock, sock->fd);
+            doTcpSocketCallback(sock);
+        }
+    }
+
+    debugf("SSLHandshake %p: dropping lock for fd %d", sock, sock->fd);
+    KQueueUnlock(m, "doSSLHandshake");
+    return NULL;
+}
+#endif // MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+
+mDNSlocal void spawnSSLHandshake(TCPSocket* sock)
+{
+    debugf("spawnSSLHandshake %p: entry", sock);
+
+    if (sock->handshake != handshake_required) LogMsg("spawnSSLHandshake: handshake status not required: %d", sock->handshake);
+    sock->handshake = handshake_in_progress;
+    KQueueSet(sock->fd, EV_DELETE, EVFILT_READ, sock->kqEntry);
+
+    // Dispatch it on a separate queue to help avoid blocking other threads/queues, and
+    // to limit the number of threads used for SSLHandshake
+    dispatch_async(SSLqueue, ^{doSSLHandshake(sock);});
+
+    debugf("spawnSSLHandshake %p: done for %d", sock, sock->fd);
+}
+
+#endif /* NO_SECURITYFRAMEWORK */
+
+mDNSlocal void tcpKQSocketCallback(__unused int fd, short filter, void *context)
+{
+    TCPSocket *sock = context;
+    sock->err = mStatus_NoError;
+
+    //if (filter == EVFILT_READ ) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_READ", filter);
+    //if (filter == EVFILT_WRITE) LogMsg("myKQSocketCallBack: tcpKQSocketCallback %d is EVFILT_WRITE", filter);
+    // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it here with EV_DELETE
+    if (filter == EVFILT_WRITE) 
+        KQueueSet(sock->fd, EV_DELETE, EVFILT_WRITE, sock->kqEntry);
+
+    if (sock->flags & kTCPSocketFlags_UseTLS)
+    {
+#ifndef NO_SECURITYFRAMEWORK
+        if (!sock->setup) 
+        { 
+            sock->setup = mDNStrue; 
+            sock->err = tlsSetupSock(sock, kSSLClientSide, kSSLStreamType);
+            if (sock->err)
+            {
+                LogMsg("ERROR: tcpKQSocketCallback: tlsSetupSock failed with error code: %d", sock->err);
+                return;
+            }
+        }
+        if (sock->handshake == handshake_required) 
+        { 
+            spawnSSLHandshake(sock); 
+            return;
+        }
+        else if (sock->handshake == handshake_in_progress || sock->handshake == handshake_to_be_closed)
+        {
+            return;
+        }
+        else if (sock->handshake != handshake_completed)
+        {
+            if (!sock->err) 
+                sock->err = mStatus_UnknownErr;
+            LogMsg("tcpKQSocketCallback called with unexpected SSLHandshake status: %d", sock->handshake);
+        }
+#else  /* NO_SECURITYFRAMEWORK */ 
+        sock->err = mStatus_UnsupportedErr;
+#endif /* NO_SECURITYFRAMEWORK */
+    }
+
+    doTcpSocketCallback(sock);
+}
+
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+mDNSexport int KQueueSet(int fd, u_short flags, short filter, KQueueEntry *const entryRef)
+{
+    dispatch_queue_t queue = dispatch_get_main_queue();
+    dispatch_source_t source;
+    if (flags == EV_DELETE)
+    {
+        if (filter == EVFILT_READ)
+        {
+            dispatch_source_cancel(entryRef->readSource);
+            dispatch_release(entryRef->readSource);
+            entryRef->readSource = mDNSNULL;
+            debugf("KQueueSet: source cancel for read %p, %p", entryRef->readSource, entryRef->writeSource);
+        }
+        else if (filter == EVFILT_WRITE)
+        {
+            dispatch_source_cancel(entryRef->writeSource);
+            dispatch_release(entryRef->writeSource);
+            entryRef->writeSource = mDNSNULL;
+            debugf("KQueueSet: source cancel for write %p, %p", entryRef->readSource, entryRef->writeSource);
+        }
+        else
+            LogMsg("KQueueSet: ERROR: Wrong filter value %d for EV_DELETE", filter);
+        return 0;
+    }
+    if (flags != EV_ADD) LogMsg("KQueueSet: Invalid flags %d", flags);
+
+    if (filter == EVFILT_READ)
+    {
+        source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, queue);
+    }
+    else if (filter == EVFILT_WRITE)
+    {
+        source = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, fd, 0, queue);
+    }
+    else
+    {
+        LogMsg("KQueueSet: ERROR: Wrong filter value %d for EV_ADD", filter);
+        return -1;
+    }
+    if (!source) return -1;
+    dispatch_source_set_event_handler(source, ^{
+
+                                          mDNSs32 stime = mDNSPlatformRawTime();
+                                          entryRef->KQcallback(fd, filter, entryRef->KQcontext);
+                                          mDNSs32 etime = mDNSPlatformRawTime();
+                                          if (etime - stime >= WatchDogReportingThreshold)
+                                              LogInfo("KQEntryCallback Block: WARNING: took %dms to complete", etime - stime);
+
+                                          // Trigger the event delivery to the application. Even though we trigger the
+                                          // event completion after handling every event source, these all will hopefully
+                                          // get merged
+                                          TriggerEventCompletion();
+
+                                      });
+    dispatch_source_set_cancel_handler(source, ^{
+                                           if (entryRef->fdClosed)
+                                           {
+                                               //LogMsg("CancelHandler: closing fd %d", fd);
+                                               close(fd);
+                                           }
+                                       });
+    dispatch_resume(source);
+    if (filter == EVFILT_READ)
+        entryRef->readSource = source;
+    else
+        entryRef->writeSource = source;
+
+    return 0;
+}
+
+mDNSexport void KQueueLock(mDNS *const m)
+{
+    (void)m; //unused
+}
+mDNSexport void KQueueUnlock(mDNS *const m, const char const *task)
+{
+    (void)m; //unused
+    (void)task; //unused
+}
+#else
+mDNSexport int KQueueSet(int fd, u_short flags, short filter, const KQueueEntry *const entryRef)
+{
+    struct kevent new_event;
+    EV_SET(&new_event, fd, filter, flags, 0, 0, (void*)entryRef);
+    return (kevent(KQueueFD, &new_event, 1, NULL, 0, NULL) < 0) ? errno : 0;
+}
+
+mDNSexport void KQueueLock(mDNS *const m)
+{
+    pthread_mutex_lock(&m->p->BigMutex);
+    m->p->BigMutexStartTime = mDNSPlatformRawTime();
+}
+
+mDNSexport void KQueueUnlock(mDNS *const m, const char* task)
+{
+    mDNSs32 end = mDNSPlatformRawTime();
+    (void)task;
+    if (end - m->p->BigMutexStartTime >= WatchDogReportingThreshold)
+        LogInfo("WARNING: %s took %dms to complete", task, end - m->p->BigMutexStartTime);
+
+    pthread_mutex_unlock(&m->p->BigMutex);
+
+    char wake = 1;
+    if (send(m->p->WakeKQueueLoopFD, &wake, sizeof(wake), 0) == -1)
+        LogMsg("ERROR: KQueueWake: send failed with error code: %d (%s)", errno, strerror(errno));
+}
+#endif
+
+mDNSexport void mDNSPlatformCloseFD(KQueueEntry *kq, int fd)
+{
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+        (void) fd; //unused
+    if (kq->readSource)
+    {
+        dispatch_source_cancel(kq->readSource);
+        kq->readSource = mDNSNULL;
+    }
+    if (kq->writeSource)
+    {
+        dispatch_source_cancel(kq->writeSource);
+        kq->writeSource = mDNSNULL;
+    }
+    // Close happens in the cancellation handler
+    debugf("mDNSPlatformCloseFD: resetting sources for %d", fd);
+    kq->fdClosed = mDNStrue;
+#else
+    (void)kq; //unused
+    close(fd);
+#endif
+}
+
+mDNSlocal mStatus SetupTCPSocket(TCPSocket *sock, u_short sa_family, mDNSIPPort *port, mDNSBool useBackgroundTrafficClass)
+{
+    KQSocketSet *cp = &sock->ss;
+    int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
+    KQueueEntry *k        = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
+    const int on = 1;  // "on" for setsockopt
+    mStatus err;
+
+    int skt = socket(sa_family, SOCK_STREAM, IPPROTO_TCP);
+    if (skt < 3) { if (errno != EAFNOSUPPORT) LogMsg("SetupTCPSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno));return(skt); }
+
+    // for TCP sockets, the traffic class is set once and not changed
+    setTrafficClass(skt, useBackgroundTrafficClass);
+
+    if (sa_family == AF_INET)
+    {
+        // Bind it
+        struct sockaddr_in addr;
+        mDNSPlatformMemZero(&addr, sizeof(addr));
+        addr.sin_family = AF_INET;
+        addr.sin_port = port->NotAnInteger;
+        err = bind(skt, (struct sockaddr*) &addr, sizeof(addr));
+        if (err < 0) { LogMsg("ERROR: bind %s", strerror(errno)); return err; }
+
+        // Receive interface identifiers
+        err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
+        if (err < 0) { LogMsg("setsockopt IP_RECVIF - %s", strerror(errno)); return err; }
+
+        mDNSPlatformMemZero(&addr, sizeof(addr));
+        socklen_t len = sizeof(addr);
+        err = getsockname(skt, (struct sockaddr*) &addr, &len);
+        if (err < 0) { LogMsg("getsockname - %s", strerror(errno)); return err; }
+
+        port->NotAnInteger = addr.sin_port;
+    }
+    else
+    {
+        // Bind it
+        struct sockaddr_in6 addr6;
+        mDNSPlatformMemZero(&addr6, sizeof(addr6));
+        addr6.sin6_family = AF_INET6;
+        addr6.sin6_port = port->NotAnInteger;
+        err = bind(skt, (struct sockaddr*) &addr6, sizeof(addr6));
+        if (err < 0) { LogMsg("ERROR: bind6 %s", strerror(errno)); return err; }
+
+        // We want to receive destination addresses and receive interface identifiers
+        err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
+        if (err < 0) { LogMsg("ERROR: setsockopt IPV6_RECVPKTINFO %s", strerror(errno)); return err; }
+
+        mDNSPlatformMemZero(&addr6, sizeof(addr6));
+        socklen_t len = sizeof(addr6);
+        err = getsockname(skt, (struct sockaddr *) &addr6, &len);
+        if (err < 0) { LogMsg("getsockname6 - %s", strerror(errno)); return err; }
+
+        port->NotAnInteger = addr6.sin6_port;
+
+    }
+    *s = skt;
+    k->KQcallback = tcpKQSocketCallback;
+    k->KQcontext  = sock;
+    k->KQtask     = "mDNSPlatformTCPSocket";
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+    k->readSource = mDNSNULL;
+    k->writeSource = mDNSNULL;
+    k->fdClosed = mDNSfalse;
+#endif
+    return mStatus_NoError;
+}
+
+mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, 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.sktv4 = -1;
+    sock->ss.sktv6 = -1;
+    err = SetupTCPSocket(sock, AF_INET, port, useBackgroundTrafficClass);
+
+    if (!err)
+    {
+        err = SetupTCPSocket(sock, AF_INET6, port, useBackgroundTrafficClass);
+        if (err) { mDNSPlatformCloseFD(&sock->ss.kqsv4, sock->ss.sktv4); sock->ss.sktv4 = -1; }
+    }
+    if (err)
+    {
+        LogMsg("mDNSPlatformTCPSocket: socket error %d errno %d (%s)", sock->fd, errno, strerror(errno));
+        freeL("TCPSocket/mDNSPlatformTCPSocket", sock);
+        return(mDNSNULL);
+    }
+    // sock->fd is used as the default fd  if the caller does not call mDNSPlatformTCPConnect
+    sock->fd                = sock->ss.sktv4;
+    sock->callback          = mDNSNULL;
+    sock->flags             = flags;
+    sock->context           = mDNSNULL;
+    sock->setup             = mDNSfalse;
+    sock->connected         = mDNSfalse;
+    sock->handshake         = handshake_required;
+    sock->m                 = m;
+    sock->err               = mStatus_NoError;
+
+    return sock;
+}
+
+mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname, mDNSInterfaceID InterfaceID, TCPConnectionCallback callback, void *context)
+{
+    KQSocketSet *cp = &sock->ss;
+    int         *s        = (dst->type == mDNSAddrType_IPv4) ? &cp->sktv4 : &cp->sktv6;
+    KQueueEntry *k        = (dst->type == mDNSAddrType_IPv4) ? &cp->kqsv4 : &cp->kqsv6;
+    mStatus err = mStatus_NoError;
+    struct sockaddr_storage ss;
+
+    sock->callback          = callback;
+    sock->context           = context;
+    sock->setup             = mDNSfalse;
+    sock->connected         = mDNSfalse;
+    sock->handshake         = handshake_required;
+    sock->err               = mStatus_NoError;
+
+    if (hostname) { debugf("mDNSPlatformTCPConnect: hostname %##s", hostname->c); AssignDomainName(&sock->hostname, hostname); }
+
+    if (dst->type == mDNSAddrType_IPv4)
+    {
+        struct sockaddr_in *saddr = (struct sockaddr_in *)&ss;
+        mDNSPlatformMemZero(saddr, sizeof(*saddr));
+        saddr->sin_family      = AF_INET;
+        saddr->sin_port        = dstport.NotAnInteger;
+        saddr->sin_len         = sizeof(*saddr);
+        saddr->sin_addr.s_addr = dst->ip.v4.NotAnInteger;
+    }
+    else
+    {
+        struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&ss;
+        mDNSPlatformMemZero(saddr6, sizeof(*saddr6));
+        saddr6->sin6_family      = AF_INET6;
+        saddr6->sin6_port        = dstport.NotAnInteger;
+        saddr6->sin6_len         = sizeof(*saddr6);
+        saddr6->sin6_addr        = *(struct in6_addr *)&dst->ip.v6;
+    }
+
+    // Watch for connect complete (write is ready)
+    // EV_ONESHOT doesn't seem to work, so we add the filter with EV_ADD, and explicitly delete it in tcpKQSocketCallback using EV_DELETE
+    if (KQueueSet(*s, EV_ADD /* | EV_ONESHOT */, EVFILT_WRITE, k))
+    {
+        LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
+        return errno;
+    }
+
+    // Watch for incoming data
+    if (KQueueSet(*s, EV_ADD, EVFILT_READ, k))
+    {
+        LogMsg("ERROR: mDNSPlatformTCPConnect - KQueueSet failed");
+        return errno;
+    }
+
+    if (fcntl(*s, F_SETFL, fcntl(*s, F_GETFL, 0) | O_NONBLOCK) < 0) // set non-blocking
+    {
+        LogMsg("ERROR: setsockopt O_NONBLOCK - %s", strerror(errno));
+        return mStatus_UnknownErr;
+    }
+
+    // We bind to the interface and all subsequent packets including the SYN will be sent out
+    // on this interface
+    //
+    // Note: If we are in Active Directory domain, we may try TCP (if the response can't fit in
+    // UDP). mDNSInterface_Unicast indicates this case and not a valid interface.
+    if (InterfaceID && InterfaceID != mDNSInterface_Unicast)
+    {
+        NetworkInterfaceInfoOSX *info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
+        if (dst->type == mDNSAddrType_IPv4)
+        {
+        #ifdef IP_BOUND_IF
+            if (info) setsockopt(*s, IPPROTO_IP, IP_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
+            else { LogMsg("mDNSPlatformTCPConnect: Invalid interface index %p", InterfaceID); return mStatus_BadParamErr; }
+        #else
+            (void)InterfaceID; // Unused
+            (void)info; // Unused
+        #endif
+        }
+        else
+        {
+        #ifdef IPV6_BOUND_IF
+            if (info) setsockopt(*s, IPPROTO_IPV6, IPV6_BOUND_IF, &info->scope_id, sizeof(info->scope_id));
+            else { LogMsg("mDNSPlatformTCPConnect: Invalid interface index %p", InterfaceID); return mStatus_BadParamErr; }
+        #else
+            (void)InterfaceID; // Unused
+            (void)info; // Unused
+        #endif
+        }
+    }
+
+    // mDNSPlatformReadTCP/WriteTCP (unlike the UDP counterpart) does not provide the destination address
+    // from which we can infer the destination address family. Hence we need to remember that here.
+    // Instead of remembering the address family, we remember the right fd.
+    sock->fd = *s;
+    sock->kqEntry = k;
+    // initiate connection wth peer
+    if (connect(*s, (struct sockaddr *)&ss, ss.ss_len) < 0)
+    {
+        if (errno == EINPROGRESS) return mStatus_ConnPending;
+        if (errno == EHOSTUNREACH || errno == EADDRNOTAVAIL || errno == ENETDOWN)
+            LogInfo("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s)", sock->fd, errno, strerror(errno));
+        else
+            LogMsg("ERROR: mDNSPlatformTCPConnect - connect failed: socket %d: Error %d (%s) length %d", sock->fd, errno, strerror(errno), ss.ss_len);
+        return mStatus_ConnFailed;
+    }
+
+    LogMsg("NOTE: mDNSPlatformTCPConnect completed synchronously");
+    // kQueue should notify us, but this LogMsg is to help track down if it doesn't
+    return err;
+}
+
+// Why doesn't mDNSPlatformTCPAccept actually call accept() ?
+mDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int fd)
+{
+    mStatus err = mStatus_NoError;
+
+    TCPSocket *sock = mallocL("TCPSocket/mDNSPlatformTCPAccept", sizeof(TCPSocket));
+    if (!sock) return(mDNSNULL);
+
+    mDNSPlatformMemZero(sock, sizeof(*sock));
+    sock->fd = fd;
+    sock->flags = flags;
+
+    if (flags & kTCPSocketFlags_UseTLS)
+    {
+#ifndef NO_SECURITYFRAMEWORK
+        if (!ServerCerts) { LogMsg("ERROR: mDNSPlatformTCPAccept: unable to find TLS certificates"); err = mStatus_UnknownErr; goto exit; }
+
+        err = tlsSetupSock(sock, kSSLServerSide, kSSLStreamType);
+        if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: tlsSetupSock failed with error code: %d", err); goto exit; }
+
+        err = SSLSetCertificate(sock->tlsContext, ServerCerts);
+        if (err) { LogMsg("ERROR: mDNSPlatformTCPAccept: SSLSetCertificate failed with error code: %d", err); goto exit; }
+#else
+        err = mStatus_UnsupportedErr;
+#endif /* NO_SECURITYFRAMEWORK */
+    }
+#ifndef NO_SECURITYFRAMEWORK
+exit:
+#endif
+
+    if (err) { freeL("TCPSocket/mDNSPlatformTCPAccept", sock); return(mDNSNULL); }
+    return(sock);
+}
+
+mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
+{
+    mDNSu16 port;
+
+    port = -1;
+    if (sock)
+    {
+        port = sock->ss.port.NotAnInteger;
+    }
+    return port;
+}
+
+mDNSlocal void CloseSocketSet(KQSocketSet *ss)
+{
+    if (ss->sktv4 != -1)
+    {
+        mDNSPlatformCloseFD(&ss->kqsv4,  ss->sktv4);
+        ss->sktv4 = -1;
+    }
+    if (ss->sktv6 != -1)
+    {
+        mDNSPlatformCloseFD(&ss->kqsv6,  ss->sktv6);
+        ss->sktv6 = -1;
+    }
+    if (ss->closeFlag) *ss->closeFlag = 1;
+}
+
+mDNSexport void mDNSPlatformTCPCloseConnection(TCPSocket *sock)
+{
+    if (sock)
+    {
+#ifndef NO_SECURITYFRAMEWORK
+        if (sock->tlsContext)
+        {
+            if (sock->handshake == handshake_in_progress) // SSLHandshake thread using this sock (esp. tlsContext)
+            {
+                LogInfo("mDNSPlatformTCPCloseConnection: called while handshake in progress");
+                // When we come back from SSLHandshake, we will notice that a close was here and
+                // call this function again which will do the cleanup then.
+                sock->handshake = handshake_to_be_closed;
+                return;
+            }
+
+            SSLClose(sock->tlsContext);
+            CFRelease(sock->tlsContext);
+            sock->tlsContext = NULL;
+        }
+#endif /* NO_SECURITYFRAMEWORK */
+        if (sock->ss.sktv4 != -1) 
+            shutdown(sock->ss.sktv4, 2);
+        if (sock->ss.sktv6 != -1) 
+            shutdown(sock->ss.sktv6, 2);
+        CloseSocketSet(&sock->ss);
+        sock->fd = -1;
+
+        freeL("TCPSocket/mDNSPlatformTCPCloseConnection", sock);
+    }
+}
+
+mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed)
+{
+    ssize_t nread = 0;
+    *closed = mDNSfalse;
+
+    if (sock->flags & kTCPSocketFlags_UseTLS)
+    {
+#ifndef NO_SECURITYFRAMEWORK
+        if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformReadTCP called while handshake required"); return 0; }
+        else if (sock->handshake == handshake_in_progress) return 0;
+        else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformReadTCP called with unexpected SSLHandshake status: %d", sock->handshake);
+
+        //LogMsg("Starting SSLRead %d %X", sock->fd, fcntl(sock->fd, F_GETFL, 0));
+        mStatus err = SSLRead(sock->tlsContext, buf, buflen, (size_t *)&nread);
+        //LogMsg("SSLRead returned %d (%d) nread %d buflen %d", err, errSSLWouldBlock, nread, buflen);
+        if (err == errSSLClosedGraceful) { nread = 0; *closed = mDNStrue; }
+        else if (err && err != errSSLWouldBlock)
+        { LogMsg("ERROR: mDNSPlatformReadTCP - SSLRead: %d", err); nread = -1; *closed = mDNStrue; }
+#else
+        nread = -1;
+        *closed = mDNStrue;
+#endif /* NO_SECURITYFRAMEWORK */
+    }
+    else
+    {
+        static int CLOSEDcount = 0;
+        static int EAGAINcount = 0;
+        nread = recv(sock->fd, buf, buflen, 0);
+
+        if (nread > 0) 
+        { 
+            CLOSEDcount = 0; 
+            EAGAINcount = 0; 
+        } // On success, clear our error counters
+        else if (nread == 0)
+        {
+            *closed = mDNStrue;
+            if ((++CLOSEDcount % 1000) == 0) 
+            { 
+                LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got CLOSED %d times", sock->fd, CLOSEDcount); 
+                assert(CLOSEDcount < 1000);
+                // Recovery Mechanism to bail mDNSResponder out of trouble: Instead of logging the same error msg multiple times,
+                // crash mDNSResponder using assert() and restart fresh. See advantages below:
+                // 1.Better User Experience 
+                // 2.CrashLogs frequency can be monitored 
+                // 3.StackTrace can be used for more info
+            }
+        }
+        // else nread is negative -- see what kind of error we got
+        else if (errno == ECONNRESET) { nread = 0; *closed = mDNStrue; }
+        else if (errno != EAGAIN) { LogMsg("ERROR: mDNSPlatformReadTCP - recv: %d (%s)", errno, strerror(errno)); nread = -1; }
+        else // errno is EAGAIN (EWOULDBLOCK) -- no data available
+        {
+            nread = 0;
+            if ((++EAGAINcount % 1000) == 0) { LogMsg("ERROR: mDNSPlatformReadTCP - recv %d got EAGAIN %d times", sock->fd, EAGAINcount); sleep(1); }
+        }
+    }
+
+    return nread;
+}
+
+mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len)
+{
+    int nsent;
+
+    if (sock->flags & kTCPSocketFlags_UseTLS)
+    {
+#ifndef NO_SECURITYFRAMEWORK
+        size_t processed;
+        if (sock->handshake == handshake_required) { LogMsg("mDNSPlatformWriteTCP called while handshake required"); return 0; }
+        if (sock->handshake == handshake_in_progress) return 0;
+        else if (sock->handshake != handshake_completed) LogMsg("mDNSPlatformWriteTCP called with unexpected SSLHandshake status: %d", sock->handshake);
+
+        mStatus err = SSLWrite(sock->tlsContext, msg, len, &processed);
+
+        if (!err) nsent = (int) processed;
+        else if (err == errSSLWouldBlock) nsent = 0;
+        else { LogMsg("ERROR: mDNSPlatformWriteTCP - SSLWrite returned %d", err); nsent = -1; }
+#else
+        nsent = -1;
+#endif /* NO_SECURITYFRAMEWORK */
+    }
+    else
+    {
+        nsent = send(sock->fd, msg, len, 0);
+        if (nsent < 0)
+        {
+            if (errno == EAGAIN) nsent = 0;
+            else { LogMsg("ERROR: mDNSPlatformWriteTCP - send %s", strerror(errno)); nsent = -1; }
+        }
+    }
+
+    return nsent;
+}
+
+mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
+{
+    return sock->fd;
+}
+
+// If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
+// If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
+mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa_family, mDNSIPPort *const outport)
+{
+    int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
+    KQueueEntry *k        = (sa_family == AF_INET) ? &cp->kqsv4 : &cp->kqsv6;
+    const int on = 1;
+    const int twofivefive = 255;
+    mStatus err = mStatus_NoError;
+    char *errstr = mDNSNULL;
+    const int mtu = 0;
+
+    cp->closeFlag = mDNSNULL;
+
+    int skt = socket(sa_family, SOCK_DGRAM, IPPROTO_UDP);
+    if (skt < 3) { if (errno != EAFNOSUPPORT) LogMsg("SetupSocket: socket error %d errno %d (%s)", skt, errno, strerror(errno));return(skt); }
+
+    // set default traffic class
+    setTrafficClass(skt, mDNSfalse);
+
+#ifdef SO_RECV_ANYIF
+    // Enable inbound packets on IFEF_AWDL interface.
+    // Only done for multicast sockets, since we don't expect unicast socket operations
+    // on the IFEF_AWDL interface. Operation is a no-op for other interface types.
+    if (mDNSSameIPPort(port, MulticastDNSPort)) 
+    {
+        err = setsockopt(skt, SOL_SOCKET, SO_RECV_ANYIF, &on, sizeof(on));
+        if (err < 0) { errstr = "setsockopt - SO_RECV_ANYIF"; goto fail; }
+    }
+#endif // SO_RECV_ANYIF
+
+    // ... with a shared UDP port, if it's for multicast receiving
+    if (mDNSSameIPPort(port, MulticastDNSPort) || mDNSSameIPPort(port, NATPMPAnnouncementPort)) err = setsockopt(skt, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
+    if (err < 0) { errstr = "setsockopt - SO_REUSEPORT"; goto fail; }
+
+    if (sa_family == AF_INET)
+    {
+        // We want to receive destination addresses
+        err = setsockopt(skt, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
+        if (err < 0) { errstr = "setsockopt - IP_RECVDSTADDR"; goto fail; }
+
+        // We want to receive interface identifiers
+        err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on));
+        if (err < 0) { errstr = "setsockopt - IP_RECVIF"; goto fail; }
+
+        // We want to receive packet TTL value so we can check it
+        err = setsockopt(skt, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
+        // We ignore errors here -- we already know Jaguar doesn't support this, but we can get by without it
+
+        // Send unicast packets with TTL 255
+        err = setsockopt(skt, IPPROTO_IP, IP_TTL, &twofivefive, sizeof(twofivefive));
+        if (err < 0) { errstr = "setsockopt - IP_TTL"; goto fail; }
+
+        // And multicast packets with TTL 255 too
+        err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive));
+        if (err < 0) { errstr = "setsockopt - IP_MULTICAST_TTL"; goto fail; }
+
+        // And start listening for packets
+        struct sockaddr_in listening_sockaddr;
+        listening_sockaddr.sin_family      = AF_INET;
+        listening_sockaddr.sin_port        = port.NotAnInteger;     // Pass in opaque ID without any byte swapping
+        listening_sockaddr.sin_addr.s_addr = mDNSSameIPPort(port, NATPMPAnnouncementPort) ? AllHosts_v4.NotAnInteger : 0;
+        err = bind(skt, (struct sockaddr *) &listening_sockaddr, sizeof(listening_sockaddr));
+        if (err) { errstr = "bind"; goto fail; }
+        if (outport) outport->NotAnInteger = listening_sockaddr.sin_port;
+    }
+    else if (sa_family == AF_INET6)
+    {
+        // NAT-PMP Announcements make no sense on IPv6, and we don't support IPv6 for PCP, so bail early w/o error
+        if (mDNSSameIPPort(port, NATPMPAnnouncementPort)) { if (outport) *outport = zeroIPPort;return mStatus_NoError; }
+
+        // We want to receive destination addresses and receive interface identifiers
+        err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
+        if (err < 0) { errstr = "setsockopt - IPV6_RECVPKTINFO"; goto fail; }
+
+        // We want to receive packet hop count value so we can check it
+        err = setsockopt(skt, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
+        if (err < 0) { errstr = "setsockopt - IPV6_RECVHOPLIMIT"; goto fail; }
+
+        // We want to receive only IPv6 packets. Without this option we get IPv4 packets too,
+        // with mapped addresses of the form 0:0:0:0:0:FFFF:xxxx:xxxx, where xxxx:xxxx is the IPv4 address
+        err = setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
+        if (err < 0) { errstr = "setsockopt - IPV6_V6ONLY"; goto fail; }
+
+        // Send unicast packets with TTL 255
+        err = setsockopt(skt, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &twofivefive, sizeof(twofivefive));
+        if (err < 0) { errstr = "setsockopt - IPV6_UNICAST_HOPS"; goto fail; }
+
+        // And multicast packets with TTL 255 too
+        err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &twofivefive, sizeof(twofivefive));
+        if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_HOPS"; goto fail; }
+
+        // Want to receive our own packets
+        err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on, sizeof(on));
+        if (err < 0) { errstr = "setsockopt - IPV6_MULTICAST_LOOP"; goto fail; }
+
+        // Disable default option to send mDNSv6 packets at min IPv6 MTU: RFC 3542, Sec 11
+        err = setsockopt(skt, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &mtu, sizeof(mtu));
+        if (err < 0) // Since it is an optimization if we fail just log the err, no need to close the skt
+            LogMsg("SetupSocket: setsockopt - IPV6_USE_MIN_MTU: IP6PO_MINMTU_DISABLE socket %d err %d errno %d (%s)", 
+                    skt, err, errno, strerror(errno));
+        
+        // And start listening for packets
+        struct sockaddr_in6 listening_sockaddr6;
+        mDNSPlatformMemZero(&listening_sockaddr6, sizeof(listening_sockaddr6));
+        listening_sockaddr6.sin6_len         = sizeof(listening_sockaddr6);
+        listening_sockaddr6.sin6_family      = AF_INET6;
+        listening_sockaddr6.sin6_port        = port.NotAnInteger;       // Pass in opaque ID without any byte swapping
+        listening_sockaddr6.sin6_flowinfo    = 0;
+        listening_sockaddr6.sin6_addr        = in6addr_any; // Want to receive multicasts AND unicasts on this socket
+        listening_sockaddr6.sin6_scope_id    = 0;
+        err = bind(skt, (struct sockaddr *) &listening_sockaddr6, sizeof(listening_sockaddr6));
+        if (err) { errstr = "bind"; goto fail; }
+        if (outport) outport->NotAnInteger = listening_sockaddr6.sin6_port;
+    }
+
+    fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
+    fcntl(skt, F_SETFD, 1); // set close-on-exec
+    *s = skt;
+    k->KQcallback = myKQSocketCallBack;
+    k->KQcontext  = cp;
+    k->KQtask     = "UDP packet reception";
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+    k->readSource = mDNSNULL;
+    k->writeSource = mDNSNULL;
+    k->fdClosed = mDNSfalse;
+#endif
+    KQueueSet(*s, EV_ADD, EVFILT_READ, k);
+
+    return(err);
+
+fail:
+    // For "bind" failures, only write log messages for our shared mDNS port, or for binding to zero
+    if (strcmp(errstr, "bind") || mDNSSameIPPort(port, MulticastDNSPort) || mDNSIPPortIsZero(port))
+        LogMsg("%s skt %d port %d error %d errno %d (%s)", errstr, skt, mDNSVal16(port), err, errno, strerror(errno));
+
+    // If we got a "bind" failure of EADDRINUSE, inform the caller as it might need to try another random port
+    if (!strcmp(errstr, "bind") && errno == EADDRINUSE)
+    {
+        err = EADDRINUSE;
+        if (mDNSSameIPPort(port, MulticastDNSPort))
+            NotifyOfElusiveBug("Setsockopt SO_REUSEPORT failed",
+                               "Congratulations, you've reproduced an elusive bug.\r"
+                               "Please contact the current assignee of <rdar://problem/3814904>.\r"
+                               "Alternatively, you can send email to radar-3387020 at group.apple.com. (Note number is different.)\r"
+                               "If possible, please leave your machine undisturbed so that someone can come to investigate the problem.");
+    }
+
+    mDNSPlatformCloseFD(k, skt);
+    return(err);
+}
+
+mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
+{
+    mStatus err;
+    mDNSIPPort port = requestedport;
+    mDNSBool randomizePort = mDNSIPPortIsZero(requestedport);
+    int i = 10000; // Try at most 10000 times to get a unique random port
+    UDPSocket *p = mallocL("UDPSocket", sizeof(UDPSocket));
+    if (!p) { LogMsg("mDNSPlatformUDPSocket: memory exhausted"); return(mDNSNULL); }
+    mDNSPlatformMemZero(p, sizeof(UDPSocket));
+    p->ss.port  = zeroIPPort;
+    p->ss.m     = m;
+    p->ss.sktv4 = -1;
+    p->ss.sktv6 = -1;
+    p->ss.proxy = mDNSfalse;
+
+    do
+    {
+        // The kernel doesn't do cryptographically strong random port allocation, so we do it ourselves here
+        if (randomizePort) port = mDNSOpaque16fromIntVal(0xC000 + mDNSRandom(0x3FFF));
+        err = SetupSocket(&p->ss, port, AF_INET, &p->ss.port);
+        if (!err)
+        {
+            err = SetupSocket(&p->ss, port, AF_INET6, &p->ss.port);
+            if (err) { mDNSPlatformCloseFD(&p->ss.kqsv4, p->ss.sktv4); p->ss.sktv4 = -1; }
+        }
+        i--;
+    } while (err == EADDRINUSE && randomizePort && i);
+
+    if (err)
+    {
+        // In customer builds we don't want to log failures with port 5351, because this is a known issue
+        // of failing to bind to this port when Internet Sharing has already bound to it
+        // We also don't want to log about port 5350, due to a known bug when some other
+        // process is bound to it.
+        if (mDNSSameIPPort(requestedport, NATPMPPort) || mDNSSameIPPort(requestedport, NATPMPAnnouncementPort))
+            LogInfo("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
+        else LogMsg("mDNSPlatformUDPSocket: SetupSocket %d failed error %d errno %d (%s)", mDNSVal16(requestedport), err, errno, strerror(errno));
+        freeL("UDPSocket", p);
+        return(mDNSNULL);
+    }
+    return(p);
+}
+
+mDNSexport void mDNSPlatformUDPClose(UDPSocket *sock)
+{
+    CloseSocketSet(&sock->ss);
+    freeL("UDPSocket", sock);
+}
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - BPF Raw packet sending/receiving
+#endif
+
+#if APPLE_OSX_mDNSResponder
+
+mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
+{
+    if (!InterfaceID) { LogMsg("mDNSPlatformSendRawPacket: No InterfaceID specified"); return; }
+    NetworkInterfaceInfoOSX *info;
+
+    info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
+    if (info == NULL)
+    {
+        LogMsg("mDNSPlatformSendUDP: Invalid interface index %p", InterfaceID);
+        return;
+    }
+    if (info->BPF_fd < 0)
+        LogMsg("mDNSPlatformSendRawPacket: %s BPF_fd %d not ready", info->ifinfo.ifname, info->BPF_fd);
+    else
+    {
+        //LogMsg("mDNSPlatformSendRawPacket %d bytes on %s", end - (mDNSu8 *)msg, info->ifinfo.ifname);
+        if (write(info->BPF_fd, msg, end - (mDNSu8 *)msg) < 0)
+            LogMsg("mDNSPlatformSendRawPacket: BPF write(%d) failed %d (%s)", info->BPF_fd, errno, strerror(errno));
+    }
+}
+
+mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
+{
+    if (!InterfaceID) { LogMsg("mDNSPlatformSetLocalAddressCacheEntry: No InterfaceID specified"); return; }
+    NetworkInterfaceInfoOSX *info;
+    info = IfindexToInterfaceInfoOSX(m, 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, mDNSNULL))
+        LogSPS("Don't need address cache entry for %s %#a %.6a",            info->ifinfo.ifname, tpa, tha);
+    else
+    {
+        int result = mDNSSetLocalAddressCacheEntry(info->scope_id, tpa->type, tpa->ip.v6.b, tha->b);
+        if (result) LogMsg("Set local address cache entry for %s %#a %.6a failed: %d", info->ifinfo.ifname, tpa, tha, result);
+        else LogSPS("Set local address cache entry for %s %#a %.6a",            info->ifinfo.ifname, tpa, tha);
+    }
+}
+
+mDNSlocal void CloseBPF(NetworkInterfaceInfoOSX *const i)
+{
+    LogSPS("%s closing BPF fd %d", i->ifinfo.ifname, i->BPF_fd);
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+    // close will happen in the cancel handler
+    dispatch_source_cancel(i->BPF_source);
+#else
+
+    // Note: MUST NOT close() the underlying native BSD sockets.
+    // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately, because
+    // it first has to unhook the sockets from its select() call on its other thread, before it can safely close them.
+    CFRunLoopRemoveSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode);
+    CFRelease(i->BPF_rls);
+    CFSocketInvalidate(i->BPF_cfs);
+    CFRelease(i->BPF_cfs);
+#endif
+    i->BPF_fd = -1;
+    if (i->BPF_mcfd >= 0) { close(i->BPF_mcfd); i->BPF_mcfd = -1; }
+}
+
+mDNSlocal void bpf_callback_common(NetworkInterfaceInfoOSX *info)
+{
+    KQueueLock(info->m);
+
+    // 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).
+    if (info->BPF_fd < 0) goto exit;
+
+    ssize_t n = read(info->BPF_fd, &info->m->imsg, info->BPF_len);
+    const mDNSu8 *ptr = (const mDNSu8 *)&info->m->imsg;
+    const mDNSu8 *end = (const mDNSu8 *)&info->m->imsg + n;
+    debugf("%3d: bpf_callback got %d bytes on %s", info->BPF_fd, n, info->ifinfo.ifname);
+
+    if (n<0)
+    {
+        /* <rdar://problem/10287386>
+         * sometimes there can be a race condition btw when the bpf socket
+         * gets data and the callback get scheduled and when we call BIOCSETF (which
+         * clears the socket).  this can cause the read to hang for a really long time
+         * and effectively prevent us from responding to requests for long periods of time.
+         * to prevent this make the socket non blocking and just bail if we dont get anything
+         */
+        if (errno == EAGAIN)
+        {
+            LogMsg("bpf_callback got EAGAIN bailing");
+            goto exit;
+        }
+        LogMsg("Closing %s BPF fd %d due to error %d (%s)", info->ifinfo.ifname, info->BPF_fd, errno, strerror(errno));
+        CloseBPF(info);
+        goto exit;
+    }
+
+    while (ptr < end)
+    {
+        const struct bpf_hdr *const bh = (const struct bpf_hdr *)ptr;
+        debugf("%3d: bpf_callback ptr %p bh_hdrlen %d data %p bh_caplen %4d bh_datalen %4d next %p remaining %4d",
+               info->BPF_fd, ptr, bh->bh_hdrlen, ptr + bh->bh_hdrlen, bh->bh_caplen, bh->bh_datalen,
+               ptr + BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen), end - (ptr + BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen)));
+        // Note that BPF guarantees that the NETWORK LAYER header will be word aligned, not the link-layer header.
+        // Given that An Ethernet header is 14 bytes, this means that if the network layer header (e.g. IP header,
+        // ARP message, etc.) is 4-byte aligned, then necessarily the Ethernet header will be NOT be 4-byte aligned.
+        mDNSCoreReceiveRawPacket(info->m, ptr + bh->bh_hdrlen, ptr + bh->bh_hdrlen + bh->bh_caplen, info->ifinfo.InterfaceID);
+        ptr += BPF_WORDALIGN(bh->bh_hdrlen + bh->bh_caplen);
+    }
+exit:
+    KQueueUnlock(info->m, "bpf_callback");
+}
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+mDNSlocal void bpf_callback_dispatch(NetworkInterfaceInfoOSX *const info)
+{
+    bpf_callback_common(info);
+}
+#else
+mDNSlocal void bpf_callback(const CFSocketRef cfs, const CFSocketCallBackType CallBackType, const CFDataRef address, const void *const data, void *const context)
+{
+    (void)cfs;
+    (void)CallBackType;
+    (void)address;
+    (void)data;
+    bpf_callback_common((NetworkInterfaceInfoOSX *)context);
+}
+#endif
+
+mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win)
+{
+    LogMsg("mDNSPlatformSendKeepalive called\n");
+    mDNSSendKeepalive(sadd->ip.v6.b, dadd->ip.v6.b, lport->NotAnInteger, rport->NotAnInteger, seq, ack, win);
+}
+
+mDNSexport mStatus  mDNSPlatformClearSPSMACAddr(void)
+{
+    SCDynamicStoreRef store = NULL;
+    CFStringRef  entityname = NULL;
+
+    if ((store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:ClearSPSMACAddress"), NULL, NULL)))
+    {
+        if ((entityname = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s%s"), "State:/Network/Interface/", "[^/]", "/BonjourSleepProxyAddress")))
+        {
+            if (SCDynamicStoreRemoveValue(store, entityname) == false)
+                LogMsg("mDNSPlatformClearSPSMACAddr: Unable to remove key");
+        }
+    }
+
+    if (entityname) CFRelease(entityname);
+    if (store)      CFRelease(store);
+    return KERN_SUCCESS;
+}
+
+mDNSexport mStatus mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname)
+{
+    int family = (spsaddr->type == mDNSAddrType_IPv4) ? AF_INET : AF_INET6;
+    LogSPS("mDNSPlatformStoreSPSMACAddr : Storing %#a on interface %s", spsaddr, ifname);
+    mDNSStoreSPSMACAddress(family, spsaddr->ip.v6.b, ifname);
+    return KERN_SUCCESS;
+}
+
+mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr)
+{
+    int family = (raddr->type == mDNSAddrType_IPv4) ? AF_INET : AF_INET6;
+
+    mDNSGetRemoteMAC(m, family, raddr->ip.v6.b);
+    return KERN_SUCCESS;
+}
+
+mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti)
+{
+    mDNSs32 intfid;
+    mDNSs32 error  = 0;
+    int     family = (laddr->type == mDNSAddrType_IPv4) ? AF_INET : AF_INET6;
+
+    error = mDNSRetrieveTCPInfo(family, laddr->ip.v6.b, lport->NotAnInteger, raddr->ip.v6.b, rport->NotAnInteger, (uint32_t *)&(mti->seq), (uint32_t *)&(mti->ack), (uint16_t *)&(mti->window), (int32_t*)&intfid);
+    if (error != KERN_SUCCESS)
+    {
+        LogMsg("%s: mDNSRetrieveTCPInfo returned : %d", __func__, error);
+        return error;
+    }
+    mti->IntfId = mDNSPlatformInterfaceIDfromInterfaceIndex(m, 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)
+{
+    int numv4 = 0, numv6 = 0;
+    AuthRecord *rr;
+
+    for (rr = m->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)
+        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);
+            numv6++;
+        }
+
+    if (p4) *p4 = numv4;
+    if (p6) *p6 = numv6;
+    return(numv4 + numv6);
+}
+
+mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
+{
+    NetworkInterfaceInfoOSX *x;
+
+    // Note: We can't use IfIndexToInterfaceInfoOSX because that looks for Registered also.
+    for (x = m->p->InterfaceList; x; x = x->next) if (x->ifinfo.InterfaceID == InterfaceID) break;
+
+    if (!x) { LogMsg("mDNSPlatformUpdateProxyList: ERROR InterfaceID %p not found", InterfaceID); return; }
+
+    #define MAX_BPF_ADDRS 250
+    int numv4 = 0, numv6 = 0;
+
+    if (CountProxyTargets(m, 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;
+        numv6 = MAX_BPF_ADDRS - numv4;
+    }
+
+    LogSPS("mDNSPlatformUpdateProxyList: fd %d %-7s MAC  %.6a %d v4 %d v6", x->BPF_fd, x->ifinfo.ifname, &x->ifinfo.MAC, numv4, numv6);
+
+    // Caution: This is a static structure, so we need to be careful that any modifications we make to it
+    // are done in such a way that they work correctly when mDNSPlatformUpdateProxyList is called multiple times
+    static struct bpf_insn filter[17 + MAX_BPF_ADDRS] =
+    {
+        BPF_STMT(BPF_LD  + BPF_H   + BPF_ABS, 12),              // 0 Read Ethertype (bytes 12,13)
+
+        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0806, 0, 1),      // 1 If Ethertype == ARP goto next, else 3
+        BPF_STMT(BPF_RET + BPF_K,             42),              // 2 Return 42-byte ARP
+
+        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0800, 4, 0),      // 3 If Ethertype == IPv4 goto 8 (IPv4 address list check) else next
+
+        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x86DD, 0, 9),      // 4 If Ethertype == IPv6 goto next, else exit
+        BPF_STMT(BPF_LD  + BPF_H   + BPF_ABS, 20),              // 5 Read Protocol and Hop Limit (bytes 20,21)
+        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x3AFF, 0, 9),      // 6 If (Prot,TTL) == (3A,FF) goto next, else IPv6 address list check
+        BPF_STMT(BPF_RET + BPF_K,             86),              // 7 Return 86-byte ND
+
+        // Is IPv4 packet; check if it's addressed to any IPv4 address we're proxying for
+        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
+
+    // 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);
+
+    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 != fail) LogMsg("mDNSPlatformUpdateProxyList: pc %p != fail %p", pc, fail);
+    *pc++ = rf;     // fail points here
+
+    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
+
+    struct bpf_program prog = { pc - filter, filter };
+
+#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);
+#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->p->NetworkChanged) m->p->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
+    }
+    
+    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)
+{
+    mDNS_Lock(m);
+
+    NetworkInterfaceInfoOSX *i;
+    for (i = m->p->InterfaceList; i; i = i->next) if (i->BPF_fd == -2) break;
+    if (!i) { LogSPS("mDNSPlatformReceiveBPF_fd: No Interfaces awaiting BPF fd %d; closing", fd); close(fd); }
+    else
+    {
+        LogSPS("%s using   BPF fd %d", i->ifinfo.ifname, fd);
+
+        struct bpf_version v;
+        if (ioctl(fd, BIOCVERSION, &v) < 0)
+            LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCVERSION failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
+        else if (BPF_MAJOR_VERSION != v.bv_major || BPF_MINOR_VERSION != v.bv_minor)
+            LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCVERSION header %d.%d kernel %d.%d",
+                   fd, i->ifinfo.ifname, BPF_MAJOR_VERSION, BPF_MINOR_VERSION, v.bv_major, v.bv_minor);
+
+        if (ioctl(fd, BIOCGBLEN, &i->BPF_len) < 0)
+            LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCGBLEN failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
+
+        if (i->BPF_len > sizeof(m->imsg))
+        {
+            i->BPF_len = sizeof(m->imsg);
+            if (ioctl(fd, BIOCSBLEN, &i->BPF_len) < 0)
+                LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSBLEN failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
+            else
+                LogSPS("mDNSPlatformReceiveBPF_fd: %d %s BIOCSBLEN %d", fd, i->ifinfo.ifname, i->BPF_len);
+        }
+
+        static const u_int opt_one = 1;
+        if (ioctl(fd, BIOCIMMEDIATE, &opt_one) < 0)
+            LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCIMMEDIATE failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
+
+        //if (ioctl(fd, BIOCPROMISC, &opt_one) < 0)
+        //	LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCPROMISC failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
+
+        //if (ioctl(fd, BIOCSHDRCMPLT, &opt_one) < 0)
+        //	LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSHDRCMPLT failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
+
+        /*  <rdar://problem/10287386>
+         *  make socket non blocking see comments in bpf_callback_common for more info
+         */
+        if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) < 0) // set non-blocking
+        {
+            LogMsg("mDNSPlatformReceiveBPF_fd: %d %s O_NONBLOCK failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno));
+        }
+
+        struct ifreq ifr;
+        mDNSPlatformMemZero(&ifr, sizeof(ifr));
+        strlcpy(ifr.ifr_name, i->ifinfo.ifname, sizeof(ifr.ifr_name));
+        if (ioctl(fd, BIOCSETIF, &ifr) < 0)
+        { LogMsg("mDNSPlatformReceiveBPF_fd: %d %s BIOCSETIF failed %d (%s)", fd, i->ifinfo.ifname, errno, strerror(errno)); i->BPF_fd = -3; }
+        else
+        {
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+            i->BPF_fd  = fd;
+            i->BPF_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, dispatch_get_main_queue());
+            if (!i->BPF_source) {LogMsg("mDNSPlatformReceiveBPF_fd: dispatch source create failed"); return;}
+            dispatch_source_set_event_handler(i->BPF_source, ^{bpf_callback_dispatch(i);});
+            dispatch_source_set_cancel_handler(i->BPF_source, ^{close(fd);});
+            dispatch_resume(i->BPF_source);
+#else
+            CFSocketContext myCFSocketContext = { 0, i, NULL, NULL, NULL };
+            i->BPF_fd  = fd;
+            i->BPF_cfs = CFSocketCreateWithNative(kCFAllocatorDefault, fd, kCFSocketReadCallBack, bpf_callback, &myCFSocketContext);
+            i->BPF_rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, i->BPF_cfs, 0);
+            CFRunLoopAddSource(i->m->p->CFRunLoop, i->BPF_rls, kCFRunLoopDefaultMode);
+#endif
+            mDNSPlatformUpdateProxyList(m, i->ifinfo.InterfaceID);
+        }
+    }
+
+    mDNS_Unlock(m);
+}
+
+#endif // APPLE_OSX_mDNSResponder
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - Key Management
+#endif
+
+#ifndef NO_SECURITYFRAMEWORK
+mDNSlocal CFArrayRef GetCertChain(SecIdentityRef identity)
+{
+    CFMutableArrayRef certChain = NULL;
+    if (!identity) { LogMsg("getCertChain: identity is NULL"); return(NULL); }
+    SecCertificateRef cert;
+    OSStatus err = SecIdentityCopyCertificate(identity, &cert);
+    if (err || !cert) LogMsg("getCertChain: SecIdentityCopyCertificate() returned %d", (int) err);
+    else
+    {
+        SecPolicySearchRef searchRef;
+        err = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &searchRef);
+        if (err || !searchRef) LogMsg("getCertChain: SecPolicySearchCreate() returned %d", (int) err);
+        else
+        {
+            SecPolicyRef policy;
+            err = SecPolicySearchCopyNext(searchRef, &policy);
+            if (err || !policy) LogMsg("getCertChain: SecPolicySearchCopyNext() returned %d", (int) err);
+            else
+            {
+                CFArrayRef wrappedCert = CFArrayCreate(NULL, (const void**) &cert, 1, &kCFTypeArrayCallBacks);
+                if (!wrappedCert) LogMsg("getCertChain: wrappedCert is NULL");
+                else
+                {
+                    SecTrustRef trust;
+                    err = SecTrustCreateWithCertificates(wrappedCert, policy, &trust);
+                    if (err || !trust) LogMsg("getCertChain: SecTrustCreateWithCertificates() returned %d", (int) err);
+                    else
+                    {
+                        err = SecTrustEvaluate(trust, NULL);
+                        if (err) LogMsg("getCertChain: SecTrustEvaluate() returned %d", (int) err);
+                        else
+                        {
+                            CFArrayRef rawCertChain;
+                            CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL;
+                            err = SecTrustGetResult(trust, NULL, &rawCertChain, &statusChain);
+                            if (err || !rawCertChain || !statusChain) LogMsg("getCertChain: SecTrustGetResult() returned %d", (int) err);
+                            else
+                            {
+                                certChain = CFArrayCreateMutableCopy(NULL, 0, rawCertChain);
+                                if (!certChain) LogMsg("getCertChain: certChain is NULL");
+                                else
+                                {
+                                    // Replace the SecCertificateRef at certChain[0] with a SecIdentityRef per documentation for SSLSetCertificate:
+                                    // <http://devworld.apple.com/documentation/Security/Reference/secureTransportRef/index.html>
+                                    CFArraySetValueAtIndex(certChain, 0, identity);
+                                    // Remove root from cert chain, but keep any and all intermediate certificates that have been signed by the root certificate
+                                    if (CFArrayGetCount(certChain) > 1) CFArrayRemoveValueAtIndex(certChain, CFArrayGetCount(certChain) - 1);
+                                }
+                                CFRelease(rawCertChain);
+                                // Do not free statusChain:
+                                // <http://developer.apple.com/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html> says:
+                                // certChain: Call the CFRelease function to release this object when you are finished with it.
+                                // statusChain: Do not attempt to free this pointer; it remains valid until the trust management object is released...
+                            }
+                        }
+                        CFRelease(trust);
+                    }
+                    CFRelease(wrappedCert);
+                }
+                CFRelease(policy);
+            }
+            CFRelease(searchRef);
+        }
+        CFRelease(cert);
+    }
+    return certChain;
+}
+#endif /* NO_SECURITYFRAMEWORK */
+
+mDNSexport mStatus mDNSPlatformTLSSetupCerts(void)
+{
+#ifdef NO_SECURITYFRAMEWORK
+    return mStatus_UnsupportedErr;
+#else
+    SecIdentityRef identity = nil;
+    SecIdentitySearchRef srchRef = nil;
+    OSStatus err;
+
+    // search for "any" identity matching specified key use
+    // In this app, we expect there to be exactly one
+    err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_DECRYPT, &srchRef);
+    if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCreate returned %d", (int) err); return err; }
+
+    err = SecIdentitySearchCopyNext(srchRef, &identity);
+    if (err) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext returned %d", (int) err); return err; }
+
+    if (CFGetTypeID(identity) != SecIdentityGetTypeID())
+    { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: SecIdentitySearchCopyNext CFTypeID failure"); return mStatus_UnknownErr; }
+
+    // Found one. Call getCertChain to create the correct certificate chain.
+    ServerCerts = GetCertChain(identity);
+    if (ServerCerts == nil) { LogMsg("ERROR: mDNSPlatformTLSSetupCerts: getCertChain error"); return mStatus_UnknownErr; }
+
+    return mStatus_NoError;
+#endif /* NO_SECURITYFRAMEWORK */
+}
+
+mDNSexport void  mDNSPlatformTLSTearDownCerts(void)
+{
+#ifndef NO_SECURITYFRAMEWORK
+    if (ServerCerts) { CFRelease(ServerCerts); ServerCerts = NULL; }
+#endif /* NO_SECURITYFRAMEWORK */
+}
+
+// This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel
+mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
+{
+    CFStringEncoding encoding = kCFStringEncodingUTF8;
+    CFStringRef cfs = SCDynamicStoreCopyComputerName(NULL, &encoding);
+    if (cfs)
+    {
+        CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
+        CFRelease(cfs);
+    }
+}
+
+// This gets the text of the field currently labelled "Local Hostname" in the Sharing Prefs Control Panel
+mDNSlocal void GetUserSpecifiedLocalHostName(domainlabel *const namelabel)
+{
+    CFStringRef cfs = SCDynamicStoreCopyLocalHostName(NULL);
+    if (cfs)
+    {
+        CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8);
+        CFRelease(cfs);
+    }
+}
+
+mDNSexport mDNSBool DictionaryIsEnabled(CFDictionaryRef dict)
+{
+    mDNSs32 val;
+    CFNumberRef state = (CFNumberRef)CFDictionaryGetValue(dict, CFSTR("Enabled"));
+    if (!state) return mDNSfalse;
+    if (!CFNumberGetValue(state, kCFNumberSInt32Type, &val))
+    { LogMsg("ERROR: DictionaryIsEnabled - CFNumberGetValue"); return mDNSfalse; }
+    return val ? mDNStrue : mDNSfalse;
+}
+
+mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
+{
+    if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
+
+    if (sa->sa_family == AF_INET)
+    {
+        struct sockaddr_in *ifa_addr = (struct sockaddr_in *)sa;
+        ip->type = mDNSAddrType_IPv4;
+        ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr;
+        return(mStatus_NoError);
+    }
+
+    if (sa->sa_family == AF_INET6)
+    {
+        struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
+        // Inside the BSD kernel they use a hack where they stuff the sin6->sin6_scope_id
+        // value into the second word of the IPv6 link-local address, so they can just
+        // pass around IPv6 address structures instead of full sockaddr_in6 structures.
+        // Those hacked IPv6 addresses aren't supposed to escape the kernel in that form, but they do.
+        // To work around this we always whack the second word of any IPv6 link-local address back to zero.
+        if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
+        ip->type = mDNSAddrType_IPv6;
+        ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
+        return(mStatus_NoError);
+    }
+
+    LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
+    return(mStatus_Invalid);
+}
+
+mDNSlocal mDNSEthAddr GetBSSID(char *ifa_name)
+{
+    mDNSEthAddr eth = zeroEthAddr;
+    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetBSSID"), NULL, NULL);
+    if (!store)
+        LogMsg("GetBSSID: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
+    else
+    {
+        CFStringRef entityname = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Interface/%s/AirPort"), ifa_name);
+        if (entityname)
+        {
+            CFDictionaryRef dict = SCDynamicStoreCopyValue(store, entityname);
+            if (dict)
+            {
+                CFRange range = { 0, 6 };       // Offset, length
+                CFDataRef data = CFDictionaryGetValue(dict, CFSTR("BSSID"));
+                if (data && CFDataGetLength(data) == 6) CFDataGetBytes(data, range, eth.b);
+                CFRelease(dict);
+            }
+            CFRelease(entityname);
+        }
+        CFRelease(store);
+    }
+    return(eth);
+}
+
+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)
+        {
+            const struct sockaddr_dl *const sdl = (const struct sockaddr_dl *)ifa->ifa_addr;
+            if (sdl->sdl_index == ifindex)
+            { mDNSPlatformMemCopy(eth->b, sdl->sdl_data + sdl->sdl_nlen, 6); return 0; }
+        }
+    *eth = zeroEthAddr;
+    return -1;
+}
+
+#ifndef SIOCGIFWAKEFLAGS
+#define SIOCGIFWAKEFLAGS _IOWR('i', 136, struct ifreq) /* get interface wake property flags */
+#endif
+
+#ifndef IF_WAKE_ON_MAGIC_PACKET
+#define IF_WAKE_ON_MAGIC_PACKET 0x01
+#endif
+
+#ifndef ifr_wake_flags
+#define ifr_wake_flags ifr_ifru.ifru_intval
+#endif
+
+mDNSlocal mDNSBool  CheckInterfaceSupport(NetworkInterfaceInfo *const intf, const char *key)
+{
+    io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOBSDNameMatching(kIOMasterPortDefault, 0, intf->ifname));
+    if (!service)
+    {
+        LogSPS("CheckInterfaceSupport: No service for interface %s", intf->ifname);
+        return mDNSfalse;
+    }
+
+    io_name_t n1, n2;
+    IOObjectGetClass(service, n1);
+    io_object_t parent;
+    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);
+        if (!ref)
+        {
+            LogSPS("CheckInterfaceSupport: No mDNS_IOREG_KEY for interface %s/%s/%s", intf->ifname, n1, n2);
+            ret = mDNSfalse;
+        }
+        else
+        {
+            ret = mDNStrue;
+            CFRelease(ref);
+        }
+        IOObjectRelease(parent);
+        CFRelease(keystr);
+    }
+    else
+    {
+        LogSPS("CheckInterfaceSupport: IORegistryEntryGetParentEntry for %s/%s failed %d", intf->ifname, n1, kr);
+        ret = mDNSfalse;
+    }
+    IOObjectRelease(service);
+    return ret;
+}
+
+
+mDNSlocal  mDNSBool InterfaceSupportsKeepAlive(NetworkInterfaceInfo *const intf)
+{
+    return CheckInterfaceSupport(intf, mDNS_IOREG_KA_KEY);
+}
+
+mDNSlocal mDNSBool NetWakeInterface(NetworkInterfaceInfoOSX *i)
+{
+    if (!MulticastInterface(i)     ) return(mDNSfalse); // We only use Sleep Proxy Service on multicast-capable interfaces
+    if (i->ifa_flags & IFF_LOOPBACK) return(mDNSfalse); // except loopback
+
+    // If the interface supports TCPKeepalive, it is capable of waking up for a magic packet
+    // This check is needed since the SIOCGIFWAKEFLAGS ioctl returns wrong values for WOMP capability
+    // when the power source is not AC Power.
+    if (InterfaceSupportsKeepAlive(&i->ifinfo))
+    {
+        LogSPS("NetWakeInterface: %s supports TCP Keepalive returning true", i->ifinfo.ifname);
+        return mDNStrue;
+    }
+
+    int s = socket(AF_INET, SOCK_DGRAM, 0);
+    if (s < 0) { LogMsg("NetWakeInterface socket failed %s error %d errno %d (%s)", i->ifinfo.ifname, s, errno, strerror(errno)); return(mDNSfalse); }
+
+    struct ifreq ifr;
+    strlcpy(ifr.ifr_name, i->ifinfo.ifname, sizeof(ifr.ifr_name));
+    if (ioctl(s, SIOCGIFWAKEFLAGS, &ifr) < 0)
+    {
+        // For some strange reason, in /usr/include/sys/errno.h, EOPNOTSUPP is defined to be
+        // 102 when compiling kernel code, and 45 when compiling user-level code. Since this
+        // error code is being returned from the kernel, we need to use the kernel version.
+        #define KERNEL_EOPNOTSUPP 102
+        if (errno != KERNEL_EOPNOTSUPP) // "Operation not supported on socket", the expected result on Leopard and earlier
+            LogMsg("NetWakeInterface SIOCGIFWAKEFLAGS %s errno %d (%s)", i->ifinfo.ifname, errno, strerror(errno));
+        // If on Leopard or earlier, we get EOPNOTSUPP, so in that case
+        // we enable WOL if this interface is not AirPort and "Wake for Network access" is turned on.
+        ifr.ifr_wake_flags = (errno == KERNEL_EOPNOTSUPP && !(i)->BSSID.l[0] && i->m->SystemWakeOnLANEnabled) ? IF_WAKE_ON_MAGIC_PACKET : 0;
+    }
+
+    close(s);
+
+    // 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");
+
+    return((ifr.ifr_wake_flags & IF_WAKE_ON_MAGIC_PACKET) != 0);
+}
+
+mDNSlocal u_int64_t getExtendedFlags(char * ifa_name)
+{
+    int sockFD;
+    struct ifreq ifr;
+
+    sockFD = socket(AF_INET, SOCK_DGRAM, 0);
+    if (sockFD < 0)
+    {
+        LogMsg("getExtendedFlags: socket() call failed, errno = %d (%s)", errno, strerror(errno));
+        return 0;
+    }
+
+    ifr.ifr_addr.sa_family = AF_INET;
+    strlcpy(ifr.ifr_name, ifa_name, sizeof(ifr.ifr_name));
+
+    if (ioctl(sockFD, SIOCGIFEFLAGS, (caddr_t)&ifr) == -1)
+    {
+        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;
+}
+
+// Returns pointer to newly created NetworkInterfaceInfoOSX object, or
+// 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)
+{
+    mDNSu32 scope_id  = if_nametoindex(ifa->ifa_name);
+    mDNSEthAddr bssid = GetBSSID(ifa->ifa_name);
+    u_int64_t   eflags = getExtendedFlags(ifa->ifa_name);
+
+    mDNSAddr ip, mask;
+    if (SetupAddr(&ip,   ifa->ifa_addr   ) != mStatus_NoError) return(NULL);
+    if (SetupAddr(&mask, ifa->ifa_netmask) != mStatus_NoError) return(NULL);
+
+    NetworkInterfaceInfoOSX **p;
+    for (p = &m->p->InterfaceList; *p; p = &(*p)->next)
+        if (scope_id == (*p)->scope_id &&
+            mDNSSameAddress(&ip, &(*p)->ifinfo.ip) &&
+            mDNSSameEthAddress(&bssid, &(*p)->BSSID))
+        {
+            debugf("AddInterfaceToList: Found existing interface %lu %.6a with address %#a at %p, ifname before %s, after %s", scope_id, &bssid, &ip, *p, (*p)->ifinfo.ifname, ifa->ifa_name);
+            // The name should be updated to the new name so that we don't report a wrong name in our SIGINFO output.
+            // When interfaces are created with same MAC address, kernel resurrects the old interface.
+            // Even though the interface index is the same (which should be sufficient), when we receive a UDP packet
+            // we get the corresponding name for the interface index on which the packet was received and check against
+            // the InterfaceList for a matching name. So, keep the name in sync
+            strlcpy((*p)->ifinfo.ifname, ifa->ifa_name, sizeof((*p)->ifinfo.ifname));
+            (*p)->Exists = mDNStrue;
+            // If interface was not in getifaddrs list last time we looked, but it is now, update 'AppearanceTime' for this record
+            if ((*p)->LastSeen != utc) (*p)->AppearanceTime = utc;
+
+            // If Wake-on-LAN capability of this interface has changed (e.g. because power cable on laptop has been disconnected)
+            // we may need to start or stop or sleep proxy browse operation
+            const mDNSBool NetWake = NetWakeInterface(*p);
+            if ((*p)->ifinfo.NetWake != NetWake)
+            {
+                (*p)->ifinfo.NetWake = NetWake;
+                // If this interface is already registered with mDNSCore, then we need to start or stop its NetWake browse on-the-fly.
+                // If this interface is not already registered (i.e. it's a dormant interface we had in our list
+                // from when we previously saw it) then we mustn't do that, because mDNSCore doesn't know about it yet.
+                // In this case, the mDNS_RegisterInterface() call will take care of starting the NetWake browse if necessary.
+                if ((*p)->Registered)
+                {
+                    mDNS_Lock(m);
+                    if (NetWake) mDNS_ActivateNetWake_internal  (m, &(*p)->ifinfo);
+                    else mDNS_DeactivateNetWake_internal(m, &(*p)->ifinfo);
+                    mDNS_Unlock(m);
+                }
+            }
+            // Reset the flag if it has changed this time.
+            (*p)->ifinfo.IgnoreIPv4LL = ((eflags & IFEF_ARPLL) != 0) ? mDNSfalse : mDNStrue;
+
+            return(*p);
+        }
+
+    NetworkInterfaceInfoOSX *i = (NetworkInterfaceInfoOSX *)mallocL("NetworkInterfaceInfoOSX", sizeof(*i));
+    debugf("AddInterfaceToList: Making   new   interface %lu %.6a with address %#a at %p", scope_id, &bssid, &ip, i);
+    if (!i) return(mDNSNULL);
+    mDNSPlatformMemZero(i, sizeof(NetworkInterfaceInfoOSX));
+    i->ifinfo.InterfaceID = (mDNSInterfaceID)(uintptr_t)scope_id;
+    i->ifinfo.ip          = ip;
+    i->ifinfo.mask        = mask;
+    strlcpy(i->ifinfo.ifname, ifa->ifa_name, sizeof(i->ifinfo.ifname));
+    i->ifinfo.ifname[sizeof(i->ifinfo.ifname)-1] = 0;
+    // We can be configured to disable multicast advertisement, but we want to to support
+    // local-only services, which need a loopback address record.
+    i->ifinfo.Advertise   = m->DivertMulticastAdvertisements ? ((ifa->ifa_flags & IFF_LOOPBACK) ? mDNStrue : mDNSfalse) : m->AdvertiseLocalAddresses;
+    i->ifinfo.McastTxRx   = mDNSfalse; // For now; will be set up later at the end of UpdateInterfaceList
+    i->ifinfo.Loopback    = ((ifa->ifa_flags & IFF_LOOPBACK) != 0) ? mDNStrue : mDNSfalse;
+    i->ifinfo.IgnoreIPv4LL = ((eflags & IFEF_ARPLL) != 0) ? mDNSfalse : mDNStrue;
+    i->ifinfo.DirectLink  = (eflags & IFEF_DIRECTLINK) ? mDNStrue: mDNSfalse;
+
+    i->next            = mDNSNULL;
+    i->m               = m;
+    i->Exists          = mDNStrue;
+    i->Flashing        = mDNSfalse;
+    i->Occulting       = mDNSfalse;
+    i->D2DInterface    = (eflags & IFEF_LOCALNET_PRIVATE) ? mDNStrue: mDNSfalse;
+    if (eflags & IFEF_AWDL)
+    {
+        AWDLInterfaceID = i->ifinfo.InterfaceID;
+        LogInfo("AddInterfaceToList: AWDLInterfaceID = %d", (int) AWDLInterfaceID);
+    }
+    i->AppearanceTime  = utc;       // Brand new interface; AppearanceTime is now
+    i->LastSeen        = utc;
+    i->ifa_flags       = ifa->ifa_flags;
+    i->scope_id        = scope_id;
+    i->BSSID           = bssid;
+    i->sa_family       = ifa->ifa_addr->sa_family;
+    i->BPF_fd          = -1;
+    i->BPF_mcfd        = -1;
+    i->BPF_len         = 0;
+    i->Registered      = mDNSNULL;
+
+    // Do this AFTER i->BSSID has been set up
+    i->ifinfo.NetWake  = NetWakeInterface(i);
+    GetMAC(&i->ifinfo.MAC, scope_id);
+    if (i->ifinfo.NetWake && !i->ifinfo.MAC.l[0])
+        LogMsg("AddInterfaceToList: Bad MAC address %.6a for %d %s %#a", &i->ifinfo.MAC, scope_id, i->ifinfo.ifname, &ip);
+
+    *p = i;
+    return(i);
+}
+
+#if APPLE_OSX_mDNSResponder
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - AutoTunnel
+#endif
+
+#define kRacoonPort 4500
+
+static DomainAuthInfo* AnonymousRacoonConfig = mDNSNULL;
+
+#ifndef NO_SECURITYFRAMEWORK
+
+static CFMutableDictionaryRef domainStatusDict = NULL;
+
+mDNSlocal mStatus CheckQuestionForStatus(const DNSQuestion *const q)
+{
+    if (q->LongLived)
+    {
+        if (q->servAddr.type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsOnes(q->servAddr.ip.v4))
+            return mStatus_NoSuchRecord;
+        else if (q->state == LLQ_Poll)
+            return mStatus_PollingMode;
+        else if (q->state != LLQ_Established && !q->DuplicateOf)
+            return mStatus_TransientErr;
+    }
+
+    return mStatus_NoError;
+}
+
+mDNSlocal mStatus UpdateLLQStatus(const mDNS *const m, 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)
+        if (q->AuthInfo == info)
+        {
+            mStatus newStatus = CheckQuestionForStatus(q);
+            if      (newStatus == mStatus_NoSuchRecord) { status = newStatus; worst_q = q; break; }
+            else if (newStatus == mStatus_PollingMode)  { status = newStatus; worst_q = q; }
+            else if (newStatus == mStatus_TransientErr && status == mStatus_NoError) { status = newStatus; worst_q = q; }
+        }
+
+    if      (status == mStatus_NoError) mDNS_snprintf(buffer, bufsz, "Success");
+    else if (status == mStatus_NoSuchRecord) mDNS_snprintf(buffer, bufsz, "GetZoneData %s: %##s", worst_q->nta ? "not yet complete" : "failed", worst_q->qname.c);
+    else if (status == mStatus_PollingMode) mDNS_snprintf(buffer, bufsz, "Query polling %##s", worst_q->qname.c);
+    else if (status == mStatus_TransientErr) mDNS_snprintf(buffer, bufsz, "Query not yet established %##s", worst_q->qname.c);
+    return status;
+}
+
+mDNSlocal mStatus UpdateRRStatus(const mDNS *const m, char *buffer, int bufsz, const DomainAuthInfo *const info)
+{
+    AuthRecord *r;
+
+    if (info->deltime) return mStatus_NoError;
+    for (r = m->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),
+        // hence we inline the code here. We just need the lock to walk the list of AuthInfos which the caller
+        // has already checked
+        const domainname *n = r->resrec.name;
+        while (n->c[0])
+        {
+            DomainAuthInfo *ptr;
+            for (ptr = m->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))
+                    {
+                        mDNS_snprintf(buffer, bufsz, "Resource record update failed for %##s", r->resrec.name);
+                        return r->updateError;
+                    }
+                }
+            n = (const domainname *)(n->c + 1 + n->c[0]);
+        }
+    }
+    return mStatus_NoError;
+}
+
+#endif // ndef NO_SECURITYFRAMEWORK
+
+// MUST be called with lock held
+mDNSlocal void UpdateAutoTunnelDomainStatus(const mDNS *const m, 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
+    const NATTraversalInfo *const llq = m->LLQNAT.clientCallback ? &m->LLQNAT : mDNSNULL;
+    const NATTraversalInfo *const tun = m->AutoTunnelNAT.clientContext ? &m->AutoTunnelNAT : mDNSNULL;
+    char buffer[1024];
+    mDNSu32 buflen = 0;
+    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+    CFStringRef domain = NULL;
+    CFStringRef tmp = NULL;
+    CFNumberRef num = NULL;
+    mStatus status = mStatus_NoError;
+    mStatus llqStatus = mStatus_NoError;
+    char llqBuffer[1024];
+
+    mDNS_CheckLock(m);
+
+    if (!domainStatusDict)
+    {
+        domainStatusDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+        if (!domainStatusDict) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFDictionary domainStatusDict"); return; }
+    }
+
+    if (!dict) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFDictionary dict"); return; }
+
+    buflen = mDNS_snprintf(buffer, sizeof(buffer), "%##s", info->domain.c);
+    domain = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
+    if (!domain) { LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString domain"); return; }
+
+    if (info->deltime)
+    {
+        if (CFDictionaryContainsKey(domainStatusDict, domain))
+        {
+            CFDictionaryRemoveValue(domainStatusDict, domain);
+            if (!m->ShutdownTime) mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, mDNSNULL, domainStatusDict);
+        }
+        CFRelease(domain);
+        CFRelease(dict);
+
+        return;
+    }
+
+    mDNS_snprintf(buffer, sizeof(buffer), "%#a", &m->Router);
+    tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
+    if (!tmp)
+        LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString RouterAddress");
+    else
+    {
+        CFDictionarySetValue(dict, CFSTR("RouterAddress"), tmp);
+        CFRelease(tmp);
+    }
+
+    if (llq)
+    {
+        mDNSu32 port = mDNSVal16(llq->ExternalPort);
+
+        num = CFNumberCreate(NULL, kCFNumberSInt32Type, &port);
+        if (!num)
+            LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LLQExternalPort");
+        else
+        {
+            CFDictionarySetValue(dict, CFSTR("LLQExternalPort"), num);
+            CFRelease(num);
+        }
+
+        if (llq->Result)
+        {
+            num = CFNumberCreate(NULL, kCFNumberSInt32Type, &llq->Result);
+            if (!num)
+                LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LLQNPMStatus");
+            else
+            {
+                CFDictionarySetValue(dict, CFSTR("LLQNPMStatus"), num);
+                CFRelease(num);
+            }
+        }
+    }
+
+    if (tun)
+    {
+        mDNSu32 port = mDNSVal16(tun->ExternalPort);
+
+        num = CFNumberCreate(NULL, kCFNumberSInt32Type, &port);
+        if (!num)
+            LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber AutoTunnelExternalPort");
+        else
+        {
+            CFDictionarySetValue(dict, CFSTR("AutoTunnelExternalPort"), num);
+            CFRelease(num);
+        }
+
+        mDNS_snprintf(buffer, sizeof(buffer), "%.4a", &tun->ExternalAddress);
+        tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
+        if (!tmp)
+            LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString ExternalAddress");
+        else
+        {
+            CFDictionarySetValue(dict, CFSTR("ExternalAddress"), tmp);
+            CFRelease(tmp);
+        }
+
+        if (tun->Result)
+        {
+            num = CFNumberCreate(NULL, kCFNumberSInt32Type, &tun->Result);
+            if (!num)
+                LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber AutoTunnelNPMStatus");
+            else
+            {
+                CFDictionarySetValue(dict, CFSTR("AutoTunnelNPMStatus"), num);
+                CFRelease(num);
+            }
+        }
+    }
+    if (tun || llq)
+    {
+        mDNSu32 code = m->LastNATMapResultCode;
+
+        num = CFNumberCreate(NULL, kCFNumberSInt32Type, &code);
+        if (!num)
+            LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber LastNATMapResultCode");
+        else
+        {
+            CFDictionarySetValue(dict, CFSTR("LastNATMapResultCode"), num);
+            CFRelease(num);
+        }
+    }
+
+    mDNS_snprintf(buffer, sizeof(buffer), "Success");
+    llqStatus = UpdateLLQStatus(m, llqBuffer, sizeof(llqBuffer), info);
+    status = UpdateRRStatus(m, 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)
+    if (status != mStatus_NoError)
+    {
+        LogInfo("UpdateAutoTunnelDomainStatus: RR Status %d, %s", status, buffer);
+    }
+    else if (m->Router.type == mDNSAddrType_None)
+    {
+        status = mStatus_NoRouter;
+        mDNS_snprintf(buffer, sizeof(buffer), "No network connection - none");
+    }
+    else if (m->Router.type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsZero(m->Router.ip.v4))
+    {
+        status = mStatus_NoRouter;
+        mDNS_snprintf(buffer, sizeof(buffer), "No network connection - v4 zero");
+    }
+    else if (mDNSIPv6AddressIsZero(info->AutoTunnelInnerAddress))
+    {
+        status = mStatus_ServiceNotRunning;
+        mDNS_snprintf(buffer, sizeof(buffer), "No inner address");
+    }
+    else if (!llq && !tun)
+    {
+        status = mStatus_NotInitializedErr;
+        mDNS_snprintf(buffer, sizeof(buffer), "Neither LLQ nor AutoTunnel NAT port mapping is currently active");
+    }
+    else if (llqStatus == mStatus_NoSuchRecord)
+    {
+        status = llqStatus;
+        mDNS_snprintf(buffer, sizeof(buffer), llqBuffer);
+    }
+    else if ((llq && llq->Result == mStatus_DoubleNAT) || (tun && tun->Result == mStatus_DoubleNAT))
+    {
+        status = mStatus_DoubleNAT;
+        mDNS_snprintf(buffer, sizeof(buffer), "Double NAT: Router is reporting a private address");
+    }
+    else if ((llq && llq->Result == mStatus_NATPortMappingDisabled) ||
+             (tun && tun->Result == mStatus_NATPortMappingDisabled) ||
+             (m->LastNATMapResultCode == NATErr_Refused && ((llq && !llq->Result && mDNSIPPortIsZero(llq->ExternalPort)) || (tun && !tun->Result && mDNSIPPortIsZero(tun->ExternalPort)))))
+    {
+        status = mStatus_NATPortMappingDisabled;
+        mDNS_snprintf(buffer, sizeof(buffer), "PCP/NAT-PMP is disabled on the router");
+    }
+    else if ((llq && llq->Result) || (tun && tun->Result))
+    {
+        status = mStatus_NATTraversal;
+        mDNS_snprintf(buffer, sizeof(buffer), "Error obtaining NAT port mapping from router");
+    }
+    else if ((llq && mDNSIPPortIsZero(llq->ExternalPort)) || (tun && mDNSIPPortIsZero(tun->ExternalPort)))
+    {
+        status = mStatus_NATTraversal;
+        mDNS_snprintf(buffer, sizeof(buffer), "Unable to obtain NAT port mapping from router");
+    }
+    else
+    {
+        status = llqStatus;
+        mDNS_snprintf(buffer, sizeof(buffer), llqBuffer);
+        LogInfo("UpdateAutoTunnelDomainStatus: LLQ Status %d, %s", status, buffer);
+    }
+
+    num = CFNumberCreate(NULL, kCFNumberSInt32Type, &status);
+    if (!num)
+        LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFNumber StatusCode");
+    else
+    {
+        CFDictionarySetValue(dict, CFSTR("StatusCode"), num);
+        CFRelease(num);
+    }
+
+    tmp = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
+    if (!tmp)
+        LogMsg("UpdateAutoTunnelDomainStatus: Could not create CFString StatusMessage");
+    else
+    {
+        CFDictionarySetValue(dict, CFSTR("StatusMessage"), tmp);
+        CFRelease(tmp);
+    }
+
+    if (!CFDictionaryContainsKey(domainStatusDict, domain) ||
+        !CFEqual(dict, (CFMutableDictionaryRef)CFDictionaryGetValue(domainStatusDict, domain)))
+    {
+        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, "");
+            mDNSDynamicStoreSetConfig(kmDNSBackToMyMacConfig, mDNSNULL, domainStatusDict);
+        }
+    }
+
+    CFRelease(domain);
+    CFRelease(dict);
+
+    debugf("UpdateAutoTunnelDomainStatus: %s", buffer);
+#endif // def NO_SECURITYFRAMEWORK
+}
+
+// MUST be called with lock held
+mDNSexport void UpdateAutoTunnelDomainStatuses(const mDNS *const m)
+{
+#ifdef NO_SECURITYFRAMEWORK
+        (void) m;
+#else
+    mDNS_CheckLock(m);
+    DomainAuthInfo* info;
+    for (info = m->AuthInfoList; info; info = info->next)
+        if (info->AutoTunnel && !info->deltime)
+            UpdateAutoTunnelDomainStatus(m, info);
+#endif // def NO_SECURITYFRAMEWORK
+}
+
+mDNSlocal void UpdateAnonymousRacoonConfig(mDNS *m)     // Determine whether we need racoon to accept incoming connections
+{
+    DomainAuthInfo *info;
+
+    for (info = m->AuthInfoList; info; info = info->next)
+        if (info->AutoTunnel && !info->deltime && (!mDNSIPPortIsZero(m->AutoTunnelNAT.ExternalPort) || !mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr)))
+            break;
+
+    if (info != AnonymousRacoonConfig)
+    {
+        AnonymousRacoonConfig = info;
+        // Create or revert configuration file, and start (or SIGHUP) Racoon
+        (void)mDNSConfigureServer(AnonymousRacoonConfig ? kmDNSUp : kmDNSDown, AnonymousRacoonConfig ? btmmprefix : mDNSNULL, AnonymousRacoonConfig ? &AnonymousRacoonConfig->domain : mDNSNULL);
+    }
+}
+
+mDNSlocal void AutoTunnelRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
+
+// Caller must hold the lock
+mDNSlocal mDNSBool DeregisterAutoTunnelRecord(mDNS *m, DomainAuthInfo *info, AuthRecord* record)
+{
+    mDNS_CheckLock(m);
+
+    LogInfo("DeregisterAutoTunnelRecord %##s %##s", &info->domain.c, record->namestorage.c);
+
+    if (record->resrec.RecordType > kDNSRecordTypeDeregistering)
+    {
+        mStatus err = mDNS_Deregister_internal(m, record, mDNS_Dereg_normal);
+        if (err)
+        {
+            record->resrec.RecordType = kDNSRecordTypeUnregistered;
+            LogMsg("DeregisterAutoTunnelRecord error %d deregistering %##s %##s", err, info->domain.c, record->namestorage.c);
+            return mDNSfalse;
+        }
+        else LogInfo("DeregisterAutoTunnelRecord: Deregistered");
+    }
+    else LogInfo("DeregisterAutoTunnelRecord: Not deregistering, state:%d", record->resrec.RecordType);
+
+    return mDNStrue;
+}
+
+// Caller must hold the lock
+mDNSlocal void DeregisterAutoTunnelHostRecord(mDNS *m, DomainAuthInfo *info)
+{
+    if (!DeregisterAutoTunnelRecord(m, info, &info->AutoTunnelHostRecord))
+    {
+        info->AutoTunnelHostRecord.namestorage.c[0] = 0;
+        m->NextSRVUpdate = NonZeroTime(m->timenow);
+    }
+}
+
+// Caller must hold the lock
+mDNSlocal void UpdateAutoTunnelHostRecord(mDNS *m, DomainAuthInfo *info)
+{
+    mStatus err;
+    mDNSBool NATProblem = mDNSIPPortIsZero(m->AutoTunnelNAT.ExternalPort) || m->AutoTunnelNAT.Result;
+
+    mDNS_CheckLock(m);
+
+    if (!info->AutoTunnelServiceStarted || info->deltime || m->ShutdownTime || mDNSIPv6AddressIsZero(info->AutoTunnelInnerAddress) || (m->SleepState != SleepState_Awake && NATProblem))
+    {
+        LogInfo("UpdateAutoTunnelHostRecord: Dereg %##s : AutoTunnelServiceStarted(%d) deltime(%d) address(%.16a) sleepstate(%d)",
+                info->domain.c, info->AutoTunnelServiceStarted, info->deltime, &info->AutoTunnelInnerAddress, m->SleepState);
+        DeregisterAutoTunnelHostRecord(m, info);
+    }
+    else if (info->AutoTunnelHostRecord.resrec.RecordType == kDNSRecordTypeUnregistered)
+    {
+        mDNS_SetupResourceRecord(&info->AutoTunnelHostRecord, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL,
+                                 kDNSRecordTypeUnregistered, AuthRecordAny, AutoTunnelRecordCallback, info);
+        info->AutoTunnelHostRecord.namestorage.c[0] = 0;
+        AppendDomainLabel(&info->AutoTunnelHostRecord.namestorage, &m->hostlabel);
+        AppendDomainName (&info->AutoTunnelHostRecord.namestorage, &info->domain);
+        info->AutoTunnelHostRecord.resrec.rdata->u.ipv6 = info->AutoTunnelInnerAddress;
+        info->AutoTunnelHostRecord.resrec.RecordType = kDNSRecordTypeKnownUnique;
+
+        err = mDNS_Register_internal(m, &info->AutoTunnelHostRecord);
+        if (err) LogMsg("UpdateAutoTunnelHostRecord error %d registering %##s", err, info->AutoTunnelHostRecord.namestorage.c);
+        else
+        {
+            // Make sure we trigger the registration of all SRV records in regState_NoTarget again
+            m->NextSRVUpdate = NonZeroTime(m->timenow);
+            LogInfo("UpdateAutoTunnelHostRecord registering %##s", info->AutoTunnelHostRecord.namestorage.c);
+        }
+    }
+    else LogInfo("UpdateAutoTunnelHostRecord: Type %d", info->AutoTunnelHostRecord.resrec.RecordType);
+}
+
+// Caller must hold the lock
+mDNSlocal void DeregisterAutoTunnelServiceRecords(mDNS *m, DomainAuthInfo *info)
+{
+    LogInfo("DeregisterAutoTunnelServiceRecords %##s", info->domain.c);
+
+    DeregisterAutoTunnelRecord(m, info, &info->AutoTunnelTarget);
+    DeregisterAutoTunnelRecord(m, info, &info->AutoTunnelService);
+    UpdateAutoTunnelHostRecord(m, info);
+}
+
+// Caller must hold the lock
+mDNSlocal void UpdateAutoTunnelServiceRecords(mDNS *m, DomainAuthInfo *info)
+{
+    mDNS_CheckLock(m);
+
+    if (!info->AutoTunnelServiceStarted || info->deltime || m->ShutdownTime || mDNSIPPortIsZero(m->AutoTunnelNAT.ExternalPort) || m->AutoTunnelNAT.Result)
+    {
+        LogInfo("UpdateAutoTunnelServiceRecords: Dereg %##s : AutoTunnelServiceStarted(%d) deltime(%d) ExtPort(%d) NATResult(%d)", info->domain.c, info->AutoTunnelServiceStarted, info->deltime, mDNSVal16(m->AutoTunnelNAT.ExternalPort), m->AutoTunnelNAT.Result);
+        DeregisterAutoTunnelServiceRecords(m, info);
+    }
+    else
+    {
+        if (info->AutoTunnelTarget.resrec.RecordType == kDNSRecordTypeUnregistered)
+        {
+            // 1. Set up our address record for the external tunnel address
+            // (Constructed name, not generally user-visible, used as target in IKE tunnel's SRV record)
+            mDNS_SetupResourceRecord(&info->AutoTunnelTarget, mDNSNULL, mDNSInterface_Any, kDNSType_A, kHostNameTTL,
+                                     kDNSRecordTypeUnregistered, AuthRecordAny, AutoTunnelRecordCallback, info);
+            AssignDomainName (&info->AutoTunnelTarget.namestorage, (const domainname*) "\x0B" "_autotunnel");
+            AppendDomainLabel(&info->AutoTunnelTarget.namestorage, &m->hostlabel);
+            AppendDomainName (&info->AutoTunnelTarget.namestorage, &info->domain);
+            info->AutoTunnelTarget.resrec.rdata->u.ipv4 = m->AutoTunnelNAT.ExternalAddress;
+            info->AutoTunnelTarget.resrec.RecordType = kDNSRecordTypeKnownUnique;
+
+            mStatus err = mDNS_Register_internal(m, &info->AutoTunnelTarget);
+            if (err) LogMsg("UpdateAutoTunnelServiceRecords error %d registering %##s", err, info->AutoTunnelTarget.namestorage.c);
+            else LogInfo("UpdateAutoTunnelServiceRecords registering %##s", info->AutoTunnelTarget.namestorage.c);
+        }
+        else LogInfo("UpdateAutoTunnelServiceRecords: NOOP Target state(%d)", info->AutoTunnelTarget.resrec.RecordType);
+
+        if (info->AutoTunnelService.resrec.RecordType == kDNSRecordTypeUnregistered)
+        {
+            // 2. Set up IKE tunnel's SRV record: _autotunnel._udp.AutoTunnelHost SRV 0 0 port AutoTunnelTarget
+            mDNS_SetupResourceRecord(&info->AutoTunnelService, mDNSNULL, mDNSInterface_Any, kDNSType_SRV,  kHostNameTTL,
+                                     kDNSRecordTypeUnregistered, AuthRecordAny, AutoTunnelRecordCallback, info);
+            AssignDomainName (&info->AutoTunnelService.namestorage, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
+            AppendDomainLabel(&info->AutoTunnelService.namestorage, &m->hostlabel);
+            AppendDomainName (&info->AutoTunnelService.namestorage, &info->domain);
+            info->AutoTunnelService.resrec.rdata->u.srv.priority = 0;
+            info->AutoTunnelService.resrec.rdata->u.srv.weight   = 0;
+            info->AutoTunnelService.resrec.rdata->u.srv.port     = m->AutoTunnelNAT.ExternalPort;
+            AssignDomainName(&info->AutoTunnelService.resrec.rdata->u.srv.target, &info->AutoTunnelTarget.namestorage);
+            info->AutoTunnelService.resrec.RecordType = kDNSRecordTypeKnownUnique;
+
+            mStatus err = mDNS_Register_internal(m, &info->AutoTunnelService);
+            if (err) LogMsg("UpdateAutoTunnelServiceRecords error %d registering %##s", err, info->AutoTunnelService.namestorage.c);
+            else LogInfo("UpdateAutoTunnelServiceRecords registering %##s", info->AutoTunnelService.namestorage.c);
+        }
+        else LogInfo("UpdateAutoTunnelServiceRecords: NOOP Service state(%d)", info->AutoTunnelService.resrec.RecordType);
+
+        UpdateAutoTunnelHostRecord(m, info);
+
+        LogInfo("AutoTunnel server listening for connections on %##s[%.4a]:%d:%##s[%.16a]",
+                info->AutoTunnelTarget.namestorage.c,     &m->AdvertisedV4.ip.v4, mDNSVal16(m->AutoTunnelNAT.IntPort),
+                info->AutoTunnelHostRecord.namestorage.c, &info->AutoTunnelInnerAddress);
+
+    }
+}
+
+// Caller must hold the lock
+mDNSlocal void DeregisterAutoTunnelDeviceInfoRecord(mDNS *m, DomainAuthInfo *info)
+{
+    DeregisterAutoTunnelRecord(m, info, &info->AutoTunnelDeviceInfo);
+}
+
+// Caller must hold the lock
+mDNSlocal void UpdateAutoTunnelDeviceInfoRecord(mDNS *m, DomainAuthInfo *info)
+{
+    mDNS_CheckLock(m);
+
+    if (!info->AutoTunnelServiceStarted || info->deltime || m->ShutdownTime)
+        DeregisterAutoTunnelDeviceInfoRecord(m, info);
+    else if (info->AutoTunnelDeviceInfo.resrec.RecordType == kDNSRecordTypeUnregistered)
+    {
+        mDNS_SetupResourceRecord(&info->AutoTunnelDeviceInfo, mDNSNULL, mDNSInterface_Any, kDNSType_TXT,  kStandardTTL, kDNSRecordTypeUnregistered, AuthRecordAny, AutoTunnelRecordCallback, info);
+        ConstructServiceName(&info->AutoTunnelDeviceInfo.namestorage, &m->nicelabel, &DeviceInfoName, &info->domain);
+
+        info->AutoTunnelDeviceInfo.resrec.rdlength = initializeDeviceInfoTXT(m, info->AutoTunnelDeviceInfo.resrec.rdata->u.data);
+        info->AutoTunnelDeviceInfo.resrec.RecordType = kDNSRecordTypeKnownUnique;
+
+        mStatus err = mDNS_Register_internal(m, &info->AutoTunnelDeviceInfo);
+        if (err) LogMsg("UpdateAutoTunnelDeviceInfoRecord error %d registering %##s", err, info->AutoTunnelDeviceInfo.namestorage.c);
+        else LogInfo("UpdateAutoTunnelDeviceInfoRecord registering %##s", info->AutoTunnelDeviceInfo.namestorage.c);
+    }
+    else
+        LogInfo("UpdateAutoTunnelDeviceInfoRecord: not in Unregistered state: %d",info->AutoTunnelDeviceInfo.resrec.RecordType);
+}
+
+// Caller must hold the lock
+mDNSlocal void DeregisterAutoTunnel6Record(mDNS *m, DomainAuthInfo *info)
+{
+    LogInfo("DeregisterAutoTunnel6Record %##s", info->domain.c);
+
+    DeregisterAutoTunnelRecord(m, info, &info->AutoTunnel6Record);
+    UpdateAutoTunnelHostRecord(m, info);
+    UpdateAutoTunnelDomainStatus(m, info);
+}
+
+// Caller must hold the lock
+mDNSlocal void UpdateAutoTunnel6Record(mDNS *m, DomainAuthInfo *info)
+{
+    mDNS_CheckLock(m);
+
+    if (!info->AutoTunnelServiceStarted || info->deltime || m->ShutdownTime || mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr) || m->SleepState != SleepState_Awake)
+        DeregisterAutoTunnel6Record(m, info);
+    else if (info->AutoTunnel6Record.resrec.RecordType == kDNSRecordTypeUnregistered)
+    {
+        mDNS_SetupResourceRecord(&info->AutoTunnel6Record, mDNSNULL, mDNSInterface_Any, kDNSType_AAAA, kHostNameTTL,
+                                 kDNSRecordTypeUnregistered, AuthRecordAny, AutoTunnelRecordCallback, info);
+        AssignDomainName (&info->AutoTunnel6Record.namestorage, (const domainname*) "\x0C" "_autotunnel6");
+        AppendDomainLabel(&info->AutoTunnel6Record.namestorage, &m->hostlabel);
+        AppendDomainName (&info->AutoTunnel6Record.namestorage, &info->domain);
+        info->AutoTunnel6Record.resrec.rdata->u.ipv6 = m->AutoTunnelRelayAddr;
+        info->AutoTunnel6Record.resrec.RecordType = kDNSRecordTypeKnownUnique;
+
+        mStatus err = mDNS_Register_internal(m, &info->AutoTunnel6Record);
+        if (err) LogMsg("UpdateAutoTunnel6Record error %d registering %##s", err, info->AutoTunnel6Record.namestorage.c);
+        else LogInfo("UpdateAutoTunnel6Record registering %##s", info->AutoTunnel6Record.namestorage.c);
+
+        UpdateAutoTunnelHostRecord(m, info);
+
+        LogInfo("AutoTunnel6 server listening for connections on %##s[%.16a] :%##s[%.16a]",
+                info->AutoTunnel6Record.namestorage.c,    &m->AutoTunnelRelayAddr,
+                info->AutoTunnelHostRecord.namestorage.c, &info->AutoTunnelInnerAddress);
+
+    }
+    else LogInfo("UpdateAutoTunnel6Record NOOP state(%d)",info->AutoTunnel6Record.resrec.RecordType);
+}
+
+mDNSlocal void AutoTunnelRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
+{
+    DomainAuthInfo *info = (DomainAuthInfo *)rr->RecordContext;
+    if (result == mStatus_MemFree)
+    {
+        LogInfo("AutoTunnelRecordCallback MemFree %s", ARDisplayString(m, rr));
+        
+        mDNS_Lock(m);
+        
+        // Reset the host record namestorage to force high-level PTR/SRV/TXT to deregister
+        if (rr == &info->AutoTunnelHostRecord)
+        {
+            rr->namestorage.c[0] = 0;
+            m->NextSRVUpdate = NonZeroTime(m->timenow);
+            LogInfo("AutoTunnelRecordCallback: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
+        }
+        if (m->ShutdownTime)
+        {
+            LogInfo("AutoTunnelRecordCallback: Shutdown, returning");
+            mDNS_Unlock(m);        
+            return;
+        }
+        if (rr == &info->AutoTunnelHostRecord)
+        {
+            LogInfo("AutoTunnelRecordCallback: calling UpdateAutoTunnelHostRecord");
+            UpdateAutoTunnelHostRecord(m,info);
+        }
+        else if (rr == &info->AutoTunnelDeviceInfo)
+        {
+            LogInfo("AutoTunnelRecordCallback: Calling UpdateAutoTunnelDeviceInfoRecord");
+            UpdateAutoTunnelDeviceInfoRecord(m,info);
+        }
+        else if (rr == &info->AutoTunnelService || rr == &info->AutoTunnelTarget)
+        {
+            LogInfo("AutoTunnelRecordCallback: Calling UpdateAutoTunnelServiceRecords");
+            UpdateAutoTunnelServiceRecords(m,info);
+        }
+        else if (rr == &info->AutoTunnel6Record)
+        {
+            LogInfo("AutoTunnelRecordCallback: Calling UpdateAutoTunnel6Record");
+            UpdateAutoTunnel6Record(m,info);
+        }
+
+        mDNS_Unlock(m);        
+    }
+}
+
+mDNSlocal void AutoTunnelNATCallback(mDNS *m, NATTraversalInfo *n)
+{
+    DomainAuthInfo *info;
+
+    LogInfo("AutoTunnelNATCallback Result %d %.4a Internal %d External %d",
+            n->Result, &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort));
+
+    mDNS_Lock(m);
+    
+    m->NextSRVUpdate = NonZeroTime(m->timenow);
+    LogInfo("AutoTunnelNATCallback: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow);
+
+    for (info = m->AuthInfoList; info; info = info->next)
+        if (info->AutoTunnel)
+            UpdateAutoTunnelServiceRecords(m, info);
+
+    UpdateAnonymousRacoonConfig(m);     // Determine whether we need racoon to accept incoming connections
+
+    UpdateAutoTunnelDomainStatuses(m);
+
+    mDNS_Unlock(m);
+}
+
+mDNSlocal void AutoTunnelHostNameChanged(mDNS *m, DomainAuthInfo *info)
+{
+    LogInfo("AutoTunnelHostNameChanged %#s.%##s", m->hostlabel.c, info->domain.c);
+
+    mDNS_Lock(m);
+    // We forcibly deregister the records that are based on the hostname.
+    // When deregistration of each completes, the MemFree callback will make the
+    // appropriate Update* call to use the new name to reregister.
+    DeregisterAutoTunnelHostRecord(m, info);
+    DeregisterAutoTunnelDeviceInfoRecord(m, info);
+    DeregisterAutoTunnelServiceRecords(m, info);
+    DeregisterAutoTunnel6Record(m, info);
+    m->NextSRVUpdate = NonZeroTime(m->timenow);
+    mDNS_Unlock(m);
+}
+
+// Must be called with the lock held
+mDNSexport void StartServerTunnel(mDNS *const m, DomainAuthInfo *const info)
+{
+    if (info->deltime) return;
+    
+    if (info->AutoTunnelServiceStarted)
+    {
+        // On wake from sleep, this function will be called when determining SRV targets,
+        // and needs to re-register the host record for the target to be set correctly
+        UpdateAutoTunnelHostRecord(m, info);
+        return;
+    }
+    
+    info->AutoTunnelServiceStarted = mDNStrue;
+
+    // Now that we have a service in this domain, we need to try to register the
+    // AutoTunnel records, because the relay connection & NAT-T may have already been
+    // started for another domain. If the relay connection is not up or the NAT-T has not
+    // yet succeeded, the Update* functions are smart enough to not register the records.
+    // Note: This should be done after we set AutoTunnelServiceStarted, as that variable is used to
+    // decide whether to register the AutoTunnel records in the calls below.
+    UpdateAutoTunnelServiceRecords(m, info);
+    UpdateAutoTunnel6Record(m, info);
+    UpdateAutoTunnelDeviceInfoRecord(m, info);
+    UpdateAutoTunnelHostRecord(m, info);
+
+    // If the global AutoTunnel NAT-T is not yet started, start it.
+    if (!m->AutoTunnelNAT.clientContext)
+    {
+        m->AutoTunnelNAT.clientCallback   = AutoTunnelNATCallback;
+        m->AutoTunnelNAT.clientContext    = (void*)1; // Means AutoTunnelNAT Traversal is active;
+        m->AutoTunnelNAT.Protocol         = NATOp_MapUDP;
+        m->AutoTunnelNAT.IntPort          = IPSECPort;
+        m->AutoTunnelNAT.RequestedPort    = IPSECPort;
+        m->AutoTunnelNAT.NATLease         = 0;
+        mStatus err = mDNS_StartNATOperation_internal(m, &m->AutoTunnelNAT);
+        if (err) LogMsg("StartServerTunnel: error %d starting NAT mapping", err);
+    }
+}
+
+mDNSlocal mStatus AutoTunnelSetKeys(ClientTunnel *tun, mDNSBool AddNew)
+{
+    mDNSv6Addr loc_outer6;
+    mDNSv6Addr rmt_outer6;
+
+    // When we are tunneling over IPv6 Relay address, the port number is zero
+    if (mDNSIPPortIsZero(tun->rmt_outer_port))
+    {
+        loc_outer6 = tun->loc_outer6;
+        rmt_outer6 = tun->rmt_outer6;
+    }
+    else
+    {
+        loc_outer6 = zerov6Addr;
+        loc_outer6.b[0] = tun->loc_outer.b[0];
+        loc_outer6.b[1] = tun->loc_outer.b[1];
+        loc_outer6.b[2] = tun->loc_outer.b[2];
+        loc_outer6.b[3] = tun->loc_outer.b[3];
+
+        rmt_outer6 = zerov6Addr;
+        rmt_outer6.b[0] = tun->rmt_outer.b[0];
+        rmt_outer6.b[1] = tun->rmt_outer.b[1];
+        rmt_outer6.b[2] = tun->rmt_outer.b[2];
+        rmt_outer6.b[3] = tun->rmt_outer.b[3];
+    }
+
+    return(mDNSAutoTunnelSetKeys(AddNew ? kmDNSAutoTunnelSetKeysReplace : kmDNSAutoTunnelSetKeysDelete, tun->loc_inner.b, loc_outer6.b, kRacoonPort, tun->rmt_inner.b, rmt_outer6.b, mDNSVal16(tun->rmt_outer_port), btmmprefix, SkipLeadingLabels(&tun->dstname, 1)));
+}
+
+// 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)
+{
+    DNSQuestion *q = m->Questions;
+    while (q)
+    {
+        if (q->NoAnswer == NoAnswer_Suspended && q->qtype == qtype && q->AuthInfo && q->AuthInfo->AutoTunnel && SameDomainName(&q->qname, d))
+        {
+            LogInfo("Restart %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+            mDNSQuestionCallback *tmp = q->QuestionCallback;
+            q->QuestionCallback = AutoTunnelCallback;   // Set QuestionCallback to suppress another call back to AddNewClientTunnel
+            mDNS_StopQuery(m, q);
+            mDNS_StartQuery(m, q);
+            q->QuestionCallback = tmp;                  // Restore QuestionCallback back to the real value
+            if (!success) q->NoAnswer = NoAnswer_Fail;
+            // When we call mDNS_StopQuery, it's possible for other subordinate questions like the GetZoneData query to be cancelled too.
+            // In general we have to assume that the question list might have changed in arbitrary ways.
+            // This code is itself called from a question callback, so the m->CurrentQuestion mechanism is
+            // already in use. The safest solution is just to go back to the start of the list and start again.
+            // In principle this sounds like an n^2 algorithm, but in practice we almost always activate
+            // just one suspended question, so it's really a 2n algorithm.
+            q = m->Questions;
+        }
+        else
+            q = q->next;
+    }
+}
+
+mDNSlocal void ReissueBlockedQuestions(mDNS *const m, 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);
+}
+
+mDNSlocal void UnlinkAndReissueBlockedQuestions(mDNS *const m, ClientTunnel *tun, mDNSBool success)
+{
+    ClientTunnel **p = &m->TunnelClients;
+    while (*p != tun && *p) p = &(*p)->next;
+    if (*p) *p = tun->next;
+    ReissueBlockedQuestions(m, &tun->dstname, success);
+    LogInfo("UnlinkAndReissueBlockedQuestions: Disposing ClientTunnel %p", tun);
+    freeL("ClientTunnel", tun);
+}
+
+mDNSlocal mDNSBool TunnelClientDeleteMatching(mDNS *const m, ClientTunnel *tun, mDNSBool v6Tunnel)
+{
+    ClientTunnel **p;
+    mDNSBool needSetKeys = mDNStrue;
+
+    p = &tun->next;
+    while (*p)
+    {
+        // Is this a tunnel to the same host that we are trying to setup now?
+        if (!mDNSSameClientTunnel(&(*p)->rmt_inner, &tun->rmt_inner)) p = &(*p)->next;
+        else
+        {
+            ClientTunnel *old = *p;
+            if (v6Tunnel)
+            {
+                if (!mDNSIPPortIsZero(old->rmt_outer_port)) { p = &old->next; continue; }
+                LogInfo("TunnelClientDeleteMatching: Found existing IPv6 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+                if (old->q.ThisQInterval >= 0)
+                {
+                    LogInfo("TunnelClientDeleteMatching: Stopping query on IPv6 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+                    mDNS_StopQuery(m, &old->q);
+                }
+                else if (!mDNSSameIPv6Address((*p)->rmt_inner, tun->rmt_inner) ||
+                         !mDNSSameIPv6Address(old->loc_inner, tun->loc_inner)   ||
+                         !mDNSSameIPv6Address(old->loc_outer6, tun->loc_outer6) ||
+                         !mDNSSameIPv6Address(old->rmt_outer6, tun->rmt_outer6))
+                {
+                    // Delete the old tunnel if the current tunnel to the same host does not have the same ULA or
+                    // the other parameters of the tunnel are different
+                    LogInfo("TunnelClientDeleteMatching: Deleting existing IPv6 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+                    AutoTunnelSetKeys(old, mDNSfalse);
+                }
+                else
+                {
+                    // Reusing the existing tunnel means that we reuse the IPsec SAs and the policies. We delete the old
+                    // as "tun" and "old" are identical
+                    LogInfo("TunnelClientDeleteMatching: Reusing the existing IPv6 AutoTunnel for %##s %.16a", old->dstname.c,
+                            &old->rmt_inner);
+                    needSetKeys = mDNSfalse;
+                }
+            }
+            else
+            {
+                if (mDNSIPPortIsZero(old->rmt_outer_port)) { p = &old->next; continue; }
+                LogInfo("TunnelClientDeleteMatching: Found existing IPv4 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+                if (old->q.ThisQInterval >= 0)
+                {
+                    LogInfo("TunnelClientDeleteMatching: Stopping query on IPv4 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+                    mDNS_StopQuery(m, &old->q);
+                }
+                else if (!mDNSSameIPv6Address((*p)->rmt_inner, tun->rmt_inner) ||
+                         !mDNSSameIPv6Address(old->loc_inner, tun->loc_inner)   ||
+                         !mDNSSameIPv4Address(old->loc_outer, tun->loc_outer)   ||
+                         !mDNSSameIPv4Address(old->rmt_outer, tun->rmt_outer)   ||
+                         !mDNSSameIPPort(old->rmt_outer_port, tun->rmt_outer_port))
+                {
+                    // Delete the old tunnel if the current tunnel to the same host does not have the same ULA or
+                    // the other parameters of the tunnel are different
+                    LogInfo("TunnelClientDeleteMatching: Deleting existing IPv4 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+                    AutoTunnelSetKeys(old, mDNSfalse);
+                }
+                else
+                {
+                    // Reusing the existing tunnel means that we reuse the IPsec SAs and the policies. We delete the old
+                    // as "tun" and "old" are identical
+                    LogInfo("TunnelClientDeleteMatching: Reusing the existing IPv4 AutoTunnel for %##s %.16a", old->dstname.c,
+                            &old->rmt_inner);
+                    needSetKeys = mDNSfalse;
+                }
+            }
+
+            *p = old->next;
+            LogInfo("TunnelClientDeleteMatching: Disposing ClientTunnel %p", old);
+            freeL("ClientTunnel", old);
+        }
+    }
+    return needSetKeys;
+}
+
+// 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)
+{
+    ClientTunnel **p;
+
+    p = &tun->next;
+    while (*p)
+    {
+        // If there is more than one client tunnel to the same host, delete all of them.
+        // We do this by just checking against the EUI64 rather than the full address
+        if (!mDNSSameClientTunnel(&(*p)->rmt_inner, &tun->rmt_inner)) p = &(*p)->next;
+        else
+        {
+            ClientTunnel *old = *p;
+            if (v6Tunnel)
+            {
+                if (!mDNSIPPortIsZero(old->rmt_outer_port)) { p = &old->next; continue;}
+                LogInfo("TunnelClientDeleteAny: Found existing IPv6 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+            }
+            else
+            {
+                if (mDNSIPPortIsZero(old->rmt_outer_port)) { p = &old->next; continue;}
+                LogInfo("TunnelClientDeleteAny: Found existing IPv4 AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+            }
+            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);
+            }
+            else
+            {
+                LogInfo("TunnelClientDeleteAny: Deleting existing AutoTunnel for %##s %.16a", old->dstname.c, &old->rmt_inner);
+                AutoTunnelSetKeys(old, mDNSfalse);
+            }
+            *p = old->next;
+            LogInfo("TunnelClientDeleteAny: Disposing ClientTunnel %p", old);
+            freeL("ClientTunnel", old);
+        }
+    }
+}
+
+mDNSlocal void TunnelClientFinish(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer)
+{
+    mDNSBool needSetKeys = mDNStrue;
+    ClientTunnel *tun = (ClientTunnel *)question->QuestionContext;
+    mDNSBool v6Tunnel = mDNSfalse;
+    DomainAuthInfo *info;
+
+    // If the port is zero, then we have a relay address of the peer
+    if (mDNSIPPortIsZero(tun->rmt_outer_port))
+        v6Tunnel = mDNStrue;
+
+    if (v6Tunnel)
+    {
+        LogInfo("TunnelClientFinish: Relay address %.16a", &answer->rdata->u.ipv6);
+        tun->rmt_outer6 = answer->rdata->u.ipv6;
+        tun->loc_outer6 = m->AutoTunnelRelayAddr;
+    }
+    else
+    {
+        LogInfo("TunnelClientFinish: SRV target address %.4a", &answer->rdata->u.ipv4);
+        tun->rmt_outer = answer->rdata->u.ipv4;
+        mDNSAddr tmpDst = { mDNSAddrType_IPv4, {{{0}}} };
+        tmpDst.ip.v4 = tun->rmt_outer;
+        mDNSAddr tmpSrc = zeroAddr;
+        mDNSPlatformSourceAddrForDest(&tmpSrc, &tmpDst);
+        if (tmpSrc.type == mDNSAddrType_IPv4) tun->loc_outer = tmpSrc.ip.v4;
+        else tun->loc_outer = m->AdvertisedV4.ip.v4;
+    }
+
+    question->ThisQInterval = -1;       // So we know this tunnel setup has completed
+
+    info = GetAuthInfoForName(m, &tun->dstname);
+    if (!info)
+    {
+        LogMsg("TunnelClientFinish: Could not get AuthInfo for %##s", tun->dstname.c);
+        ReissueBlockedQuestions(m, &tun->dstname, mDNSfalse);
+        return;
+    }
+    
+    tun->loc_inner = info->AutoTunnelInnerAddress;
+
+    // If we found a v6Relay address for our peer, delete all the v4Tunnels for our peer and
+    // 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);
+
+    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, "");
+    // Kick off any questions that were held pending this tunnel setup
+    ReissueBlockedQuestions(m, &tun->dstname, (result == mStatus_NoError) ? mDNStrue : mDNSfalse);
+}
+
+mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
+{
+    ClientTunnel *tun = (ClientTunnel *)question->QuestionContext;
+    DomainAuthInfo *info;
+
+    LogInfo("AutoTunnelCallback tun %p AddRecord %d rdlength %d qtype %d", tun, AddRecord, answer->rdlength, question->qtype);
+
+    if (!AddRecord) return;
+    mDNS_StopQuery(m, question);
+
+    // If we are looking up the AAAA record for _autotunnel6, don't consider it as failure.
+    // The code below will look for _autotunnel._udp SRV record followed by A record
+    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);
+        return;
+    }
+
+    switch (tun->tc_state)
+    {
+    case TC_STATE_AAAA_PEER:
+        if (question->qtype != kDNSType_AAAA)
+        {
+            LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_AAAA_PEER", question->qtype);
+        }
+        info = GetAuthInfoForName(m, &tun->dstname);
+        if (!info)
+        {
+            LogMsg("AutoTunnelCallback: Could not get AuthInfo for %##s", tun->dstname.c);
+            UnlinkAndReissueBlockedQuestions(m, 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);
+            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);
+            return;
+        }
+        tun->rmt_inner = answer->rdata->u.ipv6;
+        LogInfo("AutoTunnelCallback:TC_STATE_AAAA_PEER: dst host %.16a", &tun->rmt_inner);
+        if (!mDNSIPv6AddressIsZero(m->AutoTunnelRelayAddr))
+        {
+            LogInfo("AutoTunnelCallback: Looking up _autotunnel6 AAAA");
+            tun->tc_state = TC_STATE_AAAA_PEER_RELAY;
+            question->qtype = kDNSType_AAAA;
+            AssignDomainName(&question->qname, (const domainname*) "\x0C" "_autotunnel6");
+        }
+        else
+        {
+            LogInfo("AutoTunnelCallback: Looking up _autotunnel._udp SRV");
+            tun->tc_state = TC_STATE_SRV_PEER;
+            question->qtype = kDNSType_SRV;
+            AssignDomainName(&question->qname, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
+        }
+        AppendDomainName(&question->qname, &tun->dstname);
+        mDNS_StartQuery(m, &tun->q);
+        return;
+    case TC_STATE_AAAA_PEER_RELAY:
+        if (question->qtype != kDNSType_AAAA)
+        {
+            LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_AAAA_PEER_RELAY", question->qtype);
+        }
+        // If it failed, look for the SRV record.
+        if (!answer->rdlength)
+        {
+            LogInfo("AutoTunnelCallback: Looking up _autotunnel6 AAAA failed, trying SRV");
+            tun->tc_state = TC_STATE_SRV_PEER;
+            AssignDomainName(&question->qname, (const domainname*) "\x0B" "_autotunnel" "\x04" "_udp");
+            AppendDomainName(&question->qname, &tun->dstname);
+            question->qtype = kDNSType_SRV;
+            mDNS_StartQuery(m, &tun->q);
+            return;
+        }
+        TunnelClientFinish(m, question, answer);
+        return;
+    case TC_STATE_SRV_PEER:
+        if (question->qtype != kDNSType_SRV)
+        {
+            LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_SRV_PEER", question->qtype);
+        }
+        LogInfo("AutoTunnelCallback: SRV target name %##s", answer->rdata->u.srv.target.c);
+        tun->tc_state = TC_STATE_ADDR_PEER;
+        AssignDomainName(&tun->q.qname, &answer->rdata->u.srv.target);
+        tun->rmt_outer_port = answer->rdata->u.srv.port;
+        question->qtype = kDNSType_A;
+        mDNS_StartQuery(m, &tun->q);
+        return;
+    case TC_STATE_ADDR_PEER:
+        if (question->qtype != kDNSType_A)
+        {
+            LogMsg("AutoTunnelCallback: Bad question type %d in TC_STATE_ADDR_PEER", question->qtype);
+        }
+        TunnelClientFinish(m, question, answer);
+        return;
+    default:
+        LogMsg("AutoTunnelCallback: Unknown question %p", question);
+    }
+}
+
+// Must be called with the lock held
+mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
+{
+    ClientTunnel *p = mallocL("ClientTunnel", sizeof(ClientTunnel));
+    if (!p) return;
+    AssignDomainName(&p->dstname, &q->qname);
+    p->MarkedForDeletion = mDNSfalse;
+    p->loc_inner      = zerov6Addr;
+    p->loc_outer      = zerov4Addr;
+    p->loc_outer6     = zerov6Addr;
+    p->rmt_inner      = zerov6Addr;
+    p->rmt_outer      = zerov4Addr;
+    p->rmt_outer6     = zerov6Addr;
+    p->rmt_outer_port = zeroIPPort;
+    p->tc_state = TC_STATE_AAAA_PEER;
+    p->next = m->TunnelClients;
+    m->TunnelClients = p;       // We intentionally build list in reverse order
+
+    p->q.InterfaceID      = mDNSInterface_Any;
+    p->q.flags            = 0;
+    p->q.Target           = zeroAddr;
+    AssignDomainName(&p->q.qname, &q->qname);
+    p->q.qtype            = kDNSType_AAAA;
+    p->q.qclass           = kDNSClass_IN;
+    p->q.LongLived        = mDNSfalse;
+    p->q.ExpectUnique     = mDNStrue;
+    p->q.ForceMCast       = mDNSfalse;
+    p->q.ReturnIntermed   = mDNStrue;
+    p->q.SuppressUnusable = mDNSfalse;
+    p->q.SearchListIndex  = 0;
+    p->q.AppendSearchDomains = 0;
+    p->q.RetryWithSearchDomains = mDNSfalse;
+    p->q.TimeoutQuestion  = 0;
+    p->q.WakeOnResolve    = 0;
+    p->q.UseBackgroundTrafficClass = mDNSfalse;
+    p->q.ValidationRequired = 0;
+    p->q.ValidatingResponse = 0;
+    p->q.ProxyQuestion      = 0;
+    p->q.qnameOrig        = mDNSNULL;
+    p->q.AnonInfo         = mDNSNULL;
+    p->q.pid              = mDNSPlatformGetPID();
+    p->q.QuestionCallback = AutoTunnelCallback;
+    p->q.QuestionContext  = p;
+
+    LogInfo("AddNewClientTunnel start tun %p %##s (%s)%s", p, &q->qname.c, DNSTypeName(q->qtype), q->LongLived ? " LongLived" : "");
+    mDNS_StartQuery_internal(m, &p->q);
+}
+
+#endif // APPLE_OSX_mDNSResponder
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - Power State & Configuration Change Management
+#endif
+
+mDNSlocal mStatus UpdateInterfaceList(mDNS *const m, mDNSs32 utc)
+{
+    mDNSBool foundav4           = mDNSfalse;
+    mDNSBool foundav6           = mDNSfalse;
+    struct ifaddrs *ifa         = myGetIfAddrs(1);
+    struct ifaddrs *v4Loopback  = NULL;
+    struct ifaddrs *v6Loopback  = NULL;
+    char defaultname[64];
+    int InfoSocket              = socket(AF_INET6, SOCK_DGRAM, 0);
+    if (InfoSocket < 3 && errno != EAFNOSUPPORT) 
+        LogMsg("UpdateInterfaceList: InfoSocket error %d errno %d (%s)", InfoSocket, errno, strerror(errno));
+
+    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_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);
+        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);
+        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);
+        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);
+#endif
+
+        if (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))
+                mDNSPlatformMemCopy(m->PrimaryMAC.b, sdl->sdl_data + sdl->sdl_nlen, 6);
+        }
+
+        if (ifa->ifa_flags & IFF_UP && ifa->ifa_addr)
+            if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6)
+            {
+                if (!ifa->ifa_netmask)
+                {
+                    mDNSAddr ip;
+                    SetupAddr(&ip, ifa->ifa_addr);
+                    LogMsg("getifaddrs: ifa_netmask is NULL for %5s(%d) Flags %04X Family %2d %#a",
+                           ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip);
+                }
+                // Apparently it's normal for the sa_family of an ifa_netmask to sometimes be zero, so we don't complain about that
+                // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
+                else if (ifa->ifa_netmask->sa_family != ifa->ifa_addr->sa_family && ifa->ifa_netmask->sa_family != 0)
+                {
+                    mDNSAddr ip;
+                    SetupAddr(&ip, ifa->ifa_addr);
+                    LogMsg("getifaddrs ifa_netmask for %5s(%d) Flags %04X Family %2d %#a has different family: %d",
+                           ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family, &ip, ifa->ifa_netmask->sa_family);
+                }
+                // Currently we use a few internal ones like mDNSInterfaceID_LocalOnly etc. that are negative values (0, -1, -2).
+                else if ((int)if_nametoindex(ifa->ifa_name) <= 0)
+                {
+                    LogMsg("UpdateInterfaceList: if_nametoindex returned zero/negative value for %5s(%d)", ifa->ifa_name, if_nametoindex(ifa->ifa_name));
+                }
+                else
+                {
+                    // Make sure ifa_netmask->sa_family is set correctly
+                    // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
+                    ifa->ifa_netmask->sa_family = ifa->ifa_addr->sa_family;
+                    int ifru_flags6 = 0;
+
+                    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+                    if (ifa->ifa_addr->sa_family == AF_INET6 && InfoSocket >= 0)
+                    {
+                        struct in6_ifreq ifr6;
+                        mDNSPlatformMemZero((char *)&ifr6, sizeof(ifr6));
+                        strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
+                        ifr6.ifr_addr = *sin6;
+                        if (ioctl(InfoSocket, SIOCGIFAFLAG_IN6, &ifr6) != -1)
+                            ifru_flags6 = ifr6.ifr_ifru.ifru_flags6;
+                        verbosedebugf("%s %.16a %04X %04X", ifa->ifa_name, &sin6->sin6_addr, ifa->ifa_flags, ifru_flags6);
+                    }
+
+                    if (!(ifru_flags6 & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY)))
+                    {
+                        if (ifa->ifa_flags & IFF_LOOPBACK)
+                        {
+                            if (ifa->ifa_addr->sa_family == AF_INET) 
+                                v4Loopback = ifa;
+                            else if (sin6->sin6_addr.s6_addr[0] != 0xFD) 
+                                v6Loopback = ifa;
+                        }
+                        else
+                        {
+                            NetworkInterfaceInfoOSX *i = AddInterfaceToList(m, ifa, utc);
+                            if (i && MulticastInterface(i) && i->ifinfo.Advertise)
+                            {
+                                if (ifa->ifa_addr->sa_family == AF_INET) 
+                                    foundav4 = mDNStrue;
+                                else 
+                                    foundav6 = mDNStrue;
+                            }
+                        }
+                    }
+                }
+            }
+        ifa = ifa->ifa_next;
+    }
+
+    // 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);
+
+    // Now the list is complete, set the McastTxRx setting for each interface.
+    NetworkInterfaceInfoOSX *i;
+    for (i = m->p->InterfaceList; i; i = i->next)
+        if (i->Exists)
+        {
+            mDNSBool txrx = MulticastInterface(i);
+            if (i->ifinfo.McastTxRx != txrx)
+            {
+                i->ifinfo.McastTxRx = txrx;
+                i->Exists = 2; // State change; need to deregister and reregister this interface
+            }
+        }
+
+    if (InfoSocket >= 0) 
+        close(InfoSocket);
+
+    mDNS_snprintf(defaultname, sizeof(defaultname), "%.*s-%02X%02X%02X%02X%02X%02X", HINFO_HWstring_prefixlen, HINFO_HWstring,
+                  m->PrimaryMAC.b[0], m->PrimaryMAC.b[1], m->PrimaryMAC.b[2], m->PrimaryMAC.b[3], m->PrimaryMAC.b[4], m->PrimaryMAC.b[5]);
+
+    // Set up the nice label
+    domainlabel nicelabel;
+    nicelabel.c[0] = 0;
+    GetUserSpecifiedFriendlyComputerName(&nicelabel);
+    if (nicelabel.c[0] == 0)
+    {
+        debugf("Couldn’t read user-specified Computer Name; using default “%s” instead", defaultname);
+        MakeDomainLabelFromLiteralString(&nicelabel, defaultname);
+    }
+
+    // Set up the RFC 1034-compliant label
+    domainlabel hostlabel;
+    hostlabel.c[0] = 0;
+    GetUserSpecifiedLocalHostName(&hostlabel);
+    if (hostlabel.c[0] == 0)
+    {
+        debugf("Couldn’t read user-specified Local Hostname; using default “%s.local” instead", defaultname);
+        MakeDomainLabelFromLiteralString(&hostlabel, defaultname);
+    }
+
+    mDNSBool namechange = mDNSfalse;
+
+    // We use a case-sensitive comparison here because even though changing the capitalization
+    // of the name alone is not significant to DNS, it's still a change from the user's point of view
+    if (SameDomainLabelCS(m->p->usernicelabel.c, nicelabel.c))
+        debugf("Usernicelabel (%#s) unchanged since last time; not changing m->nicelabel (%#s)", m->p->usernicelabel.c, m->nicelabel.c);
+    else
+    {
+        if (m->p->usernicelabel.c[0])   // Don't show message first time through, when we first read name from prefs on boot
+            LogMsg("User updated Computer Name from “%#s” to “%#s”", m->p->usernicelabel.c, nicelabel.c);
+        m->p->usernicelabel = m->nicelabel = nicelabel;
+        namechange = mDNStrue;
+    }
+
+    if (SameDomainLabelCS(m->p->userhostlabel.c, hostlabel.c))
+        debugf("Userhostlabel (%#s) unchanged since last time; not changing m->hostlabel (%#s)", m->p->userhostlabel.c, m->hostlabel.c);
+    else
+    {
+        if (m->p->userhostlabel.c[0])   // Don't show message first time through, when we first read name from prefs on boot
+            LogMsg("User updated Local Hostname from “%#s” to “%#s”", m->p->userhostlabel.c, hostlabel.c);
+        m->p->userhostlabel = m->hostlabel = hostlabel;
+        mDNS_SetFQDN(m);
+        namechange = mDNStrue;
+    }
+
+#if APPLE_OSX_mDNSResponder
+    if (namechange)     // If either name has changed, we need to tickle our AutoTunnel state machine to update its registered records
+    {
+        DomainAuthInfo *info;
+        for (info = m->AuthInfoList; info; info = info->next)
+            if (info->AutoTunnel) AutoTunnelHostNameChanged(m, info);
+    }
+#endif // APPLE_OSX_mDNSResponder
+
+    return(mStatus_NoError);
+}
+
+// Returns number of leading one-bits in mask: 0-32 for IPv4, 0-128 for IPv6
+// Returns -1 if all the one-bits are not contiguous
+mDNSlocal int CountMaskBits(mDNSAddr *mask)
+{
+    int i = 0, bits = 0;
+    int bytes = mask->type == mDNSAddrType_IPv4 ? 4 : mask->type == mDNSAddrType_IPv6 ? 16 : 0;
+    while (i < bytes)
+    {
+        mDNSu8 b = mask->ip.v6.b[i++];
+        while (b & 0x80) { bits++; b <<= 1; }
+        if (b) return(-1);
+    }
+    while (i < bytes) if (mask->ip.v6.b[i++]) return(-1);
+    return(bits);
+}
+
+// returns count of non-link local V4 addresses registered
+mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
+{
+    NetworkInterfaceInfoOSX *i;
+    int count = 0;
+    for (i = m->p->InterfaceList; i; i = i->next)
+        if (i->Exists)
+        {
+            NetworkInterfaceInfo *const n = &i->ifinfo;
+            NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, 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
+            {
+                LogMsg("SetupActiveInterfaces ERROR! n->Registered %p != primary %p", i->Registered, primary);
+                i->Registered = mDNSNULL;
+            }
+
+            if (!i->Registered)
+            {
+                // 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
+                //
+
+                i->Registered = primary;
+
+                // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
+                // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
+                // 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
+                // everytime it creates a new interface. 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.
+                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);
+                }
+                else
+                {
+                    mDNS_RegisterInterface(m, n, i->Flashing && i->Occulting);
+                }
+
+                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),
+                        i->Flashing        ? " (Flashing)"  : "",
+                        i->Occulting       ? " (Occulting)" : "",
+                        n->InterfaceActive ? " (Primary)"   : "");
+
+                if (!n->McastTxRx)
+                    debugf("SetupActiveInterfaces:   No Tx/Rx on   %5s(%lu) %.6a InterfaceID %p %#a", i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, &n->ip);
+                else
+                {
+                    if (i->sa_family == AF_INET)
+                    {
+                        struct ip_mreq imr;
+                        primary->ifa_v4addr.s_addr = n->ip.ip.v4.NotAnInteger;
+                        imr.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
+                        imr.imr_interface        = primary->ifa_v4addr;
+
+                        // If this is our *first* IPv4 instance for this interface name, we need to do a IP_DROP_MEMBERSHIP first,
+                        // before trying to join the group, to clear out stale kernel state which may be lingering.
+                        // In particular, this happens with removable network interfaces like USB Ethernet adapters -- the kernel has stale state
+                        // from the last time the USB Ethernet adapter was connected, and part of the kernel thinks we've already joined the group
+                        // on that interface (so we get EADDRINUSE when we try to join again) but a different part of the kernel thinks we haven't
+                        // joined the group (so we receive no multicasts). Doing an IP_DROP_MEMBERSHIP before joining seems to flush the stale state.
+                        // Also, trying to make the code leave the group when the adapter is removed doesn't work either,
+                        // 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)
+                        {
+                            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));
+                            if (err < 0 && (errno != EADDRNOTAVAIL))
+                                LogMsg("setsockopt - IP_DROP_MEMBERSHIP error %d errno %d (%s)", err, errno, strerror(errno));
+                        }
+
+                        LogInfo("SetupActiveInterfaces: %5s(%lu) joining IPv4 mcast group %.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_ADD_MEMBERSHIP, &imr, sizeof(imr));
+                        // Joining same group twice can give "Address already in use" error -- no need to report that
+                        if (err < 0 && (errno != EADDRINUSE))
+                            LogMsg("setsockopt - IP_ADD_MEMBERSHIP error %d errno %d (%s) group %.4a on %.4a", err, errno, strerror(errno), &imr.imr_multiaddr, &imr.imr_interface);
+                    }
+                    if (i->sa_family == AF_INET6)
+                    {
+                        struct ipv6_mreq i6mr;
+                        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)
+                        {
+                            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));
+                            if (err < 0 && (errno != EADDRNOTAVAIL))
+                                LogMsg("setsockopt - IPV6_LEAVE_GROUP error %d errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+                        }
+
+                        LogInfo("SetupActiveInterfaces: %5s(%lu) joining IPv6 mcast group %.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_JOIN_GROUP, &i6mr, sizeof(i6mr));
+                        // Joining same group twice can give "Address already in use" error -- no need to report that
+                        if (err < 0 && (errno != EADDRINUSE))
+                            LogMsg("setsockopt - IPV6_JOIN_GROUP error %d errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+                    }
+                }
+            }
+        }
+
+    return count;
+}
+
+mDNSlocal void MarkAllInterfacesInactive(mDNS *const m, mDNSs32 utc)
+{
+    NetworkInterfaceInfoOSX *i;
+    for (i = m->p->InterfaceList; i; i = i->next)
+    {
+        if (i->Exists) i->LastSeen = utc;
+        i->Exists = mDNSfalse;
+    }
+}
+
+// returns count of non-link local V4 addresses deregistered
+mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
+{
+    // 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.
+    // We have to do this because mDNSCore will use that InterfaceID when sending packets, and if the memory
+    // it refers to has gone away we'll crash.
+    NetworkInterfaceInfoOSX *i;
+    int count = 0;
+    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);
+        if (i->Registered)
+            if (i->Exists == 0 || i->Exists == 2 || i->Registered != primary)
+            {
+                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,
+                        &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask),
+                        i->Flashing               ? " (Flashing)"  : "",
+                        i->Occulting              ? " (Occulting)" : "",
+                        i->ifinfo.InterfaceActive ? " (Primary)"   : "");
+
+                // Temporary fix to handle P2P flapping. P2P reuses the scope-id, mac address and the IP address
+                // everytime 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.
+                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);
+                }
+                else
+                {
+                    mDNS_DeregisterInterface(m, &i->ifinfo, i->Flashing && i->Occulting);
+                }
+                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,
+                // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
+                // If i->Registered is NOT set, then it's not registered and we should not call mDNS_DeregisterInterface() on it.
+
+                // Caution: If we ever decide to add code here to leave the multicast group, we need to make sure that this
+                // is the LAST representative of this physical interface, or we'll unsubscribe from the group prematurely.
+            }
+    }
+
+    // Second pass:
+    // Now that everything that's going to deregister has done so, we can clean up and free the memory
+    NetworkInterfaceInfoOSX **p = &m->p->InterfaceList;
+    while (*p)
+    {
+        i = *p;
+        // If no longer active, delete interface from list and free memory
+        if (!i->Exists)
+        {
+            if (i->LastSeen == utc) i->LastSeen = utc - 1;
+            mDNSBool delete = (NumCacheRecordsForInterfaceID(m, i->ifinfo.InterfaceID) == 0) && (utc - i->LastSeen >= 60);
+            LogInfo("ClearInactiveInterfaces: %-13s %5s(%lu) %.6a InterfaceID %p(%p) %#a/%d Age %d%s", delete ? "Deleting" : "Holding",
+                    i->ifinfo.ifname, i->scope_id, &i->BSSID, i->ifinfo.InterfaceID, i,
+                    &i->ifinfo.ip, CountMaskBits(&i->ifinfo.mask), utc - i->LastSeen,
+                    i->ifinfo.InterfaceActive ? " (Primary)" : "");
+#if APPLE_OSX_mDNSResponder
+            if (i->BPF_fd >= 0) CloseBPF(i);
+#endif // APPLE_OSX_mDNSResponder
+            if (delete)
+            {
+                *p = i->next;
+                freeL("NetworkInterfaceInfoOSX", i);
+                continue;   // After deleting this object, don't want to do the "p = &i->next;" thing at the end of the loop
+            }
+        }
+        p = &i->next;
+    }
+    return count;
+}
+
+mDNSlocal void AppendDNameListElem(DNameListElem ***List, mDNSu32 uid, domainname *name)
+{
+    DNameListElem *dnle = (DNameListElem*) mallocL("DNameListElem/AppendDNameListElem", sizeof(DNameListElem));
+    if (!dnle) LogMsg("ERROR: AppendDNameListElem: memory exhausted");
+    else
+    {
+        dnle->next = mDNSNULL;
+        dnle->uid  = uid;
+        AssignDomainName(&dnle->name, name);
+        **List = dnle;
+        *List = &dnle->next;
+    }
+}
+
+mDNSlocal int compare_dns_configs(const void *aa, const void *bb)
+{
+    dns_resolver_t *a = *(dns_resolver_t**)aa;
+    dns_resolver_t *b = *(dns_resolver_t**)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)
+{
+    char *buf = ".";
+    mDNSu32 scopeid = 0;
+    char ifid_buf[16];
+
+    if (domain)
+        buf = domain;
+    //
+    // Hash the search domain name followed by the InterfaceID.
+    // As we have scoped search domains, we also included InterfaceID. If either of them change,
+    // we will detect it. Even if the order of them change, we will detect it.
+    //
+    // Note: We have to handle a few of these tricky cases.
+    //
+    // 1) Current: com, apple.com Changing to: comapple.com
+    // 2) Current: a.com,b.com Changing to a.comb.com
+    // 3) Current: a.com,b.com (ifid 8), Changing to a.com8b.com (ifid 8)
+    // 4) Current: a.com (ifid 12), Changing to a.com1 (ifid: 2)
+    //
+    // There are more variants of the above. The key thing is if we include the null in each case
+    // at the end of name and the InterfaceID, it will prevent a new name (which can't include
+    // NULL as part of the name) to be mistakenly thought of as a old name.
+
+    scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNStrue);
+    // mDNS_snprintf always null terminates
+    if (mDNS_snprintf(ifid_buf, sizeof(ifid_buf), "%u", scopeid) >= sizeof(ifid_buf))
+        LogMsg("UpdateSearchDomainHash: mDNS_snprintf failed for scopeid %u", scopeid);
+
+    LogInfo("UpdateSearchDomainHash: buf %s, ifid_buf %s", buf, ifid_buf);
+    MD5_Update(sdc, buf, strlen(buf) + 1);
+    MD5_Update(sdc, ifid_buf, strlen(ifid_buf) + 1);
+}
+
+mDNSlocal void FinalizeSearchDomainHash(mDNS *const m, MD5_CTX *sdc)
+{
+    mDNSu8 md5_hash[MD5_LEN];
+
+    MD5_Final(md5_hash, sdc);
+
+    if (memcmp(md5_hash, m->SearchDomainsHash, MD5_LEN))
+    {
+        // If the hash is different, either the search domains have changed or
+        // the ordering between them has changed. Restart the questions that
+        // would be affected by this.
+        LogInfo("FinalizeSearchDomains: The hash is different");
+        memcpy(m->SearchDomainsHash, md5_hash, MD5_LEN);
+        RetrySearchDomainQuestions(m);
+    }
+    else { LogInfo("FinalizeSearchDomains: The hash is same"); }
+}
+
+mDNSexport const char *DNSScopeToString(mDNSu32 scope)
+{
+    switch (scope)
+    {
+        case kScopeNone:
+            return "Unscoped";
+        case kScopeInterfaceID:
+            return "InterfaceScoped";
+        case kScopeServiceID:
+            return "ServiceScoped";
+        default:
+            return "Unknown";
+    }
+}
+
+mDNSlocal void ConfigSearchDomains(mDNS *const m, dns_resolver_t *resolver, mDNSInterfaceID interface, mDNSu32 scope, MD5_CTX *sdc)
+{
+    const char *scopeString = DNSScopeToString(scope);
+    int j;
+
+    if (scope != kScopeNone)
+    {
+        LogInfo("ConfigSearchDomains: (%s) Ignoring search domain for Interface %p", scopeString, interface);
+        return;
+    }
+    for (j = 0; j < resolver->n_search; j++)
+    {
+        LogInfo("ConfigSearchDomains: (%s) configuring search list %s", scopeString, resolver->search[j]);
+        UpdateSearchDomainHash(m, sdc, resolver->search[j], NULL);
+        mDNS_AddSearchDomain_CString(resolver->search[j], NULL);
+    }
+}
+
+mDNSlocal mDNSInterfaceID ConfigParseInterfaceID(mDNS *const m, mDNSu32 ifindex)
+{
+    NetworkInterfaceInfoOSX *ni;
+    mDNSInterfaceID interface;
+
+    for (ni = m->p->InterfaceList; ni; ni = ni->next)
+    {
+        if (ni->ifinfo.InterfaceID && ni->scope_id == ifindex) 
+            break;
+    }
+    if (ni != NULL) 
+    {
+        interface = ni->ifinfo.InterfaceID;
+    }
+    else
+    {
+        // In rare circumstances, we could potentially hit this case where we cannot parse the InterfaceID
+        // (see <rdar://problem/13214785>). At this point, we still accept the DNS Config from configd 
+        // Note: We currently ack the whole dns configuration and not individual resolvers or DNS servers. 
+        // As the caller is going to ack the configuration always, we have to add all the DNS servers 
+        // in the configuration. Otherwise, we won't have any DNS servers up until the network change.
+
+        LogMsg("ConfigParseInterfaceID: interface specific index %d not found (interface may not be UP)",ifindex);
+
+        // Set the correct interface from configd before passing this to mDNS_AddDNSServer() below
+        interface = (mDNSInterfaceID)(unsigned long)ifindex;
+    }
+    return interface;
+}
+
+mDNSlocal void ConfigNonUnicastResolver(mDNS *const m, dns_resolver_t *r)
+{
+    char *opt = r->options;
+    domainname d; 
+
+    if (opt && !strncmp(opt, "mdns", strlen(opt)))
+    {
+        if (!MakeDomainNameFromDNSNameString(&d, r->domain))
+        { 
+            LogMsg("ConfigNonUnicastResolver: config->resolver bad domain %s", r->domain); 
+            return;
+        }
+        mDNS_AddMcastResolver(m, &d, mDNSInterface_Any, r->timeout);
+    }
+}
+
+mDNSlocal void ConfigDNSServers(mDNS *const m, dns_resolver_t *r, mDNSInterfaceID interface, mDNSu32 scope, mDNSu16 resGroupID)
+{
+    int n;
+    domainname d;
+    int serviceID = 0;
+    mDNSBool cellIntf = mDNSfalse;
+    mDNSBool scopedDNS = mDNSfalse;
+    mDNSBool reqA, reqAAAA;
+
+    if (!r->domain || !*r->domain) 
+    {
+        d.c[0] = 0;
+    }
+    else if (!MakeDomainNameFromDNSNameString(&d, r->domain))
+    { 
+        LogMsg("ConfigDNSServers: bad domain %s", r->domain); 
+        return;
+    }
+    // Parse the resolver specific attributes that affects all the DNS servers.
+    if (scope == kScopeInterfaceID)
+    {
+        scopedDNS = mDNStrue;
+    }
+    else if (scope == kScopeServiceID)
+    {
+        serviceID = r->service_identifier;
+    }
+
+#if TARGET_OS_IPHONE
+    cellIntf = (r->reach_flags & kSCNetworkReachabilityFlagsIsWWAN) ? mDNStrue : mDNSfalse;
+#endif
+    reqA = (r->flags & DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS ? mDNStrue : mDNSfalse);
+    reqAAAA = (r->flags & DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS ? mDNStrue : mDNSfalse);
+
+    for (n = 0; n < r->n_nameserver; n++)
+    {
+        mDNSAddr saddr;
+        DNSServer *s;
+
+        if (r->nameserver[n]->sa_family != AF_INET && r->nameserver[n]->sa_family != AF_INET6)
+            continue;
+        
+        if (SetupAddr(&saddr, r->nameserver[n]))
+        {
+            LogMsg("ConfigDNSServers: Bad address");
+            continue;
+        }
+        
+        // The timeout value is for all the DNS servers in a given resolver, hence we pass
+        // the timeout value only for the first DNSServer. If we don't have a value in the
+        // resolver, then use the core's default value
+        //
+        // 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);
+        if (s)
+        {
+            LogInfo("ConfigDNSServers(%s): DNS server %#a:%d for domain %##s", DNSScopeToString(scope), &s->addr, mDNSVal16(s->port), d.c);
+        }
+    }
+}
+
+// ConfigResolvers is called for different types of resolvers: Unscoped resolver, Interface scope resolver and
+// Service scope resolvers. This is indicated by the scope argument.
+//
+// "resolver" has entries that should only be used for unscoped questions.
+//
+// "scoped_resolver" has entries that should only be used for Interface scoped question i.e., questions that specify an
+// interface index (q->InterfaceID)
+//
+// "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)
+{
+    int i;
+    dns_resolver_t **resolver;
+    int nresolvers;
+    const char *scopeString = DNSScopeToString(scope);
+    mDNSInterfaceID interface;
+
+    switch (scope)
+    {
+        case kScopeNone:
+            resolver = config->resolver;
+            nresolvers = config->n_resolver;
+            break;
+        case kScopeInterfaceID:
+            resolver = config->scoped_resolver;
+            nresolvers = config->n_scoped_resolver;
+            break;
+        case kScopeServiceID:
+            resolver = config->service_specific_resolver;
+            nresolvers = config->n_service_specific_resolver;
+            break;
+        default:
+            return;
+    }
+    qsort(resolver, nresolvers, sizeof(dns_resolver_t*), compare_dns_configs);
+
+    for (i = 0; i < nresolvers; i++)
+    {
+        dns_resolver_t *r = resolver[i];
+
+        LogInfo("ConfigResolvers: %s resolver[%d] domain %s n_nameserver %d", scopeString, i, r->domain, r->n_nameserver);
+
+        interface = mDNSInterface_Any;
+
+        // Parse the interface index 
+        if (r->if_index != 0)
+        {
+            interface = ConfigParseInterfaceID(m, r->if_index);
+        }
+
+        if (setsearch)
+        {
+            ConfigSearchDomains(m, resolver[i], interface, scope, sdc);
+            // Parse other scoped resolvers for search lists
+            if (!setservers) 
+                continue;
+        }
+
+        if (r->port == 5353 || r->n_nameserver == 0)
+        {
+            ConfigNonUnicastResolver(m, r);
+        }
+        else
+        {
+            // Each scoped resolver gets its own ID (i.e., they are in their own group) so that responses from the
+            // scoped resolver are not used by other non-scoped or scoped resolvers.
+            if (scope != kScopeNone) 
+                resGroupID++;
+
+            ConfigDNSServers(m, r, interface, scope, resGroupID);
+        }
+    }
+}
+
+#if APPLE_OSX_mDNSResponder
+mDNSlocal mDNSBool QuestionValidForDNSTrigger(DNSQuestion *q)
+{
+    if (QuerySuppressed(q))
+    {
+        debugf("QuestionValidForDNSTrigger: Suppressed: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+        return mDNSfalse;
+    }
+    if (mDNSOpaque16IsZero(q->TargetQID))
+    {
+        debugf("QuestionValidForDNSTrigger: Multicast: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+        return mDNSfalse;
+    }
+    // If we answered using LocalOnly records e.g., /etc/hosts, don't consider that a valid response
+    // for trigger.
+    if (q->LOAddressAnswers)
+    {
+        debugf("QuestionValidForDNSTrigger: LocalOnly answers: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+        return mDNSfalse;
+    }
+    return mDNStrue;
+}
+#endif
+
+// This function is called if we are not delivering unicast answers to "A" or "AAAA" questions.
+// 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)
+{
+    if (!QuestionValidForDNSTrigger(q))
+        return;
+
+    // Ignore applications that start and stop queries for no reason before we ever talk
+    // to any DNS server.
+    if (!q->triedAllServersOnce)
+    {
+        LogInfo("QuestionValidForDNSTrigger: question %##s (%s) stopped too soon", q->qname.c, DNSTypeName(q->qtype));
+        return;
+    }
+    if (q->qtype == kDNSType_A)
+        m->p->v4answers = 0;
+    if (q->qtype == kDNSType_AAAA)
+        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,
+            DNSTypeName(q->qtype));
+    }
+}
+#endif
+
+mDNSlocal void AckConfigd(mDNS *const m, dns_config_t *config)
+{
+    mDNS_CheckLock(m);
+
+    // Acking the configuration triggers configd to reissue the reachability queries
+    m->p->DNSTrigger = NonZeroTime(m->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)
+{
+    mDNSBool trigger = mDNSfalse;
+    mDNSs32 timenow;
+
+    // Don't send triggers too often.
+    // If we have started delivering answers to questions, we should send a trigger
+    // if the time permits. If we are delivering answers, we should set the state
+    // of v4answers/v6answers to 1 and avoid sending a trigger.  But, we don't know
+    // whether the answers that are being delivered currently is for configd or some
+    // other application. If we set the v4answers/v6answers to 1 and not deliver a trigger,
+    // then we won't deliver the trigger later when it is okay to send one as the
+    // "answers" are already set to 1. Hence, don't affect the state of v4answers and
+    // v6answers if we are not delivering triggers.
+    mDNS_Lock(m);
+    timenow = m->timenow;
+    if (m->p->DNSTrigger && (timenow - m->p->DNSTrigger) < DNS_TRIGGER_INTERVAL)
+    {
+        if (!m->p->v4answers || !m->p->v6answers)
+        {
+            debugf("mDNSPlatformTriggerDNSRetry: not triggering, time since last trigger %d ms, v4ans %d, v6ans %d",
+                (timenow - m->p->DNSTrigger), m->p->v4answers, m->p->v6answers);
+        }
+        mDNS_Unlock(m);
+        return;
+    }
+    mDNS_Unlock(m);
+    if (v4q != NULL && QuestionValidForDNSTrigger(v4q))
+    {
+        int old = m->p->v4answers;
+
+        m->p->v4answers = 1;
+
+        // If there are IPv4 answers now and previously we did not have
+        // any answers, trigger a DNS change so that reachability
+        // can retry the queries again.
+        if (!old)
+        {
+            LogInfo("mDNSPlatformTriggerDNSRetry: Triggering because of IPv4, last trigger %d ms, %##s (%s)", (timenow - m->p->DNSTrigger),
+                v4q->qname.c, DNSTypeName(v4q->qtype));
+            trigger = mDNStrue;
+        }
+    }
+    if (v6q != NULL && QuestionValidForDNSTrigger(v6q))
+    {
+        int old = m->p->v6answers;
+
+        m->p->v6answers = 1;
+        // If there are IPv6 answers now and previously we did not have
+        // any answers, trigger a DNS change so that reachability
+        // can retry the queries again.
+        if (!old)
+        {
+            LogInfo("mDNSPlatformTriggerDNSRetry: Triggering because of IPv6, last trigger %d ms, %##s (%s)", (timenow - m->p->DNSTrigger),
+                v6q->qname.c, DNSTypeName(v6q->qtype));
+            trigger = mDNStrue;
+        }
+    }
+    if (trigger)
+    {
+        dns_config_t *config = dns_configuration_copy();
+        if (config)
+        {
+            mDNS_Lock(m);
+            AckConfigd(m, config);
+            mDNS_Unlock(m);
+            dns_configuration_free(config);
+        }
+        else
+        {
+            LogMsg("mDNSPlatformTriggerDNSRetry: ERROR!! configd did not return config");
+        }
+    }
+}
+
+mDNSlocal void SetupActiveDirectoryDomain(dns_config_t *config)
+{
+    // Record the so-called "primary" domain, which we use as a hint to tell if the user is on a network set up
+    // by someone using Microsoft Active Directory using "local" as a private internal top-level domain
+    if (config->n_resolver && config->resolver[0]->domain && config->resolver[0]->n_nameserver &&
+        config->resolver[0]->nameserver[0])
+    {
+        MakeDomainNameFromDNSNameString(&ActiveDirectoryPrimaryDomain, config->resolver[0]->domain);
+    }
+    else
+    {
+         ActiveDirectoryPrimaryDomain.c[0] = 0;
+    }
+
+    //MakeDomainNameFromDNSNameString(&ActiveDirectoryPrimaryDomain, "test.local");
+    ActiveDirectoryPrimaryDomainLabelCount = CountLabels(&ActiveDirectoryPrimaryDomain);
+    if (config->n_resolver && config->resolver[0]->n_nameserver &&
+        SameDomainName(SkipLeadingLabels(&ActiveDirectoryPrimaryDomain, ActiveDirectoryPrimaryDomainLabelCount - 1), &localdomain))
+    {
+        SetupAddr(&ActiveDirectoryPrimaryDomainServer, config->resolver[0]->nameserver[0]);
+    }
+    else
+    {
+        AssignDomainName(&ActiveDirectoryPrimaryDomain, (const domainname *)"");
+        ActiveDirectoryPrimaryDomainLabelCount = 0;
+        ActiveDirectoryPrimaryDomainServer = zeroAddr;
+    }
+}
+#endif
+
+mDNSlocal void SetupDDNSDomains(domainname *const fqdn, DNameListElem **RegDomains, DNameListElem **BrowseDomains)
+{
+    int i;
+    char buf[MAX_ESCAPED_DOMAIN_NAME];  // Max legal C-string name, including terminating NUL
+    domainname d;
+
+    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:mDNSPlatformSetDNSConfig"), NULL, NULL);
+    if (!store)
+    {
+        LogMsg("SetupDDNSDomains: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
+    }
+    else
+    {
+        CFDictionaryRef ddnsdict = SCDynamicStoreCopyValue(store, NetworkChangedKey_DynamicDNS);
+        if (ddnsdict)
+        {
+            if (fqdn)
+            {
+                CFArrayRef fqdnArray = CFDictionaryGetValue(ddnsdict, CFSTR("HostNames"));
+                if (fqdnArray && CFArrayGetCount(fqdnArray) > 0)
+                {
+                    // for now, we only look at the first array element.  if we ever support multiple configurations, we will walk the list
+                    CFDictionaryRef fqdnDict = CFArrayGetValueAtIndex(fqdnArray, 0);
+                    if (fqdnDict && DictionaryIsEnabled(fqdnDict))
+                    {
+                        CFStringRef name = CFDictionaryGetValue(fqdnDict, CFSTR("Domain"));
+                        if (name)
+                        {
+                            if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
+                                !MakeDomainNameFromDNSNameString(fqdn, buf) || !fqdn->c[0])
+                                LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS host name: %s", buf[0] ? buf : "(unknown)");
+                            else debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS host name: %s", buf);
+                        }
+                    }
+                }
+            }
+
+            if (RegDomains)
+            {
+                CFArrayRef regArray = CFDictionaryGetValue(ddnsdict, CFSTR("RegistrationDomains"));
+                if (regArray && CFArrayGetCount(regArray) > 0)
+                {
+                    CFDictionaryRef regDict = CFArrayGetValueAtIndex(regArray, 0);
+                    if (regDict && DictionaryIsEnabled(regDict))
+                    {
+                        CFStringRef name = CFDictionaryGetValue(regDict, CFSTR("Domain"));
+                        if (name)
+                        {
+                            if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
+                                !MakeDomainNameFromDNSNameString(&d, buf) || !d.c[0])
+                                LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS registration domain: %s", buf[0] ? buf : "(unknown)");
+                            else
+                            {
+                                debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS registration domain: %s", buf);
+                                AppendDNameListElem(&RegDomains, 0, &d);
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (BrowseDomains)
+            {
+                CFArrayRef browseArray = CFDictionaryGetValue(ddnsdict, CFSTR("BrowseDomains"));
+                if (browseArray)
+                {
+                    for (i = 0; i < CFArrayGetCount(browseArray); i++)
+                    {
+                        CFDictionaryRef browseDict = CFArrayGetValueAtIndex(browseArray, i);
+                        if (browseDict && DictionaryIsEnabled(browseDict))
+                        {
+                            CFStringRef name = CFDictionaryGetValue(browseDict, CFSTR("Domain"));
+                            if (name)
+                            {
+                                if (!CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8) ||
+                                    !MakeDomainNameFromDNSNameString(&d, buf) || !d.c[0])
+                                    LogMsg("GetUserSpecifiedDDNSConfig SCDynamicStore bad DDNS browsing domain: %s", buf[0] ? buf : "(unknown)");
+                                else
+                                {
+                                    debugf("GetUserSpecifiedDDNSConfig SCDynamicStore DDNS browsing domain: %s", buf);
+                                    AppendDNameListElem(&BrowseDomains, 0, &d);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            CFRelease(ddnsdict);
+        }
+
+        if (RegDomains)
+        {
+            CFDictionaryRef btmm = SCDynamicStoreCopyValue(store, NetworkChangedKey_BackToMyMac);
+            if (btmm)
+            {
+                CFIndex size = CFDictionaryGetCount(btmm);
+                const void *key[size];
+                const void *val[size];
+                CFDictionaryGetKeysAndValues(btmm, key, val);
+                for (i = 0; i < size; i++)
+                {
+                    LogInfo("BackToMyMac %d", i);
+                    if (!CFStringGetCString(key[i], buf, sizeof(buf), kCFStringEncodingUTF8))
+                        LogMsg("Can't read BackToMyMac %d key %s", i, buf);
+                    else
+                    {
+                        mDNSu32 uid = atoi(buf);
+                        if (!CFStringGetCString(val[i], buf, sizeof(buf), kCFStringEncodingUTF8))
+                            LogMsg("Can't read BackToMyMac %d val %s", i, buf);
+                        else if (MakeDomainNameFromDNSNameString(&d, buf) && d.c[0])
+                        {
+                            LogInfo("BackToMyMac %d %d %##s", i, uid, d.c);
+                            AppendDNameListElem(&RegDomains, uid, &d);
+                        }
+                    }
+                }
+                CFRelease(btmm);
+            }
+        }
+        CFRelease(store);
+    }
+}
+
+// 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,
+    DNameListElem **RegDomains, DNameListElem **BrowseDomains, mDNSBool ackConfig)
+{
+    MD5_CTX sdc;    // search domain context
+    static mDNSu16 resolverGroupID = 0;
+
+    // Need to set these here because we need to do this even if SCDynamicStoreCreate() or SCDynamicStoreCopyValue() below don't succeed
+    if (fqdn) fqdn->c[0]      = 0;
+    if (RegDomains   ) *RegDomains     = NULL;
+    if (BrowseDomains) *BrowseDomains  = NULL;
+
+    LogInfo("mDNSPlatformSetDNSConfig:%s%s%s%s%s",
+            setservers    ? " setservers"    : "",
+            setsearch     ? " setsearch"     : "",
+            fqdn          ? " fqdn"          : "",
+            RegDomains    ? " RegDomains"    : "",
+            BrowseDomains ? " BrowseDomains" : "");
+
+    if (setsearch) MD5_Init(&sdc);
+
+    // Add the inferred address-based configuration discovery domains
+    // (should really be in core code I think, not platform-specific)
+    if (setsearch)
+    {
+        struct ifaddrs *ifa = mDNSNULL;
+        struct sockaddr_in saddr;
+        mDNSPlatformMemZero(&saddr, sizeof(saddr));
+        saddr.sin_len = sizeof(saddr);
+        saddr.sin_family = AF_INET;
+        saddr.sin_port = 0;
+        saddr.sin_addr.s_addr = *(in_addr_t *)&m->Router.ip.v4;
+
+        // Don't add any reverse-IP search domains if doing the WAB bootstrap queries would cause dial-on-demand connection initiation
+        if (!AddrRequiresPPPConnection((struct sockaddr *)&saddr)) ifa =  myGetIfAddrs(1);
+
+        while (ifa)
+        {
+            mDNSAddr a, n;
+            char buf[64];
+
+            if (ifa->ifa_addr->sa_family == AF_INET &&
+                ifa->ifa_netmask                    &&
+                !(ifa->ifa_flags & IFF_LOOPBACK)    &&
+                !SetupAddr(&a, ifa->ifa_addr)       &&
+                !mDNSv4AddressIsLinkLocal(&a.ip.v4)  )
+            {
+                // Apparently it's normal for the sa_family of an ifa_netmask to sometimes be incorrect, so we explicitly fix it here before calling SetupAddr
+                // <rdar://problem/5492035> getifaddrs is returning invalid netmask family for fw0 and vmnet
+                ifa->ifa_netmask->sa_family = ifa->ifa_addr->sa_family;     // Make sure ifa_netmask->sa_family is set correctly
+                SetupAddr(&n, ifa->ifa_netmask);
+                // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
+                mDNS_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa.", a.ip.v4.b[3] & n.ip.v4.b[3],
+                              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);
+                mDNS_AddSearchDomain_CString(buf, mDNSNULL);
+            }
+            ifa = ifa->ifa_next;
+        }
+    }
+
+#ifndef MDNS_NO_DNSINFO
+    if (setservers || setsearch)
+    {
+        dns_config_t *config = dns_configuration_copy();
+        if (!config)
+        {
+            // When running on 10.3 (build 7xxx) and earlier, we don't expect dns_configuration_copy() to succeed
+            // On 10.4, calls to dns_configuration_copy() early in the boot process often fail.
+            // Apparently this is expected behaviour -- "not a bug".
+            // Accordingly, we suppress syslog messages for the first three minutes after boot.
+            // If we are still getting failures after three minutes, then we log them.
+            if ((mDNSu32)mDNSPlatformRawTime() > (mDNSu32)(mDNSPlatformOneSecond * 180))
+                LogMsg("mDNSPlatformSetDNSConfig: Error: dns_configuration_copy returned NULL");
+        }
+        else
+        {
+            LogInfo("mDNSPlatformSetDNSConfig: config->n_resolver = %d, generation %llu", config->n_resolver, config->generation);
+            if (m->p->LastConfigGeneration == config->generation)
+            {
+                LogInfo("mDNSPlatformSetDNSConfig: generation number %llu same, not processing", config->generation);
+                dns_configuration_free(config);
+                SetupDDNSDomains(fqdn, RegDomains, BrowseDomains);
+                return mDNSfalse;
+            }
+#if APPLE_OSX_mDNSResponder
+            SetupActiveDirectoryDomain(config);
+#endif
+
+            // With scoped DNS, we don't want to answer a non-scoped question using a scoped cache entry
+            // and vice-versa. As we compare resolverGroupID for matching cache entry with question, we need
+            // to make sure that they don't match. We ensure this by always bumping up resolverGroupID between
+            // the two calls to ConfigResolvers DNSServers for scoped and non-scoped can never have the
+            // 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);
+            resolverGroupID += config->n_resolver;
+
+            ConfigResolvers(m, config, kScopeInterfaceID, setsearch, setservers, &sdc, resolverGroupID);
+            resolverGroupID += config->n_scoped_resolver;
+
+            ConfigResolvers(m, config, kScopeServiceID, setsearch, setservers, &sdc, resolverGroupID);
+
+            // Acking provides a hint that we processed this current configuration and
+            // we will use that from now on, assuming we don't get another one immediately
+            // after we return from here.
+            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);
+            }
+            dns_configuration_free(config);
+            if (setsearch) FinalizeSearchDomainHash(m, &sdc);
+            setservers = mDNSfalse;  // Done these now -- no need to fetch the same data from SCDynamicStore
+            setsearch  = mDNSfalse;
+        }
+    }
+#endif // MDNS_NO_DNSINFO
+    SetupDDNSDomains(fqdn, RegDomains, BrowseDomains);
+    return mDNStrue;
+}
+
+
+mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *r)
+{
+    char buf[256];
+    (void)m; // Unused
+
+    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:mDNSPlatformGetPrimaryInterface"), NULL, NULL);
+    if (!store)
+        LogMsg("mDNSPlatformGetPrimaryInterface: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
+    else
+    {
+        CFDictionaryRef dict = SCDynamicStoreCopyValue(store, NetworkChangedKey_IPv4);
+        if (dict)
+        {
+            r->type  = mDNSAddrType_IPv4;
+            r->ip.v4 = zerov4Addr;
+            CFStringRef string = CFDictionaryGetValue(dict, kSCPropNetIPv4Router);
+            if (string)
+            {
+                if (!CFStringGetCString(string, buf, 256, kCFStringEncodingUTF8))
+                    LogMsg("Could not convert router to CString");
+                else
+                {
+                    struct sockaddr_in saddr;
+                    saddr.sin_len = sizeof(saddr);
+                    saddr.sin_family = AF_INET;
+                    saddr.sin_port = 0;
+                    inet_aton(buf, &saddr.sin_addr);
+
+                    *(in_addr_t *)&r->ip.v4 = saddr.sin_addr.s_addr;
+                }
+            }
+
+            string = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface);
+            if (string)
+            {
+                mDNSBool HavePrimaryGlobalv6 = mDNSfalse;  // does the primary interface have a global v6 address?
+                struct ifaddrs *ifa = myGetIfAddrs(1);
+
+                *v4 = *v6 = zeroAddr;
+
+                if (!CFStringGetCString(string, buf, 256, kCFStringEncodingUTF8)) { LogMsg("Could not convert router to CString"); goto exit; }
+
+                // find primary interface in list
+                while (ifa && (mDNSIPv4AddressIsZero(v4->ip.v4) || mDNSv4AddressIsLinkLocal(&v4->ip.v4) || !HavePrimaryGlobalv6))
+                {
+                    mDNSAddr tmp6 = zeroAddr;
+                    if (!strcmp(buf, ifa->ifa_name))
+                    {
+                        if (ifa->ifa_addr->sa_family == AF_INET)
+                        {
+                            if (mDNSIPv4AddressIsZero(v4->ip.v4) || mDNSv4AddressIsLinkLocal(&v4->ip.v4)) SetupAddr(v4, ifa->ifa_addr);
+                        }
+                        else if (ifa->ifa_addr->sa_family == AF_INET6)
+                        {
+                            SetupAddr(&tmp6, ifa->ifa_addr);
+                            if (tmp6.ip.v6.b[0] >> 5 == 1)   // global prefix: 001
+                            { HavePrimaryGlobalv6 = mDNStrue; *v6 = tmp6; }
+                        }
+                    }
+                    else
+                    {
+                        // We'll take a V6 address from the non-primary interface if the primary interface doesn't have a global V6 address
+                        if (!HavePrimaryGlobalv6 && ifa->ifa_addr->sa_family == AF_INET6 && !v6->ip.v6.b[0])
+                        {
+                            SetupAddr(&tmp6, ifa->ifa_addr);
+                            if (tmp6.ip.v6.b[0] >> 5 == 1) *v6 = tmp6;
+                        }
+                    }
+                    ifa = ifa->ifa_next;
+                }
+
+                // Note that while we advertise v6, we still require v4 (possibly NAT'd, but not link-local) because we must use
+                // V4 to communicate w/ our DNS server
+            }
+
+exit:
+            CFRelease(dict);
+        }
+        CFRelease(store);
+    }
+    return mStatus_NoError;
+}
+
+mDNSexport void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
+{
+    LogInfo("mDNSPlatformDynDNSHostNameStatusChanged %d %##s", status, dname->c);
+    char uname[MAX_ESCAPED_DOMAIN_NAME];    // Max legal C-string name, including terminating NUL
+    ConvertDomainNameToCString(dname, uname);
+
+    char *p = uname;
+    while (*p)
+    {
+        *p = tolower(*p);
+        if (!(*(p+1)) && *p == '.') *p = 0; // if last character, strip trailing dot
+        p++;
+    }
+
+    // We need to make a CFDictionary called "State:/Network/DynamicDNS" containing (at present) a single entity.
+    // That single entity is a CFDictionary with name "HostNames".
+    // The "HostNames" CFDictionary contains a set of name/value pairs, where the each name is the FQDN
+    // in question, and the corresponding value is a CFDictionary giving the state for that FQDN.
+    // (At present we only support a single FQDN, so this dictionary holds just a single name/value pair.)
+    // The CFDictionary for each FQDN holds (at present) a single name/value pair,
+    // where the name is "Status" and the value is a CFNumber giving an errror code (with zero meaning success).
+
+    const CFStringRef StateKeys [1] = { CFSTR("HostNames") };
+    const CFStringRef HostKeys  [1] = { CFStringCreateWithCString(NULL, uname, kCFStringEncodingUTF8) };
+    const CFStringRef StatusKeys[1] = { CFSTR("Status") };
+    if (!HostKeys[0]) LogMsg("SetDDNSNameStatus: CFStringCreateWithCString(%s) failed", uname);
+    else
+    {
+        const CFNumberRef StatusVals[1] = { CFNumberCreate(NULL, kCFNumberSInt32Type, &status) };
+        if (!StatusVals[0]) LogMsg("SetDDNSNameStatus: CFNumberCreate(%d) failed", status);
+        else
+        {
+            const CFDictionaryRef HostVals[1] = { CFDictionaryCreate(NULL, (void*)StatusKeys, (void*)StatusVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
+            if (HostVals[0])
+            {
+                const CFDictionaryRef StateVals[1] = { CFDictionaryCreate(NULL, (void*)HostKeys, (void*)HostVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks) };
+                if (StateVals[0])
+                {
+                    CFDictionaryRef StateDict = CFDictionaryCreate(NULL, (void*)StateKeys, (void*)StateVals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+                    if (StateDict)
+                    {
+                        mDNSDynamicStoreSetConfig(kmDNSDynamicConfig, mDNSNULL, StateDict);
+                        CFRelease(StateDict);
+                    }
+                    CFRelease(StateVals[0]);
+                }
+                CFRelease(HostVals[0]);
+            }
+            CFRelease(StatusVals[0]);
+        }
+        CFRelease(HostKeys[0]);
+    }
+}
+
+#if APPLE_OSX_mDNSResponder
+#if !NO_AWACS
+
+// checks whether a domain is present in Setup:/Network/BackToMyMac. Just because there is a key in the
+// keychain for a domain, it does not become a valid BTMM domain. If things get inconsistent, this will
+// help catch it
+mDNSlocal mDNSBool IsBTMMDomain(domainname *d)
+{
+    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:IsBTMMDomain"), NULL, NULL);
+    if (!store)
+    {
+        LogMsg("IsBTMMDomain: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
+        return mDNSfalse;
+    }
+    CFDictionaryRef btmm = SCDynamicStoreCopyValue(store, NetworkChangedKey_BackToMyMac);
+    if (btmm)
+    {
+        CFIndex size = CFDictionaryGetCount(btmm);
+        char buf[MAX_ESCAPED_DOMAIN_NAME];  // Max legal C-string name, including terminating NUL
+        const void *key[size];
+        const void *val[size];
+        domainname dom;
+        int i;
+        CFDictionaryGetKeysAndValues(btmm, key, val);
+        for (i = 0; i < size; i++)
+        {
+            LogInfo("BackToMyMac %d", i);
+            if (!CFStringGetCString(key[i], buf, sizeof(buf), kCFStringEncodingUTF8))
+                LogMsg("IsBTMMDomain: ERROR!! Can't read BackToMyMac %d key %s", i, buf);
+            else
+            {
+                mDNSu32 uid = atoi(buf);
+                if (!CFStringGetCString(val[i], buf, sizeof(buf), kCFStringEncodingUTF8))
+                    LogMsg("IsBTMMDomain: Can't read BackToMyMac %d val %s", i, buf);
+                else if (MakeDomainNameFromDNSNameString(&dom, buf) && dom.c[0])
+                {
+                    if (SameDomainName(&dom, d))
+                    {
+                        LogInfo("IsBTMMDomain: Domain %##s is a btmm domain, uid %u", d->c, uid);
+                        CFRelease(btmm);
+                        CFRelease(store);
+                        return mDNStrue;
+                    }
+                }
+            }
+        }
+        CFRelease(btmm);
+    }
+    CFRelease(store);
+    LogInfo("IsBTMMDomain: Domain %##s not a btmm domain", d->c);
+    return mDNSfalse;
+}
+
+// Appends data to the buffer
+mDNSlocal int AddOneItem(char *buf, int bufsz, char *data, int *currlen)
+{
+    int len;
+
+    len = strlcpy(buf + *currlen, data, bufsz - *currlen);
+    if (len >= (bufsz - *currlen))
+    {
+        // if we have exceeded the space in buf, it has already been NULL terminated
+        // and we have nothing more to do. Set currlen to the last byte so that the caller
+        // knows to do the right thing
+        LogMsg("AddOneItem: Exceeded the max buffer size currlen %d, len %d", *currlen, len);
+        *currlen = bufsz - 1;
+        return -1;
+    }
+    else { (*currlen) += len; }
+
+    buf[*currlen] = ',';
+    if (*currlen >= bufsz)
+    {
+        LogMsg("AddOneItem: ERROR!! How can currlen be %d", *currlen);
+        *currlen = bufsz - 1;
+        buf[*currlen] = 0;
+        return -1;
+    }
+    // if we have filled up the buffer exactly, then there is no more work to do
+    if (*currlen == bufsz - 1) { buf[*currlen] = 0; return -1; }
+    (*currlen)++;
+    return *currlen;
+}
+
+// If we have at least one BTMM domain, then trigger the connection to the relay. If we have no
+// BTMM domains, then bring down the connection to the relay.
+mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m)
+{
+    DomainAuthInfo *BTMMDomain = mDNSNULL;
+    DomainAuthInfo *FoundInList;
+    static mDNSBool AWACSDConnected = mDNSfalse;
+    char AllUsers[1024];    // maximum size of mach message
+    char AllPass[1024];     // maximum size of mach message
+    char username[MAX_DOMAIN_LABEL + 1];
+    int currulen = 0;
+    int currplen = 0;
+
+    // if a domain is being deleted, we want to send a disconnect. If we send a disconnect now,
+    // we may not be able to send the dns queries over the relay connection which may be needed
+    // for sending the deregistrations. Hence, we need to delay sending the disconnect. But we
+    // need to make sure that we send the disconnect before attempting the next connect as the
+    // awacs connections are redirected based on usernames.
+    //
+    // For now we send a disconnect immediately. When we start sending dns queries over the relay
+    // connection, we will need to fix this.
+
+    for (FoundInList = m->AuthInfoList; FoundInList; FoundInList = FoundInList->next)
+        if (!FoundInList->deltime && FoundInList->AutoTunnel && IsBTMMDomain(&FoundInList->domain))
+        {
+            // We need the passwd from the first domain.
+            BTMMDomain = FoundInList;
+            ConvertDomainLabelToCString_unescaped((domainlabel *)BTMMDomain->domain.c, username);
+            LogInfo("UpdateBTMMRelayConnection: user %s for domain %##s", username, BTMMDomain->domain.c);
+            if (AddOneItem(AllUsers, sizeof(AllUsers), username, &currulen) == -1) break;
+            if (AddOneItem(AllPass, sizeof(AllPass), BTMMDomain->b64keydata, &currplen) == -1) break;
+        }
+
+    if (BTMMDomain)
+    {
+        // In the normal case (where we neither exceed the buffer size nor write bytes that
+        // fit exactly into the buffer), currulen/currplen should be a different size than
+        // (AllUsers - 1) / (AllPass - 1). In that case, we need to override the "," with a NULL byte.
+
+        if (currulen != (int)(sizeof(AllUsers) - 1)) AllUsers[currulen - 1] = 0;
+        if (currplen != (int)(sizeof(AllPass) - 1)) AllPass[currplen - 1] = 0;
+
+        LogInfo("UpdateBTMMRelayConnection: AWS_Connect for user %s", AllUsers);
+        AWACS_Connect(AllUsers, AllPass, "hello.connectivity.me.com");
+        AWACSDConnected = mDNStrue;
+    }
+    else
+    {
+        // Disconnect only if we connected previously
+        if (AWACSDConnected)
+        {
+            LogInfo("UpdateBTMMRelayConnection: AWS_Disconnect");
+            AWACS_Disconnect();
+            AWACSDConnected = mDNSfalse;
+        }
+        else LogInfo("UpdateBTMMRelayConnection: Not calling AWS_Disconnect");
+    }
+}
+#else
+mDNSlocal void UpdateBTMMRelayConnection(mDNS *const m)
+{
+    (void) m; // Unused
+    LogInfo("UpdateBTMMRelayConnection: AWACS connection not started, no AWACS library");
+}
+#endif // ! NO_AWACS
+
+mDNSlocal void ProcessConndConfigChanges(mDNS *const m);
+
+#endif // APPLE_OSX_mDNSResponder
+
+// MUST be called holding the lock
+mDNSexport void SetDomainSecrets(mDNS *m)
+{
+#ifdef NO_SECURITYFRAMEWORK
+        (void) m;
+    LogMsg("Note: SetDomainSecrets: no keychain support");
+#else
+    mDNSBool haveAutoTunnels = mDNSfalse;
+
+    LogInfo("SetDomainSecrets");
+
+    // Rather than immediately deleting all keys now, we mark them for deletion in ten seconds.
+    // In the case where the user simultaneously removes their DDNS host name and the key
+    // for it, this gives mDNSResponder ten seconds to gracefully delete the name from the
+    // server before it loses access to the necessary key. Otherwise, we'd leave orphaned
+    // address records behind that we no longer have permission to delete.
+    DomainAuthInfo *ptr;
+    for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
+        ptr->deltime = NonZeroTime(m->timenow + mDNSPlatformOneSecond*10);
+
+#if APPLE_OSX_mDNSResponder
+    {
+        // Mark all TunnelClients for deletion
+        ClientTunnel *client;
+        for (client = m->TunnelClients; client; client = client->next)
+        {
+            LogInfo("SetDomainSecrets: tunnel to %##s marked for deletion", client->dstname.c);
+            client->MarkedForDeletion = mDNStrue;
+        }
+    }
+#endif // APPLE_OSX_mDNSResponder
+
+    // String Array used to write list of private domains to Dynamic Store
+    CFMutableArrayRef sa = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    if (!sa) { LogMsg("SetDomainSecrets: CFArrayCreateMutable failed"); return; }
+    CFIndex i;
+    CFDataRef data = NULL;
+    const int itemsPerEntry = 4; // domain name, key name, key value, Name value
+    CFArrayRef secrets = NULL;
+    int err = mDNSKeychainGetSecrets(&secrets);
+    if (err || !secrets)
+        LogMsg("SetDomainSecrets: mDNSKeychainGetSecrets failed error %d CFArrayRef %p", err, secrets);
+    else
+    {
+        CFIndex ArrayCount = CFArrayGetCount(secrets);
+        // Iterate through the secrets
+        for (i = 0; i < ArrayCount; ++i)
+        {
+            mDNSBool AutoTunnel;
+            int j, offset;
+            CFArrayRef entry = CFArrayGetValueAtIndex(secrets, i);
+            if (CFArrayGetTypeID() != CFGetTypeID(entry) || itemsPerEntry != CFArrayGetCount(entry))
+            { LogMsg("SetDomainSecrets: malformed entry %d, itemsPerEntry %d", i, itemsPerEntry); continue; }
+            for (j = 0; j < CFArrayGetCount(entry); ++j)
+                if (CFDataGetTypeID() != CFGetTypeID(CFArrayGetValueAtIndex(entry, j)))
+                { LogMsg("SetDomainSecrets: malformed entry item %d", j); continue; }
+
+            // The names have already been vetted by the helper, but checking them again here helps humans and automated tools verify correctness
+
+            // Max legal domainname as C-string, including space for btmmprefix and terminating NUL
+            // Get DNS domain this key is for (kmDNSKcWhere)
+            char stringbuf[MAX_ESCAPED_DOMAIN_NAME + sizeof(btmmprefix)];
+            data = CFArrayGetValueAtIndex(entry, kmDNSKcWhere);
+            if (CFDataGetLength(data) >= (int)sizeof(stringbuf))
+            { LogMsg("SetDomainSecrets: Bad kSecServiceItemAttr length %d", CFDataGetLength(data)); continue; }
+            CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), (UInt8 *)stringbuf);
+            stringbuf[CFDataGetLength(data)] = '\0';
+
+            AutoTunnel = mDNSfalse;
+            offset = 0;
+            if (!strncmp(stringbuf, dnsprefix, strlen(dnsprefix)))
+                offset = strlen(dnsprefix);
+            else if (!strncmp(stringbuf, btmmprefix, strlen(btmmprefix)))
+            {
+                AutoTunnel = mDNStrue;
+                offset = strlen(btmmprefix);
+            }
+            domainname domain;
+            if (!MakeDomainNameFromDNSNameString(&domain, stringbuf + offset)) { LogMsg("SetDomainSecrets: bad key domain %s", stringbuf); continue; }
+
+            // Get key name (kmDNSKcAccount)
+            data = CFArrayGetValueAtIndex(entry, kmDNSKcAccount);
+            if (CFDataGetLength(data) >= (int)sizeof(stringbuf))
+            { LogMsg("SetDomainSecrets: Bad kSecAccountItemAttr length %d", CFDataGetLength(data)); continue; }
+            CFDataGetBytes(data, CFRangeMake(0,CFDataGetLength(data)), (UInt8 *)stringbuf);
+            stringbuf[CFDataGetLength(data)] = '\0';
+
+            domainname keyname;
+            if (!MakeDomainNameFromDNSNameString(&keyname, stringbuf)) { LogMsg("SetDomainSecrets: bad key name %s", stringbuf); continue; }
+
+            // Get key data (kmDNSKcKey)
+            data = CFArrayGetValueAtIndex(entry, kmDNSKcKey);
+            if (CFDataGetLength(data) >= (int)sizeof(stringbuf))
+            { 
+                LogMsg("SetDomainSecrets: Shared secret too long: %d", CFDataGetLength(data));
+                continue;
+            }
+            CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), (UInt8 *)stringbuf);
+            stringbuf[CFDataGetLength(data)] = '\0';    // mDNS_SetSecretForDomain requires NULL-terminated C string for key
+
+            // Get the Name of the keychain entry (kmDNSKcName) host or host:port
+            // The hostname also has the port number and ":". It should take a maximum of 6 bytes.
+            char hostbuf[MAX_ESCAPED_DOMAIN_NAME + 6];  // Max legal domainname as C-string, including terminating NUL
+            data = CFArrayGetValueAtIndex(entry, kmDNSKcName);
+            if (CFDataGetLength(data) >= (int)sizeof(hostbuf))
+            { 
+                LogMsg("SetDomainSecrets: host:port data too long: %d", CFDataGetLength(data));
+                continue;
+            }
+            CFDataGetBytes(data, CFRangeMake(0,CFDataGetLength(data)), (UInt8 *)hostbuf);
+            hostbuf[CFDataGetLength(data)] = '\0';
+
+            domainname hostname;
+            mDNSIPPort port;
+            char *hptr;
+            hptr = strchr(hostbuf, ':');
+
+            port.NotAnInteger = 0;
+            if (hptr)
+            {
+                mDNSu8 *p;
+                mDNSu16 val = 0;
+
+                *hptr++ = '\0';
+                while(hptr && *hptr != 0)
+                {
+                    if (*hptr < '0' || *hptr > '9')
+                    { LogMsg("SetDomainSecrets: Malformed Port number %d, val %d", *hptr, val); val = 0; break;}
+                    val = val * 10 + *hptr - '0';
+                    hptr++;
+                }
+                if (!val) continue;
+                p = (mDNSu8 *)&val;
+                port.NotAnInteger = p[0] << 8 | p[1];
+            }
+            // The hostbuf is of the format dsid at hostname:port. We don't care about the dsid.
+            hptr = strchr(hostbuf, '@');
+            if (hptr)
+                hptr++;
+            else
+                hptr = hostbuf;
+            if (!MakeDomainNameFromDNSNameString(&hostname, hptr)) { LogMsg("SetDomainSecrets: bad host name %s", hptr); continue; }
+
+            DomainAuthInfo *FoundInList;
+            for (FoundInList = m->AuthInfoList; FoundInList; FoundInList = FoundInList->next)
+                if (SameDomainName(&FoundInList->domain, &domain)) break;
+
+#if APPLE_OSX_mDNSResponder
+            if (FoundInList)
+            {
+                // If any client tunnel destination is in this domain, set deletion flag to false
+                ClientTunnel *client;
+                for (client = m->TunnelClients; client; client = client->next)
+                    if (FoundInList == GetAuthInfoForName_internal(m, &client->dstname))
+                    {
+                        LogInfo("SetDomainSecrets: tunnel to %##s no longer marked for deletion", client->dstname.c);
+                        client->MarkedForDeletion = mDNSfalse;
+                    }
+            }
+
+#endif // APPLE_OSX_mDNSResponder
+
+            // Uncomment the line below to view the keys as they're read out of the system keychain
+            // DO NOT SHIP CODE THIS WAY OR YOU'LL LEAK SECRET DATA INTO A PUBLICLY READABLE FILE!
+            //LogInfo("SetDomainSecrets: domain %##s keyname %##s key %s hostname %##s port %d", &domain.c, &keyname.c, stringbuf, hostname.c, (port.b[0] << 8 | port.b[1]));
+            LogInfo("SetDomainSecrets: domain %##s keyname %##s hostname %##s port %d", &domain.c, &keyname.c, hostname.c, (port.b[0] << 8 | port.b[1]));
+
+            // If didn't find desired domain in the list, make a new entry
+            ptr = FoundInList;
+            if (FoundInList && FoundInList->AutoTunnel && haveAutoTunnels == mDNSfalse) haveAutoTunnels = mDNStrue;
+            if (!FoundInList)
+            {
+                ptr = (DomainAuthInfo*)mallocL("DomainAuthInfo", sizeof(*ptr));
+                if (!ptr) { LogMsg("SetDomainSecrets: No memory"); continue; }
+            }
+
+            //LogInfo("SetDomainSecrets: %d of %d %##s", i, ArrayCount, &domain);
+
+            // It is an AutoTunnel if the keychains tells us so (with btmm prefix) or if it is a TunnelModeDomain
+            if (mDNS_SetSecretForDomain(m, ptr, &domain, &keyname, stringbuf, &hostname, &port, AutoTunnel) == mStatus_BadParamErr)
+            {
+                if (!FoundInList) mDNSPlatformMemFree(ptr);     // If we made a new DomainAuthInfo here, and it turned out bad, dispose it immediately
+                continue;
+            }
+
+            ConvertDomainNameToCString(&domain, stringbuf);
+            CFStringRef cfs = CFStringCreateWithCString(NULL, stringbuf, kCFStringEncodingUTF8);
+            if (cfs) { CFArrayAppendValue(sa, cfs); CFRelease(cfs); }
+        }
+        CFRelease(secrets);
+    }
+
+    if (!privateDnsArray || !CFEqual(privateDnsArray, sa))
+    {
+        if (privateDnsArray)
+            CFRelease(privateDnsArray);
+        
+        privateDnsArray = sa;
+        CFRetain(privateDnsArray);
+        mDNSDynamicStoreSetConfig(kmDNSPrivateConfig, mDNSNULL, privateDnsArray);
+    }
+    CFRelease(sa);
+
+#if APPLE_OSX_mDNSResponder
+    {
+        // clean up ClientTunnels
+        ClientTunnel **pp = &m->TunnelClients;
+        while (*pp)
+        {
+            if ((*pp)->MarkedForDeletion)
+            {
+                ClientTunnel *cur = *pp;
+                LogInfo("SetDomainSecrets: removing client %p %##s from list", cur, cur->dstname.c);
+                if (cur->q.ThisQInterval >= 0) mDNS_StopQuery(m, &cur->q);
+                AutoTunnelSetKeys(cur, mDNSfalse);
+                *pp = cur->next;
+                freeL("ClientTunnel", cur);
+            }
+            else
+                pp = &(*pp)->next;
+        }
+
+        mDNSBool needAutoTunnelNAT = mDNSfalse;
+        DomainAuthInfo *info;
+        for (info = m->AuthInfoList; info; info = info->next)
+        {
+            if (info->AutoTunnel)
+            {
+                UpdateAutoTunnelDeviceInfoRecord(m, info);
+                UpdateAutoTunnelHostRecord(m, info);
+                UpdateAutoTunnelServiceRecords(m, info);
+                UpdateAutoTunnel6Record(m, info);
+                if (info->deltime)
+                {
+                    if (info->AutoTunnelServiceStarted) info->AutoTunnelServiceStarted = mDNSfalse;
+                }
+                else if (info->AutoTunnelServiceStarted)
+                    needAutoTunnelNAT = true;
+
+	            UpdateAutoTunnelDomainStatus(m, info);
+            }
+        }
+
+        // If the AutoTunnel NAT-T is no longer needed (& is currently running), stop it
+        if (!needAutoTunnelNAT && m->AutoTunnelNAT.clientContext)
+        {
+            // stop the NAT operation, reset port, cleanup state
+            mDNS_StopNATOperation_internal(m, &m->AutoTunnelNAT);
+            m->AutoTunnelNAT.ExternalAddress = zerov4Addr;
+            m->AutoTunnelNAT.NewAddress      = zerov4Addr;
+            m->AutoTunnelNAT.ExternalPort    = zeroIPPort;
+            m->AutoTunnelNAT.RequestedPort   = zeroIPPort;
+            m->AutoTunnelNAT.Lifetime        = 0;
+            m->AutoTunnelNAT.Result          = mStatus_NoError;
+            m->AutoTunnelNAT.clientContext   = mDNSNULL;
+        }
+
+        UpdateAnonymousRacoonConfig(m);     // Determine whether we need racoon to accept incoming connections
+        ProcessConndConfigChanges(m);       // Update AutoTunnelInnerAddress values and default ipsec policies as necessary
+    }
+#endif // APPLE_OSX_mDNSResponder
+
+    CheckSuppressUnusableQuestions(m);
+
+#endif /* NO_SECURITYFRAMEWORK */
+}
+
+mDNSlocal void SetLocalDomains(void)
+{
+    CFMutableArrayRef sa = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    if (!sa) { LogMsg("SetLocalDomains: CFArrayCreateMutable failed"); return; }
+
+    CFArrayAppendValue(sa, CFSTR("local"));
+    CFArrayAppendValue(sa, CFSTR("254.169.in-addr.arpa"));
+    CFArrayAppendValue(sa, CFSTR("8.e.f.ip6.arpa"));
+    CFArrayAppendValue(sa, CFSTR("9.e.f.ip6.arpa"));
+    CFArrayAppendValue(sa, CFSTR("a.e.f.ip6.arpa"));
+    CFArrayAppendValue(sa, CFSTR("b.e.f.ip6.arpa"));
+
+    mDNSDynamicStoreSetConfig(kmDNSMulticastConfig, mDNSNULL, sa);
+    CFRelease(sa);
+}
+
+mDNSlocal void GetCurrentPMSetting(const CFStringRef name, mDNSs32 *val)
+{
+#if USE_IOPMCOPYACTIVEPMPREFERENCES
+    CFTypeRef blob = NULL;
+    CFStringRef str = NULL;
+    CFDictionaryRef odict = NULL;
+    CFDictionaryRef idict = NULL;
+    CFNumberRef number = NULL;
+
+    blob = IOPSCopyPowerSourcesInfo();
+    if (!blob) { LogMsg("GetCurrentPMSetting: IOPSCopyPowerSourcesInfo failed!"); goto end; }
+
+    odict = IOPMCopyActivePMPreferences();
+    if (!odict) { LogMsg("GetCurrentPMSetting: IOPMCopyActivePMPreferences failed!"); goto end; }
+
+    str = IOPSGetProvidingPowerSourceType(blob);
+    if (!str) { LogMsg("GetCurrentPMSetting: IOPSGetProvidingPowerSourceType failed!"); goto end; }
+
+    idict = CFDictionaryGetValue(odict, str);
+    if (!idict)
+    {
+        char buf[256];
+        if (!CFStringGetCString(str, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
+        LogMsg("GetCurrentPMSetting: CFDictionaryGetValue (%s) failed!", buf);
+        goto end;
+    }
+
+    number = CFDictionaryGetValue(idict, name);
+    if (!number || CFGetTypeID(number) != CFNumberGetTypeID() || !CFNumberGetValue(number, kCFNumberSInt32Type, val))
+        *val = 0;
+end:
+    if (blob) CFRelease(blob);
+    if (odict) CFRelease(odict);
+
+#else
+
+    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetCurrentPMSetting"), NULL, NULL);
+    if (!store) LogMsg("GetCurrentPMSetting: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
+    else
+    {
+        CFDictionaryRef dict = SCDynamicStoreCopyValue(store, NetworkChangedKey_PowerSettings);
+        if (!dict) LogSPS("GetCurrentPMSetting: Could not get IOPM CurrentSettings dict");
+        else
+        {
+            CFNumberRef number = CFDictionaryGetValue(dict, name);
+            if (!number || CFGetTypeID(number) != CFNumberGetTypeID() || !CFNumberGetValue(number, kCFNumberSInt32Type, val))
+                *val = 0;
+            CFRelease(dict);
+        }
+        CFRelease(store);
+    }
+
+#endif
+}
+
+#if APPLE_OSX_mDNSResponder
+
+static CFMutableDictionaryRef spsStatusDict = NULL;
+static const CFStringRef kMetricRef = CFSTR("Metric");
+
+mDNSlocal void SPSStatusPutNumber(CFMutableDictionaryRef dict, const mDNSu8* const ptr, CFStringRef key)
+{
+    mDNSu8 tmp = (ptr[0] - '0') * 10 + ptr[1] - '0';
+    CFNumberRef num = CFNumberCreate(NULL, kCFNumberSInt8Type, &tmp);
+    if (!num)
+        LogMsg("SPSStatusPutNumber: Could not create CFNumber");
+    else
+    {
+        CFDictionarySetValue(dict, key, num);
+        CFRelease(num);
+    }
+}
+
+mDNSlocal CFMutableDictionaryRef SPSCreateDict(const mDNSu8* const ptr)
+{
+    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+    if (!dict) { LogMsg("SPSCreateDict: Could not create CFDictionary dict"); return dict; }
+
+    char buffer[1024];
+    buffer[mDNS_snprintf(buffer, sizeof(buffer), "%##s", ptr) - 1] = 0;
+    CFStringRef spsname = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
+    if (!spsname) { LogMsg("SPSCreateDict: Could not create CFString spsname full"); CFRelease(dict); return NULL; }
+    CFDictionarySetValue(dict, CFSTR("FullName"), spsname);
+    CFRelease(spsname);
+
+    if (ptr[0] >=  2) SPSStatusPutNumber(dict, ptr + 1, CFSTR("Type"));
+    if (ptr[0] >=  5) SPSStatusPutNumber(dict, ptr + 4, CFSTR("Portability"));
+    if (ptr[0] >=  8) SPSStatusPutNumber(dict, ptr + 7, CFSTR("MarginalPower"));
+    if (ptr[0] >= 11) SPSStatusPutNumber(dict, ptr +10, CFSTR("TotalPower"));
+
+    mDNSu32 tmp = SPSMetric(ptr);
+    CFNumberRef num = CFNumberCreate(NULL, kCFNumberSInt32Type, &tmp);
+    if (!num)
+        LogMsg("SPSCreateDict: Could not create CFNumber");
+    else
+    {
+        CFDictionarySetValue(dict, kMetricRef, num);
+        CFRelease(num);
+    }
+
+    if (ptr[0] >= 12)
+    {
+        memcpy(buffer, ptr + 13, ptr[0] - 12);
+        buffer[ptr[0] - 12] = 0;
+        spsname = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
+        if (!spsname) { LogMsg("SPSCreateDict: Could not create CFString spsname"); CFRelease(dict); return NULL; }
+        else
+        {
+            CFDictionarySetValue(dict, CFSTR("PrettyName"), spsname);
+            CFRelease(spsname);
+        }
+    }
+
+    return dict;
+}
+
+mDNSlocal CFComparisonResult CompareSPSEntries(const void *val1, const void *val2, void *context)
+{
+    (void)context;
+    return CFNumberCompare((CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)val1, kMetricRef),
+                           (CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)val2, kMetricRef),
+                           NULL);
+}
+
+mDNSlocal void UpdateSPSStatus(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
+{
+    NetworkInterfaceInfo* info = (NetworkInterfaceInfo*)question->QuestionContext;
+    debugf("UpdateSPSStatus: %s %##s %s %s", info->ifname, question->qname.c, AddRecord ? "Add" : "Rmv", answer ? RRDisplayString(m, answer) : "<null>");
+
+    mDNS_Lock(m);
+    mDNS_UpdateAllowSleep(m);
+    mDNS_Unlock(m);
+
+    if (answer && SPSMetric(answer->rdata->u.name.c) > 999999) return;  // Ignore instances with invalid names
+
+    if (!spsStatusDict)
+    {
+        spsStatusDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+        if (!spsStatusDict) { LogMsg("UpdateSPSStatus: Could not create CFDictionary spsStatusDict"); return; }
+    }
+
+    CFStringRef ifname = CFStringCreateWithCString(NULL, info->ifname, kCFStringEncodingUTF8);
+    if (!ifname) { LogMsg("UpdateSPSStatus: Could not create CFString ifname"); return; }
+
+    CFMutableArrayRef array = NULL;
+
+    if (!CFDictionaryGetValueIfPresent(spsStatusDict, ifname, (const void**) &array))
+    {
+        array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+        if (!array) { LogMsg("UpdateSPSStatus: Could not create CFMutableArray"); CFRelease(ifname); return; }
+        CFDictionarySetValue(spsStatusDict, ifname, array);
+        CFRelease(array); // let go of our reference, now that the dict has one
+    }
+    else
+    if (!array) { LogMsg("UpdateSPSStatus: Could not get CFMutableArray for %s", info->ifname); CFRelease(ifname); return; }
+
+    if (!answer) // special call that means the question has been stopped (because the interface is going away)
+        CFArrayRemoveAllValues(array);
+    else
+    {
+        CFMutableDictionaryRef dict = SPSCreateDict(answer->rdata->u.name.c);
+        if (!dict) { CFRelease(ifname); return; }
+
+        if (AddRecord)
+        {
+            if (!CFArrayContainsValue(array, CFRangeMake(0, CFArrayGetCount(array)), dict))
+            {
+                int i=0;
+                for (i=0; i<CFArrayGetCount(array); i++)
+                    if (CompareSPSEntries(CFArrayGetValueAtIndex(array, i), dict, NULL) != kCFCompareLessThan)
+                        break;
+                CFArrayInsertValueAtIndex(array, i, dict);
+            }
+            else LogMsg("UpdateSPSStatus: %s array already contains %##s", info->ifname, answer->rdata->u.name.c);
+        }
+        else
+        {
+            CFIndex i = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), dict);
+            if (i != -1) CFArrayRemoveValueAtIndex(array, i);
+            else LogMsg("UpdateSPSStatus: %s array does not contain %##s", info->ifname, answer->rdata->u.name.c);
+        }
+
+        CFRelease(dict);
+    }
+
+    if (!m->ShutdownTime) mDNSDynamicStoreSetConfig(kmDNSSleepProxyServersState, info->ifname, array);
+
+    CFRelease(ifname);
+}
+
+mDNSlocal mDNSs32 GetSystemSleepTimerSetting(void)
+{
+    mDNSs32 val = -1;
+    SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:GetSystemSleepTimerSetting"), NULL, NULL);
+    if (!store)
+        LogMsg("GetSystemSleepTimerSetting: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
+    else
+    {
+        CFDictionaryRef dict = SCDynamicStoreCopyValue(store, NetworkChangedKey_PowerSettings);
+        if (dict)
+        {
+            CFNumberRef number = CFDictionaryGetValue(dict, CFSTR("System Sleep Timer"));
+            if (number) CFNumberGetValue(number, kCFNumberSInt32Type, &val);
+            CFRelease(dict);
+        }
+        CFRelease(store);
+    }
+    return val;
+}
+
+mDNSlocal void SetSPS(mDNS *const m)
+{
+    
+    // If we ever want to know InternetSharing status in the future, use DNSXEnableProxy()
+    mDNSu8 sps = (OfferSleepProxyService && GetSystemSleepTimerSetting() == 0) ? mDNSSleepProxyMetric_IncidentalSoftware : 0;
+
+    // For devices that are not running NAT, but are set to never sleep, we may choose to act
+    // as a Sleep Proxy, but only for non-portable Macs (Portability > 35 means nominal weight < 3kg)
+    //if (sps > mDNSSleepProxyMetric_PrimarySoftware && SPMetricPortability > 35) sps = 0;
+
+    // If we decide to let laptops act as Sleep Proxy, we should do it only when running on AC power, not on battery
+
+    // For devices that are unable to sleep at all to save power, or save 1W or less by sleeping,
+    // it makes sense for them to offer low-priority Sleep Proxy service on the network.
+    // We rate such a device as metric 70 ("Incidentally Available Hardware")
+    if (SPMetricMarginalPower <= 60 && !sps) sps = mDNSSleepProxyMetric_IncidentalHardware;
+
+    // If the launchd plist specifies an explicit value for the Intent Metric, then use that instead of the
+    // computed value (currently 40 "Primary Network Infrastructure Software" or 80 "Incidentally Available Software")
+    if (sps && OfferSleepProxyService && OfferSleepProxyService < 100) sps = OfferSleepProxyService;
+
+#ifdef NO_APPLETV_SLEEP_PROXY_ON_WIFI
+    // AppleTVs are not reliable sleep proxy servers on WiFi. Do not offer to be a BSP if the WiFi interface is active.
+    if (IsAppleTV())
+    {
+        NetworkInterfaceInfo *intf  = mDNSNULL;
+        mDNSEthAddr           bssid = zeroEthAddr;
+        for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next))
+        {
+            bssid = GetBSSID(intf->ifname);
+            if (!mDNSSameEthAddress(&bssid, &zeroEthAddr))
+            {
+                LogMsg("SetSPS: AppleTV on WiFi - not advertising BSP services");
+                sps = 0;
+                break;
+            }
+        }
+    }
+#endif  //  NO_APPLETV_SLEEP_PROXY_ON_WIFI
+
+    mDNSCoreBeSleepProxyServer(m, sps, SPMetricPortability, SPMetricMarginalPower, SPMetricTotalPower, SPMetricFeatures);
+}
+
+// The definitions below should eventually come from some externally-supplied header file.
+// However, since these definitions can't really be changed without breaking binary compatibility,
+// they should never change, so in practice it should not be a big problem to have them defined here.
+
+enum
+{                               // commands from the daemon to the driver
+    cmd_mDNSOffloadRR = 21,     // give the mdns update buffer to the driver
+};
+
+typedef union { void *ptr; mDNSOpaque64 sixtyfourbits; } FatPtr;
+
+typedef struct
+{                                       // cmd_mDNSOffloadRR structure
+    uint32_t command;                 // set to OffloadRR
+    uint32_t rrBufferSize;            // number of bytes of RR records
+    uint32_t numUDPPorts;             // number of SRV UDP ports
+    uint32_t numTCPPorts;             // number of SRV TCP ports
+    uint32_t numRRRecords;            // number of RR records
+    uint32_t compression;             // rrRecords - compression is base for compressed strings
+    FatPtr rrRecords;                 // address of array of pointers to the rr records
+    FatPtr udpPorts;                  // address of udp port list (SRV)
+    FatPtr tcpPorts;                  // address of tcp port list (SRV)
+} mDNSOffloadCmd;
+
+#include <IOKit/IOKitLib.h>
+#include <dns_util.h>
+
+mDNSlocal mDNSu16 GetPortArray(mDNS *const m, int trans, mDNSIPPort *portarray)
+{
+    const domainlabel *const tp = (trans == mDNSTransport_UDP) ? (const domainlabel *)"\x4_udp" : (const domainlabel *)"\x4_tcp";
+    int count = 0;
+    AuthRecord *rr;
+    for (rr = m->ResourceRecords; rr; rr=rr->next)
+        if (rr->resrec.rrtype == kDNSType_SRV && SameDomainLabel(ThirdLabel(rr->resrec.name)->c, tp->c))
+        {
+            if (portarray) portarray[count] = rr->resrec.rdata->u.srv.port;
+            count++;
+        }
+
+    // If Back to My Mac is on, also wake for packets to the IPSEC UDP port (4500)
+    if (trans == mDNSTransport_UDP && m->AutoTunnelNAT.clientContext)
+    {
+        LogSPS("GetPortArray Back to My Mac at %d", count);
+        if (portarray) portarray[count] = IPSECPort;
+        count++;
+    }
+    return(count);
+}
+
+#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
+mDNSlocal mDNSBool SupportsTCPKeepAlive()
+{
+    IOReturn  ret      = kIOReturnSuccess;
+    CFTypeRef obj      = NULL;
+    mDNSBool  supports = mDNSfalse;
+
+    ret = IOPlatformCopyFeatureActive(CFSTR("TCPKeepAliveDuringSleep"), &obj);
+    if ((kIOReturnSuccess == ret) && (obj != NULL))
+    {
+        supports = (obj ==  kCFBooleanTrue)? mDNStrue : mDNSfalse;
+        CFRelease(obj);
+    }
+    LogSPS("%s: The hardware %s TCP Keep Alive", __func__, (supports ? "supports" : "does not support"));
+    return supports;
+}
+
+mDNSlocal mDNSBool OnBattery(void)
+{
+    CFTypeRef powerInfo = IOPSCopyPowerSourcesInfo();
+    CFTypeRef powerSrc  = IOPSGetProvidingPowerSourceType(powerInfo);
+    mDNSBool  result    = mDNSfalse;
+
+    if (powerInfo != NULL)
+    {
+        result = CFEqual(CFSTR(kIOPSBatteryPowerValue), powerSrc);
+        CFRelease(powerInfo);
+    }
+    LogSPS("%s: The system is on %s", __func__, (result)? "Battery" : "AC Power");
+    return result;
+}
+
+#endif // !TARGET_OS_EMBEDDED
+
+#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)
+{
+    *numbytes = 0;
+    int count = 0;
+
+    AuthRecord *rr;
+
+    for (rr = m->ResourceRecords; rr; rr=rr->next)
+    {
+        if (!(rr->AuthFlags & AuthFlagsWakeOnly) && rr->resrec.RecordType > kDNSRecordTypeDeregistering)
+        {
+#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
+            mDNSBool   isKeepAliveRecord = mDNS_KeepaliveRecord(&rr->resrec);
+            // Skip over all other records if we are registering TCP KeepAlive records only
+            // Skip over TCP KeepAlive records if the policy prohibits it or if the interface does not support TCP Keepalive.
+            if ((TCPKAOnly && !isKeepAliveRecord) || (isKeepAliveRecord && !supportsTCPKA))
+                continue;
+
+            // Update the record before calculating the number of bytes required
+            // We offload the TCP Keepalive record even if the update fails. When the driver gets the record, it will
+            // attempt to update the record again.
+            if (isKeepAliveRecord && (UpdateKeepaliveRData(m, rr, intf, mDNSfalse, mDNSNULL) != mStatus_NoError))
+                LogSPS("CountProxyRecords: Failed to update keepalive record - %s", ARDisplayString(m, rr));
+#else
+            (void) TCPKAOnly;     // unused
+            (void) supportsTCPKA; // unused
+            (void) intf;          // unused
+#endif // APPLE_OSX_mDNSResponder
+            if (TfrRecordToNIC(rr))
+            {
+                *numbytes += DomainNameLength(rr->resrec.name) + 10 + rr->resrec.rdestimate;
+                LogSPS("CountProxyRecords: %3d size %5d total %5d %s",
+                       count, DomainNameLength(rr->resrec.name) + 10 + rr->resrec.rdestimate, *numbytes, ARDisplayString(m,rr));
+                count++;
+            }
+        }
+    }
+    return(count);
+}
+
+mDNSlocal void GetProxyRecords(mDNS *const m, DNSMessage *const msg, uint32_t *const numbytes, FatPtr *const records, mDNSBool TCPKAOnly, mDNSBool supportsTCPKA)
+{
+    mDNSu8 *p = msg->data;
+    const mDNSu8 *const limit = p + *numbytes;
+    InitializeDNSMessage(&msg->h, zeroID, zeroID);
+
+    int count = 0;
+    AuthRecord *rr;
+
+    for (rr = m->ResourceRecords; rr; rr=rr->next)
+    {
+        if (!(rr->AuthFlags & AuthFlagsWakeOnly) && rr->resrec.RecordType > kDNSRecordTypeDeregistering)
+        {
+#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
+            mDNSBool   isKeepAliveRecord = mDNS_KeepaliveRecord(&rr->resrec);
+
+            // Skip over all other records if we are registering TCP KeepAlive records only
+            // Skip over TCP KeepAlive records if the policy prohibits it or if the interface does not support TCP Keepalive
+            if ((TCPKAOnly && !isKeepAliveRecord) || (isKeepAliveRecord && !supportsTCPKA))
+                continue;
+#else
+            (void) TCPKAOnly;     // unused
+            (void) supportsTCPKA; // unused
+#endif // APPLE_OSX_mDNSResponder
+
+            if (TfrRecordToNIC(rr))
+            {
+                records[count].sixtyfourbits = zeroOpaque64;
+                records[count].ptr = p;
+                if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
+                    rr->resrec.rrclass |= kDNSClass_UniqueRRSet;    // Temporarily set the 'unique' bit so PutResourceRecord will set it
+                p = PutResourceRecordTTLWithLimit(msg, p, &msg->h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl, limit);
+                rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;       // Make sure to clear 'unique' bit back to normal state
+                LogSPS("GetProxyRecords: %3d start %p end %p size %5d total %5d %s",
+                       count, records[count].ptr, p, p - (mDNSu8 *)records[count].ptr, p - msg->data, ARDisplayString(m,rr));
+                count++;
+            }
+        }
+    }
+    *numbytes = p - msg->data;
+}
+
+// If compiling with old headers and libraries (pre 10.5) that don't include IOConnectCallStructMethod
+// then we declare a dummy version here so that the code at least compiles
+#ifndef AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER
+static kern_return_t
+IOConnectCallStructMethod(
+    mach_port_t connection,         // In
+    uint32_t selector,              // In
+    const void  *inputStruct,       // In
+    size_t inputStructCnt,          // In
+    void        *outputStruct,      // Out
+    size_t      *outputStructCnt)   // In/Out
+{
+    (void)connection;
+    (void)selector;
+    (void)inputStruct;
+    (void)inputStructCnt;
+    (void)outputStruct;
+    (void)outputStructCnt;
+    LogMsg("Compiled without IOConnectCallStructMethod");
+    return(KERN_FAILURE);
+}
+#endif
+
+mDNSexport mDNSBool SupportsInNICProxy(NetworkInterfaceInfo *const intf)
+{
+    if(!UseInternalSleepProxy)
+    {
+        LogSPS("SupportsInNICProxy: Internal Sleep Proxy is disabled");
+        return mDNSfalse;
+    }
+    return CheckInterfaceSupport(intf, mDNS_IOREG_KEY);
+}
+
+mDNSexport mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const intf)  // Called with the lock held
+{
+    mStatus      result        = mStatus_UnknownErr;
+    mDNSBool     TCPKAOnly     = mDNSfalse;
+    mDNSBool     supportsTCPKA = mDNSfalse;
+    mDNSBool     onbattery     = mDNSfalse; 
+    io_service_t service       = IOServiceGetMatchingService(kIOMasterPortDefault, IOBSDNameMatching(kIOMasterPortDefault, 0, intf->ifname));
+
+#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
+    onbattery = OnBattery();
+    // Check if the interface supports TCP Keepalives and the system policy says it is ok to offload TCP Keepalive records
+    supportsTCPKA = (InterfaceSupportsKeepAlive(intf) && SupportsTCPKeepAlive());
+
+    // 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);
+#else
+    (void) onbattery; // unused;
+#endif
+    if (!service) { LogMsg("ActivateLocalProxy: No service for interface %s", intf->ifname); return(mStatus_UnknownErr); }
+
+    io_name_t n1, n2;
+    IOObjectGetClass(service, n1);
+    io_object_t parent;
+    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);
+        else
+        {
+            if (CFGetTypeID(ref) != CFStringGetTypeID() || !CFEqual(ref, CFSTR(mDNS_IOREG_VALUE)))
+                LogMsg("ActivateLocalProxy: mDNS_IOREG_KEY for interface %s/%s/%s value %s != %s",
+                       intf->ifname, n1, n2, CFStringGetCStringPtr(ref, mDNSNULL), mDNS_IOREG_VALUE);
+            else if (!UseInternalSleepProxy)
+                LogSPS("ActivateLocalProxy: Not using internal (NIC) sleep proxy for interface %s", intf->ifname);
+            else
+            {
+                io_connect_t conObj;
+                kr = IOServiceOpen(parent, mach_task_self(), mDNS_USER_CLIENT_CREATE_TYPE, &conObj);
+                if (kr != KERN_SUCCESS) LogMsg("ActivateLocalProxy: IOServiceOpen for %s/%s/%s failed %d", intf->ifname, n1, n2, kr);
+                else
+                {
+                    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.compression   = sizeof(DNSMessageHeader);
+
+                    DNSMessage *msg = (DNSMessage *)mallocL("mDNSOffloadCmd msg", sizeof(DNSMessageHeader) + cmd.rrBufferSize);
+                    cmd.rrRecords.ptr = mallocL("mDNSOffloadCmd rrRecords", cmd.numRRRecords * sizeof(FatPtr));
+                    cmd.udpPorts.ptr = mallocL("mDNSOffloadCmd udpPorts",  cmd.numUDPPorts  * sizeof(mDNSIPPort));
+                    cmd.tcpPorts.ptr = mallocL("mDNSOffloadCmd tcpPorts",  cmd.numTCPPorts  * sizeof(mDNSIPPort));
+
+                    LogSPS("ActivateLocalProxy: msg %p %d RR %p %d, UDP %p %d, TCP %p %d",
+                           msg, cmd.rrBufferSize,
+                           cmd.rrRecords.ptr, cmd.numRRRecords,
+                           cmd.udpPorts.ptr, cmd.numUDPPorts,
+                           cmd.tcpPorts.ptr, cmd.numTCPPorts);
+
+                    if (!msg || !cmd.rrRecords.ptr || !cmd.udpPorts.ptr || !cmd.tcpPorts.ptr)
+                        LogMsg("ActivateLocalProxy: Failed to allocate memory: msg %p %d RR %p %d, UDP %p %d, TCP %p %d",
+                               msg, cmd.rrBufferSize,
+                               cmd.rrRecords.ptr, cmd.numRRRecords,
+                               cmd.udpPorts.ptr, cmd.numUDPPorts,
+                               cmd.tcpPorts.ptr, cmd.numTCPPorts);
+                    else
+                    {
+                        GetProxyRecords(m, msg, &cmd.rrBufferSize, cmd.rrRecords.ptr, TCPKAOnly, supportsTCPKA);
+                        GetPortArray(m, mDNSTransport_UDP, cmd.udpPorts.ptr);
+                        GetPortArray(m, mDNSTransport_TCP, cmd.tcpPorts.ptr);
+                        char outputData[2];
+                        size_t outputDataSize = sizeof(outputData);
+                        kr = IOConnectCallStructMethod(conObj, 0, &cmd, sizeof(cmd), outputData, &outputDataSize);
+                        LogSPS("ActivateLocalProxy: IOConnectCallStructMethod for %s/%s/%s %d", intf->ifname, n1, n2, kr);
+                        if (kr == KERN_SUCCESS) result = mStatus_NoError;
+                    }
+
+                    if (cmd.tcpPorts.ptr) freeL("mDNSOffloadCmd udpPorts",  cmd.tcpPorts.ptr);
+                    if (cmd.udpPorts.ptr) freeL("mDNSOffloadCmd tcpPorts",  cmd.udpPorts.ptr);
+                    if (cmd.rrRecords.ptr) freeL("mDNSOffloadCmd rrRecords", cmd.rrRecords.ptr);
+                    if (msg) freeL("mDNSOffloadCmd msg",       msg);
+                    IOServiceClose(conObj);
+                }
+            }
+            CFRelease(ref);
+        }
+        IOObjectRelease(parent);
+    }
+    IOObjectRelease(service);
+    return result;
+}
+
+#endif // APPLE_OSX_mDNSResponder
+
+mDNSlocal mDNSu8 SystemWakeForNetworkAccess(void)
+{
+    mDNSs32 val = 0;
+    mDNSu8  ret = (mDNSu8)mDNS_NoWake;
+
+    if (DisableSleepProxyClient)
+    {
+       LogSPS("SystemWakeForNetworkAccess: Sleep Proxy Client disabled by command-line option");
+       return mDNSfalse;
+    }
+
+    GetCurrentPMSetting(CFSTR("Wake On LAN"), &val);
+
+    ret = (mDNSu8)(val != 0) ? mDNS_WakeOnAC : mDNS_NoWake;
+
+#if APPLE_OSX_mDNSResponder && !TARGET_OS_EMBEDDED
+    // If we have TCP Keepalive support, system is capable of registering for TCP Keepalives.
+    // Further policy decisions on whether to offload the records is handled during sleep processing.
+    if ((ret == mDNS_NoWake) && SupportsTCPKeepAlive())
+        ret = (mDNSu8)mDNS_WakeOnBattery;
+#endif // APPLE_OSX_mDNSResponder
+
+    LogSPS("SystemWakeForNetworkAccess: Wake On LAN: %d", ret);
+    return ret;
+}
+
+mDNSlocal mDNSBool SystemSleepOnlyIfWakeOnLAN(void)
+{
+    mDNSs32 val = 0;
+    GetCurrentPMSetting(CFSTR("PrioritizeNetworkReachabilityOverSleep"), &val);
+    return val != 0 ? mDNStrue : mDNSfalse;
+}
+
+#if APPLE_OSX_mDNSResponder
+// When sleeping, we always ensure that the _autotunnel6 record (if connected to RR relay)
+// gets deregistered, so that older peers are forced to connect over direct UDP instead of
+// the RR relay.
+//
+// When sleeping w/o a successful AutoTunnel NAT Mapping, we ensure that all our BTMM
+// service records are deregistered, so they do not appear in peers' Finder sidebars.
+// We do this by checking for the (non-autotunnel) SRV records, as the PTR and TXT records
+// depend on their associated SRV record and therefore will be deregistered together in a
+// single update with the SRV record.
+//
+// Also, the per-zone _kerberos TXT record is always there, including while sleeping, so
+// its presence shouldn't delay sleep.
+//
+// Note that the order of record deregistration is: first _autotunnel6 (if connected to RR
+// 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)
+{
+    if (!AuthRecord_uDNS(rr)) return mDNStrue;
+    
+    if ((rr->resrec.rrtype == kDNSType_AAAA) && SameDomainLabel(rr->namestorage.c, (const mDNSu8 *)"\x0c_autotunnel6"))
+    {
+        LogInfo("RecordReadyForSleep: %s not ready for sleep", ARDisplayString(m, rr));
+        return mDNSfalse;
+    }
+    
+    if ((mDNSIPPortIsZero(m->AutoTunnelNAT.ExternalPort) || m->AutoTunnelNAT.Result))
+    {
+        if (rr->resrec.rrtype == kDNSType_SRV && rr->state != regState_NoTarget && rr->zone
+            && !SameDomainLabel(rr->namestorage.c, (const mDNSu8 *)"\x0b_autotunnel"))
+        {
+            DomainAuthInfo *info = GetAuthInfoForName_internal(m, rr->zone);
+            if (info && info->AutoTunnel)
+            {
+                LogInfo("RecordReadyForSleep: %s not ready for sleep", ARDisplayString(m, rr));
+                return mDNSfalse;
+            }
+        }
+    }
+    
+    return mDNStrue;
+}
+
+// Caller must hold the lock
+mDNSexport void RemoveAutoTunnel6Record(mDNS *const m)
+{
+    DomainAuthInfo *info;
+    // Set the address to zero before calling UpdateAutoTunnel6Record, so that it will
+    // deregister the record, and the MemFree callback won't re-register.
+    m->AutoTunnelRelayAddr = zerov6Addr;
+    for (info = m->AuthInfoList; info; info = info->next)
+        if (info->AutoTunnel)
+            UpdateAutoTunnel6Record(m, info);
+}
+
+mDNSlocal mDNSBool IPv6AddressIsOnInterface(mDNSv6Addr ipv6Addr, char *ifname)
+{
+    struct ifaddrs  *ifa;
+    struct ifaddrs  *ifaddrs;
+    mDNSAddr addr;
+
+    if (if_nametoindex(ifname) == 0) {LogInfo("IPv6AddressIsOnInterface: Invalid name %s", ifname); return mDNSfalse;}
+
+    if (getifaddrs(&ifaddrs) < 0) {LogInfo("IPv6AddressIsOnInterface: getifaddrs failed"); return mDNSfalse;}
+
+    for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next)
+    {
+        if (strncmp(ifa->ifa_name, ifname, IFNAMSIZ) != 0)
+            continue;
+        if ((ifa->ifa_flags & IFF_UP) == 0 || !ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET6)
+            continue;
+        if (SetupAddr(&addr, ifa->ifa_addr) != mStatus_NoError)
+        {
+            LogInfo("IPv6AddressIsOnInterface: SetupAddr error, continuing to the next address");
+            continue;
+        }
+        if (mDNSSameIPv6Address(ipv6Addr, *(mDNSv6Addr*)&addr.ip.v6))
+        {
+            LogInfo("IPv6AddressIsOnInterface: found %.16a", &ipv6Addr);
+            break;
+        }
+    }
+    freeifaddrs(ifaddrs);
+    return ifa != NULL;
+}
+
+mDNSlocal mDNSv6Addr IPv6AddressFromString(char* buf)
+{
+    mDNSv6Addr retVal;
+    struct addrinfo hints;
+    struct addrinfo *res0;
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_INET6;
+    hints.ai_flags = AI_NUMERICHOST;
+
+    int err = getaddrinfo(buf, NULL, &hints, &res0);
+    if (err)
+        return zerov6Addr;
+
+    retVal = *(mDNSv6Addr*)&((struct sockaddr_in6*)res0->ai_addr)->sin6_addr;
+
+    freeaddrinfo(res0);
+
+    return retVal;
+}
+
+mDNSlocal CFDictionaryRef CopyConnectivityBackToMyMacDict()
+{
+    SCDynamicStoreRef store = NULL;
+    CFDictionaryRef connd = NULL;
+    CFDictionaryRef BTMMDict = NULL;
+
+    store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:CopyConnectivityBackToMyMacDict"), NULL, NULL);
+    if (!store)
+    {
+        LogMsg("CopyConnectivityBackToMyMacDict: SCDynamicStoreCreate failed: %s", SCErrorString(SCError()));
+        goto end;
+    }
+
+    connd = SCDynamicStoreCopyValue(store, NetworkChangedKey_BTMMConnectivity);
+    if (!connd)
+    {
+        LogInfo("CopyConnectivityBackToMyMacDict: SCDynamicStoreCopyValue failed: %s", SCErrorString(SCError()));
+        goto end;
+    }
+
+    BTMMDict = CFDictionaryGetValue(connd, CFSTR("BackToMyMac"));
+    if (!BTMMDict)
+    {
+        LogInfo("CopyConnectivityBackToMyMacDict: CFDictionaryGetValue: No value for BackToMyMac");
+        goto end;
+    }
+
+    // Non-dictionary is treated as non-existent dictionary
+    if (CFGetTypeID(BTMMDict) != CFDictionaryGetTypeID())
+    {
+        BTMMDict = NULL;
+        LogMsg("CopyConnectivityBackToMyMacDict: BackToMyMac not a dictionary");
+        goto end;
+    }
+
+    CFRetain(BTMMDict);
+
+end:
+    if (connd) CFRelease(connd);
+    if (store) CFRelease(store);
+
+    return BTMMDict;
+}
+
+#define MAX_IPV6_TEXTUAL 40
+
+mDNSlocal mDNSv6Addr ParseBackToMyMacAddr(CFDictionaryRef BTMMDict, CFStringRef ifKey, CFStringRef addrKey)
+{
+    mDNSv6Addr retVal = zerov6Addr;
+    CFTypeRef string = NULL;
+    char ifname[IFNAMSIZ];
+    char address[MAX_IPV6_TEXTUAL];
+
+    if (!BTMMDict)
+        return zerov6Addr;
+
+    if (!CFDictionaryGetValueIfPresent(BTMMDict, ifKey, &string))
+    {
+        LogInfo("ParseBackToMyMacAddr: interface key does not exist");
+        return zerov6Addr;
+    }
+
+    if (!CFStringGetCString(string, ifname, IFNAMSIZ, kCFStringEncodingUTF8))
+    {
+        LogMsg("ParseBackToMyMacAddr: Could not convert interface to CString");
+        return zerov6Addr;
+    }
+
+    if (!CFDictionaryGetValueIfPresent(BTMMDict, addrKey, &string))
+    {
+        LogMsg("ParseBackToMyMacAddr: address key does not exist, but interface key does");
+        return zerov6Addr;
+    }
+
+    if (!CFStringGetCString(string, address, sizeof(address), kCFStringEncodingUTF8))
+    {
+        LogMsg("ParseBackToMyMacAddr: Could not convert address to CString");
+        return zerov6Addr;
+    }
+
+    retVal = IPv6AddressFromString(address);
+    LogInfo("ParseBackToMyMacAddr: %s (%s) %.16a", ifname, address, &retVal);
+
+    if (mDNSIPv6AddressIsZero(retVal))
+        return zerov6Addr;
+
+    if (!IPv6AddressIsOnInterface(retVal, ifname))
+    {
+        LogMsg("ParseBackToMyMacAddr: %.16a is not on %s", &retVal, ifname);
+        return zerov6Addr;
+    }
+
+    return retVal;
+}
+
+mDNSlocal CFDictionaryRef GetBackToMyMacZones(CFDictionaryRef BTMMDict)
+{
+    CFTypeRef zones = NULL;
+
+    if (!BTMMDict)
+        return NULL;
+
+    if (!CFDictionaryGetValueIfPresent(BTMMDict, CFSTR("Zones"), &zones))
+    {
+        LogInfo("CopyBTMMZones: Zones key does not exist");
+        return NULL;
+    }
+
+    return zones;
+}
+
+mDNSlocal mDNSv6Addr ParseBackToMyMacZone(CFDictionaryRef zones, DomainAuthInfo* info)
+{
+    mDNSv6Addr addr = zerov6Addr;
+    char buffer[MAX_ESCAPED_DOMAIN_NAME];
+    CFStringRef domain = NULL;
+    CFTypeRef theZone = NULL;
+
+    if (!zones)
+        return addr;
+
+    ConvertDomainNameToCString(&info->domain, buffer);
+    domain = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingUTF8);
+    if (!domain)
+        return addr;
+
+    if (CFDictionaryGetValueIfPresent(zones, domain, &theZone))
+        addr = ParseBackToMyMacAddr(theZone, CFSTR("Interface"), CFSTR("Address"));
+
+    CFRelease(domain);
+
+    return addr;
+}
+
+mDNSlocal void SetupBackToMyMacInnerAddresses(mDNS *const m, CFDictionaryRef BTMMDict)
+{
+    DomainAuthInfo* info;
+    CFDictionaryRef zones = GetBackToMyMacZones(BTMMDict);
+    mDNSv6Addr newAddr;
+
+    for (info = m->AuthInfoList; info; info = info->next)
+    {
+        if (!info->AutoTunnel)
+            continue;
+
+        newAddr = ParseBackToMyMacZone(zones, info);
+
+        if (mDNSSameIPv6Address(newAddr, info->AutoTunnelInnerAddress))
+            continue;
+
+        info->AutoTunnelInnerAddress = newAddr;
+        DeregisterAutoTunnelHostRecord(m, info);
+        UpdateAutoTunnelHostRecord(m, info);
+        UpdateAutoTunnelDomainStatus(m, info);
+    }
+}
+
+// MUST be called holding the lock
+mDNSlocal void ProcessConndConfigChanges(mDNS *const m)
+{
+    CFDictionaryRef dict = CopyConnectivityBackToMyMacDict();
+    if (!dict)
+        LogInfo("ProcessConndConfigChanges: No BTMM dictionary");
+    mDNSv6Addr relayAddr = ParseBackToMyMacAddr(dict, CFSTR("RelayInterface"), CFSTR("RelayAddress"));
+
+    LogInfo("ProcessConndConfigChanges: relay %.16a", &relayAddr);
+
+    SetupBackToMyMacInnerAddresses(m, dict);
+
+    if (dict) CFRelease(dict);
+
+    if (!mDNSSameIPv6Address(relayAddr, m->AutoTunnelRelayAddr))
+    {
+        m->AutoTunnelRelayAddr = relayAddr;
+
+        DomainAuthInfo* info;
+        for (info = m->AuthInfoList; info; info = info->next)
+            if (info->AutoTunnel)
+            {
+                DeregisterAutoTunnel6Record(m, info);
+                UpdateAutoTunnel6Record(m, info);
+                UpdateAutoTunnelDomainStatus(m, info);
+            }
+
+        // Determine whether we need racoon to accept incoming connections
+        UpdateAnonymousRacoonConfig(m);
+    }
+
+    // If awacsd crashes or exits for some reason, restart it
+    UpdateBTMMRelayConnection(m);
+}
+#endif /* APPLE_OSX_mDNSResponder */
+
+mDNSlocal mDNSBool IsAppleNetwork(mDNS *const m)
+{
+    DNSServer *s;
+    // Determine if we're on AppleNW based on DNSServer having 17.x.y.z IPv4 addr
+    for (s = m->DNSServers; s; s = s->next)
+    {
+        if (s->addr.ip.v4.b[0] == 17)
+        {     
+            LogInfo("IsAppleNetwork: Found 17.x.y.z DNSServer concluding that we are on AppleNW: %##s %#a", s->domain.c, &s->addr);
+            return mDNStrue;
+        }     
+    }
+    return mDNSfalse;
+}
+
+mDNSexport void mDNSMacOSXNetworkChanged(mDNS *const m)
+{
+    LogInfo("***   Network Configuration Change   ***  (%d)%s",
+            m->p->NetworkChanged ? mDNS_TimeNow(m) - m->p->NetworkChanged : 0,
+            m->p->NetworkChanged ? "" : " (no scheduled configuration change)");
+    m->p->NetworkChanged = 0;       // If we received a network change event and deferred processing, we're now dealing with it
+    mDNSs32 utc = mDNSPlatformUTC();
+    m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
+    m->SystemSleepOnlyIfWakeOnLAN = SystemSleepOnlyIfWakeOnLAN();
+    MarkAllInterfacesInactive(m, utc);
+    UpdateInterfaceList(m, utc);
+    ClearInactiveInterfaces(m, utc);
+    SetupActiveInterfaces(m, utc);
+
+#if APPLE_OSX_mDNSResponder
+
+    mDNS_Lock(m);
+    ProcessConndConfigChanges(m);
+    mDNS_Unlock(m);
+
+    // Scan to find client tunnels whose questions have completed,
+    // but whose local inner/outer addresses have changed since the tunnel was set up
+    ClientTunnel *p;
+    for (p = m->TunnelClients; p; p = p->next)
+        if (p->q.ThisQInterval < 0)
+        {
+            DomainAuthInfo* info = GetAuthInfoForName(m, &p->dstname);
+            if (!info)
+            {
+                LogMsg("mDNSMacOSXNetworkChanged: Could not get AuthInfo for %##s, removing tunnel keys", p->dstname.c);
+                AutoTunnelSetKeys(p, mDNSfalse);
+            }
+            else
+            {
+                mDNSv6Addr inner = info->AutoTunnelInnerAddress;
+
+                if (!mDNSIPPortIsZero(p->rmt_outer_port))
+                {
+                    mDNSAddr tmpSrc = zeroAddr;
+                    mDNSAddr tmpDst = { mDNSAddrType_IPv4, {{{0}}} };
+                    tmpDst.ip.v4 = p->rmt_outer;
+                    mDNSPlatformSourceAddrForDest(&tmpSrc, &tmpDst);
+                    if (!mDNSSameIPv6Address(p->loc_inner, inner) ||
+                        !mDNSSameIPv4Address(p->loc_outer, tmpSrc.ip.v4))
+                    {
+                        AutoTunnelSetKeys(p, mDNSfalse);
+                        p->loc_inner = inner;
+                        p->loc_outer = tmpSrc.ip.v4;
+                        AutoTunnelSetKeys(p, mDNStrue);
+                    }
+                }
+                else
+                {
+                    if (!mDNSSameIPv6Address(p->loc_inner, inner) ||
+                        !mDNSSameIPv6Address(p->loc_outer6, m->AutoTunnelRelayAddr))
+                    {
+                        AutoTunnelSetKeys(p, mDNSfalse);
+                        p->loc_inner = inner;
+                        p->loc_outer6 = m->AutoTunnelRelayAddr;
+                        AutoTunnelSetKeys(p, mDNStrue);
+                    }
+                }
+            }
+        }
+
+    SetSPS(m);
+
+    NetworkInterfaceInfoOSX *i;
+    for (i = m->p->InterfaceList; i; i = i->next)
+    {
+        if (!m->SPSSocket)      // Not being Sleep Proxy Server; close any open BPF fds
+        {
+            if (i->BPF_fd >= 0 && CountProxyTargets(m, i, mDNSNULL, mDNSNULL) == 0) CloseBPF(i);
+        }
+        else                                // else, we're Sleep Proxy Server; open BPF fds
+        {
+            if (i->Exists && i->Registered == i && i->ifinfo.McastTxRx && !(i->ifa_flags & IFF_LOOPBACK) && i->BPF_fd == -1)
+            { LogSPS("%s requesting BPF", i->ifinfo.ifname); i->BPF_fd = -2; mDNSRequestBPF(); }
+        }
+    }
+
+#endif // APPLE_OSX_mDNSResponder
+
+    uDNS_SetupDNSConfig(m);
+    mDNS_ConfigChanged(m);
+
+    if (IsAppleNetwork(m) != mDNS_McastTracingEnabled)
+    {
+        mDNS_McastTracingEnabled = mDNS_McastTracingEnabled ? mDNSfalse : mDNStrue; 
+        LogMsg("mDNSMacOSXNetworkChanged: Multicast Tracing %s", mDNS_McastTracingEnabled ? "Enabled" : "Disabled");
+        UpdateDebugState();
+    }
+
+}
+
+// Called with KQueueLock & mDNS lock
+mDNSlocal void SetNetworkChanged(mDNS *const m, mDNSs32 delay)
+{
+    if (!m->p->NetworkChanged || m->p->NetworkChanged - NonZeroTime(m->timenow + delay) < 0)
+    {
+        m->p->NetworkChanged = NonZeroTime(m->timenow + delay);
+        LogInfo("SetNetworkChanged: scheduling in %d msec", delay);
+    }
+}
+
+// Called with KQueueLock & mDNS lock
+mDNSlocal void SetKeyChainTimer(mDNS *const m, mDNSs32 delay)
+{
+    // 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)
+    {
+        m->p->KeyChainTimer = NonZeroTime(m->timenow + delay);
+        LogInfo("SetKeyChainTimer: %d", delay);
+    }
+}
+
+// Copy the fourth slash-delimited element from either:
+//   State:/Network/Interface/<bsdname>/IPv4
+// or
+//   Setup:/Network/Service/<servicename>/Interface
+mDNSlocal CFStringRef CopyNameFromKey(CFStringRef key)
+{
+    CFArrayRef a;
+    CFStringRef name = NULL;
+
+    a = CFStringCreateArrayBySeparatingStrings(NULL, key, CFSTR("/"));
+    if (a && CFArrayGetCount(a) == 5) name = CFRetain(CFArrayGetValueAtIndex(a, 3));
+    if (a != NULL) CFRelease(a);
+
+    return name;
+}
+
+// Whether a key from a network change notification corresponds to
+// an IP service that is explicitly configured for IPv4 Link Local
+mDNSlocal mDNSBool ChangedKeysHaveIPv4LL(CFArrayRef inkeys)
+{
+    SCDynamicStoreRef store = NULL;
+    CFDictionaryRef dict = NULL;
+    CFMutableArrayRef a;
+    const void **keys = NULL, **vals = NULL;
+    CFStringRef pattern = NULL;
+    int i, ic, j, jc;
+    mDNSBool found = mDNSfalse;
+
+    jc = CFArrayGetCount(inkeys);
+    if (!jc) goto done;
+
+    store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:ChangedKeysHaveIPv4LL"), NULL, NULL);
+    if (store == NULL) goto done;
+
+    a = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    if (a == NULL) goto done;
+
+    // Setup:/Network/Service/[^/]+/Interface
+    pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetInterface);
+    if (pattern == NULL) goto done;
+    CFArrayAppendValue(a, pattern);
+    CFRelease(pattern);
+
+    // Setup:/Network/Service/[^/]+/IPv4
+    pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetIPv4);
+    if (pattern == NULL) goto done;
+    CFArrayAppendValue(a, pattern);
+    CFRelease(pattern);
+
+    dict = SCDynamicStoreCopyMultiple(store, NULL, a);
+    CFRelease(a);
+
+    if (!dict)
+    {
+        LogMsg("ChangedKeysHaveIPv4LL: Empty dictionary");
+        goto done;
+    }
+
+    ic = CFDictionaryGetCount(dict);
+    vals = mDNSPlatformMemAllocate(sizeof (void *) * ic);
+    keys = mDNSPlatformMemAllocate(sizeof (void *) * ic);
+    CFDictionaryGetKeysAndValues(dict, keys, vals);
+
+    for (j = 0; j < jc && !found; j++)
+    {
+        CFStringRef key = CFArrayGetValueAtIndex(inkeys, j);
+        CFStringRef ifname = NULL;
+
+        char buf[256];
+
+        // It would be nice to use a regex here
+        if (!CFStringHasPrefix(key, CFSTR("State:/Network/Interface/")) || !CFStringHasSuffix(key, kSCEntNetIPv4)) continue;
+
+        if ((ifname = CopyNameFromKey(key)) == NULL) continue;
+        if (mDNS_LoggingEnabled)
+        {
+            if (!CFStringGetCString(ifname, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
+            LogInfo("ChangedKeysHaveIPv4LL: potential ifname %s", buf);
+        }
+
+        for (i = 0; i < ic; i++)
+        {
+            CFDictionaryRef ipv4dict;
+            CFStringRef name;
+            CFStringRef serviceid;
+            CFStringRef configmethod;
+
+            if (!CFStringHasSuffix(keys[i], kSCEntNetInterface)) continue;
+
+            if (CFDictionaryGetTypeID() != CFGetTypeID(vals[i])) continue;
+
+            if ((name = CFDictionaryGetValue(vals[i], kSCPropNetInterfaceDeviceName)) == NULL) continue;
+
+            if (!CFEqual(ifname, name)) continue;
+
+            if ((serviceid = CopyNameFromKey(keys[i])) == NULL) continue;
+            if (mDNS_LoggingEnabled)
+            {
+                if (!CFStringGetCString(serviceid, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
+                LogInfo("ChangedKeysHaveIPv4LL: found serviceid %s", buf);
+            }
+
+            pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceid, kSCEntNetIPv4);
+            CFRelease(serviceid);
+            if (pattern == NULL) continue;
+
+            ipv4dict = CFDictionaryGetValue(dict, pattern);
+            CFRelease(pattern);
+            if (!ipv4dict || CFDictionaryGetTypeID() != CFGetTypeID(ipv4dict)) continue;
+
+            configmethod = CFDictionaryGetValue(ipv4dict, kSCPropNetIPv4ConfigMethod);
+            if (!configmethod) continue;
+
+            if (mDNS_LoggingEnabled)
+            {
+                if (!CFStringGetCString(configmethod, buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
+                LogInfo("ChangedKeysHaveIPv4LL: configmethod %s", buf);
+            }
+
+            if (CFEqual(configmethod, kSCValNetIPv4ConfigMethodLinkLocal)) { found = mDNStrue; break; }
+        }
+
+        CFRelease(ifname);
+    }
+
+done:
+    if (vals != NULL) mDNSPlatformMemFree(vals);
+    if (keys != NULL) mDNSPlatformMemFree(keys);
+    if (dict != NULL) CFRelease(dict);
+    if (store != NULL) CFRelease(store);
+
+    return found;
+}
+
+mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context)
+{
+    (void)store;        // Parameter not used
+    mDNSBool changeNow = mDNSfalse;
+    mDNS *const m = (mDNS *const)context;
+    KQueueLock(m);
+    mDNS_Lock(m);
+
+    mDNSs32 delay = mDNSPlatformOneSecond * 2;              // Start off assuming a two-second delay
+
+    int c = CFArrayGetCount(changedKeys);                   // Count changes
+    CFRange range = { 0, c };
+    int c1 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_Hostnames   ) != 0);
+    int c2 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_Computername) != 0);
+    int c3 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DynamicDNS  ) != 0);
+    int c4 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DNS         ) != 0);
+    if (c && c - c1 - c2 - c3 - c4 == 0)
+        delay = mDNSPlatformOneSecond/10;  // If these were the only changes, shorten delay
+
+    // Do immediate network changed processing for "p2p*" interfaces and
+    // for interfaces with the IFEF_DIRECTLINK flag set.
+    {
+        CFArrayRef  labels;
+        CFIndex     n;
+        for (int i = 0; i < c; i++)
+        {
+            CFStringRef key = CFArrayGetValueAtIndex(changedKeys, i);
+
+            // Only look at keys with prefix "State:/Network/Interface/"
+            if (!CFStringHasPrefix(key, NetworkChangedKey_StateInterfacePrefix))
+                continue;
+
+            // And suffix "IPv6" or "IPv4".
+            if (!CFStringHasSuffix(key, kSCEntNetIPv6) && !CFStringHasSuffix(key, kSCEntNetIPv4))
+                continue;
+
+            labels = CFStringCreateArrayBySeparatingStrings(NULL, key, CFSTR("/"));
+            if (labels == NULL)
+                break;
+            n = CFArrayGetCount(labels);
+
+            // Interface changes will have keys of the form: 
+            //     State:/Network/Interface/<interfaceName>/IPv6
+            // Thus five '/' seperated fields, the 4th one being the <interfaceName> string.
+            if (n == 5)
+            {
+                char buf[256];
+
+                // 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)))
+                {
+                    LogInfo("NetworkChanged: interface %s, not delaying network change", buf);
+                    changeNow = mDNStrue;
+                    CFRelease(labels);
+                    break;
+                }
+            }
+            CFRelease(labels);
+        }
+    }
+
+    mDNSBool btmmChanged = CFArrayContainsValue(changedKeys, range, NetworkChangedKey_BackToMyMac);
+    if (btmmChanged) delay = 0;
+
+    if (mDNS_LoggingEnabled)
+    {
+        int i;
+        for (i=0; i<c; i++)
+        {
+            char buf[256];
+            if (!CFStringGetCString(CFArrayGetValueAtIndex(changedKeys, i), buf, sizeof(buf), kCFStringEncodingUTF8)) buf[0] = 0;
+            LogInfo("***   NetworkChanged SC key: %s", buf);
+        }
+        LogInfo("***   NetworkChanged   *** %d change%s %s%s%s%sdelay %d",
+                c, c>1 ? "s" : "",
+                c1 ? "(Local Hostname) " : "",
+                c2 ? "(Computer Name) "  : "",
+                c3 ? "(DynamicDNS) "     : "",
+                c4 ? "(DNS) "            : "",
+                changeNow ? 0 : delay);
+    }
+
+    if (!changeNow)
+        SetNetworkChanged(m, delay);
+
+    // Other software might pick up these changes to register or browse in WAB or BTMM domains,
+    // so in order for secure updates to be made to the server, make sure to read the keychain and
+    // setup the DomainAuthInfo before handing the network change.
+    // If we don't, then we will first try to register services in the clear, then later setup the
+    // DomainAuthInfo, which is incorrect.
+    if (c3 || btmmChanged)
+        SetKeyChainTimer(m, delay);
+
+    mDNS_Unlock(m);
+
+    // If DNS settings changed, immediately force a reconfig (esp. cache flush)
+    // Similarly, if an interface changed that is explicitly IPv4 link local, immediately force a reconfig
+    if (c4 || ChangedKeysHaveIPv4LL(changedKeys) || changeNow) mDNSMacOSXNetworkChanged(m);
+
+    KQueueUnlock(m, "NetworkChanged");
+}
+
+#if APPLE_OSX_mDNSResponder
+mDNSlocal void RefreshSPSStatus(const void *key, const void *value, void *context)
+{
+    (void)context;
+    char buf[IFNAMSIZ];
+
+    CFStringRef ifnameStr = (CFStringRef)key;
+    CFArrayRef array = (CFArrayRef)value;
+    if (!CFStringGetCString(ifnameStr, buf, sizeof(buf), kCFStringEncodingUTF8)) 
+        buf[0] = 0;
+
+    LogInfo("RefreshSPSStatus: Updating SPS state for key %s, array count %d", buf, CFArrayGetCount(array));
+    mDNSDynamicStoreSetConfig(kmDNSSleepProxyServersState, buf, value);
+}
+#endif
+
+mDNSlocal void DynamicStoreReconnected(SCDynamicStoreRef store, void *info)
+{
+    mDNS *const m = (mDNS *const)info;
+    (void)store;
+
+    LogInfo("DynamicStoreReconnected: Reconnected");
+
+    // State:/Network/MulticastDNS
+    SetLocalDomains();
+
+    // State:/Network/DynamicDNS
+    if (m->FQDN.c[0])
+        mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1);
+
+    // Note: PrivateDNS and BackToMyMac are automatically populated when configd is restarted
+    // as we receive network change notifications and thus not necessary. But we leave it here
+    // so that if things are done differently in the future, this code still works.
+
+    // State:/Network/PrivateDNS
+    if (privateDnsArray)
+        mDNSDynamicStoreSetConfig(kmDNSPrivateConfig, mDNSNULL, privateDnsArray);
+
+#if APPLE_OSX_mDNSResponder
+    mDNS_Lock(m);
+    // State:/Network/BackToMyMac
+    UpdateAutoTunnelDomainStatuses(m);
+    mDNS_Unlock(m);
+
+    // State:/Network/Interface/en0/SleepProxyServers
+    if (spsStatusDict) 
+        CFDictionaryApplyFunction(spsStatusDict, RefreshSPSStatus, NULL);
+#endif
+}
+
+mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m)
+{
+    mStatus err = -1;
+    SCDynamicStoreContext context = { 0, m, NULL, NULL, NULL };
+    SCDynamicStoreRef store    = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:WatchForNetworkChanges"), NetworkChanged, &context);
+    CFMutableArrayRef keys     = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    CFStringRef pattern1 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4);
+    CFStringRef pattern2 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6);
+    CFMutableArrayRef patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+    if (!store) { LogMsg("SCDynamicStoreCreate failed: %s", SCErrorString(SCError())); goto error; }
+    if (!keys || !pattern1 || !pattern2 || !patterns) goto error;
+
+    CFArrayAppendValue(keys, NetworkChangedKey_IPv4);
+    CFArrayAppendValue(keys, NetworkChangedKey_IPv6);
+    CFArrayAppendValue(keys, NetworkChangedKey_Hostnames);
+    CFArrayAppendValue(keys, NetworkChangedKey_Computername);
+    CFArrayAppendValue(keys, NetworkChangedKey_DNS);
+    CFArrayAppendValue(keys, NetworkChangedKey_DynamicDNS);
+    CFArrayAppendValue(keys, NetworkChangedKey_BackToMyMac);
+    CFArrayAppendValue(keys, NetworkChangedKey_PowerSettings); // should remove as part of <rdar://problem/6751656>
+    CFArrayAppendValue(keys, NetworkChangedKey_BTMMConnectivity);
+    CFArrayAppendValue(patterns, pattern1);
+    CFArrayAppendValue(patterns, pattern2);
+    CFArrayAppendValue(patterns, CFSTR("State:/Network/Interface/[^/]+/AirPort"));
+    if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns))
+    { LogMsg("SCDynamicStoreSetNotificationKeys failed: %s", SCErrorString(SCError())); goto error; }
+
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+    if (!SCDynamicStoreSetDispatchQueue(store, dispatch_get_main_queue()))
+    { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error; }
+#else
+    m->p->StoreRLS = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
+    if (!m->p->StoreRLS) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s", SCErrorString(SCError())); goto error; }
+    CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode);
+#endif
+    SCDynamicStoreSetDisconnectCallBack(store, DynamicStoreReconnected);
+    m->p->Store = store;
+    err = 0;
+    goto exit;
+
+error:
+    if (store) CFRelease(store);
+
+exit:
+    if (patterns) CFRelease(patterns);
+    if (pattern2) CFRelease(pattern2);
+    if (pattern1) CFRelease(pattern1);
+    if (keys) CFRelease(keys);
+
+    return(err);
+}
+
+#if 0 // <rdar://problem/6751656>
+mDNSlocal void PMChanged(void *context)
+{
+    mDNS *const m = (mDNS *const)context;
+
+    KQueueLock(m);
+    mDNS_Lock(m);
+
+    LogSPS("PMChanged");
+
+    SetNetworkChanged(m, mDNSPlatformOneSecond * 2);
+
+    mDNS_Unlock(m);
+    KQueueUnlock(m, "PMChanged");
+}
+
+mDNSlocal mStatus WatchForPMChanges(mDNS *const m)
+{
+    m->p->PMRLS = IOPMPrefsNotificationCreateRunLoopSource(PMChanged, m);
+    if (!m->p->PMRLS) { LogMsg("IOPMPrefsNotificationCreateRunLoopSource failed!"); return mStatus_UnknownErr; }
+
+    CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->PMRLS, kCFRunLoopDefaultMode);
+
+    return mStatus_NoError;
+}
+#endif
+
+#if !TARGET_OS_EMBEDDED     // don't setup packet filter rules on embedded
+
+mDNSlocal void mDNSSetPacketFilterRules(mDNS *const m, char * ifname, const ResourceRecord *const excludeRecord)
+{
+    AuthRecord  *rr;
+    pfArray_t portArray;
+    pfArray_t protocolArray;
+    uint32_t count = 0;
+
+    for (rr = m->ResourceRecords; rr; rr=rr->next)
+    {
+        if ((rr->resrec.rrtype == kDNSServiceType_SRV) 
+            && ((rr->ARType == AuthRecordAnyIncludeP2P) || (rr->ARType == AuthRecordAnyIncludeAWDLandP2P)))
+        {
+            const mDNSu8    *p;
+
+            if (count >= PFPortArraySize)
+            {
+                LogMsg("mDNSSetPacketFilterRules: %d service limit, skipping %s", PFPortArraySize, ARDisplayString(m, rr));
+                continue;
+            }
+
+            if (excludeRecord && IdenticalResourceRecord(&rr->resrec, excludeRecord))
+            {
+                LogInfo("mDNSSetPacketFilterRules: record being removed, skipping %s", ARDisplayString(m, rr));
+                continue;
+            }
+
+            LogInfo("mDNSSetPacketFilterRules: found %s", ARDisplayString(m, rr));
+
+            portArray[count] = rr->resrec.rdata->u.srv.port.NotAnInteger;
+
+            // Assume <Service Instance>.<App Protocol>.<Transport Protocol>.<Name>
+            p = rr->resrec.name->c;
+
+            // Skip to App Protocol
+            if (p[0]) p += 1 + p[0];
+
+            // Skip to Transport Protocol
+            if (p[0]) p += 1 + p[0];
+
+            if      (SameDomainLabel(p, (mDNSu8 *)"\x4" "_tcp")) protocolArray[count] = IPPROTO_TCP;
+            else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) protocolArray[count] = IPPROTO_UDP;
+            else
+            {
+                LogMsg("mDNSSetPacketFilterRules: could not determine transport protocol of service");
+                LogMsg("mDNSSetPacketFilterRules: %s", ARDisplayString(m, rr));
+                return;
+            }
+            count++;
+        }
+    }
+    mDNSPacketFilterControl(PF_SET_RULES, ifname, count, portArray, protocolArray);
+}
+
+// If the p2p interface already exists, update the Bonjour packet filter rules for it.
+mDNSexport void mDNSUpdatePacketFilter(const ResourceRecord *const excludeRecord)
+{
+    mDNS *const m = &mDNSStorage;
+
+    NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
+    while (intf)
+    {
+        if (strncmp(intf->ifname, "p2p", 3) == 0)
+        {
+            LogInfo("mDNSInitPacketFilter: Setting rules for ifname %s", intf->ifname);
+            mDNSSetPacketFilterRules(m, intf->ifname, excludeRecord);
+            break;
+        }
+        intf = GetFirstActiveInterface(intf->next);
+    }
+}
+
+#else // !TARGET_OS_EMBEDDED
+
+// Currently no packet filter setup required on embedded platforms.
+mDNSexport void mDNSUpdatePacketFilter(const ResourceRecord *const excludeRecord)
+{
+    (void) excludeRecord; // unused
+}
+
+#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)
+{
+    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);
+
+    if (!interfaceIndex)
+    {
+        LogMsg("newMasterElected: if_nametoindex(%s) failed", ifname);
+        return;
+    }
+
+    LogInfo("newMasterElected: ifname = %s, interfaceIndex = %d", ifname, interfaceIndex);
+    infoOSX = IfindexToInterfaceInfoOSX(m, (mDNSInterfaceID)(uintptr_t)interfaceIndex);
+
+    // Can get an KEV_DL_MASTER_ELECTED event prior to the interface existing
+    // when it is first brought up.
+    if (!infoOSX)
+    {
+        LogInfo("newMasterElected: interface not yet active");
+        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);
+        }
+    }
+}
+
+// An ssth array of all zeroes indicates the peer has no services registered.
+mDNSlocal mDNSBool allZeroSSTH(struct opaque_presence_indication *op)
+{
+    int i;
+    int *intp = (int *) op->ssth;
+
+    // MAX_SSTH_SIZE should always be a multiple of sizeof(int), if
+    // it's not, print an error message and return false so that
+    // corresponding peer records are not flushed when KEV_DL_NODE_PRESENCE event
+    // is received.
+    if (MAX_SSTH_SIZE % sizeof(int))
+    {
+        LogInfo("allZeroSSTH: MAX_SSTH_SIZE = %d not a multiple of sizeof(int)", MAX_SSTH_SIZE);
+        return mDNSfalse;
+    }
+
+    for (i = 0; i < (int)(MAX_SSTH_SIZE / sizeof(int)); i++, intp++)
+    {
+        if (*intp)
+            return mDNSfalse;
+    }
+    return mDNStrue;
+}
+
+// mDNS_Reconfirm_internal() adds 33% to this interval, so the records should
+// be removed in 4 seconds.
+#define kAWDLReconfirmTime ((mDNSu32)mDNSPlatformOneSecond *  3)
+
+// Mark records from this peer for deletion from the cache.
+mDNSlocal void removeCachedPeerRecords(mDNS *const m, mDNSu32 ifindex, mDNSAddr *ap)
+{
+    mDNSu32     slot;
+    CacheGroup  *cg;
+    CacheRecord *cr;
+    mDNSInterfaceID InterfaceID = mDNSPlatformInterfaceIDfromInterfaceIndex(m, ifindex);
+
+    if (!InterfaceID)
+    {
+        LogInfo("removeCachedPeerRecords: Invalid ifindex: %d", ifindex);
+        return;
+    }
+
+    FORALL_CACHERECORDS(slot, cg, cr)
+    {
+        if ((InterfaceID == cr->resrec.InterfaceID) && mDNSSameAddress(ap, & cr->sourceAddress))
+        {
+            LogInfo("removeCachedPeerRecords: %s %##s marking for deletion",
+                 DNSTypeName(cr->resrec.rrtype), cr->resrec.name->c);
+            mDNS_Reconfirm_internal(m, cr, kAWDLReconfirmTime);
+        }
+    }
+}
+
+// Handle KEV_DL_NODE_PRESENCE event.
+mDNSlocal void nodePresence(mDNS *const m, struct kev_dl_node_presence * p)
+{
+    char buf[INET6_ADDRSTRLEN];
+    struct opaque_presence_indication *op = (struct opaque_presence_indication *) p->node_service_info;
+
+    if (inet_ntop(AF_INET6, & p->sin6_node_address.sin6_addr, buf, sizeof(buf)))
+        LogInfo("nodePresence:  IPv6 address: %s, SUI %d", buf, op->SUI);
+    else
+        LogInfo("nodePresence:  inet_ntop() error");
+ 
+    // AWDL will generate a KEV_DL_NODE_PRESENCE event with SSTH field of
+    // all zeroes when a node is present and has no services registered.
+    if (allZeroSSTH(op))
+    {
+        mDNSAddr    peerAddr;
+
+        peerAddr.type = mDNSAddrType_IPv6;
+        peerAddr.ip.v6 = *(mDNSv6Addr*)&p->sin6_node_address.sin6_addr;
+
+        LogInfo("nodePresence: ssth is all zeroes, delete cached records from this peer");
+        removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr);
+    }
+}
+
+// Handle KEV_DL_NODE_ABSENCE event.
+mDNSlocal void nodeAbsence(mDNS *const m, struct kev_dl_node_absence * p)
+{
+    mDNSAddr    peerAddr;
+    char buf[INET6_ADDRSTRLEN];
+
+    if (inet_ntop(AF_INET6, & p->sin6_node_address.sin6_addr, buf, sizeof(buf)))
+        LogInfo("nodeAbsence:  IPv6 address: %s", buf);
+    else
+        LogInfo("nodeAbsence:  inet_ntop() error");
+
+    peerAddr.type = mDNSAddrType_IPv6;
+    peerAddr.ip.v6 = *(mDNSv6Addr*)&p->sin6_node_address.sin6_addr;
+
+    LogInfo("nodeAbsence: delete cached records from this peer");
+    removeCachedPeerRecords(m, p->sdl_node_address.sdl_index, & peerAddr);
+}
+
+mDNSlocal void SysEventCallBack(int s1, short __unused filter, void *context)
+{
+    mDNS *const m = (mDNS *const)context;
+
+    mDNS_Lock(m);
+
+    struct { struct kern_event_msg k; char extra[256]; } msg;
+    int bytes = recv(s1, &msg, sizeof(msg), 0);
+    if (bytes < 0)
+        LogMsg("SysEventCallBack: recv error %d errno %d (%s)", bytes, errno, strerror(errno));
+    else
+    {
+        LogInfo("SysEventCallBack got %d bytes size %d %X %s %X %s %X %s id %d code %d %s",
+                bytes, msg.k.total_size,
+                msg.k.vendor_code, msg.k.vendor_code  == KEV_VENDOR_APPLE  ? "KEV_VENDOR_APPLE"  : "?",
+                msg.k.kev_class, msg.k.kev_class    == KEV_NETWORK_CLASS ? "KEV_NETWORK_CLASS" : "?",
+                msg.k.kev_subclass, msg.k.kev_subclass == KEV_DL_SUBCLASS   ? "KEV_DL_SUBCLASS"   : "?",
+                msg.k.id, msg.k.event_code,
+                msg.k.event_code == KEV_DL_SIFFLAGS             ? "KEV_DL_SIFFLAGS"             :
+                msg.k.event_code == KEV_DL_SIFMETRICS           ? "KEV_DL_SIFMETRICS"           :
+                msg.k.event_code == KEV_DL_SIFMTU               ? "KEV_DL_SIFMTU"               :
+                msg.k.event_code == KEV_DL_SIFPHYS              ? "KEV_DL_SIFPHYS"              :
+                msg.k.event_code == KEV_DL_SIFMEDIA             ? "KEV_DL_SIFMEDIA"             :
+                msg.k.event_code == KEV_DL_SIFGENERIC           ? "KEV_DL_SIFGENERIC"           :
+                msg.k.event_code == KEV_DL_ADDMULTI             ? "KEV_DL_ADDMULTI"             :
+                msg.k.event_code == KEV_DL_DELMULTI             ? "KEV_DL_DELMULTI"             :
+                msg.k.event_code == KEV_DL_IF_ATTACHED          ? "KEV_DL_IF_ATTACHED"          :
+                msg.k.event_code == KEV_DL_IF_DETACHING         ? "KEV_DL_IF_DETACHING"         :
+                msg.k.event_code == KEV_DL_IF_DETACHED          ? "KEV_DL_IF_DETACHED"          :
+                msg.k.event_code == KEV_DL_LINK_OFF             ? "KEV_DL_LINK_OFF"             :
+                msg.k.event_code == KEV_DL_LINK_ON              ? "KEV_DL_LINK_ON"              :
+                msg.k.event_code == KEV_DL_PROTO_ATTACHED       ? "KEV_DL_PROTO_ATTACHED"       :
+                msg.k.event_code == KEV_DL_PROTO_DETACHED       ? "KEV_DL_PROTO_DETACHED"       :
+                msg.k.event_code == KEV_DL_LINK_ADDRESS_CHANGED ? "KEV_DL_LINK_ADDRESS_CHANGED" :
+                msg.k.event_code == KEV_DL_WAKEFLAGS_CHANGED    ? "KEV_DL_WAKEFLAGS_CHANGED"    :
+                msg.k.event_code == KEV_DL_IF_IDLE_ROUTE_REFCNT ? "KEV_DL_IF_IDLE_ROUTE_REFCNT" :
+                msg.k.event_code == KEV_DL_IFCAP_CHANGED        ? "KEV_DL_IFCAP_CHANGED"        :
+                msg.k.event_code == KEV_DL_LINK_QUALITY_METRIC_CHANGED    ? "KEV_DL_LINK_QUALITY_METRIC_CHANGED"    :
+                msg.k.event_code == KEV_DL_NODE_PRESENCE        ? "KEV_DL_NODE_PRESENCE"        :
+                msg.k.event_code == KEV_DL_NODE_ABSENCE         ? "KEV_DL_NODE_ABSENCE"         :
+                msg.k.event_code == KEV_DL_MASTER_ELECTED       ? "KEV_DL_MASTER_ELECTED"       :
+                 "?");
+
+        if (msg.k.event_code == KEV_DL_NODE_PRESENCE)
+            nodePresence(m, (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);
+
+        if (msg.k.event_code == KEV_DL_MASTER_ELECTED)
+            newMasterElected(m, (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)
+        // always during sleep/wakeup due to some race conditions (See radar:8666757). At the same time, if
+        // "Wake on Network Access" is not turned on, the notification will not have KEV_DL_WAKEFLAGS_CHANGED.
+        // 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);
+
+#if !TARGET_OS_EMBEDDED     // don't setup packet filter rules on embedded
+
+        // For p2p interfaces, need to open the advertised service port in the firewall.
+        if (msg.k.event_code == KEV_DL_IF_ATTACHED)
+        {
+            struct net_event_data   * p;
+            p = (struct net_event_data *) &msg.k.event_data;
+
+            if (strncmp(p->if_name, "p2p", 3) == 0)
+            {
+                char ifname[IFNAMSIZ];
+                snprintf(ifname, IFNAMSIZ, "%s%d", p->if_name, p->if_unit);
+
+                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);
+            }
+        }
+
+        // For p2p interfaces, need to clear the firewall rules on interface detach
+        if (msg.k.event_code == KEV_DL_IF_DETACHED)
+        {
+            struct net_event_data   * p;
+            p = (struct net_event_data *) &msg.k.event_data;
+
+            if (strncmp(p->if_name, "p2p", 3) == 0)
+            {
+                pfArray_t portArray, protocolArray; // not initialized since count is 0 for PF_CLEAR_RULES
+                char ifname[IFNAMSIZ];
+                snprintf(ifname, IFNAMSIZ, "%s%d", p->if_name, p->if_unit);
+
+                LogInfo("SysEventCallBack: KEV_DL_IF_DETACHED if_family = %d, if_unit = %d, if_name = %s", p->if_family, p->if_unit, p->if_name);
+
+                mDNSPacketFilterControl(PF_CLEAR_RULES, ifname, 0, portArray, protocolArray);
+            }
+        }
+#endif // !TARGET_OS_EMBEDDED
+
+    }
+
+    mDNS_Unlock(m);
+}
+
+mDNSlocal mStatus WatchForSysEvents(mDNS *const m)
+{
+    m->p->SysEventNotifier = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT);
+    if (m->p->SysEventNotifier < 0)
+    { LogMsg("WatchForSysEvents: socket failed error %d errno %d (%s)", m->p->SysEventNotifier, errno, strerror(errno)); return(mStatus_NoMemoryErr); }
+
+    struct kev_request kev_req = { KEV_VENDOR_APPLE, KEV_NETWORK_CLASS, KEV_DL_SUBCLASS };
+    int err = ioctl(m->p->SysEventNotifier, SIOCSKEVFILT, &kev_req);
+    if (err < 0)
+    {
+        LogMsg("WatchForSysEvents: SIOCSKEVFILT failed error %d errno %d (%s)", err, errno, strerror(errno));
+        close(m->p->SysEventNotifier);
+        m->p->SysEventNotifier = -1;
+        return(mStatus_UnknownErr);
+    }
+
+    m->p->SysEventKQueue.KQcallback = SysEventCallBack;
+    m->p->SysEventKQueue.KQcontext  = m;
+    m->p->SysEventKQueue.KQtask     = "System Event Notifier";
+    KQueueSet(m->p->SysEventNotifier, EV_ADD, EVFILT_READ, &m->p->SysEventKQueue);
+
+    return(mStatus_NoError);
+}
+
+#ifndef NO_SECURITYFRAMEWORK
+mDNSlocal OSStatus KeychainChanged(SecKeychainEvent keychainEvent, SecKeychainCallbackInfo *info, void *context)
+{
+    LogInfo("***   Keychain Changed   ***");
+    mDNS *const m = (mDNS *const)context;
+    SecKeychainRef skc;
+    OSStatus err = SecKeychainCopyDefault(&skc);
+    if (!err)
+    {
+        if (info->keychain == skc)
+        {
+            // For delete events, attempt to verify what item was deleted fail because the item is already gone, so we just assume they may be relevant
+            mDNSBool relevant = (keychainEvent == kSecDeleteEvent);
+            if (!relevant)
+            {
+                UInt32 tags[3] = { kSecTypeItemAttr, kSecServiceItemAttr, kSecAccountItemAttr };
+                SecKeychainAttributeInfo attrInfo = { 3, tags, NULL };  // Count, array of tags, array of formats
+                SecKeychainAttributeList *a = NULL;
+                err = SecKeychainItemCopyAttributesAndData(info->item, &attrInfo, NULL, &a, NULL, NULL);
+                if (!err)
+                {
+                    relevant = ((a->attr[0].length == 4 && (!strncasecmp(a->attr[0].data, "ddns", 4) || !strncasecmp(a->attr[0].data, "sndd", 4))) ||
+                                (a->attr[1].length >= mDNSPlatformStrLen(dnsprefix) && (!strncasecmp(a->attr[1].data, dnsprefix, mDNSPlatformStrLen(dnsprefix)))) ||
+                                (a->attr[1].length >= mDNSPlatformStrLen(btmmprefix) && (!strncasecmp(a->attr[1].data, btmmprefix, mDNSPlatformStrLen(btmmprefix)))));
+                    SecKeychainItemFreeAttributesAndData(a, NULL);
+                }
+            }
+            if (relevant)
+            {
+                LogInfo("***   Keychain Changed   *** KeychainEvent=%d %s",
+                        keychainEvent,
+                        keychainEvent == kSecAddEvent    ? "kSecAddEvent"    :
+                        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);
+                mDNS_Lock(m);
+
+                // To not read the keychain twice: when BTMM is enabled, changes happen to the keychain
+                // then the BTMM DynStore dictionary, so delay reading the keychain for a second.
+                // NetworkChanged() will reset the keychain timer to fire immediately when the DynStore changes.
+                //
+                // In the "fixup" case where the BTMM DNS servers aren't accepting the key mDNSResponder has,
+                // the DynStore dictionary won't change (because the BTMM zone won't change).  In that case,
+                // a one second delay is ok, as we'll still converge to correctness, and there's no race
+                // condition between the RegistrationDomain and the DomainAuthInfo.
+                //
+                // 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);
+
+                mDNS_Unlock(m);
+                KQueueUnlock(m, "KeychainChanged");
+            }
+        }
+        CFRelease(skc);
+    }
+
+    return 0;
+}
+#endif
+
+mDNSlocal void PowerOn(mDNS *const m)
+{
+    mDNSCoreMachineSleep(m, false);     // Will set m->SleepState = SleepState_Awake;
+    if (m->p->WakeAtUTC)
+    {
+        long utc = mDNSPlatformUTC();
+        mDNSPowerRequest(-1,-1);        // Need to explicitly clear any previous power requests -- they're not cleared automatically on wake
+        if (m->p->WakeAtUTC - utc > 30)
+        { 
+            LogSPS("PowerChanged PowerOn %d seconds early, assuming not maintenance wake", m->p->WakeAtUTC - utc);
+        }
+        else if (utc - m->p->WakeAtUTC > 30) 
+        {
+            LogSPS("PowerChanged PowerOn %d seconds late, assuming not maintenance wake", utc - m->p->WakeAtUTC);
+        }
+        else if (IsAppleTV())
+        { 
+            LogSPS("PowerChanged PowerOn %d seconds late, device is an AppleTV running iOS so not re-sleeping", utc - m->p->WakeAtUTC);
+        }
+        else
+        {
+            LogSPS("PowerChanged: Waking for network maintenance operations %d seconds early; re-sleeping in 20 seconds", m->p->WakeAtUTC - utc);
+            m->p->RequestReSleep = mDNS_TimeNow(m) + 20 * mDNSPlatformOneSecond;
+        }
+    }
+}
+
+mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messageType, void *messageArgument)
+{
+    mDNS *const m = (mDNS *const)refcon;
+    KQueueLock(m);
+    (void)service;    // Parameter not used
+    debugf("PowerChanged %X %lX", messageType, messageArgument);
+
+    // Make sure our m->SystemWakeOnLANEnabled value correctly reflects the current system setting
+    m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
+
+    switch(messageType)
+    {
+    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);
+        break;
+    case kIOMessageSystemWillNotPowerOff:   LogSPS("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break;          // E0000260
+    case kIOMessageCanSystemSleep:          LogSPS("PowerChanged kIOMessageCanSystemSleep        (no action)"); break;          // E0000270
+    case kIOMessageSystemWillSleep:         LogSPS("PowerChanged kIOMessageSystemWillSleep");                                   // E0000280
+        mDNSCoreMachineSleep(m, true);
+        break;
+    case kIOMessageSystemWillNotSleep:      LogSPS("PowerChanged kIOMessageSystemWillNotSleep    (no action)"); break;          // E0000290
+    case kIOMessageSystemHasPoweredOn:      LogSPS("PowerChanged kIOMessageSystemHasPoweredOn");                                // E0000300
+        // If still sleeping (didn't get 'WillPowerOn' message for some reason?) wake now
+        if (m->SleepState)
+        {
+            LogMsg("PowerChanged kIOMessageSystemHasPoweredOn: ERROR m->SleepState %d", m->SleepState);
+            PowerOn(m);
+        }
+        // Just to be safe, schedule a mDNSMacOSXNetworkChanged(), in case we never received
+        // the System Configuration Framework "network changed" event that we expect
+        // to receive some time shortly after the kIOMessageSystemWillPowerOn message
+        mDNS_Lock(m);
+        if (!m->p->NetworkChanged ||
+            m->p->NetworkChanged - NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2) < 0)
+            m->p->NetworkChanged = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 2);
+        mDNS_Unlock(m);
+
+        break;
+    case kIOMessageSystemWillRestart:       LogSPS("PowerChanged kIOMessageSystemWillRestart     (no action)"); break;          // E0000310
+    case kIOMessageSystemWillPowerOn:       LogSPS("PowerChanged kIOMessageSystemWillPowerOn");                                 // E0000320
+
+        // Make sure our interface list is cleared to the empty state, then tell mDNSCore to wake
+        if (m->SleepState != SleepState_Sleeping)
+        {
+            LogMsg("kIOMessageSystemWillPowerOn: ERROR m->SleepState %d", m->SleepState);
+            m->SleepState = SleepState_Sleeping;
+            mDNSMacOSXNetworkChanged(m);
+        }
+        PowerOn(m);
+        break;
+    default:                                LogSPS("PowerChanged unknown message %X", messageType); break;
+    }
+
+    if (messageType == kIOMessageSystemWillSleep) m->p->SleepCookie = (long)messageArgument;
+    else IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
+
+    KQueueUnlock(m, "PowerChanged Sleep/Wake");
+}
+
+// iPhone OS doesn't currently have SnowLeopard's IO Power Management
+// but it does define kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+#if defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements) && !TARGET_OS_EMBEDDED
+mDNSlocal void SnowLeopardPowerChanged(void *refcon, IOPMConnection connection, IOPMConnectionMessageToken token, IOPMSystemPowerStateCapabilities eventDescriptor)
+{
+    mDNS *const m = (mDNS *const)refcon;
+    KQueueLock(m);
+    LogSPS("SnowLeopardPowerChanged %X %X %X%s%s%s%s%s",
+           connection, token, eventDescriptor,
+           eventDescriptor & kIOPMSystemPowerStateCapabilityCPU     ? " CPU"     : "",
+           eventDescriptor & kIOPMSystemPowerStateCapabilityVideo   ? " Video"   : "",
+           eventDescriptor & kIOPMSystemPowerStateCapabilityAudio   ? " Audio"   : "",
+           eventDescriptor & kIOPMSystemPowerStateCapabilityNetwork ? " Network" : "",
+           eventDescriptor & kIOPMSystemPowerStateCapabilityDisk    ? " Disk"    : "");
+
+    // Make sure our m->SystemWakeOnLANEnabled value correctly reflects the current system setting
+    m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
+
+    if (eventDescriptor & kIOPMSystemPowerStateCapabilityCPU)
+    {
+        // We might be in Sleeping or Transferring state. When we go from "wakeup" to "sleep" state, we don't
+        // go directly to sleep state, but transfer in to the sleep state during which SleepState is set to
+        // SleepState_Transferring. During that time, we might get another wakeup before we transition to Sleeping
+        // state. In that case, we need to acknowledge the previous "sleep" before we acknowledge the wakeup.
+        if (m->SleepLimit)
+        {
+            LogSPS("SnowLeopardPowerChanged: Waking up, Acking old Sleep, SleepLimit %d SleepState %d", m->SleepLimit, m->SleepState);
+            IOPMConnectionAcknowledgeEvent(connection, m->p->SleepCookie);
+            m->SleepLimit = 0;
+        }
+        LogSPS("SnowLeopardPowerChanged: Waking up, Acking Wakeup, SleepLimit %d SleepState %d", m->SleepLimit, m->SleepState);
+        // If the network notifications have already come before we got the wakeup, we ignored them and
+        // in case we get no more, we need to trigger one.
+        mDNS_Lock(m);
+        SetNetworkChanged(m, 2 * mDNSPlatformOneSecond);
+        mDNS_Unlock(m);
+        // CPU Waking. Note: Can get this message repeatedly, as other subsystems power up or down.
+        if (m->SleepState != SleepState_Awake) PowerOn(m);
+        IOPMConnectionAcknowledgeEvent(connection, token);
+    }
+    else
+    {
+        // CPU sleeping. Should not get this repeatedly -- once we're told that the CPU is halting
+        // we should hear nothing more until we're told that the CPU has started executing again.
+        if (m->SleepState) LogMsg("SnowLeopardPowerChanged: Sleep Error %X m->SleepState %d", eventDescriptor, m->SleepState);
+        //sleep(5);
+        //mDNSMacOSXNetworkChanged(m);
+        mDNSCoreMachineSleep(m, true);
+        //if (m->SleepState == SleepState_Sleeping) mDNSMacOSXNetworkChanged(m);
+        m->p->SleepCookie = token;
+    }
+
+    KQueueUnlock(m, "SnowLeopardPowerChanged Sleep/Wake");
+}
+#endif
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - /etc/hosts support
+#endif
+
+// Implementation Notes
+//
+// As /etc/hosts file can be huge (1000s of entries - when this comment was written, the test file had about
+// 23000 entries with about 4000 duplicates), we can't use a linked list to store these entries. So, we parse
+// them into a hash table. The implementation need to be able to do the following things efficiently
+//
+// 1. Detect duplicates e.g., two entries with "1.2.3.4 foo"
+// 2. Detect whether /etc/hosts has changed and what has changed since the last read from the disk
+// 3. Ability to support multiple addresses per name e.g., "1.2.3.4 foo, 2.3.4.5 foo". To support this, we
+//    need to be able set the RRSet of a resource record to the first one in the list and also update when
+//    one of them go away. This is needed so that the core thinks that they are all part of the same RRSet and
+//    not a duplicate
+// 4. Don't maintain any local state about any records registered with the core to detect changes to /etc/hosts
+//
+// CFDictionary is not a suitable candidate because it does not support duplicates and even if we use a custom
+// "hash" function to solve this, the others are hard to solve. Hence, we share the hash (AuthHash) implementation
+// of the core layer which does all of the above very efficiently
+
+#define ETCHOSTS_BUFSIZE    1024    // Buffer size to parse a single line in /etc/hosts
+
+mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
+{
+    (void)m;  // unused
+    (void)rr;
+    (void)result;
+    if (result == mStatus_MemFree)
+    {
+        LogInfo("FreeEtcHosts: %s", ARDisplayString(m, rr));
+        freeL("etchosts", rr);
+    }
+}
+
+// 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)
+{
+    AuthRecord *rr;
+    mDNSu32 slot;
+    mDNSu32 namehash;
+    AuthGroup *ag;
+    mDNSInterfaceID InterfaceID = mDNSInterface_LocalOnly;
+    mDNSu16 rrtype;
+
+    if (!domain)
+    {
+        LogMsg("mDNSMacOSXCreateEtcHostsEntry: ERROR!! name NULL");
+        return mDNSfalse;
+    }
+    if (!sa && !cname)
+    {
+        LogMsg("mDNSMacOSXCreateEtcHostsEntry: ERROR!! sa and cname both NULL");
+        return mDNSfalse;
+    }
+
+    if (sa && sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
+    {
+        LogMsg("mDNSMacOSXCreateEtcHostsEntry: ERROR!! sa with bad family %d", sa->sa_family);
+        return mDNSfalse;
+    }
+
+
+    if (ifname)
+    {
+        mDNSu32 ifindex = if_nametoindex(ifname);
+        if (!ifindex)
+        {
+            LogMsg("mDNSMacOSXCreateEtcHostsEntry: hosts entry %##s with invalid ifname %s", domain->c, ifname);
+            return mDNSfalse;
+        }
+        InterfaceID = (mDNSInterfaceID)(uintptr_t)ifindex;
+    }
+
+    if (sa)
+        rrtype = (sa->sa_family == AF_INET ? kDNSType_A : kDNSType_AAAA);
+    else
+        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);
+    if (ag)
+    {
+        rr = ag->members;
+        while (rr)
+        {
+            if (rr->resrec.rrtype == rrtype)
+            {
+                if (rrtype == kDNSType_A)
+                {
+                    mDNSv4Addr ip;
+                    ip.NotAnInteger = ((struct sockaddr_in*)sa)->sin_addr.s_addr;
+                    if (mDNSSameIPv4Address(rr->resrec.rdata->u.ipv4, ip))
+                    {
+                        LogInfo("mDNSMacOSXCreateEtcHostsEntry: Same IPv4 address for name %##s", domain->c);
+                        return mDNSfalse;
+                    }
+                }
+                else if (rrtype == kDNSType_AAAA)
+                {
+                    mDNSv6Addr ip6;
+                    ip6.l[0] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[0];
+                    ip6.l[1] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[1];
+                    ip6.l[2] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[2];
+                    ip6.l[3] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[3];
+                    if (mDNSSameIPv6Address(rr->resrec.rdata->u.ipv6, ip6))
+                    {
+                        LogInfo("mDNSMacOSXCreateEtcHostsEntry: Same IPv6 address for name %##s", domain->c);
+                        return mDNSfalse;
+                    }
+                }
+                else if (rrtype == kDNSType_CNAME)
+                {
+                    if (SameDomainName(&rr->resrec.rdata->u.name, cname))
+                    {
+                        LogInfo("mDNSMacOSXCreateEtcHostsEntry: Same cname %##s for name %##s", cname->c, domain->c);
+                        return mDNSfalse;
+                    }
+                }
+            }
+            rr = rr->next;
+        }
+    }
+    rr= mallocL("etchosts", sizeof(*rr));
+    if (rr == NULL) return mDNSfalse;
+    mDNSPlatformMemZero(rr, sizeof(*rr));
+    mDNS_SetupResourceRecord(rr, NULL, InterfaceID, rrtype, 1, kDNSRecordTypeKnownUnique, AuthRecordLocalOnly, FreeEtcHosts, NULL);
+    AssignDomainName(&rr->namestorage, domain);
+
+    if (sa)
+    {
+        rr->resrec.rdlength = sa->sa_family == AF_INET ? sizeof(mDNSv4Addr) : sizeof(mDNSv6Addr);
+        if (sa->sa_family == AF_INET)
+            rr->resrec.rdata->u.ipv4.NotAnInteger = ((struct sockaddr_in*)sa)->sin_addr.s_addr;
+        else
+        {
+            rr->resrec.rdata->u.ipv6.l[0] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[0];
+            rr->resrec.rdata->u.ipv6.l[1] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[1];
+            rr->resrec.rdata->u.ipv6.l[2] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[2];
+            rr->resrec.rdata->u.ipv6.l[3] = ((struct sockaddr_in6*)sa)->sin6_addr.__u6_addr.__u6_addr32[3];
+        }
+    }
+    else
+    {
+        rr->resrec.rdlength = DomainNameLength(cname);
+        rr->resrec.rdata->u.name.c[0] = 0;
+        AssignDomainName(&rr->resrec.rdata->u.name, cname);
+    }
+    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);
+    return mDNStrue;
+}
+
+mDNSlocal int EtcHostsParseOneName(int start, int length, char *buffer, char **name)
+{
+    int i;
+
+    *name = NULL;
+    for (i = start; i < length; i++)
+    {
+        if (buffer[i] == '#')
+            return -1;
+        if (buffer[i] != ' ' && buffer[i] != ',' && buffer[i] != '\t')
+        {
+            *name = &buffer[i];
+
+            // Found the start of a name, find the end and null terminate
+            for (i++; i < length; i++)
+            {
+                if (buffer[i] == ' ' || buffer[i] == ',' || buffer[i] == '\t')
+                {
+                    buffer[i] = 0;
+                    break;
+                }
+            }
+            return i;
+        }
+    }
+    return -1;
+}
+
+mDNSlocal void mDNSMacOSXParseEtcHostsLine(mDNS *const m, char *buffer, ssize_t length, AuthHash *auth)
+{
+    int i;
+    int ifStart = 0;
+    char *ifname = NULL;
+    domainname name1d;
+    domainname name2d;
+    char *name1;
+    char *name2;
+    int aliasIndex;
+
+    //Ignore leading whitespaces and tabs
+    while (*buffer == ' ' || *buffer == '\t')
+    {
+        buffer++;
+        length--;
+    }
+
+    // Find the end of the address string
+    for (i = 0; i < length; i++)
+    {
+        if (buffer[i] == ' ' || buffer[i] == ',' || buffer[i] == '\t' || buffer[i] == '%')
+        {
+            if (buffer[i] == '%')
+                ifStart = i + 1;
+            buffer[i] = 0;
+            break;
+        }
+    }
+
+    // Convert the address string to an address
+    struct addrinfo hints;
+    bzero(&hints, sizeof(hints));
+    hints.ai_flags = AI_NUMERICHOST;
+    struct addrinfo *gairesults = NULL;
+    if (getaddrinfo(buffer, NULL, &hints, &gairesults) != 0)
+    {
+        LogInfo("mDNSMacOSXParseEtcHostsLine: getaddrinfo returning null");
+        return;
+    }
+
+    if (ifStart)
+    {
+        // Parse the interface
+        ifname = &buffer[ifStart];
+        for (i = ifStart + 1; i < length; i++)
+        {
+            if (buffer[i] == ' ' || buffer[i] == ',' || buffer[i] == '\t')
+            {
+                buffer[i] = 0;
+                break;
+            }
+        }
+    }
+
+    i = EtcHostsParseOneName(i + 1, length, buffer, &name1);
+    if (i == length)
+    {
+        // Common case (no aliases) : The entry is of the form "1.2.3.4 somehost" with no trailing white spaces/tabs etc.
+        if (!MakeDomainNameFromDNSNameString(&name1d, name1))
+        {
+            LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name1);
+            freeaddrinfo(gairesults);
+            return;
+        }
+        mDNSMacOSXCreateEtcHostsEntry(m, &name1d, gairesults->ai_addr, mDNSNULL, ifname, auth);
+    }
+    else if (i != -1)
+    {
+        domainname first;
+        // We might have some extra white spaces at the end for the common case of "1.2.3.4 somehost".
+        // When we parse again below, EtchHostsParseOneName would return -1 and we will end up
+        // doing the right thing.
+        if (!MakeDomainNameFromDNSNameString(&first, name1))
+        {
+            LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name1);
+            freeaddrinfo(gairesults);
+            return;
+        }
+        // If the /etc/hosts has an entry like this
+        //
+        // 1.2.3.4 sun star bright
+        //
+        // star and bright are aliases (gethostbyname h_alias should point to these) and sun is the canonical
+        // name (getaddrinfo ai_cannonname and gethostbyname h_name points to "sun")
+        //
+        // To achieve this, we need to add the entry like this:
+        //
+        // star CNAME bright
+        // bright CNAME sun
+        // sun A 1.2.3.4
+        //
+        // We store the first name we parsed in "first". Then we parse additional names adding CNAME records
+        // till we reach the end. When we reach the end, we wrap around and add one final CNAME with the last
+        // entry and the first entry. Finally, we add the Address (A/AAAA) record.
+        aliasIndex = 0;
+        while (i <= length)
+        {
+            // Parse a name. If there are no names, we need to know whether we
+            // parsed CNAMEs before or not. If we parsed CNAMEs before, then we
+            // add a CNAME with the last name and the first name. Otherwise, this
+            // is same as the common case above where the line has just one name
+            // but with trailing white spaces.
+            i = EtcHostsParseOneName(i + 1, length, buffer, &name2);
+            if (name2)
+            {
+                if (!MakeDomainNameFromDNSNameString(&name2d, name2))
+                {
+                    LogMsg("mDNSMacOSXParseEtcHostsLine: ERROR!! cannot convert to domain name %s", name2);
+                    freeaddrinfo(gairesults);
+                    return;
+                }
+                aliasIndex++;
+            }
+            else if (!aliasIndex)
+            {
+                // We have never parsed any aliases. This case happens if there
+                // is just one name and some extra white spaces at the end.
+                LogInfo("mDNSMacOSXParseEtcHostsLine: White space at the end of %##s", first.c);
+                break;
+            }
+            else
+            {
+                // We have parsed at least one alias before and we reached the end of the line.
+                // Setup a CNAME for the last name with "first" name as its RDATA
+                name2d.c[0] = 0;
+                AssignDomainName(&name2d, &first);
+            }
+
+            // Don't add a CNAME for the first alias we parse (see the example above).
+            // As we parse more, we might discover that there are no more aliases, in
+            // which case we would have set "name2d" to "first" above. We need to add
+            // the CNAME in that case.
+
+            if (aliasIndex > 1 || SameDomainName(&name2d, &first))
+            {
+                // Ignore if it points to itself
+                if (!SameDomainName(&name1d, &name2d))
+                {
+                    if (!mDNSMacOSXCreateEtcHostsEntry(m, &name1d, mDNSNULL, &name2d, ifname, auth))
+                    {
+                        freeaddrinfo(gairesults);
+                        return;
+                    }
+                }
+                else
+                    LogMsg("mDNSMacOSXParseEtcHostsLine: Ignoring entry with same names name1 %##s, name2 %##s", name1d.c, name2d.c);
+            }
+
+            // If we have already wrapped around, we just need to add the A/AAAA record alone
+            // which is done below
+            if (SameDomainName(&name2d, &first)) break;
+
+            // Remember the current name so that we can set the CNAME record if we parse one
+            // more name
+            name1d.c[0] = 0;
+            AssignDomainName(&name1d, &name2d);
+        }
+        // Added all the CNAMEs if any, add the "A/AAAA" record
+        mDNSMacOSXCreateEtcHostsEntry(m, &first, gairesults->ai_addr, mDNSNULL, ifname, auth);
+    }
+    freeaddrinfo(gairesults);
+}
+
+mDNSlocal void mDNSMacOSXParseEtcHosts(mDNS *const m, int fd, AuthHash *auth)
+{
+    mDNSBool good;
+    char buf[ETCHOSTS_BUFSIZE];
+    ssize_t len;
+    FILE *fp;
+
+    if (fd == -1) { LogInfo("mDNSMacOSXParseEtcHosts: fd is -1"); return; }
+
+    fp = fopen("/etc/hosts", "r");
+    if (!fp) { LogInfo("mDNSMacOSXParseEtcHosts: fp is NULL"); return; }
+
+    while (1)
+    {
+        good = (fgets(buf, ETCHOSTS_BUFSIZE, fp) != NULL);
+        if (!good) break;
+
+        // skip comment and empty lines
+        if (buf[0] == '#' || buf[0] == '\r' || buf[0] == '\n')
+            continue;
+
+        len = strlen(buf);
+        if (!len) break;    // sanity check
+        //Check for end of line code(mostly only \n but pre-OS X Macs could have only \r)
+        if (buf[len - 1] == '\r' || buf[len - 1] == '\n')
+        {
+            buf[len - 1] = '\0';
+            len = len - 1;
+        }
+        // fgets always null terminates and hence even if we have no
+        // newline at the end, it is null terminated. The callee
+        // (mDNSMacOSXParseEtcHostsLine) expects the length to be such that
+        // buf[length] is zero and hence we decrement len to reflect that.
+        if (len)
+        {
+            //Additional check when end of line code is 2 chars ie\r\n(DOS, other old OSes)
+            //here we need to check for just \r but taking extra caution.
+            if (buf[len - 1] == '\r' || buf[len - 1] == '\n')
+            {
+                buf[len - 1] = '\0';
+                len = len - 1;
+            }
+        }
+        if (!len) //Sanity Check: len should never be zero
+        {
+            LogMsg("mDNSMacOSXParseEtcHosts: Length is zero!");
+            continue;
+        }
+        mDNSMacOSXParseEtcHostsLine(m, buf, len, auth);
+    }
+    fclose(fp);
+}
+
+mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m);
+
+mDNSlocal int mDNSMacOSXGetEtcHostsFD(mDNS *const m)
+{
+#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;
+    static dispatch_source_t etcsrc   = 0;
+    static dispatch_source_t hostssrc = 0;
+
+    // First time through? just schedule ourselves on the main queue and we'll do the work later
+    if (!etcq)
+    {
+        etcq = dispatch_get_main_queue();
+        if (etcq)
+        {
+            // Do this work on the queue, not here - solves potential synchronization issues
+            dispatch_async(etcq, ^{mDNSMacOSXUpdateEtcHosts(m);});
+        }
+        return -1;
+    }
+
+    if (hostssrc) return dispatch_source_get_handle(hostssrc);
+#endif
+
+    int fd = open("/etc/hosts", O_RDONLY);
+
+#ifdef __DISPATCH_GROUP__
+    // Can't do this stuff to be notified of changes in /etc/hosts if we don't have libdispatch
+    if (fd == -1)
+    {
+        // If the open failed and we're already watching /etc, we're done
+        if (etcsrc) { LogInfo("mDNSMacOSXGetEtcHostsFD: Returning etcfd because no etchosts"); return fd; }
+
+        // we aren't watching /etc, we should be
+        fd = open("/etc", O_RDONLY);
+        if (fd == -1) { LogInfo("mDNSMacOSXGetEtcHostsFD: etc does not exist"); return -1; }
+        etcsrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fd, DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_RENAME, etcq);
+        if (etcsrc == NULL)
+        {
+            close(fd);
+            return -1;
+        }
+        dispatch_source_set_event_handler(etcsrc,
+                                          ^{
+                                              u_int32_t flags = dispatch_source_get_data(etcsrc);
+                                              LogMsg("mDNSMacOSXGetEtcHostsFD: /etc changed 0x%x", flags);
+                                              if ((flags & (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_RENAME)) != 0)
+                                              {
+                                                  dispatch_source_cancel(etcsrc);
+                                                  dispatch_release(etcsrc);
+                                                  etcsrc = NULL;
+                                                  dispatch_async(etcq, ^{mDNSMacOSXUpdateEtcHosts(m);});
+                                                  return;
+                                              }
+                                              if ((flags & DISPATCH_VNODE_WRITE) != 0 && hostssrc == NULL)
+                                              {
+                                                  mDNSMacOSXUpdateEtcHosts(m);
+                                              }
+                                          });
+        dispatch_source_set_cancel_handler(etcsrc, ^{close(fd);});
+        dispatch_resume(etcsrc);
+
+        // Try and open /etc/hosts once more now that we're watching /etc, in case we missed the creation
+        fd = open("/etc/hosts", O_RDONLY | O_EVTONLY);
+        if (fd == -1) { LogMsg("mDNSMacOSXGetEtcHostsFD etc hosts does not exist, watching etc"); return -1; }
+    }
+
+    // create a dispatch source to watch for changes to hosts file
+    hostssrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fd,
+                                      (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_RENAME |
+                                       DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_LINK | DISPATCH_VNODE_REVOKE), etcq);
+    if (hostssrc == NULL)
+    {
+        close(fd);
+        return -1;
+    }
+    dispatch_source_set_event_handler(hostssrc,
+                                      ^{
+                                          u_int32_t flags = dispatch_source_get_data(hostssrc);
+                                          LogInfo("mDNSMacOSXGetEtcHostsFD: /etc/hosts changed 0x%x", flags);
+                                          if ((flags & (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_RENAME)) != 0)
+                                          {
+                                              dispatch_source_cancel(hostssrc);
+                                              dispatch_release(hostssrc);
+                                              hostssrc = NULL;
+                                              // Bug in LibDispatch: wait a second before scheduling the block. If we schedule
+                                              // the block immediately, we try to open the file and the file may not exist and may
+                                              // fail to get a notification in the future. When the file does not exist and
+                                              // we start to monitor the directory, on "dispatch_resume" of that source, there
+                                              // is no guarantee that the file creation will be notified always because when
+                                              // the dispatch_resume returns, the kevent manager may not have registered the
+                                              // kevent yet but the file may have been created
+                                              usleep(1000000);
+                                              dispatch_async(etcq, ^{mDNSMacOSXUpdateEtcHosts(m);});
+                                              return;
+                                          }
+                                          if ((flags & DISPATCH_VNODE_WRITE) != 0)
+                                          {
+                                              mDNSMacOSXUpdateEtcHosts(m);
+                                          }
+                                      });
+    dispatch_source_set_cancel_handler(hostssrc, ^{LogInfo("mDNSMacOSXGetEtcHostsFD: Closing etchosts fd %d", fd); close(fd);});
+    dispatch_resume(hostssrc);
+
+    // Cleanup /etc source, no need to watch it if we already have /etc/hosts
+    if (etcsrc)
+    {
+        dispatch_source_cancel(etcsrc);
+        dispatch_release(etcsrc);
+        etcsrc = NULL;
+    }
+
+    LogInfo("mDNSMacOSXGetEtcHostsFD: /etc/hosts being monitored, and not etc");
+    return hostssrc ? (int)dispatch_source_get_handle(hostssrc) : -1;
+#else
+    (void)m;
+    return fd;
+#endif
+}
+
+// When /etc/hosts is modified, flush all the cache records as there may be local
+// authoritative answers now
+mDNSlocal void FlushAllCacheRecords(mDNS *const m)
+{
+    CacheRecord *cr;
+    mDNSu32 slot;
+    CacheGroup *cg;
+
+    FORALL_CACHERECORDS(slot, cg, cr)
+    {
+        // Skip multicast.
+        if (cr->resrec.InterfaceID) continue;
+
+        // If a resource record can answer A or AAAA, they need to be flushed so that we will
+        // never used to deliver an ADD or RMV
+        if (RRTypeAnswersQuestionType(&cr->resrec, kDNSType_A) ||
+            RRTypeAnswersQuestionType(&cr->resrec, kDNSType_AAAA))
+        {
+            LogInfo("FlushAllCacheRecords: Purging Resourcerecord %s", CRDisplayString(m, cr));
+            mDNS_PurgeCacheResourceRecord(m, cr);
+        }
+    }
+}
+
+// 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)
+{
+    AuthGroup *ag;
+    mDNSu32 slot;
+    AuthRecord *rr, *primary, *rrnext;
+    for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
+        for (ag = newhosts->rrauth_hash[slot]; ag; ag = ag->next)
+        {
+            primary = NULL;
+            for (rr = ag->members; rr; rr = rrnext)
+            {
+                rrnext = rr->next;
+                AuthGroup *ag1;
+                AuthRecord *rr1;
+                mDNSBool found = mDNSfalse;
+                ag1 = AuthGroupForRecord(&m->rrauth, slot, &rr->resrec);
+                if (ag1 && ag1->members)
+                {
+                    if (!primary) primary = ag1->members;
+                    rr1 = ag1->members;
+                    while (rr1)
+                    {
+                        // We are not using InterfaceID in checking for duplicates. This means,
+                        // if there are two addresses for a given name e.g., fe80::1%en0 and
+                        // fe80::1%en1, we only add the first one. It is not clear whether
+                        // this is a common case. To fix this, we also need to modify
+                        // mDNS_Register_internal in how it handles duplicates. If it becomes a
+                        // common case, we will fix it then.
+                        if (IdenticalResourceRecord(&rr1->resrec, &rr->resrec))
+                        {
+                            LogInfo("EtcHostsAddNewEntries: Skipping, not adding %s", ARDisplayString(m, rr1));
+                            found = mDNStrue;
+                            break;
+                        }
+                        rr1 = rr1->next;
+                    }
+                }
+                if (!found)
+                {
+                    if (justCheck)
+                    {
+                        LogInfo("EtcHostsAddNewEntries: Entry %s not registered with core yet", ARDisplayString(m, rr));
+                        return mDNStrue;
+                    }
+                    RemoveAuthRecord(m, newhosts, rr);
+                    // if there is no primary, point to self
+                    rr->RRSet = (primary ? primary : rr);
+                    rr->next = NULL;
+                    LogInfo("EtcHostsAddNewEntries: Adding %s", ARDisplayString(m, rr));
+                    if (mDNS_Register_internal(m, rr) != mStatus_NoError)
+                        LogMsg("EtcHostsAddNewEntries: mDNS_Register failed for %s", ARDisplayString(m, rr));
+                }
+            }
+        }
+    return mDNSfalse;
+}
+
+// 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)
+{
+    AuthGroup *ag;
+    mDNSu32 slot;
+    AuthRecord *rr, *primary, *rrnext;
+    for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
+        for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next)
+            for (rr = ag->members; rr; rr = rrnext)
+            {
+                mDNSBool found = mDNSfalse;
+                AuthGroup *ag1;
+                AuthRecord *rr1;
+                rrnext = rr->next;
+                if (rr->RecordCallback != FreeEtcHosts) continue;
+                ag1 = AuthGroupForRecord(newhosts, slot, &rr->resrec);
+                if (ag1)
+                {
+                    primary = rr1 = ag1->members;
+                    while (rr1)
+                    {
+                        if (IdenticalResourceRecord(&rr1->resrec, &rr->resrec))
+                        {
+                            LogInfo("EtcHostsDeleteOldEntries: Old record %s found in new, skipping", ARDisplayString(m, rr));
+                            found = mDNStrue;
+                            break;
+                        }
+                        rr1 = rr1->next;
+                    }
+                }
+                // there is no corresponding record in newhosts for the same name. This means
+                // we should delete this from the core.
+                if (!found)
+                {
+                    if (justCheck)
+                    {
+                        LogInfo("EtcHostsDeleteOldEntries: Record %s not found in new, deleting", ARDisplayString(m, rr));
+                        return mDNStrue;
+                    }
+                    // if primary is going away, make sure that the rest of the records
+                    // point to the new primary
+                    if (rr == ag->members)
+                    {
+                        AuthRecord *new_primary = rr->next;
+                        AuthRecord *r = new_primary;
+                        while (r)
+                        {
+                            if (r->RRSet == rr)
+                            {
+                                LogInfo("EtcHostsDeleteOldEntries: Updating Resource Record %s to primary", ARDisplayString(m, r));
+                                r->RRSet = new_primary;
+                            }
+                            else LogMsg("EtcHostsDeleteOldEntries: ERROR!! Resource Record %s not pointing to primary %##s", ARDisplayString(m, r), r->resrec.name);
+                            r = r->next;
+                        }
+                    }
+                    LogInfo("EtcHostsDeleteOldEntries: Deleting %s", ARDisplayString(m, rr));
+                    mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
+                }
+            }
+    return mDNSfalse;
+}
+
+mDNSlocal void UpdateEtcHosts(mDNS *const m, void *context)
+{
+    AuthHash *newhosts = (AuthHash *)context;
+
+    mDNS_CheckLock(m);
+
+    //Delete old entries from the core if they are not present in the newhosts
+    EtcHostsDeleteOldEntries(m, newhosts, mDNSfalse);
+    // Add the new entries to the core if not already present in the core
+    EtcHostsAddNewEntries(m, newhosts, mDNSfalse);
+}
+
+mDNSlocal void FreeNewHosts(AuthHash *newhosts)
+{
+    mDNSu32 slot;
+    AuthGroup *ag, *agnext;
+    AuthRecord *rr, *rrnext;
+
+    for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
+        for (ag = newhosts->rrauth_hash[slot]; ag; ag = agnext)
+        {
+            agnext = ag->next;
+            for (rr = ag->members; rr; rr = rrnext)
+            {
+                rrnext = rr->next;
+                freeL("etchosts", rr);
+            }
+            freeL("AuthGroups", ag);
+        }
+}
+
+mDNSlocal void mDNSMacOSXUpdateEtcHosts(mDNS *const m)
+{
+    AuthHash newhosts;
+
+    // As we will be modifying the core, we can only have one thread running at
+    // any point in time.
+    KQueueLock(m);
+
+    mDNSPlatformMemZero(&newhosts, sizeof(AuthHash));
+
+    // Get the file desecriptor (will trigger us to start watching for changes)
+    int fd = mDNSMacOSXGetEtcHostsFD(m);
+    if (fd != -1)
+    {
+        LogInfo("mDNSMacOSXUpdateEtcHosts: Parsing /etc/hosts fd %d", fd);
+        mDNSMacOSXParseEtcHosts(m, fd, &newhosts);
+    }
+    else LogInfo("mDNSMacOSXUpdateEtcHosts: /etc/hosts is not present");
+
+    // Optimization: Detect whether /etc/hosts changed or not.
+    //
+    // 1. Check to see if there are any new entries. We do this by seeing whether any entries in
+    //    newhosts is already registered with core.  If we find at least one entry that is not
+    //    registered with core, then it means we have work to do.
+    //
+    // 2. Next, we check to see if any of the entries that are registered with core is not present
+    //   in newhosts. If we find at least one entry that is not present, it means we have work to
+    //   do.
+    //
+    // Note: We may not have to hold the lock right here as KQueueLock is held which prevents any
+    // other thread from running. But mDNS_Lock is needed here as we will be traversing the core
+    // data structure in EtcHostsDeleteOldEntries/NewEntries which might expect the lock to be held
+    // 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))
+    {
+        // 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))
+        {
+            LogInfo("mDNSMacOSXUpdateEtcHosts: No work");
+            mDNS_Unlock(m);
+            KQueueUnlock(m, "/etc/hosts changed");
+            FreeNewHosts(&newhosts);
+            return;
+        }
+    }
+
+    // This will flush the cache, stop and start the query so that the queries
+    // can look at the /etc/hosts again
+    //
+    // Notes:
+    //
+    // We can't delete and free the records here. We wait for the mDNSCoreRestartAddressQueries to
+    // deliver RMV events. It has to be done in a deferred way because we can't deliver RMV
+    // events for local records *before* the RMV events for cache records. mDNSCoreRestartAddressQueries
+    // delivers these events in the right order and then calls us back to delete them.
+    //
+    // Similarly, we do a deferred Registration of the record because mDNSCoreRestartAddressQueries
+    // is a common function that looks at all local auth records and delivers a RMV including
+    // the records that we might add here. If we deliver a ADD here, it will get a RMV and then when
+    // the query is restarted, it will get another ADD. To avoid this (ADD-RMV-ADD), we defer registering
+    // the record until the RMVs are delivered in mDNSCoreRestartAddressQueries after which UpdateEtcHosts
+    // is called back where we do the Registration of the record. This results in RMV followed by ADD which
+    // looks normal.
+    mDNSCoreRestartAddressQueries(m, mDNSfalse, FlushAllCacheRecords, UpdateEtcHosts, &newhosts);
+    mDNS_Unlock(m);
+
+    KQueueUnlock(m, "/etc/hosts changed");
+    FreeNewHosts(&newhosts);
+}
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - Initialization & Teardown
+#endif
+
+CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
+CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey;
+CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey;
+CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey;
+
+// Major version 13 is 10.9.x 
+mDNSexport void mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring)
+{
+    int major = 0, minor = 0;
+    char letter = 0, prodname[256]="<Unknown>", prodvers[256]="<Unknown>", buildver[256]="<Unknown>";
+    CFDictionaryRef vers = _CFCopySystemVersionDictionary();
+    if (vers)
+    {
+        CFStringRef cfprodname = CFDictionaryGetValue(vers, _kCFSystemVersionProductNameKey);
+        CFStringRef cfprodvers = CFDictionaryGetValue(vers, _kCFSystemVersionProductVersionKey);
+        CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey);
+        if (cfprodname) 
+            CFStringGetCString(cfprodname, prodname, sizeof(prodname), kCFStringEncodingUTF8);
+        if (cfprodvers) 
+            CFStringGetCString(cfprodvers, prodvers, sizeof(prodvers), kCFStringEncodingUTF8);
+        if (cfbuildver && CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8))
+            sscanf(buildver, "%d%c%d", &major, &letter, &minor);
+        CFRelease(vers);
+    }
+    if (!major) 
+    { 
+        major = 13; 
+        LogMsg("Note: No Major Build Version number found; assuming 13"); 
+    }
+    if (HINFO_SWstring) 
+        mDNS_snprintf(HINFO_SWstring, 256, "%s %s (%s), %s", prodname, prodvers, buildver, STRINGIFY(mDNSResponderVersion));
+    //LogMsg("%s %s (%s), %d %c %d", prodname, prodvers, buildver, major, letter, minor);
+
+    // If product name is "Mac OS X" (or similar) we set OSXVers, else we set iOSVers;
+    if ((prodname[0] & 0xDF) == 'M') 
+        OSXVers = major;
+    else 
+        iOSVers = major;
+}
+
+// Test to see if we're the first client running on UDP port 5353, by trying to bind to 5353 without using SO_REUSEPORT.
+// If we fail, someone else got here first. That's not a big problem; we can share the port for multicast responses --
+// we just need to be aware that we shouldn't expect to successfully receive unicast UDP responses.
+mDNSlocal mDNSBool mDNSPlatformInit_CanReceiveUnicast(void)
+{
+    int err = -1;
+    int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if (s < 3)
+        LogMsg("mDNSPlatformInit_CanReceiveUnicast: socket error %d errno %d (%s)", s, errno, strerror(errno));
+    else
+    {
+        struct sockaddr_in s5353;
+        s5353.sin_family      = AF_INET;
+        s5353.sin_port        = MulticastDNSPort.NotAnInteger;
+        s5353.sin_addr.s_addr = 0;
+        err = bind(s, (struct sockaddr *)&s5353, sizeof(s5353));
+        close(s);
+    }
+
+    if (err) LogMsg("No unicast UDP responses");
+    else debugf("Unicast UDP responses okay");
+    return(err == 0);
+}
+
+mDNSlocal void CreatePTRRecord(mDNS *const m, const domainname *domain)
+{
+    AuthRecord *rr;
+    const domainname *pname = (domainname *)"\x9" "localhost";
+
+    rr= mallocL("localhosts", sizeof(*rr));
+    if (rr == NULL) return;
+    mDNSPlatformMemZero(rr, sizeof(*rr));
+
+    mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSInterface_LocalOnly, kDNSType_PTR, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordLocalOnly, mDNSNULL, mDNSNULL);
+    AssignDomainName(&rr->namestorage, domain);
+
+    rr->resrec.rdlength = DomainNameLength(pname);
+    rr->resrec.rdata->u.name.c[0] = 0;
+    AssignDomainName(&rr->resrec.rdata->u.name, pname);
+
+    rr->resrec.namehash = DomainNameHashValue(rr->resrec.name);
+    SetNewRData(&rr->resrec, mDNSNULL, 0);  // Sets rr->rdatahash for us
+    mDNS_Register(m, rr);
+}
+
+// Setup PTR records for 127.0.0.1 and ::1. This helps answering them locally rather than relying
+// on the external DNS server to answer this. Sometimes, the DNS servers don't respond in a timely
+// fashion and applications depending on this e.g., telnetd, times out after 30 seconds creating
+// a bad user experience. For now, we specifically create only localhosts to handle radar://9354225
+//
+// 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)
+{
+    char buffer[MAX_REVERSE_MAPPING_NAME];
+    domainname name;
+    int i;
+    struct in6_addr addr;
+    mDNSu8 *ptr = addr.__u6_addr.__u6_addr8;
+
+    if (inet_pton(AF_INET, "127.0.0.1", &addr) == 1)
+    {
+        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);
+    }
+    else LogMsg("SetupLocalHostRecords: ERROR!! inet_pton AF_INET failed");
+
+    if (inet_pton(AF_INET6, "::1", &addr) == 1)
+    {
+        for (i = 0; i < 16; i++)
+        {
+            static const char hexValues[] = "0123456789ABCDEF";
+            buffer[i * 4    ] = hexValues[ptr[15 - i] & 0x0F];
+            buffer[i * 4 + 1] = '.';
+            buffer[i * 4 + 2] = hexValues[ptr[15 - i] >> 4];
+            buffer[i * 4 + 3] = '.';
+        }
+        mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa.");
+        MakeDomainNameFromDNSNameString(&name, buffer);
+        CreatePTRRecord(m, &name);
+    }
+    else LogMsg("SetupLocalHostRecords: ERROR!! inet_pton AF_INET6 failed");
+}
+
+// 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)
+// 2) for each search domain (from prefs pane), query for b._dns-sd._udp.<searchdomain>.
+// 3) for each result from (2), register LocalOnly PTR record b._dns-sd._udp.local. -> <result>
+// 4) result above should generate a callback from question in (1).  result added to global list
+// 5) global list delivered to client via GetSearchDomainList()
+// 6) client calls to enumerate domains now go over LocalOnly interface
+//    (!!!KRS may add outgoing interface in addition)
+
+mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
+{
+    mStatus err;
+    m->p->CFRunLoop = CFRunLoopGetCurrent();
+
+    char HINFO_SWstring[256] = "";
+    mDNSMacOSXSystemBuildNumber(HINFO_SWstring);
+
+    err = mDNSHelperInit();
+    if (err)
+        return err;
+    
+    DynamicStoreQueue = dispatch_queue_create("com.apple.mDNSResponder.DynamicStoreQueue", NULL);
+    if (DynamicStoreQueue == NULL)
+    {
+        LogMsg("dispatch_queue_create: DynamicStoreQueue NULL!");
+        return mStatus_NoMemoryErr;
+    }
+
+    // Store mDNSResponder Platform 
+    if (OSXVers)
+    {
+        m->mDNS_plat = platform_OSX;
+    }
+    else if (iOSVers)
+    {
+        if (IsAppleTV())
+            m->mDNS_plat = platform_Atv;
+        else
+            m->mDNS_plat = platform_iOS;
+    }
+    else
+    {
+        m->mDNS_plat = platform_NonApple; 
+    }   
+        
+    // In 10.4, mDNSResponder is launched very early in the boot process, while other subsystems are still in the process of starting up.
+    // If we can't read the user's preferences, then we sleep a bit and try again, for up to five seconds before we give up.
+    int i;
+    for (i=0; i<100; i++)
+    {
+        domainlabel testlabel;
+        testlabel.c[0] = 0;
+        GetUserSpecifiedLocalHostName(&testlabel);
+        if (testlabel.c[0]) break;
+        usleep(50000);
+    }
+
+    m->hostlabel.c[0]        = 0;
+
+    int get_model[2] = { CTL_HW, HW_MODEL };
+    size_t len_model = sizeof(HINFO_HWstring_buffer);
+
+    // Normal Apple model names are of the form "iPhone2,1", and
+    // internal code names are strings containing no commas, e.g. "N88AP".
+    // We used to ignore internal code names, but Apple now uses these internal code names
+    // even in released shipping products, so we no longer ignore strings containing no commas.
+//	if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0 && strchr(HINFO_HWstring_buffer, ','))
+    if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0)
+        HINFO_HWstring = HINFO_HWstring_buffer;
+
+    // For names of the form "iPhone2,1" we use "iPhone" as the prefix for automatic name generation.
+    // For names of the form "N88AP" containg no comma, we use the entire string.
+    HINFO_HWstring_prefixlen = strchr(HINFO_HWstring_buffer, ',') ? strcspn(HINFO_HWstring, "0123456789") : strlen(HINFO_HWstring);
+
+    if (mDNSPlatformInit_CanReceiveUnicast()) 
+        m->CanReceiveUnicastOn5353 = mDNStrue;
+
+    mDNSu32 hlen = mDNSPlatformStrLen(HINFO_HWstring);
+    mDNSu32 slen = mDNSPlatformStrLen(HINFO_SWstring);
+    if (hlen + slen < 254)
+    {
+        m->HIHardware.c[0] = hlen;
+        m->HISoftware.c[0] = slen;
+        mDNSPlatformMemCopy(&m->HIHardware.c[1], HINFO_HWstring, hlen);
+        mDNSPlatformMemCopy(&m->HISoftware.c[1], HINFO_SWstring, slen);
+    }
+
+    m->p->permanentsockets.port  = MulticastDNSPort;
+    m->p->permanentsockets.m     = m;
+    m->p->permanentsockets.sktv4 = -1;
+    m->p->permanentsockets.kqsv4.KQcallback = myKQSocketCallBack;
+    m->p->permanentsockets.kqsv4.KQcontext  = &m->p->permanentsockets;
+    m->p->permanentsockets.kqsv4.KQtask     = "UDP packet reception";
+    m->p->permanentsockets.sktv6 = -1;
+    m->p->permanentsockets.kqsv6.KQcallback = myKQSocketCallBack;
+    m->p->permanentsockets.kqsv6.KQcontext  = &m->p->permanentsockets;
+    m->p->permanentsockets.kqsv6.KQtask     = "UDP packet reception";
+
+    err = SetupSocket(&m->p->permanentsockets, MulticastDNSPort, AF_INET, mDNSNULL);
+    err = SetupSocket(&m->p->permanentsockets, MulticastDNSPort, AF_INET6, mDNSNULL);
+
+    struct sockaddr_in s4;
+    socklen_t n4 = sizeof(s4);
+    if (getsockname(m->p->permanentsockets.sktv4, (struct sockaddr *)&s4, &n4) < 0) 
+        LogMsg("getsockname v4 error %d (%s)", errno, strerror(errno));
+    else 
+        m->UnicastPort4.NotAnInteger = s4.sin_port;
+
+    if (m->p->permanentsockets.sktv6 >= 0)
+    {
+        struct sockaddr_in6 s6;
+        socklen_t n6 = sizeof(s6);
+        if (getsockname(m->p->permanentsockets.sktv6, (struct sockaddr *)&s6, &n6) < 0) LogMsg("getsockname v6 error %d (%s)", errno, strerror(errno));
+        else m->UnicastPort6.NotAnInteger = s6.sin6_port;
+    }
+
+    m->p->InterfaceList      = mDNSNULL;
+    m->p->userhostlabel.c[0] = 0;
+    m->p->usernicelabel.c[0] = 0;
+    m->p->prevoldnicelabel.c[0] = 0;
+    m->p->prevnewnicelabel.c[0] = 0;
+    m->p->prevoldhostlabel.c[0] = 0;
+    m->p->prevnewhostlabel.c[0] = 0;
+    m->p->NotifyUser         = 0;
+    m->p->KeyChainTimer      = 0;
+    m->p->WakeAtUTC          = 0;
+    m->p->RequestReSleep     = 0;
+    // Assume that everything is good to begin with. If something is not working,
+    // we will detect that when we start sending questions.
+    m->p->v4answers          = 1;
+    m->p->v6answers          = 1;
+    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);
+    NetworkChangedKey_IPv6         = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6);
+    NetworkChangedKey_Hostnames    = SCDynamicStoreKeyCreateHostNames(NULL);
+    NetworkChangedKey_Computername = SCDynamicStoreKeyCreateComputerName(NULL);
+    NetworkChangedKey_DNS          = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
+    NetworkChangedKey_StateInterfacePrefix = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, CFSTR(""), NULL);
+    if (!NetworkChangedKey_IPv4 || !NetworkChangedKey_IPv6 || !NetworkChangedKey_Hostnames || !NetworkChangedKey_Computername || !NetworkChangedKey_DNS || !NetworkChangedKey_StateInterfacePrefix)
+    { LogMsg("SCDynamicStore string setup failed"); return(mStatus_NoMemoryErr); }
+
+    err = WatchForNetworkChanges(m);
+    if (err) { LogMsg("mDNSPlatformInit_setup: WatchForNetworkChanges failed %d", err); return(err); }
+
+#if 0 // <rdar://problem/6751656>
+    err = WatchForPMChanges(m);
+    if (err) { LogMsg("mDNSPlatformInit_setup: WatchForPMChanges failed %d", err); return(err); }
+#endif
+
+    err = WatchForSysEvents(m);
+    if (err) { LogMsg("mDNSPlatformInit_setup: WatchForSysEvents failed %d", err); return(err); }
+
+    mDNSs32 utc = mDNSPlatformUTC();
+    m->SystemWakeOnLANEnabled = SystemWakeForNetworkAccess();
+    UpdateInterfaceList(m, utc);
+    SetupActiveInterfaces(m, utc);
+
+    // Explicitly ensure that our Keychain operations utilize the system domain.
+#ifndef NO_SECURITYFRAMEWORK
+    SecKeychainSetPreferenceDomain(kSecPreferencesDomainSystem);
+#endif
+
+    mDNS_Lock(m);
+    SetDomainSecrets(m);
+    SetLocalDomains();
+    mDNS_Unlock(m);
+
+#ifndef NO_SECURITYFRAMEWORK
+    err = SecKeychainAddCallback(KeychainChanged, kSecAddEventMask|kSecDeleteEventMask|kSecUpdateEventMask, m);
+    if (err) { LogMsg("mDNSPlatformInit_setup: SecKeychainAddCallback failed %d", err); return(err); }
+#endif
+
+#if !defined(kIOPMAcknowledgmentOptionSystemCapabilityRequirements) || TARGET_OS_EMBEDDED
+    LogMsg("Note: Compiled without SnowLeopard Fine-Grained Power Management support");
+#else
+    IOPMConnection c;
+    IOReturn iopmerr = IOPMConnectionCreate(CFSTR("mDNSResponder"), kIOPMSystemPowerStateCapabilityCPU, &c);
+    if (iopmerr) LogMsg("IOPMConnectionCreate failed %d", iopmerr);
+    else
+    {
+        iopmerr = IOPMConnectionSetNotification(c, m, SnowLeopardPowerChanged);
+        if (iopmerr) LogMsg("IOPMConnectionSetNotification failed %d", iopmerr);
+        else
+        {
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+            IOPMConnectionSetDispatchQueue(c, dispatch_get_main_queue());
+            LogInfo("IOPMConnectionSetDispatchQueue is now running");
+#else
+            iopmerr = IOPMConnectionScheduleWithRunLoop(c, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+            if (iopmerr) LogMsg("IOPMConnectionScheduleWithRunLoop failed %d", iopmerr);
+            LogInfo("IOPMConnectionScheduleWithRunLoop is now running");
+#endif /* MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM */
+        }
+    }
+    m->p->IOPMConnection = iopmerr ? mDNSNULL : c;
+    if (iopmerr) // If IOPMConnectionCreate unavailable or failed, proceed with old-style power notification code below
+#endif // kIOPMAcknowledgmentOptionSystemCapabilityRequirements
+    {
+        m->p->PowerConnection = IORegisterForSystemPower(m, &m->p->PowerPortRef, PowerChanged, &m->p->PowerNotifier);
+        if (!m->p->PowerConnection) { LogMsg("mDNSPlatformInit_setup: IORegisterForSystemPower failed"); return(-1); }
+        else
+        {
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+            IONotificationPortSetDispatchQueue(m->p->PowerPortRef, dispatch_get_main_queue());
+#else
+            CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
+#endif /* MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM */
+        }
+    }
+
+#if APPLE_OSX_mDNSResponder
+    // Note: We use SPMetricPortability > 35 to indicate a laptop of some kind
+    // SPMetricPortability <= 35 means nominally a non-portable machine (i.e. Mac mini or better)
+    // Apple TVs, AirPort base stations, and Time Capsules do not actually weigh 3kg, but we assign them
+    // higher 'nominal' masses to indicate they should be treated as being relatively less portable than a laptop
+    if      (!strncasecmp(HINFO_HWstring, "Xserve",       6)) { SPMetricPortability = 25 /* 30kg */; SPMetricMarginalPower = 84 /* 250W */; SPMetricTotalPower = 85 /* 300W */; }
+    else if (!strncasecmp(HINFO_HWstring, "RackMac",      7)) { SPMetricPortability = 25 /* 30kg */; SPMetricMarginalPower = 84 /* 250W */; SPMetricTotalPower = 85 /* 300W */; }
+    else if (!strncasecmp(HINFO_HWstring, "MacPro",       6)) { SPMetricPortability = 27 /* 20kg */; SPMetricMarginalPower = 84 /* 250W */; SPMetricTotalPower = 85 /* 300W */; }
+    else if (!strncasecmp(HINFO_HWstring, "PowerMac",     8)) { SPMetricPortability = 27 /* 20kg */; SPMetricMarginalPower = 82 /* 160W */; SPMetricTotalPower = 83 /* 200W */; }
+    else if (!strncasecmp(HINFO_HWstring, "iMac",         4)) { SPMetricPortability = 30 /* 10kg */; SPMetricMarginalPower = 77 /*  50W */; SPMetricTotalPower = 78 /*  60W */; }
+    else if (!strncasecmp(HINFO_HWstring, "Macmini",      7)) { SPMetricPortability = 33 /*  5kg */; SPMetricMarginalPower = 73 /*  20W */; SPMetricTotalPower = 74 /*  25W */; }
+    else if (!strncasecmp(HINFO_HWstring, "TimeCapsule", 11)) { SPMetricPortability = 34 /*  4kg */; SPMetricMarginalPower = 10 /*  ~0W */; SPMetricTotalPower = 70 /*  13W */; }
+    else if (!strncasecmp(HINFO_HWstring, "AirPort",      7)) { SPMetricPortability = 35 /*  3kg */; SPMetricMarginalPower = 10 /*  ~0W */; SPMetricTotalPower = 70 /*  12W */; }
+    else if (  IsAppleTV()  )                                 { SPMetricPortability = 35 /*  3kg */; SPMetricMarginalPower = 60 /*   1W */; SPMetricTotalPower = 63 /*   2W */; }
+    else if (!strncasecmp(HINFO_HWstring, "MacBook",      7)) { SPMetricPortability = 37 /*  2kg */; SPMetricMarginalPower = 71 /*  13W */; SPMetricTotalPower = 72 /*  15W */; }
+    else if (!strncasecmp(HINFO_HWstring, "PowerBook",    9)) { SPMetricPortability = 37 /*  2kg */; SPMetricMarginalPower = 71 /*  13W */; SPMetricTotalPower = 72 /*  15W */; }
+    LogSPS("HW_MODEL: %.*s (%s) Portability %d Marginal Power %d Total Power %d Features %d",
+           HINFO_HWstring_prefixlen, HINFO_HWstring, HINFO_HWstring, SPMetricPortability, SPMetricMarginalPower, SPMetricTotalPower, SPMetricFeatures);
+#endif // APPLE_OSX_mDNSResponder
+
+    // Currently this is not defined. SSL code will eventually fix this. If it becomes
+    // critical, we will define this to workaround the bug in SSL.
+#ifdef __SSL_NEEDS_SERIALIZATION__
+    SSLqueue = dispatch_queue_create("com.apple.mDNSResponder.SSLQueue", NULL);
+#else
+    SSLqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+#endif
+    if (SSLqueue == mDNSNULL) LogMsg("dispatch_queue_create: SSL queue NULL");
+
+    mDNSMacOSXUpdateEtcHosts(m);
+    SetupLocalHostRecords(m);
+    CUPInit(m);
+
+    return(mStatus_NoError);
+}
+
+mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
+{
+#if MDNS_NO_DNSINFO
+    LogMsg("Note: Compiled without Apple-specific Split-DNS support");
+#endif
+
+    // Adding interfaces will use this flag, so set it now.
+    m->DivertMulticastAdvertisements = !m->AdvertiseLocalAddresses;
+
+#if APPLE_OSX_mDNSResponder
+    m->SPSBrowseCallback = UpdateSPSStatus;
+#endif // APPLE_OSX_mDNSResponder
+
+    mStatus result = mDNSPlatformInit_setup(m);
+
+    // We don't do asynchronous initialization on OS X, so by the time we get here the setup will already
+    // have succeeded or failed -- so if it succeeded, we should just call mDNSCoreInitComplete() immediately
+    if (result == mStatus_NoError)
+    {
+        mDNSCoreInitComplete(m, mStatus_NoError);
+
+#if !NO_D2D
+        // We only initialize if mDNSCore successfully initialized.
+        if (D2DInitialize)
+        {
+            D2DStatus ds = D2DInitialize(m->p->CFRunLoop, xD2DServiceCallback, m) ;
+            if (ds != kD2DSuccess)
+                LogMsg("D2DInitialiize failed: %d", ds);
+            else
+                LogMsg("D2DInitialize succeeded");
+        }
+#endif // ! NO_D2D
+
+    }
+    result = DNSSECCryptoInit(m);
+    return(result);
+}
+
+mDNSexport void mDNSPlatformClose(mDNS *const m)
+{
+    if (m->p->PowerConnection)
+    {
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+        IONotificationPortSetDispatchQueue(m->p->PowerPortRef, NULL);
+#else
+        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(m->p->PowerPortRef), kCFRunLoopDefaultMode);
+#endif
+        // According to <http://developer.apple.com/qa/qa2004/qa1340.html>, a single call
+        // to IORegisterForSystemPower creates *three* objects that need to be disposed individually:
+        IODeregisterForSystemPower(&m->p->PowerNotifier);
+        IOServiceClose            ( m->p->PowerConnection);
+        IONotificationPortDestroy ( m->p->PowerPortRef);
+        m->p->PowerConnection = 0;
+    }
+
+    if (m->p->Store)
+    {
+#ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM
+        if (!SCDynamicStoreSetDispatchQueue(m->p->Store, NULL))
+            LogMsg("mDNSPlatformClose: SCDynamicStoreSetDispatchQueue failed");
+#else
+        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode);
+        CFRunLoopSourceInvalidate(m->p->StoreRLS);
+        CFRelease(m->p->StoreRLS);
+        m->p->StoreRLS = NULL;
+#endif
+        CFRelease(m->p->Store);
+        m->p->Store    = NULL;
+    }
+
+    if (m->p->PMRLS)
+    {
+        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->PMRLS, kCFRunLoopDefaultMode);
+        CFRunLoopSourceInvalidate(m->p->PMRLS);
+        CFRelease(m->p->PMRLS);
+        m->p->PMRLS = NULL;
+    }
+
+    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
+
+    mDNSs32 utc = mDNSPlatformUTC();
+    MarkAllInterfacesInactive(m, utc);
+    ClearInactiveInterfaces(m, utc);
+    CloseSocketSet(&m->p->permanentsockets);
+
+#if APPLE_OSX_mDNSResponder
+    // clean up tunnels
+    while (m->TunnelClients)
+    {
+        ClientTunnel *cur = m->TunnelClients;
+        LogInfo("mDNSPlatformClose: removing client tunnel %p %##s from list", cur, cur->dstname.c);
+        if (cur->q.ThisQInterval >= 0) mDNS_StopQuery(m, &cur->q);
+        AutoTunnelSetKeys(cur, mDNSfalse);
+        m->TunnelClients = cur->next;
+        freeL("ClientTunnel", cur);
+    }
+
+    if (AnonymousRacoonConfig)
+    {
+        AnonymousRacoonConfig = mDNSNULL;
+        LogInfo("mDNSPlatformClose: Deconfiguring autotunnel");
+        (void)mDNSConfigureServer(kmDNSDown, mDNSNULL, mDNSNULL);
+    }
+#endif // APPLE_OSX_mDNSResponder
+}
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - General Platform Support Layer functions
+#endif
+
+mDNSexport mDNSu32 mDNSPlatformRandomNumber(void)
+{
+    return(arc4random());
+}
+
+mDNSexport mDNSs32 mDNSPlatformOneSecond = 1000;
+mDNSexport mDNSu32 mDNSPlatformClockDivisor = 0;
+
+mDNSexport mStatus mDNSPlatformTimeInit(void)
+{
+    // Notes: Typical values for mach_timebase_info:
+    // tbi.numer = 1000 million
+    // tbi.denom =   33 million
+    // These are set such that (mach_absolute_time() * numer/denom) gives us nanoseconds;
+    //          numer  / denom = nanoseconds per hardware clock tick (e.g. 30);
+    //          denom  / numer = hardware clock ticks per nanosecond (e.g. 0.033)
+    // (denom*1000000) / numer = hardware clock ticks per millisecond (e.g. 33333)
+    // So: mach_absolute_time() / ((denom*1000000)/numer) = milliseconds
+    //
+    // Arithmetic notes:
+    // tbi.denom is at least 1, and not more than 2^32-1.
+    // Therefore (tbi.denom * 1000000) is at least one million, but cannot overflow a uint64_t.
+    // tbi.denom is at least 1, and not more than 2^32-1.
+    // Therefore clockdivisor should end up being a number roughly in the range 10^3 - 10^9.
+    // If clockdivisor is less than 10^3 then that means that the native clock frequency is less than 1MHz,
+    // which is unlikely on any current or future Macintosh.
+    // If clockdivisor is greater than 10^9 then that means the native clock frequency is greater than 1000GHz.
+    // When we ship Macs with clock frequencies above 1000GHz, we may have to update this code.
+    struct mach_timebase_info tbi;
+    kern_return_t result = mach_timebase_info(&tbi);
+    if (result == KERN_SUCCESS) mDNSPlatformClockDivisor = ((uint64_t)tbi.denom * 1000000) / tbi.numer;
+    return(result);
+}
+
+mDNSexport mDNSs32 mDNSPlatformRawTime(void)
+{
+    if (mDNSPlatformClockDivisor == 0) { LogMsg("mDNSPlatformRawTime called before mDNSPlatformTimeInit"); return(0); }
+
+    static uint64_t last_mach_absolute_time = 0;
+    //static uint64_t last_mach_absolute_time = 0x8000000000000000LL;	// Use this value for testing the alert display
+    uint64_t this_mach_absolute_time = mach_absolute_time();
+    if ((int64_t)this_mach_absolute_time - (int64_t)last_mach_absolute_time < 0)
+    {
+        LogMsg("mDNSPlatformRawTime: last_mach_absolute_time %08X%08X", last_mach_absolute_time);
+        LogMsg("mDNSPlatformRawTime: this_mach_absolute_time %08X%08X", this_mach_absolute_time);
+        // Update last_mach_absolute_time *before* calling NotifyOfElusiveBug()
+        last_mach_absolute_time = this_mach_absolute_time;
+        // Note: This bug happens all the time on 10.3
+        NotifyOfElusiveBug("mach_absolute_time went backwards!",
+                           "This error occurs from time to time, often on newly released hardware, "
+                           "and usually the exact cause is different in each instance.\r\r"
+                           "Please file a new Radar bug report with the title “mach_absolute_time went backwards” "
+                           "and assign it to Radar Component “Kernel” Version “X”.");
+    }
+    last_mach_absolute_time = this_mach_absolute_time;
+
+    return((mDNSs32)(this_mach_absolute_time / mDNSPlatformClockDivisor));
+}
+
+mDNSexport mDNSs32 mDNSPlatformUTC(void)
+{
+    return time(NULL);
+}
+
+// Locking is a no-op here, because we're single-threaded with a CFRunLoop, so we can never interrupt ourselves
+mDNSexport void     mDNSPlatformLock   (const mDNS *const m) { (void)m; }
+mDNSexport void     mDNSPlatformUnlock (const mDNS *const m) { (void)m; }
+mDNSexport void     mDNSPlatformStrCopy(      void *dst, const void *src)              { strcpy((char *)dst, (char *)src); }
+mDNSexport mDNSu32  mDNSPlatformStrLen (                 const void *src)              { return(strlen((char*)src)); }
+mDNSexport void     mDNSPlatformMemCopy(      void *dst, const void *src, mDNSu32 len) { memcpy(dst, src, len); }
+mDNSexport mDNSBool mDNSPlatformMemSame(const void *dst, const void *src, mDNSu32 len) { return(memcmp(dst, src, len) == 0); }
+mDNSexport int      mDNSPlatformMemCmp(const void *dst, const void *src, mDNSu32 len) { return(memcmp(dst, src, len)); }
+mDNSexport void     mDNSPlatformMemZero(      void *dst,                  mDNSu32 len) { memset(dst, 0, len); }
+mDNSexport void     mDNSPlatformQsort  (      void *base, int nel, int width, int (*compar)(const void *, const void *))
+{
+    return (qsort(base, nel, width, compar));
+}
+#if !(APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING)
+mDNSexport void *   mDNSPlatformMemAllocate(mDNSu32 len) { return(mallocL("mDNSPlatformMemAllocate", len)); }
+#endif
+mDNSexport void     mDNSPlatformMemFree    (void *mem)   { freeL("mDNSPlatformMemFree", mem); }
+
+mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason)
+{
+    if (allowSleep && m->p->IOPMAssertion)
+    {
+        LogInfo("%s Destroying NoIdleSleep power assertion", __FUNCTION__);
+        IOPMAssertionRelease(m->p->IOPMAssertion);
+        m->p->IOPMAssertion = 0;
+    }
+    else if (!allowSleep)
+    {
+#ifdef kIOPMAssertionTypeNoIdleSleep
+        if (m->p->IOPMAssertion)
+        {
+            IOPMAssertionRelease(m->p->IOPMAssertion);
+            m->p->IOPMAssertion = 0;
+        }
+
+        CFStringRef assertionName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s.%d %s"), getprogname(), getpid(), reason ? reason : "");
+        IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, assertionName ? assertionName : CFSTR("mDNSResponder"), &m->p->IOPMAssertion);
+        if (assertionName) CFRelease(assertionName);
+        LogInfo("%s Creating NoIdleSleep power assertion", __FUNCTION__);
+#endif
+    }
+}
+
+mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
+{
+    mDNSu32 ifindex;
+
+    // Sanity check
+    ifindex = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNStrue);
+    if (ifindex <= 0)
+    {
+        LogMsg("mDNSPlatformSendWakeupPacket: ERROR!! Invalid InterfaceID %u", ifindex);
+        return;
+    }
+    mDNSSendWakeupPacket(ifindex, EthAddr, IPAddr, iteration);
+}
+
+mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
+{
+    NetworkInterfaceInfoOSX *info;
+
+    if (InterfaceID == mDNSInterface_P2P)
+        return mDNStrue;
+
+    if (   (InterfaceID == mDNSInterface_Any) 
+        || (InterfaceID == mDNSInterfaceMark)
+        || (InterfaceID == mDNSInterface_LocalOnly)
+        || (InterfaceID == mDNSInterface_Unicast))
+        return mDNSfalse;
+
+    info = IfindexToInterfaceInfoOSX(&mDNSStorage, InterfaceID);
+    if (info == NULL)
+    {
+        // this log message can print when operations are stopped on an interface that has gone away
+        LogInfo("mDNSPlatformInterfaceIsD2D: Invalid interface index %d", InterfaceID);
+        return mDNSfalse;
+    }
+
+    return (mDNSBool) info->D2DInterface;
+}
+
+// Filter records send over P2P (D2D) type interfaces
+// Note that the terms P2P and D2D are used synonymously in the current code and comments.
+mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf)
+{
+    // For an explicit match to a valid interface ID, return true. 
+    if (rr->resrec.InterfaceID == intf->InterfaceID)
+        return mDNStrue;
+
+    // Only filtering records for D2D type interfaces, return true for all other interface types.
+    if (!mDNSPlatformInterfaceIsD2D(intf->InterfaceID))
+        return mDNStrue;
+    
+    // If it's an AWDL interface the record must be explicitly marked to include AWDL.
+    if (intf->InterfaceID == AWDLInterfaceID)
+    {
+        if (rr->ARType == AuthRecordAnyIncludeAWDL || rr->ARType == AuthRecordAnyIncludeAWDLandP2P)
+            return mDNStrue;
+        else
+            return mDNSfalse;
+    }
+    
+    // Send record if it is explicitly marked to include all other P2P type interfaces.
+    if (rr->ARType == AuthRecordAnyIncludeP2P || rr->ARType == AuthRecordAnyIncludeAWDLandP2P)
+        return mDNStrue;
+
+    // Don't send the record over this interface.
+    return mDNSfalse;
+}
+
+// Filter questions send over P2P (D2D) type interfaces.
+mDNSexport mDNSBool mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf)
+{
+    // For an explicit match to a valid interface ID, return true. 
+    if (q->InterfaceID == intf->InterfaceID)
+        return mDNStrue;
+
+    // Only filtering questions for D2D type interfaces
+    if (!mDNSPlatformInterfaceIsD2D(intf->InterfaceID))
+        return mDNStrue;
+
+    // If it's an AWDL interface the question must be explicitly marked to include AWDL.
+    if (intf->InterfaceID == AWDLInterfaceID)
+    {
+        if (q->flags & kDNSServiceFlagsIncludeAWDL)
+            return mDNStrue;
+        else
+            return mDNSfalse;
+    }
+    
+    // Sent question if it is explicitly marked to include all other P2P type interfaces.
+    if (q->flags & kDNSServiceFlagsIncludeP2P)
+        return mDNStrue;
+
+    // Don't send the question over this interface.
+    return mDNSfalse;
+}
+
+// Returns true unless record was received over the AWDL interface and
+// the question was not specific to the AWDL interface or did not specify kDNSServiceInterfaceIndexAny
+// with the kDNSServiceFlagsIncludeAWDL flag set.
+mDNSexport mDNSBool   mDNSPlatformValidRecordForQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
+{
+    if (!rr->InterfaceID || (rr->InterfaceID == q->InterfaceID))
+        return mDNStrue;
+
+    if ((rr->InterfaceID == AWDLInterfaceID) && !(q->flags & kDNSServiceFlagsIncludeAWDL))
+    {
+        LogInfo("mDNSPlatformValidRecordForQuestion: Record recieved over AWDL not returned for %s %##s query",
+                DNSTypeName(q->qtype), q->qname.c);
+        return mDNSfalse;
+    }
+
+    return mDNStrue;
+}
+
+// formating time to RFC 4034 format
+mDNSexport void mDNSPlatformFormatTime(unsigned long te, mDNSu8 *buf, int bufsize)
+{
+    struct tm tmTime;
+    time_t t = (time_t)te;
+    // Time since epoch : strftime takes "tm". Convert seconds to "tm" using
+    // gmtime_r first and then use strftime
+    gmtime_r(&t, &tmTime);
+    strftime((char *)buf, bufsize, "%Y%m%d%H%M%S", &tmTime);
+}
+
+mDNSexport mDNSs32 mDNSPlatformGetPID()
+{
+    return getpid();
+}
+
+// Schedule a function asynchronously on the main queue
+mDNSexport void mDNSPlatformDispatchAsync(mDNS *const m, void *context, AsyncDispatchFunc func)
+{
+    // KQueueLock/Unlock is used for two purposes
+    //
+    // 1. We can't be running along with the KQueue thread and hence acquiring the lock
+    //    serializes the access to the "core"
+    //
+    // 2. KQueueUnlock also sends a message wake up the KQueue thread which in turn wakes
+    //    up and calls udsserver_idle which schedules the messages across the uds socket.
+    //    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);
+        func(m, context);
+        KQueueUnlock(m, "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.
+        TriggerEventCompletion();
+#endif
+    });
+}
+
+// definitions for device-info record construction
+#define DEVINFO_MODEL       "model="
+#define DEVINFO_MODEL_LEN   strlen(DEVINFO_MODEL)
+
+#define OSX_VER         "osxvers="
+#define OSX_VER_LEN     strlen(OSX_VER) 
+#define VER_NUM_LEN     2  // 2 digits of version number added to base string
+
+// Bytes available in TXT record for model name after subtracting space for other 
+// fixed size strings and their length bytes.
+#define MAX_MODEL_NAME_LEN   (256 - (DEVINFO_MODEL_LEN + 1) - (OSX_VER_LEN + VER_NUM_LEN + 1))
+
+// Initialize device-info TXT record contents and return total length of record data.
+mDNSexport mDNSu32 initializeDeviceInfoTXT(mDNS *m, mDNSu8 *ptr)
+{
+    mDNSu8 *bufferStart = ptr;
+    mDNSu8 len = m->HIHardware.c[0] < MAX_MODEL_NAME_LEN ? m->HIHardware.c[0] : MAX_MODEL_NAME_LEN;
+
+    *ptr = DEVINFO_MODEL_LEN + len; // total length of DEVINFO_MODEL string plus the hardware name string
+    ptr++;
+    mDNSPlatformMemCopy(ptr, DEVINFO_MODEL, DEVINFO_MODEL_LEN);
+    ptr += DEVINFO_MODEL_LEN;
+    mDNSPlatformMemCopy(ptr, m->HIHardware.c + 1, len);
+    ptr += len;
+
+    // only include this string for OSX
+    if (OSXVers)
+    {
+        char    ver_num[VER_NUM_LEN + 1]; // version digits + null written by snprintf
+        *ptr = OSX_VER_LEN + VER_NUM_LEN; // length byte
+        ptr++;
+        mDNSPlatformMemCopy(ptr, OSX_VER, OSX_VER_LEN);
+        ptr += OSX_VER_LEN;
+        // convert version number to ASCII, add 1 for terminating null byte written by snprintf()
+        snprintf(ver_num, VER_NUM_LEN + 1, "%d", OSXVers);
+        mDNSPlatformMemCopy(ptr, ver_num, VER_NUM_LEN);
+        ptr += VER_NUM_LEN;
+    }
+
+    return (ptr - bufferStart);
+}

Deleted: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
===================================================================
--- vendor/apple/mDNSResponder/dist/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj	2014-06-30 23:58:12 UTC (rev 6706)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj	2015-03-20 01:14:52 UTC (rev 6985)
@@ -1,3137 +0,0 @@
-// !$*UTF8*$!
-{
-	archiveVersion = 1;
-	classes = {
-	};
-	objectVersion = 45;
-	objects = {
-
-/* Begin PBXAggregateTarget section */
-		00AD62BB032D7A0C0CCA2C71 /* Build More */ = {
-			isa = PBXAggregateTarget;
-			buildConfigurationList = D284BE280ADD78180027CCDF /* Build configuration list for PBXAggregateTarget "Build More" */;
-			buildPhases = (
-			);
-			dependencies = (
-				03067D860C849CC30022BE1F /* PBXTargetDependency */,
-				D284BF2C0ADD815A0027CCDF /* PBXTargetDependency */,
-				D284BF2E0ADD81600027CCDF /* PBXTargetDependency */,
-				D284BF300ADD81630027CCDF /* PBXTargetDependency */,
-			);
-			name = "Build More";
-			productName = "Build All";
-		};
-		03067D640C83A3700022BE1F /* Build Some */ = {
-			isa = PBXAggregateTarget;
-			buildConfigurationList = 03067D730C83A3CB0022BE1F /* Build configuration list for PBXAggregateTarget "Build Some" */;
-			buildPhases = (
-				FF045B6A0C7E4AA600448140 /* ShellScript */,
-			);
-			dependencies = (
-				217A4C49138EE14C000A5BA8 /* PBXTargetDependency */,
-				03067D680C83A3830022BE1F /* PBXTargetDependency */,
-				03067D6A0C83A3890022BE1F /* PBXTargetDependency */,
-				03067D6C0C83A3920022BE1F /* PBXTargetDependency */,
-				03067D6E0C83A39C0022BE1F /* PBXTargetDependency */,
-				84C5B3411665544B00C324A8 /* PBXTargetDependency */,
-				72FB546A166D5FE40090B2D9 /* PBXTargetDependency */,
-			);
-			name = "Build Some";
-			productName = "Build Some";
-		};
-		2141DCF8123FFB5D0086D23E /* SystemLibraries */ = {
-			isa = PBXAggregateTarget;
-			buildConfigurationList = 2141DD08123FFB830086D23E /* Build configuration list for PBXAggregateTarget "SystemLibraries" */;
-			buildPhases = (
-			);
-			dependencies = (
-				2141DD0E123FFC960086D23E /* PBXTargetDependency */,
-				2130257112400E9300AC839F /* PBXTargetDependency */,
-			);
-			name = SystemLibraries;
-			productName = SystemLibraries;
-		};
-		2141DD0B123FFC7F0086D23E /* SystemLibrariesStatic */ = {
-			isa = PBXAggregateTarget;
-			buildConfigurationList = 2141DD18123FFC990086D23E /* Build configuration list for PBXAggregateTarget "SystemLibrariesStatic" */;
-			buildPhases = (
-			);
-			dependencies = (
-				215FFB1D124002CC00470DE1 /* PBXTargetDependency */,
-				215FFB1B124002C700470DE1 /* PBXTargetDependency */,
-				215FFB19124002C100470DE1 /* PBXTargetDependency */,
-			);
-			name = SystemLibrariesStatic;
-			productName = SystemLibrariesStatic;
-		};
-		FFA572650AF190F10055A0F1 /* SystemLibrariesDynamic */ = {
-			isa = PBXAggregateTarget;
-			buildConfigurationList = FFA5726E0AF191200055A0F1 /* Build configuration list for PBXAggregateTarget "SystemLibrariesDynamic" */;
-			buildPhases = (
-				1F7B473C12B82BFD00868AEF /* ShellScript */,
-			);
-			dependencies = (
-				FFA572690AF190FF0055A0F1 /* PBXTargetDependency */,
-				FFA5726B0AF191010055A0F1 /* PBXTargetDependency */,
-				FFA5726D0AF191020055A0F1 /* PBXTargetDependency */,
-			);
-			name = SystemLibrariesDynamic;
-			productName = SystemLibraries;
-		};
-		FFB7657B0AEED96B00583A2C /* Build All */ = {
-			isa = PBXAggregateTarget;
-			buildConfigurationList = FFB7657E0AEED99D00583A2C /* Build configuration list for PBXAggregateTarget "Build All" */;
-			buildPhases = (
-			);
-			dependencies = (
-				FFB7657D0AEED97F00583A2C /* PBXTargetDependency */,
-				2141DCFD123FFB7D0086D23E /* PBXTargetDependency */,
-			);
-			name = "Build All";
-			productName = "Build All";
-		};
-/* End PBXAggregateTarget section */
-
-/* Begin PBXBuildFile section */
-		21070E5F16486B9000A69507 /* DNSSECSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21070E5D16486B9000A69507 /* DNSSECSupport.c */; };
-		21070E6016486B9000A69507 /* DNSSECSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21070E5D16486B9000A69507 /* DNSSECSupport.c */; };
-		21070E6116486B9000A69507 /* DNSSECSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21070E5E16486B9000A69507 /* DNSSECSupport.h */; };
-		21070E6216486B9000A69507 /* DNSSECSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21070E5E16486B9000A69507 /* DNSSECSupport.h */; };
-		2120ABD516B71614007089B6 /* CUPolicy.c in Sources */ = {isa = PBXBuildFile; fileRef = 2120ABD416B71614007089B6 /* CUPolicy.c */; };
-		2120ABD616B71614007089B6 /* CUPolicy.c in Sources */ = {isa = PBXBuildFile; fileRef = 2120ABD416B71614007089B6 /* CUPolicy.c */; };
-		2124FA2C1471E98C0021D7BB /* nsec.h in Headers */ = {isa = PBXBuildFile; fileRef = 2124FA2B1471E98C0021D7BB /* nsec.h */; };
-		2124FA2D1471E98C0021D7BB /* nsec.h in Headers */ = {isa = PBXBuildFile; fileRef = 2124FA2B1471E98C0021D7BB /* nsec.h */; };
-		2124FA301471E9B50021D7BB /* dnssec.h in Headers */ = {isa = PBXBuildFile; fileRef = 2124FA2F1471E9B50021D7BB /* dnssec.h */; };
-		2124FA311471E9B50021D7BB /* dnssec.h in Headers */ = {isa = PBXBuildFile; fileRef = 2124FA2F1471E9B50021D7BB /* dnssec.h */; };
-		2124FA331471E9DE0021D7BB /* nsec.c in Sources */ = {isa = PBXBuildFile; fileRef = 2124FA321471E9DE0021D7BB /* nsec.c */; };
-		2124FA341471E9DE0021D7BB /* nsec.c in Sources */ = {isa = PBXBuildFile; fileRef = 2124FA321471E9DE0021D7BB /* nsec.c */; };
-		2127A47715C3C7B900A857FC /* nsec3.c in Sources */ = {isa = PBXBuildFile; fileRef = 2127A47515C3C7B900A857FC /* nsec3.c */; };
-		2127A47815C3C7B900A857FC /* nsec3.c in Sources */ = {isa = PBXBuildFile; fileRef = 2127A47515C3C7B900A857FC /* nsec3.c */; };
-		2127A47915C3C7B900A857FC /* nsec3.h in Headers */ = {isa = PBXBuildFile; fileRef = 2127A47615C3C7B900A857FC /* nsec3.h */; };
-		2127A47A15C3C7B900A857FC /* nsec3.h in Headers */ = {isa = PBXBuildFile; fileRef = 2127A47615C3C7B900A857FC /* nsec3.h */; };
-		213BDC6D147319F400000896 /* dnssec.c in Sources */ = {isa = PBXBuildFile; fileRef = 213BDC6C147319F400000896 /* dnssec.c */; };
-		213BDC6E147319F400000896 /* dnssec.c in Sources */ = {isa = PBXBuildFile; fileRef = 213BDC6C147319F400000896 /* dnssec.c */; };
-		213FB23C12028C4A002B3A08 /* BonjourEvents.c in Sources */ = {isa = PBXBuildFile; fileRef = 213FB22C12028B53002B3A08 /* BonjourEvents.c */; };
-		213FB23D12028C5A002B3A08 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
-		215FFAEE124000F900470DE1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
-		215FFAEF124000F900470DE1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
-		215FFAF0124000F900470DE1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
-		215FFAF1124000F900470DE1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
-		215FFAF2124000F900470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
-		215FFAF3124000F900470DE1 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-		215FFAF41240011800470DE1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
-		215FFAF51240011800470DE1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
-		215FFAF61240011800470DE1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
-		215FFAF71240011800470DE1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
-		215FFAF81240011800470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
-		215FFAF91240011800470DE1 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-		215FFAFA1240013400470DE1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
-		215FFAFB1240013400470DE1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
-		215FFAFC1240013400470DE1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
-		215FFAFD1240013400470DE1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
-		215FFAFE1240013400470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
-		215FFAFF1240013400470DE1 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-		216D9ACE1720C9F5008066E1 /* VPNService.c in Sources */ = {isa = PBXBuildFile; fileRef = 216D9ACD1720C9F5008066E1 /* VPNService.c */; };
-		216D9ACF1720C9F5008066E1 /* VPNService.c in Sources */ = {isa = PBXBuildFile; fileRef = 216D9ACD1720C9F5008066E1 /* VPNService.c */; };
-		218E8E51156D8C0300720DA0 /* dnsproxy.c in Sources */ = {isa = PBXBuildFile; fileRef = 218E8E4F156D8C0300720DA0 /* dnsproxy.c */; };
-		218E8E52156D8C0300720DA0 /* dnsproxy.c in Sources */ = {isa = PBXBuildFile; fileRef = 218E8E4F156D8C0300720DA0 /* dnsproxy.c */; };
-		218E8E53156D8C0300720DA0 /* dnsproxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 218E8E50156D8C0300720DA0 /* dnsproxy.h */; };
-		218E8E54156D8C0300720DA0 /* dnsproxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 218E8E50156D8C0300720DA0 /* dnsproxy.h */; };
-		219D5542149ED645004464AE /* libxml2.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 219D5541149ED645004464AE /* libxml2.2.dylib */; };
-		219D5543149ED645004464AE /* libxml2.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 219D5541149ED645004464AE /* libxml2.2.dylib */; };
-		21A57F4C145B2AE100939099 /* CryptoAlg.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F4A145B2AE100939099 /* CryptoAlg.c */; };
-		21A57F4D145B2AE100939099 /* CryptoAlg.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F4A145B2AE100939099 /* CryptoAlg.c */; };
-		21A57F4E145B2AE100939099 /* CryptoAlg.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F4B145B2AE100939099 /* CryptoAlg.h */; };
-		21A57F4F145B2AE100939099 /* CryptoAlg.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F4B145B2AE100939099 /* CryptoAlg.h */; };
-		21A57F53145B2B1400939099 /* CryptoSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F51145B2B1400939099 /* CryptoSupport.c */; };
-		21A57F54145B2B1400939099 /* CryptoSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F51145B2B1400939099 /* CryptoSupport.c */; };
-		21A57F55145B2B1400939099 /* CryptoSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F52145B2B1400939099 /* CryptoSupport.h */; };
-		21A57F56145B2B1400939099 /* CryptoSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F52145B2B1400939099 /* CryptoSupport.h */; };
-		21DCD05C1461B23700702FC8 /* CryptoAlg.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F4A145B2AE100939099 /* CryptoAlg.c */; };
-		21DCD05D1461B23700702FC8 /* CryptoAlg.h in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F4B145B2AE100939099 /* CryptoAlg.h */; };
-		21DD8FBF161E9A250033C8F8 /* anonymous.c in Sources */ = {isa = PBXBuildFile; fileRef = 21DD8FBD161E9A250033C8F8 /* anonymous.c */; };
-		21DD8FC0161E9A250033C8F8 /* anonymous.c in Sources */ = {isa = PBXBuildFile; fileRef = 21DD8FBD161E9A250033C8F8 /* anonymous.c */; };
-		21DD8FC1161E9A250033C8F8 /* anonymous.h in Headers */ = {isa = PBXBuildFile; fileRef = 21DD8FBE161E9A250033C8F8 /* anonymous.h */; };
-		21DD8FC2161E9A250033C8F8 /* anonymous.h in Headers */ = {isa = PBXBuildFile; fileRef = 21DD8FBE161E9A250033C8F8 /* anonymous.h */; };
-		21DED43515702C0F0060B6B9 /* DNSProxySupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21DED43415702C0F0060B6B9 /* DNSProxySupport.c */; };
-		21DED43615702C0F0060B6B9 /* DNSProxySupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21DED43415702C0F0060B6B9 /* DNSProxySupport.c */; };
-		2E0405F50C3195F700F13B59 /* helper.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405F40C3195F700F13B59 /* helper.c */; };
-		2E0405F60C31961100F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; settings = {ATTRIBUTES = (Client, Server, ); COMPILER_FLAGS = "-Wno-error"; }; };
-		2E0406150C3197CB00F13B59 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E0406140C3197CB00F13B59 /* libbsm.dylib */; };
-		2E04061F0C3198B700F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; };
-		2E0406200C3198B700F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; };
-		2E04070A0C31EEEC00F13B59 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
-		2E04070B0C31EEEC00F13B59 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
-		2E3552900C3A95C100CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; };
-		2E3552910C3A95C100CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; };
-		2E3552920C3A95C100CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; };
-		2E35529D0C3A9E7600CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; };
-		2E35529E0C3A9E7600CA1CB7 /* helper-stubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */; };
-		2E35529F0C3A9E7600CA1CB7 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
-		2E4D9B050C38C19500480551 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
-		2E8165E80C5980E300485EB2 /* libpfkey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A8202520C56C36500DDFD48 /* libpfkey.h */; };
-		2E8165E90C5980EE00485EB2 /* pfkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A8202530C56C36600DDFD48 /* pfkey.c */; };
-		2E8165EA0C5980F700485EB2 /* ipsec_strerror.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A8202510C56C36500DDFD48 /* ipsec_strerror.h */; };
-		2E8165F90C59838100485EB2 /* libipsec.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E8165F60C59835F00485EB2 /* libipsec.dylib */; };
-		2E96A51D0C39BDAC0087C4D2 /* helper-main.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0406CA0C31E9AD00F13B59 /* helper-main.c */; };
-		2E96A5260C39BE480087C4D2 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
-		2E96A5270C39BE480087C4D2 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
-		2E96A5300C39C1A50087C4D2 /* helper-stubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */; };
-		2E96A5320C39C1A50087C4D2 /* helper-stubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */; };
-		2EAE955A0C31F4D30021F738 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; };
-		2EC8F8EC0C39CCAC003C9C48 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
-		2ECC11A60C4FEC3800CB1885 /* helpermsg-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */; };
-		2ECC11A70C4FEC3800CB1885 /* helpermsg-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */; };
-		2ECC11A80C4FEC3800CB1885 /* helpermsg-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */; };
-		2EDC5E730C39EA640092701B /* helper-server.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EDC5E720C39EA640092701B /* helper-server.h */; };
-		2EDC5E740C39EA640092701B /* helper-server.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EDC5E720C39EA640092701B /* helper-server.h */; };
-		2EDC5E750C39EA640092701B /* helper-server.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EDC5E720C39EA640092701B /* helper-server.h */; };
-		4A7B9E8014FDA25000B84CC1 /* mDNSResponder.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A7B9E7E14FDA1BB00B84CC1 /* mDNSResponder.plist */; };
-		4A7B9E8214FDA26C00B84CC1 /* mDNSResponder.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A7B9E7C14FDA19F00B84CC1 /* mDNSResponder.txt */; };
-		4AAE0C9A0C68EA81003882A5 /* mDNSResponderHelper.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */; };
-		4BD2B63A134FE09F002B96D5 /* P2PPacketFilter.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BD2B638134FE09F002B96D5 /* P2PPacketFilter.c */; };
-		4BD2B63B134FE09F002B96D5 /* P2PPacketFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BD2B639134FE09F002B96D5 /* P2PPacketFilter.h */; };
-		72FB5467166D5FCA0090B2D9 /* dnsctl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72FB545A166D5F960090B2D9 /* dnsctl.c */; };
-		72FB5468166D5FD20090B2D9 /* libdns_services.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 84C5B3351665529800C324A8 /* libdns_services.dylib */; };
-		8418673E15AB8C2D00BB7F70 /* com.apple.networking.mDNSResponder in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8418673A15AB8B6900BB7F70 /* com.apple.networking.mDNSResponder */; };
-		848DA5C7165477E000D2E8B4 /* xpc_services.c in Sources */ = {isa = PBXBuildFile; fileRef = 848DA5C6165477E000D2E8B4 /* xpc_services.c */; };
-		848DA5C8165477E000D2E8B4 /* xpc_services.c in Sources */ = {isa = PBXBuildFile; fileRef = 848DA5C6165477E000D2E8B4 /* xpc_services.c */; };
-		848DA5CA165477EB00D2E8B4 /* xpc_services.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5C9165477EB00D2E8B4 /* xpc_services.h */; };
-		848DA5CB165477EB00D2E8B4 /* xpc_services.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5C9165477EB00D2E8B4 /* xpc_services.h */; };
-		848DA5D616547F7200D2E8B4 /* dns_xpc.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5D516547F7200D2E8B4 /* dns_xpc.h */; };
-		848DA5D716547F7200D2E8B4 /* 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 */; };
-		84C5B33D166553F900C324A8 /* dns_services.h in Headers */ = {isa = PBXBuildFile; fileRef = 84C5B338166553A000C324A8 /* dns_services.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		D284BE530ADD80740027CCDF /* DNSServiceDiscoveryDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */; };
-		D284BE540ADD80740027CCDF /* dnssd_ipc.h in Headers */ = {isa = PBXBuildFile; fileRef = F5E11B5B04A28126019798ED /* dnssd_ipc.h */; };
-		D284BE560ADD80740027CCDF /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Client, ); }; };
-		D284BE570ADD80740027CCDF /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-		D284BE580ADD80740027CCDF /* mDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBE9022EAF5A00000109 /* mDNS.c */; };
-		D284BE590ADD80740027CCDF /* uDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F70587CEF6001880B3 /* uDNS.c */; };
-		D284BE5A0ADD80740027CCDF /* DNSCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F60587CEF6001880B3 /* DNSCommon.c */; };
-		D284BE5B0ADD80740027CCDF /* DNSDigest.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F461DB5062DBF2900672BF3 /* DNSDigest.c */; };
-		D284BE5D0ADD80740027CCDF /* mDNSDebug.c in Sources */ = {isa = PBXBuildFile; fileRef = DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */; };
-		D284BE5E0ADD80740027CCDF /* uds_daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = F525E72804AA167501F1CF4D /* uds_daemon.c */; };
-		D284BE5F0ADD80740027CCDF /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
-		D284BE600ADD80740027CCDF /* PlatformCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FFCB6D73075D539900B8AF62 /* PlatformCommon.c */; };
-		D284BE610ADD80740027CCDF /* mDNSMacOSX.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBEB022EAF7200000109 /* mDNSMacOSX.c */; };
-		D284BE620ADD80740027CCDF /* LegacyNATTraversal.c in Sources */ = {isa = PBXBuildFile; fileRef = 7FC8F9D406D14E66007E879D /* LegacyNATTraversal.c */; };
-		D284BE630ADD80740027CCDF /* daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBEC022EAF7200000109 /* daemon.c */; };
-		D284BE650ADD80740027CCDF /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
-		D284BE660ADD80740027CCDF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
-		D284BE670ADD80740027CCDF /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA213D02786FC30CCA2C71 /* IOKit.framework */; };
-		D284BE680ADD80740027CCDF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
-		D284BE6B0ADD80740027CCDF /* mDNSResponder.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FF485D5105632E0000130380 /* mDNSResponder.8 */; };
-		D284BE780ADD80800027CCDF /* DNSServiceDiscoveryDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */; };
-		D284BE790ADD80800027CCDF /* dnssd_ipc.h in Headers */ = {isa = PBXBuildFile; fileRef = F5E11B5B04A28126019798ED /* dnssd_ipc.h */; };
-		D284BE7A0ADD80800027CCDF /* mDNSEmbeddedAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 654BE64F02B63B93000001D1 /* mDNSEmbeddedAPI.h */; };
-		D284BE7B0ADD80800027CCDF /* mDNSDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 654BE65002B63B93000001D1 /* mDNSDebug.h */; };
-		D284BE7C0ADD80800027CCDF /* mDNSMacOSX.h in Headers */ = {isa = PBXBuildFile; fileRef = 000753D303367C1C0CCA2C71 /* mDNSMacOSX.h */; };
-		D284BE7E0ADD80800027CCDF /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Client, ); }; };
-		D284BE7F0ADD80800027CCDF /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-		D284BE800ADD80800027CCDF /* mDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBE9022EAF5A00000109 /* mDNS.c */; };
-		D284BE810ADD80800027CCDF /* uDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F70587CEF6001880B3 /* uDNS.c */; };
-		D284BE820ADD80800027CCDF /* DNSCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F60587CEF6001880B3 /* DNSCommon.c */; };
-		D284BE830ADD80800027CCDF /* DNSDigest.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F461DB5062DBF2900672BF3 /* DNSDigest.c */; };
-		D284BE850ADD80800027CCDF /* mDNSDebug.c in Sources */ = {isa = PBXBuildFile; fileRef = DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */; };
-		D284BE860ADD80800027CCDF /* uds_daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = F525E72804AA167501F1CF4D /* uds_daemon.c */; };
-		D284BE870ADD80800027CCDF /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
-		D284BE880ADD80800027CCDF /* PlatformCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FFCB6D73075D539900B8AF62 /* PlatformCommon.c */; };
-		D284BE890ADD80800027CCDF /* mDNSMacOSX.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBEB022EAF7200000109 /* mDNSMacOSX.c */; };
-		D284BE8A0ADD80800027CCDF /* LegacyNATTraversal.c in Sources */ = {isa = PBXBuildFile; fileRef = 7FC8F9D406D14E66007E879D /* LegacyNATTraversal.c */; };
-		D284BE8B0ADD80800027CCDF /* daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBEC022EAF7200000109 /* daemon.c */; };
-		D284BE8D0ADD80800027CCDF /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
-		D284BE8E0ADD80800027CCDF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
-		D284BE8F0ADD80800027CCDF /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA213D02786FC30CCA2C71 /* IOKit.framework */; };
-		D284BE900ADD80800027CCDF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
-		D284BEA80ADD80920027CCDF /* dns-sd.c in Sources */ = {isa = PBXBuildFile; fileRef = FF1C919F07021E3F001048AB /* dns-sd.c */; };
-		D284BEAC0ADD80920027CCDF /* dns-sd.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FF1C919D07021D77001048AB /* dns-sd.1 */; };
-		D284BEB70ADD809A0027CCDF /* JNISupport.c in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC44B0662DD1100335AB3 /* JNISupport.c */; };
-		D284BEB90ADD809A0027CCDF /* JavaVM.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB2CC4680662DFF500335AB3 /* JavaVM.framework */; };
-		D284BEC50ADD80A20027CCDF /* DNSCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F60587CEF6001880B3 /* DNSCommon.c */; };
-		D284BEC60ADD80A20027CCDF /* DNSDigest.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F461DB5062DBF2900672BF3 /* DNSDigest.c */; };
-		D284BEC70ADD80A20027CCDF /* dnsextd.c in Sources */ = {isa = PBXBuildFile; fileRef = FF25794606C9A8BF00376F7B /* dnsextd.c */; };
-		D284BEC80ADD80A20027CCDF /* mDNSDebug.c in Sources */ = {isa = PBXBuildFile; fileRef = DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */; };
-		D284BEC90ADD80A20027CCDF /* GenLinkedList.c in Sources */ = {isa = PBXBuildFile; fileRef = DBAAFE2C057E8F660085CAD0 /* GenLinkedList.c */; };
-		D284BECA0ADD80A20027CCDF /* mDNSMacOSX.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBEB022EAF7200000109 /* mDNSMacOSX.c */; };
-		D284BECB0ADD80A20027CCDF /* dnsextd_lexer.l in Sources */ = {isa = PBXBuildFile; fileRef = FF13FFEA0A5DA44A00897C81 /* dnsextd_lexer.l */; settings = {COMPILER_FLAGS = "-Wno-error"; }; };
-		D284BECC0ADD80A20027CCDF /* dnsextd_parser.y in Sources */ = {isa = PBXBuildFile; fileRef = FF13FFEC0A5DA45500897C81 /* dnsextd_parser.y */; };
-		D284BECD0ADD80A20027CCDF /* PlatformCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FFCB6D73075D539900B8AF62 /* PlatformCommon.c */; };
-		D284BECF0ADD80A20027CCDF /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
-		D284BED00ADD80A20027CCDF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
-		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 */; };
-		D284BEE00ADD80A70027CCDF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFFB0DB407B43D2700B88D48 /* Foundation.framework */; };
-		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 */; };
-		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 */; };
-		FFA572490AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
-		FFA5724A0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
-		FFA5724B0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
-		FFAE66F0105F0CD900162116 /* ddnswriteconfig in Resources */ = {isa = PBXBuildFile; fileRef = D284BEE80ADD80A70027CCDF /* ddnswriteconfig */; };
-		FFB437150EB165BD00E17C68 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA213D02786FC30CCA2C71 /* IOKit.framework */; };
-		FFC22AA20B00F42A00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
-		FFC22AA30B00F42B00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
-		FFC22AA40B00F42C00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
-		FFC22AA50B00F43000BAB070 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-		FFC22AA60B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-		FFC22AA70B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-		FFF589B70E37F66800EF515C /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF5852100DD27BD300862BDF /* ClientCommon.c */; };
-		FFF589C10E37F67E00EF515C /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF5852100DD27BD300862BDF /* ClientCommon.c */; };
-		FFFA38630AEEDB090065B80A /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
-		FFFA38650AEEDB130065B80A /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
-		FFFA38660AEEDB2B0065B80A /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
-		FFFF8F810C3307C400722979 /* dnsextd.conf in CopyFiles */ = {isa = PBXBuildFile; fileRef = FFFF8F800C3307AC00722979 /* dnsextd.conf */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXBuildRule section */
-		D284BF750ADD850C0027CCDF /* PBXBuildRule */ = {
-			isa = PBXBuildRule;
-			compilerSpec = com.apple.compilers.proxy.script;
-			fileType = sourcecode.yacc;
-			isEditable = 1;
-			outputFiles = (
-				"$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).h",
-				"$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).c",
-			);
-			script = "echo NOOP yacc ${INPUT_FILE_PATH}";
-		};
-		D284BFB80ADD8E510027CCDF /* PBXBuildRule */ = {
-			isa = PBXBuildRule;
-			compilerSpec = com.apple.compilers.proxy.script;
-			fileType = sourcecode.lex;
-			isEditable = 1;
-			outputFiles = (
-				"$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).c",
-			);
-			script = "/usr/bin/flex -i -o${DERIVED_FILE_DIR}/${INPUT_FILE_BASE}.c ${INPUT_FILE_PATH}";
-		};
-/* End PBXBuildRule section */
-
-/* Begin PBXContainerItemProxy section */
-		03067D670C83A3830022BE1F /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = D284BE500ADD80740027CCDF;
-			remoteInfo = mDNSResponder;
-		};
-		03067D690C83A3890022BE1F /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = D284BE750ADD80800027CCDF;
-			remoteInfo = "mDNSResponder debug";
-		};
-		03067D6B0C83A3920022BE1F /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = D284BEA50ADD80920027CCDF;
-			remoteInfo = "dns-sd tool";
-		};
-		03067D6D0C83A39C0022BE1F /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 2E0405EF0C31955500F13B59;
-			remoteInfo = mDNSResponderHelper;
-		};
-		03067D850C849CC30022BE1F /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 03067D640C83A3700022BE1F;
-			remoteInfo = "Build Some";
-		};
-		2130257012400E9300AC839F /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = FFA572650AF190F10055A0F1;
-			remoteInfo = SystemLibrariesDynamic;
-		};
-		2141DCFC123FFB7D0086D23E /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 2141DCF8123FFB5D0086D23E;
-			remoteInfo = SystemLibraries;
-		};
-		2141DD0D123FFC960086D23E /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 2141DD0B123FFC7F0086D23E;
-			remoteInfo = SystemLibrariesStatic;
-		};
-		215FFB18124002C100470DE1 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 2141DD1C123FFCDB0086D23E;
-			remoteInfo = libdns_sd_static;
-		};
-		215FFB1A124002C700470DE1 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 2141DD23123FFD0F0086D23E;
-			remoteInfo = libdns_sd_debug_static;
-		};
-		215FFB1C124002CC00470DE1 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 2141DD29123FFD2C0086D23E;
-			remoteInfo = libdns_sd_profile_static;
-		};
-		217A4C48138EE14C000A5BA8 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 213FB21712028A7A002B3A08;
-			remoteInfo = BonjourEvents;
-		};
-		4AE471690EAFF83800A6C5AD /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 4AE471670EAFF81900A6C5AD;
-			remoteInfo = dns_sd.jar;
-		};
-		72FB5469166D5FE40090B2D9 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 72FB545E166D5FB00090B2D9;
-			remoteInfo = dnsctl;
-		};
-		84C5B3401665544B00C324A8 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 84C5B3341665529800C324A8;
-			remoteInfo = dns_services;
-		};
-		D284BF2B0ADD815A0027CCDF /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = D284BEBF0ADD80A20027CCDF;
-			remoteInfo = dnsextd;
-		};
-		D284BF2D0ADD81600027CCDF /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = D284BEDB0ADD80A70027CCDF;
-			remoteInfo = ddnswriteconfig;
-		};
-		D284BF2F0ADD81630027CCDF /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = D284BEEA0ADD80B00027CCDF;
-			remoteInfo = PreferencePane;
-		};
-		FFA572680AF190FF0055A0F1 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = FFB765830AEED9C700583A2C;
-			remoteInfo = libdns_sd;
-		};
-		FFA5726A0AF191010055A0F1 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = FFA572300AF18F1C0055A0F1;
-			remoteInfo = "libdns_sd debug";
-		};
-		FFA5726C0AF191020055A0F1 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-			proxyType = 1;
-			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 */;
-			proxyType = 1;
-			remoteGlobalIDString = 00AD62BB032D7A0C0CCA2C71;
-			remoteInfo = "Build Main";
-		};
-/* End PBXContainerItemProxy section */
-
-/* Begin PBXCopyFilesBuildPhase section */
-		4A7B9E7F14FDA21B00B84CC1 /* CopyFiles */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 8;
-			dstPath = /usr/local/OpenSourceVersions;
-			dstSubfolderSpec = 0;
-			files = (
-				4A7B9E8014FDA25000B84CC1 /* mDNSResponder.plist in CopyFiles */,
-			);
-			runOnlyForDeploymentPostprocessing = 1;
-		};
-		4A7B9E8114FDA25500B84CC1 /* CopyFiles */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 8;
-			dstPath = /usr/local/OpenSourceLicenses;
-			dstSubfolderSpec = 0;
-			files = (
-				4A7B9E8214FDA26C00B84CC1 /* mDNSResponder.txt in CopyFiles */,
-			);
-			runOnlyForDeploymentPostprocessing = 1;
-		};
-		4AAE0C5A0C68E6EC003882A5 /* CopyFiles */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 8;
-			dstPath = /usr/share/man/man8;
-			dstSubfolderSpec = 0;
-			files = (
-				4AAE0C9A0C68EA81003882A5 /* mDNSResponderHelper.8 in CopyFiles */,
-			);
-			runOnlyForDeploymentPostprocessing = 1;
-		};
-		72FB545D166D5FB00090B2D9 /* CopyFiles */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 12;
-			dstPath = /usr/share/man/man1/;
-			dstSubfolderSpec = 0;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		8418673D15AB8BFF00BB7F70 /* CopyFiles */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 8;
-			dstPath = /private/etc/asl/;
-			dstSubfolderSpec = 0;
-			files = (
-				8418673E15AB8C2D00BB7F70 /* com.apple.networking.mDNSResponder in CopyFiles */,
-			);
-			runOnlyForDeploymentPostprocessing = 1;
-		};
-		D284BE6A0ADD80740027CCDF /* CopyFiles */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 8;
-			dstPath = /usr/share/man/man8;
-			dstSubfolderSpec = 0;
-			files = (
-				D284BE6B0ADD80740027CCDF /* mDNSResponder.8 in CopyFiles */,
-			);
-			runOnlyForDeploymentPostprocessing = 1;
-		};
-		D284BEAB0ADD80920027CCDF /* CopyFiles */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 8;
-			dstPath = /usr/share/man/man1;
-			dstSubfolderSpec = 0;
-			files = (
-				D284BEAC0ADD80920027CCDF /* dns-sd.1 in CopyFiles */,
-			);
-			runOnlyForDeploymentPostprocessing = 1;
-		};
-		D284BED40ADD80A20027CCDF /* CopyFiles */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 8;
-			dstPath = /usr/share/man/man8;
-			dstSubfolderSpec = 0;
-			files = (
-				D284BED50ADD80A20027CCDF /* dnsextd.8 in CopyFiles */,
-			);
-			runOnlyForDeploymentPostprocessing = 1;
-		};
-		FFFF8F770C32F0FD00722979 /* CopyFiles */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 8;
-			dstPath = /private/etc;
-			dstSubfolderSpec = 0;
-			files = (
-				FFFF8F810C3307C400722979 /* dnsextd.conf in CopyFiles */,
-			);
-			runOnlyForDeploymentPostprocessing = 1;
-		};
-/* End PBXCopyFilesBuildPhase section */
-
-/* Begin PBXFileReference section */
-		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>"; };
-		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>"; };
-		2120ABD416B71614007089B6 /* CUPolicy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CUPolicy.c; sourceTree = "<group>"; };
-		2124FA2B1471E98C0021D7BB /* nsec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nsec.h; path = ../mDNSCore/nsec.h; sourceTree = "<group>"; };
-		2124FA2F1471E9B50021D7BB /* dnssec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dnssec.h; path = ../mDNSCore/dnssec.h; sourceTree = "<group>"; };
-		2124FA321471E9DE0021D7BB /* nsec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nsec.c; path = ../mDNSCore/nsec.c; sourceTree = "<group>"; };
-		2127A47515C3C7B900A857FC /* nsec3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nsec3.c; path = ../mDNSCore/nsec3.c; sourceTree = "<group>"; };
-		2127A47615C3C7B900A857FC /* nsec3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nsec3.h; path = ../mDNSCore/nsec3.h; sourceTree = "<group>"; };
-		213BDC6C147319F400000896 /* dnssec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnssec.c; path = ../mDNSCore/dnssec.c; sourceTree = "<group>"; };
-		213FB21812028A7A002B3A08 /* BonjourEvents.plugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BonjourEvents.plugin; sourceTree = BUILT_PRODUCTS_DIR; };
-		213FB22C12028B53002B3A08 /* BonjourEvents.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BonjourEvents.c; sourceTree = "<group>"; };
-		213FB22D12028B53002B3A08 /* BonjourEvents-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "BonjourEvents-Info.plist"; sourceTree = "<group>"; };
-		2141DD1D123FFCDB0086D23E /* libdns_sd.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdns_sd.a; sourceTree = BUILT_PRODUCTS_DIR; };
-		2141DD24123FFD0F0086D23E /* libdns_sd_debug.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdns_sd_debug.a; sourceTree = BUILT_PRODUCTS_DIR; };
-		2141DD2A123FFD2C0086D23E /* libdns_sd_profile.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdns_sd_profile.a; sourceTree = BUILT_PRODUCTS_DIR; };
-		216D9ACD1720C9F5008066E1 /* VPNService.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = VPNService.c; sourceTree = "<group>"; };
-		218E8E4F156D8C0300720DA0 /* dnsproxy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnsproxy.c; path = ../mDNSCore/dnsproxy.c; sourceTree = "<group>"; };
-		218E8E50156D8C0300720DA0 /* dnsproxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dnsproxy.h; path = ../mDNSCore/dnsproxy.h; sourceTree = "<group>"; };
-		219D5541149ED645004464AE /* libxml2.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.2.dylib; path = SDKs/MacOSX10.8.sdk/usr/lib/libxml2.2.dylib; sourceTree = DEVELOPER_DIR; };
-		21A57F4A145B2AE100939099 /* CryptoAlg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CryptoAlg.c; path = ../mDNSCore/CryptoAlg.c; sourceTree = "<group>"; };
-		21A57F4B145B2AE100939099 /* CryptoAlg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CryptoAlg.h; path = ../mDNSCore/CryptoAlg.h; sourceTree = "<group>"; };
-		21A57F51145B2B1400939099 /* CryptoSupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CryptoSupport.c; sourceTree = "<group>"; };
-		21A57F52145B2B1400939099 /* CryptoSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoSupport.h; sourceTree = "<group>"; };
-		21DD8FBD161E9A250033C8F8 /* anonymous.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = anonymous.c; path = ../mDNSCore/anonymous.c; sourceTree = "<group>"; };
-		21DD8FBE161E9A250033C8F8 /* anonymous.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = anonymous.h; path = ../mDNSCore/anonymous.h; sourceTree = "<group>"; };
-		21DED43415702C0F0060B6B9 /* DNSProxySupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DNSProxySupport.c; sourceTree = "<group>"; };
-		21F432971134AA6800581B69 /* WebFilterDNS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebFilterDNS.framework; path = /System/Library/PrivateFrameworks/WebFilterDNS.framework; sourceTree = "<absolute>"; };
-		2E0405EB0C3190DC00F13B59 /* helpermsg.defs */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.mig; path = helpermsg.defs; 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>"; };
-		2E0406CA0C31E9AD00F13B59 /* helper-main.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "helper-main.c"; sourceTree = "<group>"; };
-		2E35528F0C3A95C100CA1CB7 /* helper-error.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "helper-error.h"; sourceTree = "<group>"; };
-		2E8165F60C59835F00485EB2 /* libipsec.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libipsec.dylib; path = /usr/lib/libipsec.dylib; sourceTree = "<absolute>"; };
-		2E96A5250C39BE480087C4D2 /* helper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = helper.h; sourceTree = "<group>"; };
-		2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "helper-stubs.c"; sourceTree = "<group>"; };
-		2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "helpermsg-types.h"; sourceTree = "<group>"; };
-		2EDC5E720C39EA640092701B /* helper-server.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "helper-server.h"; sourceTree = "<group>"; };
-		4A2E69DD0F5475A3004A87B0 /* uds_daemon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = uds_daemon.h; path = ../mDNSShared/uds_daemon.h; sourceTree = SOURCE_ROOT; };
-		4A3600DF0F34F8CD00453EFB /* DeviceToDeviceManager.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DeviceToDeviceManager.framework; path = /System/Library/PrivateFrameworks/DeviceToDeviceManager.framework; sourceTree = "<absolute>"; };
-		4A7B9E7C14FDA19F00B84CC1 /* mDNSResponder.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = mDNSResponder.txt; sourceTree = "<group>"; };
-		4A7B9E7E14FDA1BB00B84CC1 /* mDNSResponder.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = mDNSResponder.plist; sourceTree = "<group>"; };
-		4A8202510C56C36500DDFD48 /* ipsec_strerror.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipsec_strerror.h; sourceTree = "<group>"; };
-		4A8202520C56C36500DDFD48 /* libpfkey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libpfkey.h; sourceTree = "<group>"; };
-		4A8202530C56C36600DDFD48 /* pfkey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pfkey.c; sourceTree = "<group>"; };
-		4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mDNSResponderHelper.8; sourceTree = SOURCE_ROOT; };
-		4ADB5F230F6AB9F400B95BF3 /* helper-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "helper-entitlements.plist"; sourceTree = "<group>"; };
-		4BD2B638134FE09F002B96D5 /* P2PPacketFilter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = P2PPacketFilter.c; sourceTree = "<group>"; };
-		4BD2B639134FE09F002B96D5 /* P2PPacketFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = P2PPacketFilter.h; sourceTree = "<group>"; };
-		654BE64F02B63B93000001D1 /* mDNSEmbeddedAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mDNSEmbeddedAPI.h; path = ../mDNSCore/mDNSEmbeddedAPI.h; sourceTree = "<group>"; };
-		654BE65002B63B93000001D1 /* mDNSDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mDNSDebug.h; path = ../mDNSCore/mDNSDebug.h; sourceTree = "<group>"; };
-		65713D46025A293200000109 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = /System/Library/Frameworks/SystemConfiguration.framework; sourceTree = "<absolute>"; };
-		6575FBE9022EAF5A00000109 /* mDNS.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; name = mDNS.c; path = ../mDNSCore/mDNS.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		6575FBEB022EAF7200000109 /* mDNSMacOSX.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = mDNSMacOSX.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		6575FBEC022EAF7200000109 /* daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = daemon.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscoveryDefines.h; sourceTree = "<group>"; };
-		6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = DNSServiceDiscoveryReply.defs; sourceTree = "<group>"; };
-		6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = DNSServiceDiscoveryRequest.defs; sourceTree = "<group>"; };
-		6575FC20022EB7AA00000109 /* SamplemDNSClient.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = SamplemDNSClient.c; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 0; };
-		72FB545A166D5F960090B2D9 /* dnsctl.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dnsctl.c; path = ../Clients/dnsctl.c; sourceTree = "<group>"; };
-		72FB545F166D5FB00090B2D9 /* dnsctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dnsctl; sourceTree = BUILT_PRODUCTS_DIR; };
-		7F18A9F60587CEF6001880B3 /* DNSCommon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = DNSCommon.c; path = ../mDNSCore/DNSCommon.c; sourceTree = SOURCE_ROOT; };
-		7F18A9F70587CEF6001880B3 /* uDNS.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = uDNS.c; path = ../mDNSCore/uDNS.c; sourceTree = SOURCE_ROOT; };
-		7F461DB5062DBF2900672BF3 /* DNSDigest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = DNSDigest.c; path = ../mDNSCore/DNSDigest.c; sourceTree = SOURCE_ROOT; };
-		7F869685066EE02400D2A2DC /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = "<absolute>"; };
-		7FC8F9D406D14E66007E879D /* LegacyNATTraversal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = LegacyNATTraversal.c; sourceTree = SOURCE_ROOT; };
-		8418673A15AB8B6900BB7F70 /* com.apple.networking.mDNSResponder */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.networking.mDNSResponder; sourceTree = "<group>"; };
-		8418673C15AB8B8000BB7F70 /* mDNSResponderLogging.mobileconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = mDNSResponderLogging.mobileconfig; sourceTree = "<group>"; };
-		848DA5C6165477E000D2E8B4 /* xpc_services.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xpc_services.c; path = Private/xpc_services.c; sourceTree = "<group>"; };
-		848DA5C9165477EB00D2E8B4 /* xpc_services.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xpc_services.h; path = Private/xpc_services.h; sourceTree = "<group>"; };
-		848DA5D516547F7200D2E8B4 /* dns_xpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_xpc.h; path = Private/dns_xpc.h; sourceTree = "<group>"; };
-		84C5B3351665529800C324A8 /* libdns_services.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libdns_services.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
-		84C5B338166553A000C324A8 /* dns_services.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dns_services.h; path = Private/dns_services.h; sourceTree = "<group>"; };
-		84C5B339166553AF00C324A8 /* dns_services.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dns_services.c; path = Private/dns_services.c; sourceTree = "<group>"; };
-		D284BE730ADD80740027CCDF /* mDNSResponder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mDNSResponder; sourceTree = BUILT_PRODUCTS_DIR; };
-		D284BE950ADD80800027CCDF /* mDNSResponder.debug */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mDNSResponder.debug; 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; };
-		D284C04D0ADD95D30027CCDF /* Info-PreferencePane.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Info-PreferencePane.plist"; path = "PreferencePane/Info-PreferencePane.plist"; sourceTree = "<group>"; };
-		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; };
-		DB2CC4450662DD1100335AB3 /* DNSRecord.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSRecord.java; path = ../mDNSShared/Java/DNSRecord.java; sourceTree = SOURCE_ROOT; };
-		DB2CC4460662DD1100335AB3 /* DNSSD.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSSD.java; path = ../mDNSShared/Java/DNSSD.java; sourceTree = SOURCE_ROOT; };
-		DB2CC4470662DD1100335AB3 /* DNSSDException.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSSDException.java; path = ../mDNSShared/Java/DNSSDException.java; sourceTree = SOURCE_ROOT; };
-		DB2CC4480662DD1100335AB3 /* DNSSDRegistration.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSSDRegistration.java; path = ../mDNSShared/Java/DNSSDRegistration.java; sourceTree = SOURCE_ROOT; };
-		DB2CC4490662DD1100335AB3 /* DNSSDService.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSSDService.java; path = ../mDNSShared/Java/DNSSDService.java; sourceTree = SOURCE_ROOT; };
-		DB2CC44A0662DD1100335AB3 /* DomainListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DomainListener.java; path = ../mDNSShared/Java/DomainListener.java; sourceTree = SOURCE_ROOT; };
-		DB2CC44B0662DD1100335AB3 /* JNISupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = JNISupport.c; path = ../mDNSShared/Java/JNISupport.c; sourceTree = SOURCE_ROOT; };
-		DB2CC44C0662DD1100335AB3 /* QueryListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = QueryListener.java; path = ../mDNSShared/Java/QueryListener.java; sourceTree = SOURCE_ROOT; };
-		DB2CC44D0662DD1100335AB3 /* RegisterListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = RegisterListener.java; path = ../mDNSShared/Java/RegisterListener.java; sourceTree = SOURCE_ROOT; };
-		DB2CC44E0662DD1100335AB3 /* ResolveListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = ResolveListener.java; path = ../mDNSShared/Java/ResolveListener.java; sourceTree = SOURCE_ROOT; };
-		DB2CC44F0662DD1100335AB3 /* TXTRecord.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = TXTRecord.java; path = ../mDNSShared/Java/TXTRecord.java; sourceTree = SOURCE_ROOT; };
-		DB2CC4680662DFF500335AB3 /* JavaVM.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaVM.framework; path = /System/Library/Frameworks/JavaVM.framework; sourceTree = "<absolute>"; };
-		DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mDNSDebug.c; path = ../mDNSShared/mDNSDebug.c; sourceTree = SOURCE_ROOT; };
-		DBAAFE2C057E8F660085CAD0 /* GenLinkedList.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GenLinkedList.c; path = ../mDNSShared/GenLinkedList.c; sourceTree = SOURCE_ROOT; };
-		F525E72804AA167501F1CF4D /* uds_daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = uds_daemon.c; path = ../mDNSShared/uds_daemon.c; sourceTree = SOURCE_ROOT; };
-		F5E11B5A04A28126019798ED /* dnssd_ipc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnssd_ipc.c; path = ../mDNSShared/dnssd_ipc.c; sourceTree = SOURCE_ROOT; };
-		F5E11B5B04A28126019798ED /* dnssd_ipc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dnssd_ipc.h; path = ../mDNSShared/dnssd_ipc.h; sourceTree = SOURCE_ROOT; };
-		FF08480607CEB8E800AE6769 /* inprogress.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = inprogress.tiff; path = PreferencePane/Artwork/inprogress.tiff; sourceTree = SOURCE_ROOT; };
-		FF13FFEA0A5DA44A00897C81 /* dnsextd_lexer.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; name = dnsextd_lexer.l; path = ../mDNSShared/dnsextd_lexer.l; sourceTree = SOURCE_ROOT; };
-		FF13FFEC0A5DA45500897C81 /* dnsextd_parser.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; name = dnsextd_parser.y; path = ../mDNSShared/dnsextd_parser.y; sourceTree = SOURCE_ROOT; };
-		FF1C919D07021D77001048AB /* dns-sd.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = "dns-sd.1"; path = "../mDNSShared/dns-sd.1"; sourceTree = SOURCE_ROOT; };
-		FF1C919F07021E3F001048AB /* dns-sd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "dns-sd.c"; path = "../Clients/dns-sd.c"; sourceTree = SOURCE_ROOT; };
-		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; };
-		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; };
-		FFA572390AF18F1C0055A0F1 /* libsystem_dnssd_debug.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_dnssd_debug.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
-		FFA572450AF18F450055A0F1 /* libsystem_dnssd_profile.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_dnssd_profile.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
-		FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DNSServiceDiscovery.c; sourceTree = "<group>"; };
-		FFA572600AF1908D0055A0F1 /* DNSServiceDiscovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscovery.h; sourceTree = "<group>"; };
-		FFA572630AF190C20055A0F1 /* dns_sd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_sd.h; path = ../mDNSShared/dns_sd.h; sourceTree = SOURCE_ROOT; };
-		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>"; };
-		FFFB0DB407B43D2700B88D48 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
-		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 */
-		213FB21612028A7A002B3A08 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				213FB23D12028C5A002B3A08 /* CoreFoundation.framework in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		2141DD1B123FFCDB0086D23E /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		2141DD22123FFD0F0086D23E /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		2141DD28123FFD2C0086D23E /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		2E0405EE0C31955500F13B59 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				FFB437150EB165BD00E17C68 /* IOKit.framework in Frameworks */,
-				2E0406150C3197CB00F13B59 /* libbsm.dylib in Frameworks */,
-				2E04070A0C31EEEC00F13B59 /* CoreFoundation.framework in Frameworks */,
-				2E04070B0C31EEEC00F13B59 /* SystemConfiguration.framework in Frameworks */,
-				2E4D9B050C38C19500480551 /* Security.framework in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		72FB545C166D5FB00090B2D9 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				72FB5468166D5FD20090B2D9 /* libdns_services.dylib in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		84C5B3321665529800C324A8 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BE640ADD80740027CCDF /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				D284BE650ADD80740027CCDF /* CoreFoundation.framework in Frameworks */,
-				D284BE660ADD80740027CCDF /* SystemConfiguration.framework in Frameworks */,
-				D284BE670ADD80740027CCDF /* IOKit.framework in Frameworks */,
-				D284BE680ADD80740027CCDF /* Security.framework in Frameworks */,
-				219D5542149ED645004464AE /* libxml2.2.dylib in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BE8C0ADD80800027CCDF /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				D284BE8D0ADD80800027CCDF /* CoreFoundation.framework in Frameworks */,
-				D284BE8E0ADD80800027CCDF /* SystemConfiguration.framework in Frameworks */,
-				D284BE8F0ADD80800027CCDF /* IOKit.framework in Frameworks */,
-				D284BE900ADD80800027CCDF /* Security.framework in Frameworks */,
-				219D5543149ED645004464AE /* libxml2.2.dylib in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEA90ADD80920027CCDF /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEB80ADD809A0027CCDF /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				D284BEB90ADD809A0027CCDF /* JavaVM.framework in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BECE0ADD80A20027CCDF /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				D284BECF0ADD80A20027CCDF /* CoreFoundation.framework in Frameworks */,
-				D284BED00ADD80A20027CCDF /* SystemConfiguration.framework in Frameworks */,
-				D284BED10ADD80A20027CCDF /* IOKit.framework in Frameworks */,
-				D284BED20ADD80A20027CCDF /* Security.framework in Frameworks */,
-				2E8165F90C59838100485EB2 /* libipsec.dylib in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEDF0ADD80A70027CCDF /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				D284BEE00ADD80A70027CCDF /* 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;
-			files = (
-				D284BF020ADD80B00027CCDF /* SystemConfiguration.framework in Frameworks */,
-				D284BF030ADD80B00027CCDF /* Security.framework in Frameworks */,
-				D284BF040ADD80B00027CCDF /* Cocoa.framework in Frameworks */,
-				D284BF050ADD80B00027CCDF /* PreferencePanes.framework in Frameworks */,
-				D284BF060ADD80B00027CCDF /* CoreFoundation.framework in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		FFA572360AF18F1C0055A0F1 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		FFA572420AF18F450055A0F1 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		FFB765820AEED9C700583A2C /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
-		08FB7794FE84155DC02AAC07 /* mDNSResponder */ = {
-			isa = PBXGroup;
-			children = (
-				08FB7795FE84155DC02AAC07 /* mDNS Server Sources */,
-				6575FC1F022EB78C00000109 /* Command-Line Clients */,
-				213FB20912028902002B3A08 /* Bonjour Events Plugin */,
-				6575FBFE022EAFA800000109 /* MIG files */,
-				DB2CC4420662DCE500335AB3 /* Java Support */,
-				FFFB0DA407B43BED00B88D48 /* PreferencePane */,
-				08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
-				19C28FBDFE9D53C911CA2CBB /* Products */,
-			);
-			name = mDNSResponder;
-			sourceTree = "<group>";
-		};
-		08FB7795FE84155DC02AAC07 /* mDNS Server Sources */ = {
-			isa = PBXGroup;
-			children = (
-				216D9ACD1720C9F5008066E1 /* VPNService.c */,
-				2120ABD416B71614007089B6 /* CUPolicy.c */,
-				84C5B338166553A000C324A8 /* dns_services.h */,
-				72FB545A166D5F960090B2D9 /* dnsctl.c */,
-				84C5B339166553AF00C324A8 /* dns_services.c */,
-				848DA5D516547F7200D2E8B4 /* dns_xpc.h */,
-				848DA5C9165477EB00D2E8B4 /* xpc_services.h */,
-				848DA5C6165477E000D2E8B4 /* xpc_services.c */,
-				21070E5D16486B9000A69507 /* DNSSECSupport.c */,
-				21070E5E16486B9000A69507 /* DNSSECSupport.h */,
-				21DD8FBD161E9A250033C8F8 /* anonymous.c */,
-				21DD8FBE161E9A250033C8F8 /* anonymous.h */,
-				2127A47515C3C7B900A857FC /* nsec3.c */,
-				2127A47615C3C7B900A857FC /* nsec3.h */,
-				8418673C15AB8B8000BB7F70 /* mDNSResponderLogging.mobileconfig */,
-				8418673A15AB8B6900BB7F70 /* com.apple.networking.mDNSResponder */,
-				21DED43415702C0F0060B6B9 /* DNSProxySupport.c */,
-				218E8E4F156D8C0300720DA0 /* dnsproxy.c */,
-				218E8E50156D8C0300720DA0 /* dnsproxy.h */,
-				213BDC6C147319F400000896 /* dnssec.c */,
-				2124FA321471E9DE0021D7BB /* nsec.c */,
-				2124FA2F1471E9B50021D7BB /* dnssec.h */,
-				2124FA2B1471E98C0021D7BB /* nsec.h */,
-				21A57F51145B2B1400939099 /* CryptoSupport.c */,
-				21A57F52145B2B1400939099 /* CryptoSupport.h */,
-				21A57F4A145B2AE100939099 /* CryptoAlg.c */,
-				21A57F4B145B2AE100939099 /* CryptoAlg.h */,
-				4ADB5F230F6AB9F400B95BF3 /* helper-entitlements.plist */,
-				4A2E69DD0F5475A3004A87B0 /* uds_daemon.h */,
-				4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */,
-				2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */,
-				2E35528F0C3A95C100CA1CB7 /* helper-error.h */,
-				2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */,
-				2EDC5E720C39EA640092701B /* helper-server.h */,
-				2E96A5250C39BE480087C4D2 /* helper.h */,
-				2E0405F40C3195F700F13B59 /* helper.c */,
-				2E0406CA0C31E9AD00F13B59 /* helper-main.c */,
-				4A8202510C56C36500DDFD48 /* ipsec_strerror.h */,
-				4A8202520C56C36500DDFD48 /* libpfkey.h */,
-				4A8202530C56C36600DDFD48 /* pfkey.c */,
-				7FC8F9D406D14E66007E879D /* LegacyNATTraversal.c */,
-				7F461DB5062DBF2900672BF3 /* DNSDigest.c */,
-				F525E72804AA167501F1CF4D /* uds_daemon.c */,
-				F5E11B5A04A28126019798ED /* dnssd_ipc.c */,
-				F5E11B5B04A28126019798ED /* dnssd_ipc.h */,
-				6575FBEC022EAF7200000109 /* daemon.c */,
-				6575FBE9022EAF5A00000109 /* mDNS.c */,
-				6575FBEB022EAF7200000109 /* mDNSMacOSX.c */,
-				654BE64F02B63B93000001D1 /* mDNSEmbeddedAPI.h */,
-				654BE65002B63B93000001D1 /* mDNSDebug.h */,
-				DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */,
-				000753D303367C1C0CCA2C71 /* mDNSMacOSX.h */,
-				DBAAFE2C057E8F660085CAD0 /* GenLinkedList.c */,
-				FFCB6D73075D539900B8AF62 /* PlatformCommon.c */,
-				FF1C919D07021D77001048AB /* dns-sd.1 */,
-				FF485D5105632E0000130380 /* mDNSResponder.8 */,
-				FFF4F63A06CFE4DD00459EFD /* dnsextd.8 */,
-				FFFF8F800C3307AC00722979 /* dnsextd.conf */,
-				FF85880B0BD599F40080D89F /* mDNSResponder.sb */,
-				4A7B9E7C14FDA19F00B84CC1 /* mDNSResponder.txt */,
-				4A7B9E7E14FDA1BB00B84CC1 /* mDNSResponder.plist */,
-				7F18A9F60587CEF6001880B3 /* DNSCommon.c */,
-				7F18A9F70587CEF6001880B3 /* uDNS.c */,
-				FF25794606C9A8BF00376F7B /* dnsextd.c */,
-				FF13FFEA0A5DA44A00897C81 /* dnsextd_lexer.l */,
-				FF13FFEC0A5DA45500897C81 /* dnsextd_parser.y */,
-				FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */,
-				FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */,
-				FFA572600AF1908D0055A0F1 /* DNSServiceDiscovery.h */,
-				FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */,
-				FFA572630AF190C20055A0F1 /* dns_sd.h */,
-				4BD2B638134FE09F002B96D5 /* P2PPacketFilter.c */,
-				4BD2B639134FE09F002B96D5 /* P2PPacketFilter.h */,
-			);
-			name = "mDNS Server Sources";
-			sourceTree = "<group>";
-		};
-		08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
-			isa = PBXGroup;
-			children = (
-				219D5541149ED645004464AE /* libxml2.2.dylib */,
-				4A3600DF0F34F8CD00453EFB /* DeviceToDeviceManager.framework */,
-				2E8165F60C59835F00485EB2 /* libipsec.dylib */,
-				65713D46025A293200000109 /* SystemConfiguration.framework */,
-				2E0406140C3197CB00F13B59 /* libbsm.dylib */,
-				7F869685066EE02400D2A2DC /* Security.framework */,
-				FFFB0DB407B43D2700B88D48 /* Foundation.framework */,
-				09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */,
-				00CA213D02786FC30CCA2C71 /* IOKit.framework */,
-				DB2CC4680662DFF500335AB3 /* JavaVM.framework */,
-				FF2609FA07B4433800CE10E5 /* Cocoa.framework */,
-				FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */,
-				21F432971134AA6800581B69 /* WebFilterDNS.framework */,
-			);
-			name = "External Frameworks and Libraries";
-			sourceTree = "<group>";
-		};
-		19C28FBDFE9D53C911CA2CBB /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				D284C04D0ADD95D30027CCDF /* Info-PreferencePane.plist */,
-				D284BE730ADD80740027CCDF /* mDNSResponder */,
-				D284BE950ADD80800027CCDF /* mDNSResponder.debug */,
-				D284BEB00ADD80920027CCDF /* dns-sd */,
-				D284BEBE0ADD809A0027CCDF /* libjdns_sd.jnilib */,
-				D284BED90ADD80A20027CCDF /* dnsextd */,
-				D284BEE80ADD80A70027CCDF /* ddnswriteconfig */,
-				D284BF0C0ADD80B00027CCDF /* Bonjour.prefPane */,
-				FFB765840AEED9C700583A2C /* libsystem_dnssd.dylib */,
-				FFA572390AF18F1C0055A0F1 /* libsystem_dnssd_debug.dylib */,
-				FFA572450AF18F450055A0F1 /* libsystem_dnssd_profile.dylib */,
-				2E0405F00C31955500F13B59 /* mDNSResponderHelper */,
-				213FB21812028A7A002B3A08 /* BonjourEvents.plugin */,
-				2141DD1D123FFCDB0086D23E /* libdns_sd.a */,
-				2141DD24123FFD0F0086D23E /* libdns_sd_debug.a */,
-				2141DD2A123FFD2C0086D23E /* libdns_sd_profile.a */,
-				84C5B3351665529800C324A8 /* libdns_services.dylib */,
-				72FB545F166D5FB00090B2D9 /* dnsctl */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		213FB20912028902002B3A08 /* Bonjour Events Plugin */ = {
-			isa = PBXGroup;
-			children = (
-				213FB22C12028B53002B3A08 /* BonjourEvents.c */,
-				213FB22D12028B53002B3A08 /* BonjourEvents-Info.plist */,
-			);
-			name = "Bonjour Events Plugin";
-			sourceTree = "<group>";
-		};
-		6575FBFE022EAFA800000109 /* MIG files */ = {
-			isa = PBXGroup;
-			children = (
-				2E0405EB0C3190DC00F13B59 /* helpermsg.defs */,
-				6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */,
-				6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */,
-				6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */,
-			);
-			name = "MIG files";
-			sourceTree = "<group>";
-		};
-		6575FC1F022EB78C00000109 /* Command-Line Clients */ = {
-			isa = PBXGroup;
-			children = (
-				6575FC20022EB7AA00000109 /* SamplemDNSClient.c */,
-				FF1C919F07021E3F001048AB /* dns-sd.c */,
-				FF5852100DD27BD300862BDF /* ClientCommon.c */,
-			);
-			name = "Command-Line Clients";
-			sourceTree = "<group>";
-		};
-		DB2CC4420662DCE500335AB3 /* Java Support */ = {
-			isa = PBXGroup;
-			children = (
-				DB2CC4430662DD1100335AB3 /* BaseListener.java */,
-				DB2CC4440662DD1100335AB3 /* BrowseListener.java */,
-				DB2CC4450662DD1100335AB3 /* DNSRecord.java */,
-				DB2CC4460662DD1100335AB3 /* DNSSD.java */,
-				DB2CC4470662DD1100335AB3 /* DNSSDException.java */,
-				DB2CC4480662DD1100335AB3 /* DNSSDRegistration.java */,
-				DB2CC4490662DD1100335AB3 /* DNSSDService.java */,
-				DB2CC44A0662DD1100335AB3 /* DomainListener.java */,
-				DB2CC44B0662DD1100335AB3 /* JNISupport.c */,
-				DB2CC44C0662DD1100335AB3 /* QueryListener.java */,
-				DB2CC44D0662DD1100335AB3 /* RegisterListener.java */,
-				DB2CC44E0662DD1100335AB3 /* ResolveListener.java */,
-				DB2CC44F0662DD1100335AB3 /* TXTRecord.java */,
-				FF2C5FB00A48B8680066DA11 /* DNSSDRecordRegistrar.java */,
-				FF2C5FB20A48B86E0066DA11 /* RegisterRecordListener.java */,
-			);
-			name = "Java Support";
-			sourceTree = "<group>";
-		};
-		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 */,
-			);
-			name = Resources;
-			sourceTree = "<group>";
-		};
-		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 */,
-				FF260A2307B4463400CE10E5 /* Resources */,
-			);
-			path = PreferencePane;
-			sourceTree = SOURCE_ROOT;
-		};
-/* End PBXGroup section */
-
-/* Begin PBXHeadersBuildPhase section */
-		2141DD19123FFCDB0086D23E /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		2141DD20123FFD0F0086D23E /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		2141DD26123FFD2C0086D23E /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		2EC8F8ED0C39CCCA003C9C48 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				2EC8F8EC0C39CCAC003C9C48 /* helper.h in Headers */,
-				2EDC5E730C39EA640092701B /* helper-server.h in Headers */,
-				2E3552920C3A95C100CA1CB7 /* helper-error.h in Headers */,
-				2ECC11A80C4FEC3800CB1885 /* helpermsg-types.h in Headers */,
-				2E8165E80C5980E300485EB2 /* libpfkey.h in Headers */,
-				2E8165EA0C5980F700485EB2 /* ipsec_strerror.h in Headers */,
-				4BD2B63B134FE09F002B96D5 /* P2PPacketFilter.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		84C5B3331665529800C324A8 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				84C5B33D166553F900C324A8 /* dns_services.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BE520ADD80740027CCDF /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				D284BE530ADD80740027CCDF /* DNSServiceDiscoveryDefines.h in Headers */,
-				D284BE540ADD80740027CCDF /* dnssd_ipc.h in Headers */,
-				2E96A5260C39BE480087C4D2 /* helper.h in Headers */,
-				2EDC5E750C39EA640092701B /* helper-server.h in Headers */,
-				2E3552900C3A95C100CA1CB7 /* helper-error.h in Headers */,
-				2ECC11A60C4FEC3800CB1885 /* helpermsg-types.h in Headers */,
-				21A57F4E145B2AE100939099 /* CryptoAlg.h in Headers */,
-				21A57F55145B2B1400939099 /* CryptoSupport.h in Headers */,
-				2124FA2C1471E98C0021D7BB /* nsec.h in Headers */,
-				2124FA301471E9B50021D7BB /* dnssec.h in Headers */,
-				218E8E53156D8C0300720DA0 /* dnsproxy.h in Headers */,
-				2127A47915C3C7B900A857FC /* nsec3.h in Headers */,
-				21DD8FC1161E9A250033C8F8 /* anonymous.h in Headers */,
-				21070E6116486B9000A69507 /* DNSSECSupport.h in Headers */,
-				848DA5CA165477EB00D2E8B4 /* xpc_services.h in Headers */,
-				848DA5D616547F7200D2E8B4 /* dns_xpc.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BE770ADD80800027CCDF /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				D284BE780ADD80800027CCDF /* DNSServiceDiscoveryDefines.h in Headers */,
-				D284BE790ADD80800027CCDF /* dnssd_ipc.h in Headers */,
-				D284BE7A0ADD80800027CCDF /* mDNSEmbeddedAPI.h in Headers */,
-				D284BE7B0ADD80800027CCDF /* mDNSDebug.h in Headers */,
-				D284BE7C0ADD80800027CCDF /* mDNSMacOSX.h in Headers */,
-				2E96A5270C39BE480087C4D2 /* helper.h in Headers */,
-				2EDC5E740C39EA640092701B /* helper-server.h in Headers */,
-				2E3552910C3A95C100CA1CB7 /* helper-error.h in Headers */,
-				2ECC11A70C4FEC3800CB1885 /* helpermsg-types.h in Headers */,
-				21A57F4F145B2AE100939099 /* CryptoAlg.h in Headers */,
-				21A57F56145B2B1400939099 /* CryptoSupport.h in Headers */,
-				2124FA2D1471E98C0021D7BB /* nsec.h in Headers */,
-				2124FA311471E9B50021D7BB /* dnssec.h in Headers */,
-				218E8E54156D8C0300720DA0 /* dnsproxy.h in Headers */,
-				2127A47A15C3C7B900A857FC /* nsec3.h in Headers */,
-				21DD8FC2161E9A250033C8F8 /* anonymous.h in Headers */,
-				21070E6216486B9000A69507 /* DNSSECSupport.h in Headers */,
-				848DA5CB165477EB00D2E8B4 /* xpc_services.h in Headers */,
-				848DA5D716547F7200D2E8B4 /* dns_xpc.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEA60ADD80920027CCDF /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEB50ADD809A0027CCDF /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEC20ADD80A20027CCDF /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				2E35529D0C3A9E7600CA1CB7 /* helper-error.h in Headers */,
-				2E35529F0C3A9E7600CA1CB7 /* helper.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEDC0ADD80A70027CCDF /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEED0ADD80B00027CCDF /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		FFA572310AF18F1C0055A0F1 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		FFA5723D0AF18F450055A0F1 /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		FFB765800AEED9C700583A2C /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXHeadersBuildPhase section */
-
-/* Begin PBXLegacyTarget section */
-		4AE471670EAFF81900A6C5AD /* dns_sd.jar */ = {
-			isa = PBXLegacyTarget;
-			buildArgumentsString = "-f ${SRCROOT}/../mDNSPosix/Makefile OBJDIR=${CONFIGURATION_TEMP_DIR}/dns_sd.jar.build BUILDDIR=${BUILT_PRODUCTS_DIR} SHAREDDIR=${SRCROOT}/../mDNSShared os=x JavaForXcode_$(ACTION)";
-			buildConfigurationList = 4AE471770EAFF84000A6C5AD /* Build configuration list for PBXLegacyTarget "dns_sd.jar" */;
-			buildPhases = (
-			);
-			buildToolPath = /usr/bin/make;
-			buildWorkingDirectory = "";
-			comments = "Multiplatform .jar file that implements Java interface to DNS-SD";
-			dependencies = (
-			);
-			name = dns_sd.jar;
-			passBuildSettingsInEnvironment = 1;
-			productName = dns_sd.jar;
-		};
-/* End PBXLegacyTarget section */
-
-/* Begin PBXNativeTarget section */
-		213FB21712028A7A002B3A08 /* BonjourEvents */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 213FB21B12028A7C002B3A08 /* Build configuration list for PBXNativeTarget "BonjourEvents" */;
-			buildPhases = (
-				213FB21412028A7A002B3A08 /* Resources */,
-				213FB21512028A7A002B3A08 /* Sources */,
-				213FB21612028A7A002B3A08 /* Frameworks */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = BonjourEvents;
-			productName = BonjourEvents;
-			productReference = 213FB21812028A7A002B3A08 /* BonjourEvents.plugin */;
-			productType = "com.apple.product-type.bundle";
-		};
-		2141DD1C123FFCDB0086D23E /* libdns_sd_static */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 2141DD1F123FFCF90086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_static" */;
-			buildPhases = (
-				2141DD19123FFCDB0086D23E /* Headers */,
-				2141DD1A123FFCDB0086D23E /* Sources */,
-				2141DD1B123FFCDB0086D23E /* Frameworks */,
-				2130256B12400DE600AC839F /* ShellScript */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = libdns_sd_static;
-			productName = libdns_sd_static;
-			productReference = 2141DD1D123FFCDB0086D23E /* libdns_sd.a */;
-			productType = "com.apple.product-type.library.static";
-		};
-		2141DD23123FFD0F0086D23E /* libdns_sd_debug_static */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 2141DD35123FFD3B0086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_debug_static" */;
-			buildPhases = (
-				2141DD20123FFD0F0086D23E /* Headers */,
-				2141DD21123FFD0F0086D23E /* Sources */,
-				2141DD22123FFD0F0086D23E /* Frameworks */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = libdns_sd_debug_static;
-			productName = libdns_sd_debug_static;
-			productReference = 2141DD24123FFD0F0086D23E /* libdns_sd_debug.a */;
-			productType = "com.apple.product-type.library.static";
-		};
-		2141DD29123FFD2C0086D23E /* libdns_sd_profile_static */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 2141DD36123FFD3B0086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_profile_static" */;
-			buildPhases = (
-				2141DD26123FFD2C0086D23E /* Headers */,
-				2141DD27123FFD2C0086D23E /* Sources */,
-				2141DD28123FFD2C0086D23E /* Frameworks */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = libdns_sd_profile_static;
-			productName = libdns_sd_profile_static;
-			productReference = 2141DD2A123FFD2C0086D23E /* libdns_sd_profile.a */;
-			productType = "com.apple.product-type.library.static";
-		};
-		2E0405EF0C31955500F13B59 /* mDNSResponderHelper */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 2E0405F30C31956600F13B59 /* Build configuration list for PBXNativeTarget "mDNSResponderHelper" */;
-			buildPhases = (
-				030BBED60CE11EEC00472F0C /* ShellScript */,
-				2EC8F8ED0C39CCCA003C9C48 /* Headers */,
-				2E0405ED0C31955500F13B59 /* Sources */,
-				2E0405EE0C31955500F13B59 /* Frameworks */,
-				4AAE0C5A0C68E6EC003882A5 /* CopyFiles */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = mDNSResponderHelper;
-			productName = mDNSResponderHelper;
-			productReference = 2E0405F00C31955500F13B59 /* mDNSResponderHelper */;
-			productType = "com.apple.product-type.tool";
-		};
-		72FB545E166D5FB00090B2D9 /* dnsctl */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 72FB5465166D5FB00090B2D9 /* Build configuration list for PBXNativeTarget "dnsctl" */;
-			buildPhases = (
-				72FB545B166D5FB00090B2D9 /* Sources */,
-				72FB545C166D5FB00090B2D9 /* Frameworks */,
-				72FB545D166D5FB00090B2D9 /* CopyFiles */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = dnsctl;
-			productName = dnsctl;
-			productReference = 72FB545F166D5FB00090B2D9 /* dnsctl */;
-			productType = "com.apple.product-type.tool";
-		};
-		84C5B3341665529800C324A8 /* dns_services */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 84C5B3361665529800C324A8 /* Build configuration list for PBXNativeTarget "dns_services" */;
-			buildPhases = (
-				84C5B3311665529800C324A8 /* Sources */,
-				84C5B3321665529800C324A8 /* Frameworks */,
-				84C5B3331665529800C324A8 /* Headers */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = dns_services;
-			productName = dns_services;
-			productReference = 84C5B3351665529800C324A8 /* libdns_services.dylib */;
-			productType = "com.apple.product-type.library.dynamic";
-		};
-		D284BE500ADD80740027CCDF /* mDNSResponder */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = D284BE6D0ADD80740027CCDF /* Build configuration list for PBXNativeTarget "mDNSResponder" */;
-			buildPhases = (
-				D284BE510ADD80740027CCDF /* ShellScript */,
-				D284BE520ADD80740027CCDF /* Headers */,
-				D284BE550ADD80740027CCDF /* Sources */,
-				D284BE640ADD80740027CCDF /* Frameworks */,
-				D284BE690ADD80740027CCDF /* Rez */,
-				D284BE6A0ADD80740027CCDF /* CopyFiles */,
-				4A7B9E7F14FDA21B00B84CC1 /* CopyFiles */,
-				4A7B9E8114FDA25500B84CC1 /* CopyFiles */,
-				D284BE6C0ADD80740027CCDF /* ShellScript */,
-				8418673D15AB8BFF00BB7F70 /* CopyFiles */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = mDNSResponder;
-			productInstallPath = "${HOME}/bin";
-			productName = mDNSResponder;
-			productReference = D284BE730ADD80740027CCDF /* mDNSResponder */;
-			productType = "com.apple.product-type.tool";
-		};
-		D284BE750ADD80800027CCDF /* mDNSResponder debug */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = D284BE920ADD80800027CCDF /* Build configuration list for PBXNativeTarget "mDNSResponder debug" */;
-			buildPhases = (
-				D284BE760ADD80800027CCDF /* ShellScript */,
-				D284BE770ADD80800027CCDF /* Headers */,
-				D284BE7D0ADD80800027CCDF /* Sources */,
-				D284BE8C0ADD80800027CCDF /* Frameworks */,
-				D284BE910ADD80800027CCDF /* Rez */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = "mDNSResponder debug";
-			productName = mDNSResponder;
-			productReference = D284BE950ADD80800027CCDF /* mDNSResponder.debug */;
-			productType = "com.apple.product-type.tool";
-		};
-		D284BEA50ADD80920027CCDF /* dns-sd tool */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = D284BEAD0ADD80920027CCDF /* Build configuration list for PBXNativeTarget "dns-sd tool" */;
-			buildPhases = (
-				D284BEA60ADD80920027CCDF /* Headers */,
-				D284BEA70ADD80920027CCDF /* Sources */,
-				D284BEA90ADD80920027CCDF /* Frameworks */,
-				D284BEAA0ADD80920027CCDF /* Rez */,
-				D284BEAB0ADD80920027CCDF /* CopyFiles */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = "dns-sd tool";
-			productInstallPath = /usr/bin;
-			productName = "dns-sd command-line tool";
-			productReference = D284BEB00ADD80920027CCDF /* dns-sd */;
-			productType = "com.apple.product-type.tool";
-		};
-		D284BEB20ADD809A0027CCDF /* libjdns_sd.jnilib */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = D284BEBB0ADD809A0027CCDF /* Build configuration list for PBXNativeTarget "libjdns_sd.jnilib" */;
-			buildPhases = (
-				D284BEB50ADD809A0027CCDF /* Headers */,
-				D284BEB60ADD809A0027CCDF /* Sources */,
-				D284BEB80ADD809A0027CCDF /* Frameworks */,
-				D284BEBA0ADD809A0027CCDF /* Rez */,
-			);
-			buildRules = (
-			);
-			comments = "Platform-specific JNI library that bridges dns_sd.jar to <dns_sd.h>.";
-			dependencies = (
-				4AE4716A0EAFF83800A6C5AD /* PBXTargetDependency */,
-			);
-			name = libjdns_sd.jnilib;
-			productInstallPath = /usr/lib/java;
-			productName = libjdns_sd.jnilib;
-			productReference = D284BEBE0ADD809A0027CCDF /* libjdns_sd.jnilib */;
-			productType = "com.apple.product-type.library.dynamic";
-		};
-		D284BEBF0ADD80A20027CCDF /* dnsextd */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = D284BED60ADD80A20027CCDF /* Build configuration list for PBXNativeTarget "dnsextd" */;
-			buildPhases = (
-				D284BEC20ADD80A20027CCDF /* Headers */,
-				4A4EE3A413CB8E82005C624B /* Build yacc file into derived source files */,
-				D284BEC40ADD80A20027CCDF /* Sources */,
-				D284BECE0ADD80A20027CCDF /* Frameworks */,
-				D284BED40ADD80A20027CCDF /* CopyFiles */,
-				FFFF8F770C32F0FD00722979 /* CopyFiles */,
-				FF37FAAD0BC581780044A5CF /* ShellScript */,
-			);
-			buildRules = (
-				D284BFB80ADD8E510027CCDF /* PBXBuildRule */,
-				D284BF750ADD850C0027CCDF /* PBXBuildRule */,
-			);
-			dependencies = (
-			);
-			name = dnsextd;
-			productInstallPath = /usr/sbin;
-			productName = mDNSResponder;
-			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 */,
-				D284BEE40ADD80A70027CCDF /* Rez */,
-			);
-			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" */;
-			buildPhases = (
-				D284BEED0ADD80B00027CCDF /* Headers */,
-				D284BEEE0ADD80B00027CCDF /* Resources */,
-				D284BEFD0ADD80B00027CCDF /* Sources */,
-				D284BF010ADD80B00027CCDF /* Frameworks */,
-				D284BF070ADD80B00027CCDF /* Rez */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				FFAE66F9105F0CF100162116 /* PBXTargetDependency */,
-			);
-			name = PreferencePane;
-			productInstallPath = "${SYSTEM_LIBRARY_DIR}/PreferencePanes";
-			productName = PreferencePane;
-			productReference = D284BF0C0ADD80B00027CCDF /* Bonjour.prefPane */;
-			productType = "com.apple.product-type.bundle";
-		};
-		FFA572300AF18F1C0055A0F1 /* libdns_sd_debug_dynamic */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = FFA572370AF18F1C0055A0F1 /* Build configuration list for PBXNativeTarget "libdns_sd_debug_dynamic" */;
-			buildPhases = (
-				FFA572310AF18F1C0055A0F1 /* Headers */,
-				FFA572320AF18F1C0055A0F1 /* Sources */,
-				FFA572360AF18F1C0055A0F1 /* Frameworks */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = libdns_sd_debug_dynamic;
-			productName = libdns_sd.dylib;
-			productReference = FFA572390AF18F1C0055A0F1 /* libsystem_dnssd_debug.dylib */;
-			productType = "com.apple.product-type.library.dynamic";
-		};
-		FFA5723C0AF18F450055A0F1 /* libdns_sd_profile_dynamic */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = FFA572430AF18F450055A0F1 /* Build configuration list for PBXNativeTarget "libdns_sd_profile_dynamic" */;
-			buildPhases = (
-				FFA5723D0AF18F450055A0F1 /* Headers */,
-				FFA5723E0AF18F450055A0F1 /* Sources */,
-				FFA572420AF18F450055A0F1 /* Frameworks */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = libdns_sd_profile_dynamic;
-			productName = libdns_sd.dylib;
-			productReference = FFA572450AF18F450055A0F1 /* libsystem_dnssd_profile.dylib */;
-			productType = "com.apple.product-type.library.dynamic";
-		};
-		FFB765830AEED9C700583A2C /* libdns_sd_dynamic */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = FFB765890AEED9FB00583A2C /* Build configuration list for PBXNativeTarget "libdns_sd_dynamic" */;
-			buildPhases = (
-				FFB765800AEED9C700583A2C /* Headers */,
-				FFB765810AEED9C700583A2C /* Sources */,
-				FFB765820AEED9C700583A2C /* Frameworks */,
-				21DE714D115831CB00DD4BD1 /* ShellScript */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = libdns_sd_dynamic;
-			productName = libdns_sd.dylib;
-			productReference = FFB765840AEED9C700583A2C /* libsystem_dnssd.dylib */;
-			productType = "com.apple.product-type.library.dynamic";
-		};
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
-		08FB7793FE84155DC02AAC07 /* Project object */ = {
-			isa = PBXProject;
-			attributes = {
-			};
-			buildConfigurationList = D284BE2B0ADD78180027CCDF /* Build configuration list for PBXProject "mDNSResponder" */;
-			compatibilityVersion = "Xcode 3.1";
-			developmentRegion = English;
-			hasScannedForEncodings = 1;
-			knownRegions = (
-				English,
-				Japanese,
-				French,
-				German,
-			);
-			mainGroup = 08FB7794FE84155DC02AAC07 /* mDNSResponder */;
-			projectDirPath = "";
-			projectRoot = "";
-			targets = (
-				00AD62BB032D7A0C0CCA2C71 /* Build More */,
-				03067D640C83A3700022BE1F /* Build Some */,
-				FFB7657B0AEED96B00583A2C /* Build All */,
-				D284BE500ADD80740027CCDF /* mDNSResponder */,
-				D284BE750ADD80800027CCDF /* mDNSResponder debug */,
-				2E0405EF0C31955500F13B59 /* mDNSResponderHelper */,
-				D284BEA50ADD80920027CCDF /* dns-sd tool */,
-				4AE471670EAFF81900A6C5AD /* dns_sd.jar */,
-				D284BEB20ADD809A0027CCDF /* libjdns_sd.jnilib */,
-				D284BEBF0ADD80A20027CCDF /* dnsextd */,
-				D284BEDB0ADD80A70027CCDF /* ddnswriteconfig */,
-				D284BEEA0ADD80B00027CCDF /* PreferencePane */,
-				FFB765830AEED9C700583A2C /* libdns_sd_dynamic */,
-				FFA572300AF18F1C0055A0F1 /* libdns_sd_debug_dynamic */,
-				FFA5723C0AF18F450055A0F1 /* libdns_sd_profile_dynamic */,
-				FFA572650AF190F10055A0F1 /* SystemLibrariesDynamic */,
-				213FB21712028A7A002B3A08 /* BonjourEvents */,
-				2141DCF8123FFB5D0086D23E /* SystemLibraries */,
-				2141DD0B123FFC7F0086D23E /* SystemLibrariesStatic */,
-				2141DD1C123FFCDB0086D23E /* libdns_sd_static */,
-				2141DD23123FFD0F0086D23E /* libdns_sd_debug_static */,
-				2141DD29123FFD2C0086D23E /* libdns_sd_profile_static */,
-				84C5B3341665529800C324A8 /* dns_services */,
-				72FB545E166D5FB00090B2D9 /* dnsctl */,
-			);
-		};
-/* End PBXProject section */
-
-/* Begin PBXResourcesBuildPhase section */
-		213FB21412028A7A002B3A08 /* 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;
-		};
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXRezBuildPhase section */
-		D284BE690ADD80740027CCDF /* Rez */ = {
-			isa = PBXRezBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BE910ADD80800027CCDF /* Rez */ = {
-			isa = PBXRezBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEAA0ADD80920027CCDF /* Rez */ = {
-			isa = PBXRezBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEBA0ADD809A0027CCDF /* Rez */ = {
-			isa = PBXRezBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEE40ADD80A70027CCDF /* Rez */ = {
-			isa = PBXRezBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BF070ADD80B00027CCDF /* Rez */ = {
-			isa = PBXRezBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXRezBuildPhase section */
-
-/* Begin PBXShellScriptBuildPhase section */
-		030BBED60CE11EEC00472F0C /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-			);
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "if [ -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";
-		};
-		1F7B473C12B82BFD00868AEF /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-			);
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/bash;
-			shellScript = "# check if we're building for the simulator and patch the \"id\" of the library (as reported by otool -D) to\n# be just /usr/lib/system/libsystem_sim_dnssd.dylib etc. Also remove the usr directory as it is not needed\n# for simulator\nif [ \"${RC_ProjectName%_Sim}\" != \"${RC_ProjectName}\" ] ; then\n\tif [ -d ${DSTROOT}${SDKROOT}/usr/lib/system ] ; then\n\t\tfor lib in ${DSTROOT}${SDKROOT}/usr/lib/system/*.dylib ; do\n\t\t\tinstall_name_tool -id \"${lib#${DSTROOT}${SDKROOT}}\" \"${lib}\"\n\t\tdone\n\tfi\n\trm -rf $DSTROOT/usr\nfi\n";
-		};
-		2130256B12400DE600AC839F /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 8;
-			files = (
-			);
-			inputPaths = (
-			);
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 1;
-			shellPath = /bin/sh;
-			shellScript = "#if we are building for simulator, change the installation path\nif [ \"${RC_ProjectName%_Sim}\" != \"${RC_ProjectName}\" ] ; then\n\tDSTROOT=${DSTROOT}${SDKROOT}\nfi\nmkdir -p \"$DSTROOT/usr/include\"\nsed 's/\\(^#define _DNS_SD_LIBDISPATCH \\)0$/\\1 1/' \"$SRCROOT/../mDNSShared/dns_sd.h\" > \"$DSTROOT/usr/include/dns_sd.h\"";
-		};
-		21DE714D115831CB00DD4BD1 /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 8;
-			files = (
-			);
-			inputPaths = (
-			);
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 1;
-			shellPath = /bin/sh;
-			shellScript = "#if we are building for simulator, change the installation path\nif [ \"${RC_ProjectName%_Sim}\" != \"${RC_ProjectName}\" ] ; then\n\tDSTROOT=${DSTROOT}${SDKROOT}\nfi\nmkdir -p \"$DSTROOT/usr/include\"\nsed 's/\\(^#define _DNS_SD_LIBDISPATCH \\)0$/\\1 1/' \"$SRCROOT/../mDNSShared/dns_sd.h\" > \"$DSTROOT/usr/include/dns_sd.h\"";
-		};
-		4A4EE3A413CB8E82005C624B /* Build yacc file into derived source files */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-				"$(SRCROOT)/../mDNSShared/dnsextd_parser.y",
-			);
-			name = "Build yacc file into derived source files";
-			outputPaths = (
-				"$(DERIVED_FILE_DIR)/dnsextd_parser.c",
-				"$(DERIVED_FILE_DIR)/dnsextd_parser.h",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "/usr/bin/bison -o ${SCRIPT_OUTPUT_FILE_0} -d ${SCRIPT_INPUT_FILE_0}";
-		};
-		D284BE510ADD80740027CCDF /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "if [ -e \"${SDKROOT}/usr/local/include/dnsinfo.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.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}/libdnsinfo.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n\nif [ -e \"${SDKROOT}/usr/include/sandbox.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nelse\necho \"#define MDNS_NO_SANDBOX 1\" > \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nfi\n\nif [ -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}/System/Library/Frameworks/IOKit.framework/PrivateHeaders/pwr_mgt/IOPMLibPrivate.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/IOKit\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt\"\ntouch \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt/IOPMLibPrivate.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/PrivateFrameworks/DeviceToDeviceManager.framework/Headers/DeviceToDeviceManager.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager\"\necho \"#define NO_D2D 1\" > \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager/DeviceToDeviceManager.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/PrivateFrameworks/WebFilterDNS.framework/Headers/WebFilterDNS.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS\"\necho \"#define NO_WCF 1\" > \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS/WebFilterDNS.h\"\nfi\n\nif [ -e \"${SDKROOT}/usr/local/include/AWACS.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/AWACS.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libAWACS.a\"\nelse\necho \"#define NO_AWACS 1\" > \"${CONFIGURATION_T!
 EMP_DIR}/AWACS.h\"\ntouch \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libAWACS.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\"\nfi\n";
-		};
-		D284BE6C0ADD80740027CCDF /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 8;
-			files = (
-			);
-			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}\" ] ; then\n  SANDBOXDST=\"${DSTROOT}/usr/local/share/sandbox/profiles/embedded/builtin\"\nelse\n  SANDBOXDST=\"${DSTROOT}/usr/share/sandbox\"\nfi\n(umask 022; mkdir -p -m 0755 \"$SANDBOXDST\")\ncp \"${SRCROOT}/mDNSResponder.sb\" \"${SANDBOXDST}/mDNSResponder.sb\"\n";
-		};
-		D284BE760ADD80800027CCDF /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "if [ -e \"${SDKROOT}/usr/local/include/dnsinfo.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.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}/libdnsinfo.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n\nif [ -e \"${SDKROOT}/usr/include/sandbox.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nelse\necho \"#define MDNS_NO_SANDBOX 1\" > \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nfi\n\nif [ -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}/System/Library/Frameworks/IOKit.framework/PrivateHeaders/pwr_mgt/IOPMLibPrivate.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/IOKit\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt\"\ntouch \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt/IOPMLibPrivate.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/PrivateFrameworks/DeviceToDeviceManager.framework/Headers/DeviceToDeviceManager.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager\"\necho \"#define NO_D2D 1\" > \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager/DeviceToDeviceManager.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/PrivateFrameworks/WebFilterDNS.framework/Headers/WebFilterDNS.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS\"\necho \"#define NO_WCF 1\" > \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS/WebFilterDNS.h\"\nfi\n\nif [ -e \"${SDKROOT}/usr/local/include/AWACS.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/AWACS.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libAWACS.a\"\nelse\necho \"#define NO_AWACS 1\" > \"${CONFIGURATION_T!
 EMP_DIR}/AWACS.h\"\ntouch \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libAWACS.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\"\nfi";
-		};
-		FF045B6A0C7E4AA600448140 /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 8;
-			files = (
-			);
-			inputPaths = (
-			);
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 1;
-			shellPath = /bin/sh;
-			shellScript = "# Install plists to tell launchd how to start mDNSResponder and mDNSResponderHelper\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons\n\nif [ \"${MACOSX_DEPLOYMENT_TARGET}\" == \"10.4\" ] ; then\ncp ${SRCROOT}/LaunchDaemonInfo-Tiger.plist        ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponder.plist\ncp ${SRCROOT}/LaunchDaemonInfo-Tiger.helper.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponderHelper.plist\nelse\ncp ${SRCROOT}/LaunchDaemonInfo.plist              ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponder.plist\ncp ${SRCROOT}/LaunchDaemonInfo.helper.plist       ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponderHelper.plist\nfi\n\nif [ ! -z \"${IPHONEOS_DEPLOYMENT_TARGET}\" ] ; then\nplutil -convert binary1 ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponder.plist\nplutil -convert binary1 ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponderHelper.plist\nfi\n";
-		};
-		FF37FAAD0BC581780044A5CF /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 8;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 1;
-			shellPath = /bin/tcsh;
-			shellScript = "# Install plist to tell launchd how to start dnsextd\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons\ncp ${SRCROOT}/LaunchDaemonInfo.dnsextd.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.dnsextd.plist\n";
-		};
-/* End PBXShellScriptBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
-		213FB21512028A7A002B3A08 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				213FB23C12028C4A002B3A08 /* BonjourEvents.c in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		2141DD1A123FFCDB0086D23E /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				215FFAEE124000F900470DE1 /* dnssd_ipc.c in Sources */,
-				215FFAEF124000F900470DE1 /* dnssd_clientlib.c in Sources */,
-				215FFAF0124000F900470DE1 /* dnssd_clientstub.c in Sources */,
-				215FFAF1124000F900470DE1 /* DNSServiceDiscovery.c in Sources */,
-				215FFAF2124000F900470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */,
-				215FFAF3124000F900470DE1 /* DNSServiceDiscoveryReply.defs in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		2141DD21123FFD0F0086D23E /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				215FFAF41240011800470DE1 /* dnssd_ipc.c in Sources */,
-				215FFAF51240011800470DE1 /* dnssd_clientlib.c in Sources */,
-				215FFAF61240011800470DE1 /* dnssd_clientstub.c in Sources */,
-				215FFAF71240011800470DE1 /* DNSServiceDiscovery.c in Sources */,
-				215FFAF81240011800470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */,
-				215FFAF91240011800470DE1 /* DNSServiceDiscoveryReply.defs in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		2141DD27123FFD2C0086D23E /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				215FFAFA1240013400470DE1 /* dnssd_ipc.c in Sources */,
-				215FFAFB1240013400470DE1 /* dnssd_clientlib.c in Sources */,
-				215FFAFC1240013400470DE1 /* dnssd_clientstub.c in Sources */,
-				215FFAFD1240013400470DE1 /* DNSServiceDiscovery.c in Sources */,
-				215FFAFE1240013400470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */,
-				215FFAFF1240013400470DE1 /* DNSServiceDiscoveryReply.defs in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		2E0405ED0C31955500F13B59 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				2E0405F50C3195F700F13B59 /* helper.c in Sources */,
-				2E0405F60C31961100F13B59 /* helpermsg.defs in Sources */,
-				2E96A51D0C39BDAC0087C4D2 /* helper-main.c in Sources */,
-				2E8165E90C5980EE00485EB2 /* pfkey.c in Sources */,
-				4BD2B63A134FE09F002B96D5 /* P2PPacketFilter.c in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		72FB545B166D5FB00090B2D9 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				72FB5467166D5FCA0090B2D9 /* dnsctl.c in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		84C5B3311665529800C324A8 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				84C5B33C166553F100C324A8 /* dns_services.c in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BE550ADD80740027CCDF /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				D284BE560ADD80740027CCDF /* DNSServiceDiscoveryReply.defs in Sources */,
-				D284BE570ADD80740027CCDF /* DNSServiceDiscoveryRequest.defs in Sources */,
-				D284BE580ADD80740027CCDF /* mDNS.c in Sources */,
-				D284BE590ADD80740027CCDF /* uDNS.c in Sources */,
-				D284BE5A0ADD80740027CCDF /* DNSCommon.c in Sources */,
-				D284BE5B0ADD80740027CCDF /* DNSDigest.c in Sources */,
-				D284BE5D0ADD80740027CCDF /* mDNSDebug.c in Sources */,
-				D284BE5E0ADD80740027CCDF /* uds_daemon.c in Sources */,
-				D284BE5F0ADD80740027CCDF /* dnssd_ipc.c in Sources */,
-				D284BE600ADD80740027CCDF /* PlatformCommon.c in Sources */,
-				D284BE610ADD80740027CCDF /* mDNSMacOSX.c in Sources */,
-				D284BE620ADD80740027CCDF /* LegacyNATTraversal.c in Sources */,
-				D284BE630ADD80740027CCDF /* daemon.c in Sources */,
-				2E04061F0C3198B700F13B59 /* helpermsg.defs in Sources */,
-				2E96A5320C39C1A50087C4D2 /* helper-stubs.c in Sources */,
-				21A57F4C145B2AE100939099 /* CryptoAlg.c in Sources */,
-				21A57F53145B2B1400939099 /* CryptoSupport.c in Sources */,
-				2124FA331471E9DE0021D7BB /* nsec.c in Sources */,
-				213BDC6D147319F400000896 /* dnssec.c in Sources */,
-				218E8E51156D8C0300720DA0 /* dnsproxy.c in Sources */,
-				21DED43515702C0F0060B6B9 /* DNSProxySupport.c in Sources */,
-				216D9ACE1720C9F5008066E1 /* VPNService.c in Sources */,
-				2127A47715C3C7B900A857FC /* nsec3.c in Sources */,
-				21DD8FBF161E9A250033C8F8 /* anonymous.c in Sources */,
-				21070E5F16486B9000A69507 /* DNSSECSupport.c in Sources */,
-				848DA5C7165477E000D2E8B4 /* xpc_services.c in Sources */,
-				2120ABD516B71614007089B6 /* CUPolicy.c in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BE7D0ADD80800027CCDF /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				D284BE7E0ADD80800027CCDF /* DNSServiceDiscoveryReply.defs in Sources */,
-				D284BE7F0ADD80800027CCDF /* DNSServiceDiscoveryRequest.defs in Sources */,
-				D284BE800ADD80800027CCDF /* mDNS.c in Sources */,
-				D284BE810ADD80800027CCDF /* uDNS.c in Sources */,
-				D284BE820ADD80800027CCDF /* DNSCommon.c in Sources */,
-				D284BE830ADD80800027CCDF /* DNSDigest.c in Sources */,
-				D284BE850ADD80800027CCDF /* mDNSDebug.c in Sources */,
-				D284BE860ADD80800027CCDF /* uds_daemon.c in Sources */,
-				D284BE870ADD80800027CCDF /* dnssd_ipc.c in Sources */,
-				D284BE880ADD80800027CCDF /* PlatformCommon.c in Sources */,
-				D284BE890ADD80800027CCDF /* mDNSMacOSX.c in Sources */,
-				D284BE8A0ADD80800027CCDF /* LegacyNATTraversal.c in Sources */,
-				D284BE8B0ADD80800027CCDF /* daemon.c in Sources */,
-				2E0406200C3198B700F13B59 /* helpermsg.defs in Sources */,
-				2E96A5300C39C1A50087C4D2 /* helper-stubs.c in Sources */,
-				21A57F4D145B2AE100939099 /* CryptoAlg.c in Sources */,
-				21A57F54145B2B1400939099 /* CryptoSupport.c in Sources */,
-				2124FA341471E9DE0021D7BB /* nsec.c in Sources */,
-				213BDC6E147319F400000896 /* dnssec.c in Sources */,
-				218E8E52156D8C0300720DA0 /* dnsproxy.c in Sources */,
-				21DED43615702C0F0060B6B9 /* DNSProxySupport.c in Sources */,
-				216D9ACF1720C9F5008066E1 /* VPNService.c in Sources */,
-				2127A47815C3C7B900A857FC /* nsec3.c in Sources */,
-				21DD8FC0161E9A250033C8F8 /* anonymous.c in Sources */,
-				21070E6016486B9000A69507 /* DNSSECSupport.c in Sources */,
-				848DA5C8165477E000D2E8B4 /* xpc_services.c in Sources */,
-				2120ABD616B71614007089B6 /* CUPolicy.c in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEA70ADD80920027CCDF /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				D284BEA80ADD80920027CCDF /* dns-sd.c in Sources */,
-				FFF589B70E37F66800EF515C /* ClientCommon.c in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEB60ADD809A0027CCDF /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				D284BEB70ADD809A0027CCDF /* JNISupport.c in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		D284BEC40ADD80A20027CCDF /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				21DCD05C1461B23700702FC8 /* CryptoAlg.c in Sources */,
-				21DCD05D1461B23700702FC8 /* CryptoAlg.h in Sources */,
-				D284BEC50ADD80A20027CCDF /* DNSCommon.c in Sources */,
-				D284BEC60ADD80A20027CCDF /* DNSDigest.c in Sources */,
-				D284BEC70ADD80A20027CCDF /* dnsextd.c in Sources */,
-				D284BEC80ADD80A20027CCDF /* mDNSDebug.c in Sources */,
-				D284BEC90ADD80A20027CCDF /* GenLinkedList.c in Sources */,
-				D284BECA0ADD80A20027CCDF /* mDNSMacOSX.c in Sources */,
-				D284BECC0ADD80A20027CCDF /* dnsextd_parser.y in Sources */,
-				D284BECB0ADD80A20027CCDF /* dnsextd_lexer.l in Sources */,
-				D284BECD0ADD80A20027CCDF /* PlatformCommon.c in Sources */,
-				2EAE955A0C31F4D30021F738 /* helpermsg.defs in Sources */,
-				2E35529E0C3A9E7600CA1CB7 /* helper-stubs.c in Sources */,
-			);
-			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 */,
-				FFF589C10E37F67E00EF515C /* ClientCommon.c in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		FFA572320AF18F1C0055A0F1 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				FFA572330AF18F1C0055A0F1 /* dnssd_ipc.c in Sources */,
-				FFA572340AF18F1C0055A0F1 /* dnssd_clientlib.c in Sources */,
-				FFA572350AF18F1C0055A0F1 /* dnssd_clientstub.c in Sources */,
-				FFA5724A0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */,
-				FFC22AA40B00F42C00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */,
-				FFC22AA60B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		FFA5723E0AF18F450055A0F1 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				FFA5723F0AF18F450055A0F1 /* dnssd_ipc.c in Sources */,
-				FFA572400AF18F450055A0F1 /* dnssd_clientlib.c in Sources */,
-				FFA572410AF18F450055A0F1 /* dnssd_clientstub.c in Sources */,
-				FFA5724B0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */,
-				FFC22AA30B00F42B00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */,
-				FFC22AA70B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		FFB765810AEED9C700583A2C /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				FFFA38660AEEDB2B0065B80A /* dnssd_ipc.c in Sources */,
-				FFFA38630AEEDB090065B80A /* dnssd_clientlib.c in Sources */,
-				FFFA38650AEEDB130065B80A /* dnssd_clientstub.c in Sources */,
-				FFA572490AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */,
-				FFC22AA20B00F42A00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */,
-				FFC22AA50B00F43000BAB070 /* DNSServiceDiscoveryReply.defs in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXTargetDependency section */
-		03067D680C83A3830022BE1F /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = D284BE500ADD80740027CCDF /* mDNSResponder */;
-			targetProxy = 03067D670C83A3830022BE1F /* PBXContainerItemProxy */;
-		};
-		03067D6A0C83A3890022BE1F /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = D284BE750ADD80800027CCDF /* mDNSResponder debug */;
-			targetProxy = 03067D690C83A3890022BE1F /* PBXContainerItemProxy */;
-		};
-		03067D6C0C83A3920022BE1F /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = D284BEA50ADD80920027CCDF /* dns-sd tool */;
-			targetProxy = 03067D6B0C83A3920022BE1F /* PBXContainerItemProxy */;
-		};
-		03067D6E0C83A39C0022BE1F /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 2E0405EF0C31955500F13B59 /* mDNSResponderHelper */;
-			targetProxy = 03067D6D0C83A39C0022BE1F /* PBXContainerItemProxy */;
-		};
-		03067D860C849CC30022BE1F /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 03067D640C83A3700022BE1F /* Build Some */;
-			targetProxy = 03067D850C849CC30022BE1F /* PBXContainerItemProxy */;
-		};
-		2130257112400E9300AC839F /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = FFA572650AF190F10055A0F1 /* SystemLibrariesDynamic */;
-			targetProxy = 2130257012400E9300AC839F /* PBXContainerItemProxy */;
-		};
-		2141DCFD123FFB7D0086D23E /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 2141DCF8123FFB5D0086D23E /* SystemLibraries */;
-			targetProxy = 2141DCFC123FFB7D0086D23E /* PBXContainerItemProxy */;
-		};
-		2141DD0E123FFC960086D23E /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 2141DD0B123FFC7F0086D23E /* SystemLibrariesStatic */;
-			targetProxy = 2141DD0D123FFC960086D23E /* PBXContainerItemProxy */;
-		};
-		215FFB19124002C100470DE1 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 2141DD1C123FFCDB0086D23E /* libdns_sd_static */;
-			targetProxy = 215FFB18124002C100470DE1 /* PBXContainerItemProxy */;
-		};
-		215FFB1B124002C700470DE1 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 2141DD23123FFD0F0086D23E /* libdns_sd_debug_static */;
-			targetProxy = 215FFB1A124002C700470DE1 /* PBXContainerItemProxy */;
-		};
-		215FFB1D124002CC00470DE1 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 2141DD29123FFD2C0086D23E /* libdns_sd_profile_static */;
-			targetProxy = 215FFB1C124002CC00470DE1 /* PBXContainerItemProxy */;
-		};
-		217A4C49138EE14C000A5BA8 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 213FB21712028A7A002B3A08 /* BonjourEvents */;
-			targetProxy = 217A4C48138EE14C000A5BA8 /* PBXContainerItemProxy */;
-		};
-		4AE4716A0EAFF83800A6C5AD /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 4AE471670EAFF81900A6C5AD /* dns_sd.jar */;
-			targetProxy = 4AE471690EAFF83800A6C5AD /* PBXContainerItemProxy */;
-		};
-		72FB546A166D5FE40090B2D9 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 72FB545E166D5FB00090B2D9 /* dnsctl */;
-			targetProxy = 72FB5469166D5FE40090B2D9 /* PBXContainerItemProxy */;
-		};
-		84C5B3411665544B00C324A8 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 84C5B3341665529800C324A8 /* dns_services */;
-			targetProxy = 84C5B3401665544B00C324A8 /* 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 */;
-			targetProxy = D284BF2F0ADD81630027CCDF /* PBXContainerItemProxy */;
-		};
-		FFA572690AF190FF0055A0F1 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = FFB765830AEED9C700583A2C /* libdns_sd_dynamic */;
-			targetProxy = FFA572680AF190FF0055A0F1 /* PBXContainerItemProxy */;
-		};
-		FFA5726B0AF191010055A0F1 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = FFA572300AF18F1C0055A0F1 /* libdns_sd_debug_dynamic */;
-			targetProxy = FFA5726A0AF191010055A0F1 /* PBXContainerItemProxy */;
-		};
-		FFA5726D0AF191020055A0F1 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			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 */;
-			targetProxy = FFB7657C0AEED97F00583A2C /* PBXContainerItemProxy */;
-		};
-/* End PBXTargetDependency section */
-
-/* Begin PBXVariantGroup section */
-		FF260A4807B4475600CE10E5 /* DNSServiceDiscoveryPref.nib */ = {
-			isa = PBXVariantGroup;
-			children = (
-				FF260A4907B4475600CE10E5 /* English */,
-			);
-			name = DNSServiceDiscoveryPref.nib;
-			path = PreferencePane;
-			sourceTree = SOURCE_ROOT;
-		};
-		FF260A4B07B4477F00CE10E5 /* InfoPlist.strings */ = {
-			isa = PBXVariantGroup;
-			children = (
-				FF260A4C07B4477F00CE10E5 /* English */,
-			);
-			name = InfoPlist.strings;
-			path = PreferencePane;
-			sourceTree = SOURCE_ROOT;
-		};
-/* End PBXVariantGroup section */
-
-/* Begin XCBuildConfiguration section */
-		03067D740C83A3CB0022BE1F /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				COPY_PHASE_STRIP = NO;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				GCC_OPTIMIZATION_LEVEL = s;
-				PRODUCT_NAME = "Build Some";
-			};
-			name = Development;
-		};
-		213FB21A12028A7B002B3A08 /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = NO;
-				BUNDLE_LOADER = /usr/libexec/UserEventAgent;
-				CODE_SIGN_IDENTITY = "-";
-				COPY_PHASE_STRIP = NO;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_MODEL_TUNING = G5;
-				INFOPLIST_FILE = "BonjourEvents-Info.plist";
-				INSTALL_PATH = /System/Library/UserEventPlugins/;
-				PREBINDING = NO;
-				PRODUCT_NAME = BonjourEvents;
-				PROVISIONING_PROFILE = "";
-				WRAPPER_EXTENSION = plugin;
-			};
-			name = Development;
-		};
-		2141DCF9123FFB5D0086D23E /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				COPY_PHASE_STRIP = NO;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_OPTIMIZATION_LEVEL = 0;
-				PRODUCT_NAME = SystemLibraries;
-			};
-			name = Development;
-		};
-		2141DD0C123FFC7F0086D23E /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				COPY_PHASE_STRIP = NO;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_OPTIMIZATION_LEVEL = s;
-				PRODUCT_NAME = SystemLibrariesStatic;
-			};
-			name = Development;
-		};
-		2141DD1E123FFCDB0086D23E /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				COPY_PHASE_STRIP = NO;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"$(inherited)",
-					"__DARWIN_NON_CANCELABLE=1",
-				);
-				HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
-				INSTALLHDRS_COPY_PHASE = YES;
-				INSTALLHDRS_SCRIPT_PHASE = YES;
-				INSTALL_PATH = /usr/local/lib/system;
-				PREBINDING = NO;
-				PRODUCT_NAME = dns_sd;
-			};
-			name = Development;
-		};
-		2141DD25123FFD100086D23E /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				COPY_PHASE_STRIP = NO;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"$(inherited)",
-					"__DARWIN_NON_CANCELABLE=1",
-				);
-				HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
-				INSTALL_PATH = /usr/local/lib/system;
-				PREBINDING = NO;
-				PRODUCT_NAME = dns_sd_debug;
-			};
-			name = Development;
-		};
-		2141DD2B123FFD2C0086D23E /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				COPY_PHASE_STRIP = NO;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"$(inherited)",
-					"__DARWIN_NON_CANCELABLE=1",
-				);
-				HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
-				INSTALL_PATH = /usr/local/lib/system;
-				PREBINDING = NO;
-				PRODUCT_NAME = dns_sd_profile;
-			};
-			name = Development;
-		};
-		2E0405F20C31955500F13B59 /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				"CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "helper-entitlements.plist";
-				CODE_SIGN_IDENTITY = "-";
-				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)";
-				CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)";
-				COPY_PHASE_STRIP = NO;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_WARN_CHECK_SWITCH_STATEMENTS = NO;
-				HEADER_SEARCH_PATHS = (
-					"${CONFIGURATION_TEMP_DIR}",
-					"$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
-				);
-				INSTALL_PATH = /usr/sbin;
-				LD_MAP_FILE_PATH = "$(TARGET_TEMP_DIR)/$(PRODUCT_NAME)-LinkMap-$(CURRENT_VARIANT)-$(CURRENT_ARCH).txt";
-				LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
-				MACOSX_DEPLOYMENT_TARGET = 10.5;
-				"OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = "$(inherited)";
-				OTHER_LDFLAGS = (
-					"$(inherited)",
-					"-lipsec",
-				);
-				"OTHER_LDFLAGS[sdk=iphoneos*] [arch=*]" = "-lipsec -Wl,-pie";
-				"OTHER_LDFLAGS[sdk=macosx*][arch=*]" = (
-					"-lipsec",
-					"-Wl,-pie",
-				);
-				PREBINDING = NO;
-				PRODUCT_NAME = mDNSResponderHelper;
-				PROVISIONING_PROFILE = "";
-			};
-			name = Development;
-		};
-		4AE471680EAFF81900A6C5AD /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				COPY_PHASE_STRIP = NO;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_OPTIMIZATION_LEVEL = 0;
-				PRODUCT_NAME = dns_sd.jar;
-			};
-			name = Development;
-		};
-		72FB5466166D5FB00090B2D9 /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = NO;
-				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
-				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[sdk=*]" = "dnsctl-entitlements.plist";
-				CODE_SIGN_IDENTITY = "-";
-				COPY_PHASE_STRIP = NO;
-				GCC_C_LANGUAGE_STANDARD = gnu99;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
-				GCC_OPTIMIZATION_LEVEL = s;
-				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/bin;
-				MACOSX_DEPLOYMENT_TARGET = 10.9;
-				ONLY_ACTIVE_ARCH = NO;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				PROVISIONING_PROFILE = "";
-				SDKROOT = macosx;
-			};
-			name = Development;
-		};
-		84C5B3371665529800C324A8 /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = NO;
-				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
-				CLANG_CXX_LIBRARY = "libc++";
-				CLANG_WARN_EMPTY_BODY = YES;
-				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-				COPY_PHASE_STRIP = NO;
-				EXECUTABLE_PREFIX = lib;
-				GCC_C_LANGUAGE_STANDARD = gnu99;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
-				GCC_OPTIMIZATION_LEVEL = s;
-				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 = Development;
-		};
-		D284BE290ADD78180027CCDF /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				OTHER_CFLAGS = "";
-				OTHER_LDFLAGS = "";
-				OTHER_REZFLAGS = "";
-				PRODUCT_NAME = "Build All";
-				SECTORDER_FLAGS = "";
-			};
-			name = Development;
-		};
-		D284BE2C0ADD78180027CCDF /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)";
-				DEAD_CODE_STRIPPING = YES;
-				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",
-				);
-				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
-				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
-				MVERS = "\"(Engineering Build)\"";
-				OTHER_CFLAGS = (
-					"-DUSE_SYSTEMCONFIGURATION_PRIVATE_HEADERS",
-					"-fwrapv",
-				);
-				"OTHER_LDFLAGS[sdk=macosx*]" = "";
-				PREBINDING = NO;
-				STRIP_STYLE = debugging;
-				WARNING_CFLAGS = (
-					"-W",
-					"-Wall",
-					"-Wmissing-prototypes",
-					"-Wno-four-char-constants",
-					"-Wno-unknown-pragmas",
-					"-Wshadow",
-				);
-				YACC_GENERATED_FILE_STEM = Standard;
-			};
-			name = Development;
-		};
-		D284BE6E0ADD80740027CCDF /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				"CODE_SIGN_ENTITLEMENTS[sdk=*]" = "mDNSResponder-entitlements.plist";
-				CODE_SIGN_IDENTITY = "-";
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				FRAMEWORK_SEARCH_PATHS = (
-					"$(inherited)",
-					"$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
-				);
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				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",
-				);
-				INSTALL_PATH = /usr/sbin;
-				LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
-				MACOSX_DEPLOYMENT_TARGET = 10.5;
-				ORDER_FILE = "${SRCROOT}/mDNSResponder.order";
-				OTHER_CFLAGS = (
-					"$(inherited)",
-					"-no-cpp-precomp",
-				);
-				"OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = "$(inherited)";
-				OTHER_LDFLAGS = "";
-				"OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = (
-					"-Wl,-pie",
-					"-weak_framework",
-					DeviceToDeviceManager,
-					"-lMobileGestalt",
-					"-lcupolicy",
-				);
-				"OTHER_LDFLAGS[sdk=macosx*][arch=*]" = (
-					"-Wl,-pie",
-					"-lAWACS",
-					"-weak_framework",
-					WebFilterDNS,
-					"-weak_framework",
-					DeviceToDeviceManager,
-				);
-				"OTHER_LDFLAGS[sdk=macosx10.6][arch=*]" = "-lAWACS";
-				OTHER_REZFLAGS = "";
-				PRODUCT_NAME = mDNSResponder;
-				PROVISIONING_PROFILE = "";
-				REZ_EXECUTABLE = YES;
-			};
-			name = Development;
-		};
-		D284BE930ADD80800027CCDF /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				FRAMEWORK_SEARCH_PATHS = (
-					"$(inherited)",
-					"$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
-				);
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				GCC_OPTIMIZATION_LEVEL = s;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"$(inherited)",
-					"MDNS_DEBUGMSGS=1",
-				);
-				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",
-				);
-				LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
-				MACOSX_DEPLOYMENT_TARGET = 10.5;
-				OTHER_CFLAGS = (
-					"$(inherited)",
-					"-no-cpp-precomp",
-				);
-				OTHER_LDFLAGS = "";
-				"OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = (
-					"-Wl,-pie",
-					"-weak_framework",
-					DeviceToDeviceManager,
-					"-lMobileGestalt",
-					"-lcupolicy",
-				);
-				"OTHER_LDFLAGS[sdk=macosx*][arch=*]" = (
-					"-Wl,-pie",
-					"-lAWACS",
-					"-weak_framework",
-					WebFilterDNS,
-					"-weak_framework",
-					DeviceToDeviceManager,
-				);
-				"OTHER_LDFLAGS[sdk=macosx10.6][arch=*]" = "-lAWACS";
-				OTHER_REZFLAGS = "";
-				PRODUCT_NAME = mDNSResponder.debug;
-				REZ_EXECUTABLE = YES;
-				SECTORDER_FLAGS = (
-					"-sectorder",
-					__TEXT,
-					__text,
-					mDNSResponder.order,
-				);
-				SKIP_INSTALL = YES;
-			};
-			name = Development;
-		};
-		D284BEAE0ADD80920027CCDF /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				HEADER_SEARCH_PATHS = (
-					../mDNSShared,
-					"${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders",
-				);
-				INSTALL_PATH = /usr/bin;
-				OTHER_CFLAGS = "-no-cpp-precomp";
-				OTHER_LDFLAGS = "";
-				OTHER_REZFLAGS = "";
-				PRODUCT_NAME = "dns-sd";
-				REZ_EXECUTABLE = YES;
-				SECTORDER_FLAGS = "";
-			};
-			name = Development;
-		};
-		D284BEBC0ADD809A0027CCDF /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				DYLIB_COMPATIBILITY_VERSION = 1;
-				DYLIB_CURRENT_VERSION = 1;
-				EXECUTABLE_EXTENSION = jnilib;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
-				HEADER_SEARCH_PATHS = (
-					../mDNSShared,
-					"${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/A/Headers",
-					"${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/1.3.1/Headers",
-					"${PROJECT_DERIVED_FILE_DIR}",
-				);
-				INSTALL_PATH = /usr/lib/java;
-				LIBRARY_STYLE = DYNAMIC;
-				MACH_O_TYPE = mh_dylib;
-				OTHER_CFLAGS = "";
-				OTHER_LIBTOOL_FLAGS = "";
-				OTHER_REZFLAGS = "";
-				PRODUCT_NAME = libjdns_sd;
-				REZ_EXECUTABLE = YES;
-				SECTORDER_FLAGS = "";
-			};
-			name = Development;
-		};
-		D284BED70ADD80A20027CCDF /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				FRAMEWORK_SEARCH_PATHS = "";
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				HEADER_SEARCH_PATHS = (
-					"${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders",
-					"${APPLE_INTERNAL_DEVELOPER_DIR}/Headers",
-					"${CONFIGURATION_TEMP_DIR}",
-					/System/Library/Frameworks/System.Framework/PrivateHeaders,
-				);
-				INSTALL_PATH = /usr/sbin;
-				LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
-				MACOSX_DEPLOYMENT_TARGET = 10.5;
-				OTHER_CFLAGS = (
-					"-no-cpp-precomp",
-					"-UAPPLE_OSX_mDNSResponder",
-				);
-				OTHER_LDFLAGS = "";
-				"OTHER_LDFLAGS[sdk=macosx*][arch=*]" = "-Wl,-pie";
-				PRODUCT_NAME = dnsextd;
-				SECTORDER_FLAGS = "";
-			};
-			name = Development;
-		};
-		D284BEE60ADD80A70027CCDF /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				INSTALL_PATH = "/Library/Application Support/Bonjour";
-				MACOSX_DEPLOYMENT_TARGET = 10.5;
-				OTHER_CFLAGS = "";
-				OTHER_LDFLAGS = "";
-				"OTHER_LDFLAGS[sdk=macosx*]" = "-Wl,-pie";
-				OTHER_REZFLAGS = "";
-				PRODUCT_NAME = ddnswriteconfig;
-				REZ_EXECUTABLE = YES;
-				SECTORDER_FLAGS = "";
-			};
-			name = Development;
-		};
-		D284BF090ADD80B00027CCDF /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				EXPORTED_SYMBOLS_FILE = "";
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_ENABLE_OBJC_GC = supported;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
-				INFOPLIST_FILE = "PreferencePane/Info-PreferencePane.plist";
-				INSTALL_PATH = /AppleInternal/Library/PreferencePanes;
-				MACOSX_DEPLOYMENT_TARGET = 10.5;
-				OTHER_CFLAGS = "";
-				OTHER_LDFLAGS = "-twolevel_namespace";
-				OTHER_REZFLAGS = "";
-				PRODUCT_NAME = Bonjour;
-				SECTORDER_FLAGS = "";
-				WRAPPER_EXTENSION = prefPane;
-			};
-			name = Development;
-		};
-		FFA572380AF18F1C0055A0F1 /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				COPY_PHASE_STRIP = NO;
-				DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
-				EXECUTABLE_EXTENSION = dylib;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"$(inherited)",
-					"__DARWIN_NON_CANCELABLE=1",
-				);
-				HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
-				INSTALL_PATH = /usr/lib/system;
-				"INSTALL_PATH[sdk=iphonesimulator*]" = "$(SDKROOT)/usr/lib/system";
-				LINK_WITH_STANDARD_LIBRARIES = NO;
-				OTHER_LDFLAGS = (
-					"-Wl,-umbrella,System",
-					"-L/usr/lib/system",
-					"-ldyld",
-					"-lcompiler_rt",
-					"-lsystem_kernel",
-					"-lsystem_platform",
-					"-lsystem_pthread",
-					"-lsystem_malloc",
-					"-lsystem_c",
-					"-lsystem_blocks",
-					"-ldispatch",
-					"-llaunch",
-					"-lsystem_asl",
-				);
-				"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
-					"-Wl,-umbrella,System",
-					"-L/usr/lib/system",
-					"-ldyld_sim",
-					"-lcompiler_rt_sim",
-					"-lsystem_sim_c",
-					"-lsystem_sim_blocks",
-					"-ldispatch",
-					"-Wl,-upward-lSystem",
-				);
-				PRODUCT_NAME = libsystem_dnssd_debug;
-				"PRODUCT_NAME[sdk=iphonesimulator*]" = libsystem_sim_dnssd_debug;
-			};
-			name = Development;
-		};
-		FFA572440AF18F450055A0F1 /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				COPY_PHASE_STRIP = NO;
-				DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
-				EXECUTABLE_EXTENSION = dylib;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"$(inherited)",
-					"__DARWIN_NON_CANCELABLE=1",
-				);
-				GENERATE_PROFILING_CODE = YES;
-				HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
-				INSTALL_PATH = /usr/lib/system;
-				"INSTALL_PATH[sdk=iphonesimulator*]" = "$(SDKROOT)/usr/lib/system";
-				LINK_WITH_STANDARD_LIBRARIES = NO;
-				OTHER_LDFLAGS = (
-					"-Wl,-umbrella,System",
-					"-L/usr/lib/system",
-					"-ldyld",
-					"-lcompiler_rt",
-					"-lsystem_kernel",
-					"-lsystem_platform",
-					"-lsystem_pthread",
-					"-lsystem_malloc",
-					"-lsystem_c",
-					"-lsystem_blocks",
-					"-ldispatch",
-					"-llaunch",
-					"-lsystem_asl",
-				);
-				"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
-					"-Wl,-umbrella,System",
-					"-L/usr/lib/system",
-					"-ldyld_sim",
-					"-lcompiler_rt_sim",
-					"-lsystem_sim_c",
-					"-lsystem_sim_blocks",
-					"-ldispatch",
-					"-Wl,-upward-lSystem",
-				);
-				PRODUCT_NAME = libsystem_dnssd_profile;
-				"PRODUCT_NAME[sdk=iphonesimulator*]" = libsystem_sim_dnssd_profile;
-			};
-			name = Development;
-		};
-		FFA5726F0AF191200055A0F1 /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				COPY_PHASE_STRIP = NO;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				PRODUCT_NAME = SystemLibrariesDynamic;
-			};
-			name = Development;
-		};
-		FFB7657F0AEED99D00583A2C /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				COPY_PHASE_STRIP = NO;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				PRODUCT_NAME = "Build All";
-			};
-			name = Development;
-		};
-		FFB7658A0AEED9FB00583A2C /* Development */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
-				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
-				COPY_PHASE_STRIP = NO;
-				DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
-				EXECUTABLE_EXTENSION = dylib;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"$(inherited)",
-					"__DARWIN_NON_CANCELABLE=1",
-				);
-				HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
-				INSTALLHDRS_COPY_PHASE = YES;
-				INSTALLHDRS_SCRIPT_PHASE = YES;
-				INSTALL_PATH = /usr/lib/system;
-				"INSTALL_PATH[sdk=iphonesimulator*]" = "$(SDKROOT)/usr/lib/system";
-				LINK_WITH_STANDARD_LIBRARIES = NO;
-				OTHER_LDFLAGS = (
-					"-Wl,-umbrella,System",
-					"-L/usr/lib/system",
-					"-ldyld",
-					"-lcompiler_rt",
-					"-lsystem_kernel",
-					"-lsystem_platform",
-					"-lsystem_pthread",
-					"-lsystem_malloc",
-					"-lsystem_c",
-					"-lsystem_blocks",
-					"-ldispatch",
-					"-llaunch",
-					"-lsystem_asl",
-				);
-				"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
-					"-Wl,-umbrella,System",
-					"-L/usr/lib/system",
-					"-ldyld_sim",
-					"-lcompiler_rt_sim",
-					"-lsystem_sim_c",
-					"-lsystem_sim_blocks",
-					"-ldispatch",
-					"-Wl,-upward-lSystem",
-				);
-				PRODUCT_NAME = libsystem_dnssd;
-				"PRODUCT_NAME[sdk=iphonesimulator*]" = libsystem_sim_dnssd;
-			};
-			name = Development;
-		};
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
-		03067D730C83A3CB0022BE1F /* Build configuration list for PBXAggregateTarget "Build Some" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				03067D740C83A3CB0022BE1F /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		213FB21B12028A7C002B3A08 /* Build configuration list for PBXNativeTarget "BonjourEvents" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				213FB21A12028A7B002B3A08 /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		2141DD08123FFB830086D23E /* Build configuration list for PBXAggregateTarget "SystemLibraries" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				2141DCF9123FFB5D0086D23E /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		2141DD18123FFC990086D23E /* Build configuration list for PBXAggregateTarget "SystemLibrariesStatic" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				2141DD0C123FFC7F0086D23E /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		2141DD1F123FFCF90086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_static" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				2141DD1E123FFCDB0086D23E /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		2141DD35123FFD3B0086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_debug_static" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				2141DD25123FFD100086D23E /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		2141DD36123FFD3B0086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_profile_static" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				2141DD2B123FFD2C0086D23E /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		2E0405F30C31956600F13B59 /* Build configuration list for PBXNativeTarget "mDNSResponderHelper" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				2E0405F20C31955500F13B59 /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		4AE471770EAFF84000A6C5AD /* Build configuration list for PBXLegacyTarget "dns_sd.jar" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				4AE471680EAFF81900A6C5AD /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		72FB5465166D5FB00090B2D9 /* Build configuration list for PBXNativeTarget "dnsctl" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				72FB5466166D5FB00090B2D9 /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		84C5B3361665529800C324A8 /* Build configuration list for PBXNativeTarget "dns_services" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				84C5B3371665529800C324A8 /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		D284BE280ADD78180027CCDF /* Build configuration list for PBXAggregateTarget "Build More" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				D284BE290ADD78180027CCDF /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		D284BE2B0ADD78180027CCDF /* Build configuration list for PBXProject "mDNSResponder" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				D284BE2C0ADD78180027CCDF /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		D284BE6D0ADD80740027CCDF /* Build configuration list for PBXNativeTarget "mDNSResponder" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				D284BE6E0ADD80740027CCDF /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		D284BE920ADD80800027CCDF /* Build configuration list for PBXNativeTarget "mDNSResponder debug" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				D284BE930ADD80800027CCDF /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		D284BEAD0ADD80920027CCDF /* Build configuration list for PBXNativeTarget "dns-sd tool" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				D284BEAE0ADD80920027CCDF /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		D284BEBB0ADD809A0027CCDF /* Build configuration list for PBXNativeTarget "libjdns_sd.jnilib" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				D284BEBC0ADD809A0027CCDF /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		D284BED60ADD80A20027CCDF /* Build configuration list for PBXNativeTarget "dnsextd" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				D284BED70ADD80A20027CCDF /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		D284BEE50ADD80A70027CCDF /* Build configuration list for PBXNativeTarget "ddnswriteconfig" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				D284BEE60ADD80A70027CCDF /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		D284BF080ADD80B00027CCDF /* Build configuration list for PBXNativeTarget "PreferencePane" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				D284BF090ADD80B00027CCDF /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		FFA572370AF18F1C0055A0F1 /* Build configuration list for PBXNativeTarget "libdns_sd_debug_dynamic" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				FFA572380AF18F1C0055A0F1 /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		FFA572430AF18F450055A0F1 /* Build configuration list for PBXNativeTarget "libdns_sd_profile_dynamic" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				FFA572440AF18F450055A0F1 /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		FFA5726E0AF191200055A0F1 /* Build configuration list for PBXAggregateTarget "SystemLibrariesDynamic" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				FFA5726F0AF191200055A0F1 /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		FFB7657E0AEED99D00583A2C /* Build configuration list for PBXAggregateTarget "Build All" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				FFB7657F0AEED99D00583A2C /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-		FFB765890AEED9FB00583A2C /* Build configuration list for PBXNativeTarget "libdns_sd_dynamic" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				FFB7658A0AEED9FB00583A2C /* Development */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Development;
-		};
-/* End XCConfigurationList section */
-	};
-	rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
-}

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,3128 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 45;
+	objects = {
+
+/* Begin PBXAggregateTarget section */
+		00AD62BB032D7A0C0CCA2C71 /* Build More */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = D284BE280ADD78180027CCDF /* Build configuration list for PBXAggregateTarget "Build More" */;
+			buildPhases = (
+			);
+			dependencies = (
+				03067D860C849CC30022BE1F /* PBXTargetDependency */,
+				D284BF2C0ADD815A0027CCDF /* PBXTargetDependency */,
+				D284BF2E0ADD81600027CCDF /* PBXTargetDependency */,
+				D284BF300ADD81630027CCDF /* PBXTargetDependency */,
+			);
+			name = "Build More";
+			productName = "Build All";
+		};
+		03067D640C83A3700022BE1F /* Build Some */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 03067D730C83A3CB0022BE1F /* Build configuration list for PBXAggregateTarget "Build Some" */;
+			buildPhases = (
+				FF045B6A0C7E4AA600448140 /* ShellScript */,
+			);
+			dependencies = (
+				217A4C49138EE14C000A5BA8 /* PBXTargetDependency */,
+				03067D680C83A3830022BE1F /* PBXTargetDependency */,
+				03067D6A0C83A3890022BE1F /* PBXTargetDependency */,
+				03067D6C0C83A3920022BE1F /* PBXTargetDependency */,
+				03067D6E0C83A39C0022BE1F /* PBXTargetDependency */,
+				84C5B3411665544B00C324A8 /* PBXTargetDependency */,
+			);
+			name = "Build Some";
+			productName = "Build Some";
+		};
+		2141DCF8123FFB5D0086D23E /* SystemLibraries */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 2141DD08123FFB830086D23E /* Build configuration list for PBXAggregateTarget "SystemLibraries" */;
+			buildPhases = (
+			);
+			dependencies = (
+				2141DD0E123FFC960086D23E /* PBXTargetDependency */,
+				2130257112400E9300AC839F /* PBXTargetDependency */,
+			);
+			name = SystemLibraries;
+			productName = SystemLibraries;
+		};
+		2141DD0B123FFC7F0086D23E /* SystemLibrariesStatic */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 2141DD18123FFC990086D23E /* Build configuration list for PBXAggregateTarget "SystemLibrariesStatic" */;
+			buildPhases = (
+			);
+			dependencies = (
+				215FFB1D124002CC00470DE1 /* PBXTargetDependency */,
+				215FFB1B124002C700470DE1 /* PBXTargetDependency */,
+				215FFB19124002C100470DE1 /* PBXTargetDependency */,
+			);
+			name = SystemLibrariesStatic;
+			productName = SystemLibrariesStatic;
+		};
+		FFA572650AF190F10055A0F1 /* SystemLibrariesDynamic */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = FFA5726E0AF191200055A0F1 /* Build configuration list for PBXAggregateTarget "SystemLibrariesDynamic" */;
+			buildPhases = (
+			);
+			dependencies = (
+				FFA572690AF190FF0055A0F1 /* PBXTargetDependency */,
+				FFA5726B0AF191010055A0F1 /* PBXTargetDependency */,
+				FFA5726D0AF191020055A0F1 /* PBXTargetDependency */,
+			);
+			name = SystemLibrariesDynamic;
+			productName = SystemLibraries;
+		};
+		FFB7657B0AEED96B00583A2C /* Build All */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = FFB7657E0AEED99D00583A2C /* Build configuration list for PBXAggregateTarget "Build All" */;
+			buildPhases = (
+			);
+			dependencies = (
+				FFB7657D0AEED97F00583A2C /* PBXTargetDependency */,
+				2141DCFD123FFB7D0086D23E /* PBXTargetDependency */,
+			);
+			name = "Build All";
+			productName = "Build All";
+		};
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+		21070E5F16486B9000A69507 /* DNSSECSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21070E5D16486B9000A69507 /* DNSSECSupport.c */; };
+		21070E6016486B9000A69507 /* DNSSECSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21070E5D16486B9000A69507 /* DNSSECSupport.c */; };
+		21070E6116486B9000A69507 /* DNSSECSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21070E5E16486B9000A69507 /* DNSSECSupport.h */; };
+		21070E6216486B9000A69507 /* DNSSECSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21070E5E16486B9000A69507 /* DNSSECSupport.h */; };
+		2120ABD516B71614007089B6 /* CUPolicy.c in Sources */ = {isa = PBXBuildFile; fileRef = 2120ABD416B71614007089B6 /* CUPolicy.c */; };
+		2120ABD616B71614007089B6 /* CUPolicy.c in Sources */ = {isa = PBXBuildFile; fileRef = 2120ABD416B71614007089B6 /* CUPolicy.c */; };
+		2124FA2C1471E98C0021D7BB /* nsec.h in Headers */ = {isa = PBXBuildFile; fileRef = 2124FA2B1471E98C0021D7BB /* nsec.h */; };
+		2124FA2D1471E98C0021D7BB /* nsec.h in Headers */ = {isa = PBXBuildFile; fileRef = 2124FA2B1471E98C0021D7BB /* nsec.h */; };
+		2124FA301471E9B50021D7BB /* dnssec.h in Headers */ = {isa = PBXBuildFile; fileRef = 2124FA2F1471E9B50021D7BB /* dnssec.h */; };
+		2124FA311471E9B50021D7BB /* dnssec.h in Headers */ = {isa = PBXBuildFile; fileRef = 2124FA2F1471E9B50021D7BB /* dnssec.h */; };
+		2124FA331471E9DE0021D7BB /* nsec.c in Sources */ = {isa = PBXBuildFile; fileRef = 2124FA321471E9DE0021D7BB /* nsec.c */; };
+		2124FA341471E9DE0021D7BB /* nsec.c in Sources */ = {isa = PBXBuildFile; fileRef = 2124FA321471E9DE0021D7BB /* nsec.c */; };
+		2127A47715C3C7B900A857FC /* nsec3.c in Sources */ = {isa = PBXBuildFile; fileRef = 2127A47515C3C7B900A857FC /* nsec3.c */; };
+		2127A47815C3C7B900A857FC /* nsec3.c in Sources */ = {isa = PBXBuildFile; fileRef = 2127A47515C3C7B900A857FC /* nsec3.c */; };
+		2127A47915C3C7B900A857FC /* nsec3.h in Headers */ = {isa = PBXBuildFile; fileRef = 2127A47615C3C7B900A857FC /* nsec3.h */; };
+		2127A47A15C3C7B900A857FC /* nsec3.h in Headers */ = {isa = PBXBuildFile; fileRef = 2127A47615C3C7B900A857FC /* nsec3.h */; };
+		213BDC6D147319F400000896 /* dnssec.c in Sources */ = {isa = PBXBuildFile; fileRef = 213BDC6C147319F400000896 /* dnssec.c */; };
+		213BDC6E147319F400000896 /* dnssec.c in Sources */ = {isa = PBXBuildFile; fileRef = 213BDC6C147319F400000896 /* dnssec.c */; };
+		213FB23C12028C4A002B3A08 /* BonjourEvents.c in Sources */ = {isa = PBXBuildFile; fileRef = 213FB22C12028B53002B3A08 /* BonjourEvents.c */; };
+		213FB23D12028C5A002B3A08 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
+		215FFAEE124000F900470DE1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
+		215FFAEF124000F900470DE1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
+		215FFAF0124000F900470DE1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
+		215FFAF1124000F900470DE1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
+		215FFAF2124000F900470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
+		215FFAF3124000F900470DE1 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
+		215FFAF41240011800470DE1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
+		215FFAF51240011800470DE1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
+		215FFAF61240011800470DE1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
+		215FFAF71240011800470DE1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
+		215FFAF81240011800470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
+		215FFAF91240011800470DE1 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
+		215FFAFA1240013400470DE1 /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
+		215FFAFB1240013400470DE1 /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
+		215FFAFC1240013400470DE1 /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
+		215FFAFD1240013400470DE1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
+		215FFAFE1240013400470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
+		215FFAFF1240013400470DE1 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
+		216D9ACE1720C9F5008066E1 /* VPNService.c in Sources */ = {isa = PBXBuildFile; fileRef = 216D9ACD1720C9F5008066E1 /* VPNService.c */; };
+		216D9ACF1720C9F5008066E1 /* VPNService.c in Sources */ = {isa = PBXBuildFile; fileRef = 216D9ACD1720C9F5008066E1 /* VPNService.c */; };
+		218E8E51156D8C0300720DA0 /* dnsproxy.c in Sources */ = {isa = PBXBuildFile; fileRef = 218E8E4F156D8C0300720DA0 /* dnsproxy.c */; };
+		218E8E52156D8C0300720DA0 /* dnsproxy.c in Sources */ = {isa = PBXBuildFile; fileRef = 218E8E4F156D8C0300720DA0 /* dnsproxy.c */; };
+		218E8E53156D8C0300720DA0 /* dnsproxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 218E8E50156D8C0300720DA0 /* dnsproxy.h */; };
+		218E8E54156D8C0300720DA0 /* dnsproxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 218E8E50156D8C0300720DA0 /* dnsproxy.h */; };
+		219D5542149ED645004464AE /* libxml2.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 219D5541149ED645004464AE /* libxml2.2.dylib */; };
+		219D5543149ED645004464AE /* libxml2.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 219D5541149ED645004464AE /* libxml2.2.dylib */; };
+		21A57F4C145B2AE100939099 /* CryptoAlg.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F4A145B2AE100939099 /* CryptoAlg.c */; };
+		21A57F4D145B2AE100939099 /* CryptoAlg.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F4A145B2AE100939099 /* CryptoAlg.c */; };
+		21A57F4E145B2AE100939099 /* CryptoAlg.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F4B145B2AE100939099 /* CryptoAlg.h */; };
+		21A57F4F145B2AE100939099 /* CryptoAlg.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F4B145B2AE100939099 /* CryptoAlg.h */; };
+		21A57F53145B2B1400939099 /* CryptoSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F51145B2B1400939099 /* CryptoSupport.c */; };
+		21A57F54145B2B1400939099 /* CryptoSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F51145B2B1400939099 /* CryptoSupport.c */; };
+		21A57F55145B2B1400939099 /* CryptoSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F52145B2B1400939099 /* CryptoSupport.h */; };
+		21A57F56145B2B1400939099 /* CryptoSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A57F52145B2B1400939099 /* CryptoSupport.h */; };
+		21DCD05C1461B23700702FC8 /* CryptoAlg.c in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F4A145B2AE100939099 /* CryptoAlg.c */; };
+		21DCD05D1461B23700702FC8 /* CryptoAlg.h in Sources */ = {isa = PBXBuildFile; fileRef = 21A57F4B145B2AE100939099 /* CryptoAlg.h */; };
+		21DD8FBF161E9A250033C8F8 /* anonymous.c in Sources */ = {isa = PBXBuildFile; fileRef = 21DD8FBD161E9A250033C8F8 /* anonymous.c */; };
+		21DD8FC0161E9A250033C8F8 /* anonymous.c in Sources */ = {isa = PBXBuildFile; fileRef = 21DD8FBD161E9A250033C8F8 /* anonymous.c */; };
+		21DD8FC1161E9A250033C8F8 /* anonymous.h in Headers */ = {isa = PBXBuildFile; fileRef = 21DD8FBE161E9A250033C8F8 /* anonymous.h */; };
+		21DD8FC2161E9A250033C8F8 /* anonymous.h in Headers */ = {isa = PBXBuildFile; fileRef = 21DD8FBE161E9A250033C8F8 /* anonymous.h */; };
+		21DED43515702C0F0060B6B9 /* DNSProxySupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21DED43415702C0F0060B6B9 /* DNSProxySupport.c */; };
+		21DED43615702C0F0060B6B9 /* DNSProxySupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 21DED43415702C0F0060B6B9 /* DNSProxySupport.c */; };
+		2E0405F50C3195F700F13B59 /* helper.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405F40C3195F700F13B59 /* helper.c */; };
+		2E0405F60C31961100F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; settings = {ATTRIBUTES = (Client, Server, ); COMPILER_FLAGS = "-Wno-error"; }; };
+		2E0406150C3197CB00F13B59 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E0406140C3197CB00F13B59 /* libbsm.dylib */; };
+		2E04061F0C3198B700F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; };
+		2E0406200C3198B700F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; };
+		2E04070A0C31EEEC00F13B59 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
+		2E04070B0C31EEEC00F13B59 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
+		2E3552900C3A95C100CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; };
+		2E3552910C3A95C100CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; };
+		2E3552920C3A95C100CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; };
+		2E35529D0C3A9E7600CA1CB7 /* helper-error.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E35528F0C3A95C100CA1CB7 /* helper-error.h */; };
+		2E35529E0C3A9E7600CA1CB7 /* helper-stubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */; };
+		2E35529F0C3A9E7600CA1CB7 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
+		2E4D9B050C38C19500480551 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
+		2E8165E80C5980E300485EB2 /* libpfkey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A8202520C56C36500DDFD48 /* libpfkey.h */; };
+		2E8165E90C5980EE00485EB2 /* pfkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A8202530C56C36600DDFD48 /* pfkey.c */; };
+		2E8165EA0C5980F700485EB2 /* ipsec_strerror.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A8202510C56C36500DDFD48 /* ipsec_strerror.h */; };
+		2E8165F90C59838100485EB2 /* libipsec.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E8165F60C59835F00485EB2 /* libipsec.dylib */; };
+		2E96A51D0C39BDAC0087C4D2 /* helper-main.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0406CA0C31E9AD00F13B59 /* helper-main.c */; };
+		2E96A5260C39BE480087C4D2 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
+		2E96A5270C39BE480087C4D2 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
+		2E96A5300C39C1A50087C4D2 /* helper-stubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */; };
+		2E96A5320C39C1A50087C4D2 /* helper-stubs.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */; };
+		2EAE955A0C31F4D30021F738 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; };
+		2EC8F8EC0C39CCAC003C9C48 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
+		2ECC11A60C4FEC3800CB1885 /* helpermsg-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */; };
+		2ECC11A70C4FEC3800CB1885 /* helpermsg-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */; };
+		2ECC11A80C4FEC3800CB1885 /* helpermsg-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */; };
+		2EDC5E730C39EA640092701B /* helper-server.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EDC5E720C39EA640092701B /* helper-server.h */; };
+		2EDC5E740C39EA640092701B /* helper-server.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EDC5E720C39EA640092701B /* helper-server.h */; };
+		2EDC5E750C39EA640092701B /* helper-server.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EDC5E720C39EA640092701B /* helper-server.h */; };
+		3F347CF6185D57CD00367B40 /* base.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 3F347CF5185D57CD00367B40 /* base.xcconfig */; };
+		4A7B9E8014FDA25000B84CC1 /* mDNSResponder.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A7B9E7E14FDA1BB00B84CC1 /* mDNSResponder.plist */; };
+		4A7B9E8214FDA26C00B84CC1 /* mDNSResponder.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A7B9E7C14FDA19F00B84CC1 /* mDNSResponder.txt */; };
+		4AAE0C9A0C68EA81003882A5 /* mDNSResponderHelper.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */; };
+		4BD2B63A134FE09F002B96D5 /* P2PPacketFilter.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BD2B638134FE09F002B96D5 /* P2PPacketFilter.c */; };
+		4BD2B63B134FE09F002B96D5 /* P2PPacketFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BD2B639134FE09F002B96D5 /* P2PPacketFilter.h */; };
+		72FB5467166D5FCA0090B2D9 /* dnsctl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72FB545A166D5F960090B2D9 /* dnsctl.c */; };
+		8415A6571897109000BDBA26 /* libdns_services.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8415A6561897109000BDBA26 /* libdns_services.dylib */; };
+		8418673E15AB8C2D00BB7F70 /* com.apple.networking.mDNSResponder in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8418673A15AB8B6900BB7F70 /* com.apple.networking.mDNSResponder */; };
+		848DA5C7165477E000D2E8B4 /* xpc_services.c in Sources */ = {isa = PBXBuildFile; fileRef = 848DA5C6165477E000D2E8B4 /* xpc_services.c */; };
+		848DA5C8165477E000D2E8B4 /* xpc_services.c in Sources */ = {isa = PBXBuildFile; fileRef = 848DA5C6165477E000D2E8B4 /* xpc_services.c */; };
+		848DA5CA165477EB00D2E8B4 /* xpc_services.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5C9165477EB00D2E8B4 /* xpc_services.h */; };
+		848DA5CB165477EB00D2E8B4 /* xpc_services.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5C9165477EB00D2E8B4 /* xpc_services.h */; };
+		848DA5D616547F7200D2E8B4 /* dns_xpc.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DA5D516547F7200D2E8B4 /* dns_xpc.h */; };
+		848DA5D716547F7200D2E8B4 /* 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_mdns.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F4C08F188F04CF00D1E1DE /* dns_services_mdns.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		D284BE530ADD80740027CCDF /* DNSServiceDiscoveryDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */; };
+		D284BE540ADD80740027CCDF /* dnssd_ipc.h in Headers */ = {isa = PBXBuildFile; fileRef = F5E11B5B04A28126019798ED /* dnssd_ipc.h */; };
+		D284BE560ADD80740027CCDF /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Client, ); }; };
+		D284BE570ADD80740027CCDF /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; settings = {ATTRIBUTES = (Server, ); }; };
+		D284BE580ADD80740027CCDF /* mDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBE9022EAF5A00000109 /* mDNS.c */; };
+		D284BE590ADD80740027CCDF /* uDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F70587CEF6001880B3 /* uDNS.c */; };
+		D284BE5A0ADD80740027CCDF /* DNSCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F60587CEF6001880B3 /* DNSCommon.c */; };
+		D284BE5B0ADD80740027CCDF /* DNSDigest.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F461DB5062DBF2900672BF3 /* DNSDigest.c */; };
+		D284BE5D0ADD80740027CCDF /* mDNSDebug.c in Sources */ = {isa = PBXBuildFile; fileRef = DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */; };
+		D284BE5E0ADD80740027CCDF /* uds_daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = F525E72804AA167501F1CF4D /* uds_daemon.c */; };
+		D284BE5F0ADD80740027CCDF /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
+		D284BE600ADD80740027CCDF /* PlatformCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FFCB6D73075D539900B8AF62 /* PlatformCommon.c */; };
+		D284BE610ADD80740027CCDF /* mDNSMacOSX.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBEB022EAF7200000109 /* mDNSMacOSX.c */; };
+		D284BE620ADD80740027CCDF /* LegacyNATTraversal.c in Sources */ = {isa = PBXBuildFile; fileRef = 7FC8F9D406D14E66007E879D /* LegacyNATTraversal.c */; };
+		D284BE630ADD80740027CCDF /* daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBEC022EAF7200000109 /* daemon.c */; };
+		D284BE650ADD80740027CCDF /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
+		D284BE660ADD80740027CCDF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
+		D284BE670ADD80740027CCDF /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA213D02786FC30CCA2C71 /* IOKit.framework */; };
+		D284BE680ADD80740027CCDF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
+		D284BE6B0ADD80740027CCDF /* mDNSResponder.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FF485D5105632E0000130380 /* mDNSResponder.8 */; };
+		D284BE780ADD80800027CCDF /* DNSServiceDiscoveryDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */; };
+		D284BE790ADD80800027CCDF /* dnssd_ipc.h in Headers */ = {isa = PBXBuildFile; fileRef = F5E11B5B04A28126019798ED /* dnssd_ipc.h */; };
+		D284BE7A0ADD80800027CCDF /* mDNSEmbeddedAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 654BE64F02B63B93000001D1 /* mDNSEmbeddedAPI.h */; };
+		D284BE7B0ADD80800027CCDF /* mDNSDebug.h in Headers */ = {isa = PBXBuildFile; fileRef = 654BE65002B63B93000001D1 /* mDNSDebug.h */; };
+		D284BE7C0ADD80800027CCDF /* mDNSMacOSX.h in Headers */ = {isa = PBXBuildFile; fileRef = 000753D303367C1C0CCA2C71 /* mDNSMacOSX.h */; };
+		D284BE7E0ADD80800027CCDF /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Client, ); }; };
+		D284BE7F0ADD80800027CCDF /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; settings = {ATTRIBUTES = (Server, ); }; };
+		D284BE800ADD80800027CCDF /* mDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBE9022EAF5A00000109 /* mDNS.c */; };
+		D284BE810ADD80800027CCDF /* uDNS.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F70587CEF6001880B3 /* uDNS.c */; };
+		D284BE820ADD80800027CCDF /* DNSCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F60587CEF6001880B3 /* DNSCommon.c */; };
+		D284BE830ADD80800027CCDF /* DNSDigest.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F461DB5062DBF2900672BF3 /* DNSDigest.c */; };
+		D284BE850ADD80800027CCDF /* mDNSDebug.c in Sources */ = {isa = PBXBuildFile; fileRef = DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */; };
+		D284BE860ADD80800027CCDF /* uds_daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = F525E72804AA167501F1CF4D /* uds_daemon.c */; };
+		D284BE870ADD80800027CCDF /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
+		D284BE880ADD80800027CCDF /* PlatformCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FFCB6D73075D539900B8AF62 /* PlatformCommon.c */; };
+		D284BE890ADD80800027CCDF /* mDNSMacOSX.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBEB022EAF7200000109 /* mDNSMacOSX.c */; };
+		D284BE8A0ADD80800027CCDF /* LegacyNATTraversal.c in Sources */ = {isa = PBXBuildFile; fileRef = 7FC8F9D406D14E66007E879D /* LegacyNATTraversal.c */; };
+		D284BE8B0ADD80800027CCDF /* daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBEC022EAF7200000109 /* daemon.c */; };
+		D284BE8D0ADD80800027CCDF /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
+		D284BE8E0ADD80800027CCDF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
+		D284BE8F0ADD80800027CCDF /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA213D02786FC30CCA2C71 /* IOKit.framework */; };
+		D284BE900ADD80800027CCDF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F869685066EE02400D2A2DC /* Security.framework */; };
+		D284BEA80ADD80920027CCDF /* dns-sd.c in Sources */ = {isa = PBXBuildFile; fileRef = FF1C919F07021E3F001048AB /* dns-sd.c */; };
+		D284BEAC0ADD80920027CCDF /* dns-sd.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FF1C919D07021D77001048AB /* dns-sd.1 */; };
+		D284BEB70ADD809A0027CCDF /* JNISupport.c in Sources */ = {isa = PBXBuildFile; fileRef = DB2CC44B0662DD1100335AB3 /* JNISupport.c */; };
+		D284BEB90ADD809A0027CCDF /* JavaVM.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB2CC4680662DFF500335AB3 /* JavaVM.framework */; };
+		D284BEC50ADD80A20027CCDF /* DNSCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F18A9F60587CEF6001880B3 /* DNSCommon.c */; };
+		D284BEC60ADD80A20027CCDF /* DNSDigest.c in Sources */ = {isa = PBXBuildFile; fileRef = 7F461DB5062DBF2900672BF3 /* DNSDigest.c */; };
+		D284BEC70ADD80A20027CCDF /* dnsextd.c in Sources */ = {isa = PBXBuildFile; fileRef = FF25794606C9A8BF00376F7B /* dnsextd.c */; };
+		D284BEC80ADD80A20027CCDF /* mDNSDebug.c in Sources */ = {isa = PBXBuildFile; fileRef = DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */; };
+		D284BEC90ADD80A20027CCDF /* GenLinkedList.c in Sources */ = {isa = PBXBuildFile; fileRef = DBAAFE2C057E8F660085CAD0 /* GenLinkedList.c */; };
+		D284BECA0ADD80A20027CCDF /* mDNSMacOSX.c in Sources */ = {isa = PBXBuildFile; fileRef = 6575FBEB022EAF7200000109 /* mDNSMacOSX.c */; };
+		D284BECB0ADD80A20027CCDF /* dnsextd_lexer.l in Sources */ = {isa = PBXBuildFile; fileRef = FF13FFEA0A5DA44A00897C81 /* dnsextd_lexer.l */; settings = {COMPILER_FLAGS = "-Wno-error"; }; };
+		D284BECC0ADD80A20027CCDF /* dnsextd_parser.y in Sources */ = {isa = PBXBuildFile; fileRef = FF13FFEC0A5DA45500897C81 /* dnsextd_parser.y */; };
+		D284BECD0ADD80A20027CCDF /* PlatformCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FFCB6D73075D539900B8AF62 /* PlatformCommon.c */; };
+		D284BECF0ADD80A20027CCDF /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */; };
+		D284BED00ADD80A20027CCDF /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65713D46025A293200000109 /* SystemConfiguration.framework */; };
+		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 */; };
+		D284BEE00ADD80A70027CCDF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFFB0DB407B43D2700B88D48 /* Foundation.framework */; };
+		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 */; };
+		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 */; };
+		FFA572490AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
+		FFA5724A0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
+		FFA5724B0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */ = {isa = PBXBuildFile; fileRef = FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */; };
+		FFAE66F0105F0CD900162116 /* ddnswriteconfig in Resources */ = {isa = PBXBuildFile; fileRef = D284BEE80ADD80A70027CCDF /* ddnswriteconfig */; };
+		FFB437150EB165BD00E17C68 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA213D02786FC30CCA2C71 /* IOKit.framework */; };
+		FFC22AA20B00F42A00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
+		FFC22AA30B00F42B00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
+		FFC22AA40B00F42C00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */; };
+		FFC22AA50B00F43000BAB070 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
+		FFC22AA60B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
+		FFC22AA70B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = 6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
+		FFF589B70E37F66800EF515C /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF5852100DD27BD300862BDF /* ClientCommon.c */; };
+		FFF589C10E37F67E00EF515C /* ClientCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = FF5852100DD27BD300862BDF /* ClientCommon.c */; };
+		FFFA38630AEEDB090065B80A /* dnssd_clientlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */; };
+		FFFA38650AEEDB130065B80A /* dnssd_clientstub.c in Sources */ = {isa = PBXBuildFile; fileRef = FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */; };
+		FFFA38660AEEDB2B0065B80A /* dnssd_ipc.c in Sources */ = {isa = PBXBuildFile; fileRef = F5E11B5A04A28126019798ED /* dnssd_ipc.c */; };
+		FFFF8F810C3307C400722979 /* dnsextd.conf in CopyFiles */ = {isa = PBXBuildFile; fileRef = FFFF8F800C3307AC00722979 /* dnsextd.conf */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXBuildRule section */
+		D284BF750ADD850C0027CCDF /* PBXBuildRule */ = {
+			isa = PBXBuildRule;
+			compilerSpec = com.apple.compilers.proxy.script;
+			fileType = sourcecode.yacc;
+			isEditable = 1;
+			outputFiles = (
+				"$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).h",
+				"$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).c",
+			);
+			script = "echo NOOP yacc ${INPUT_FILE_PATH}";
+		};
+		D284BFB80ADD8E510027CCDF /* PBXBuildRule */ = {
+			isa = PBXBuildRule;
+			compilerSpec = com.apple.compilers.proxy.script;
+			fileType = sourcecode.lex;
+			isEditable = 1;
+			outputFiles = (
+				"$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).c",
+			);
+			script = "/usr/bin/flex -i -o${DERIVED_FILE_DIR}/${INPUT_FILE_BASE}.c ${INPUT_FILE_PATH}";
+		};
+/* End PBXBuildRule section */
+
+/* Begin PBXContainerItemProxy section */
+		03067D670C83A3830022BE1F /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = D284BE500ADD80740027CCDF;
+			remoteInfo = mDNSResponder;
+		};
+		03067D690C83A3890022BE1F /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = D284BE750ADD80800027CCDF;
+			remoteInfo = "mDNSResponder debug";
+		};
+		03067D6B0C83A3920022BE1F /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = D284BEA50ADD80920027CCDF;
+			remoteInfo = "dns-sd tool";
+		};
+		03067D6D0C83A39C0022BE1F /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 2E0405EF0C31955500F13B59;
+			remoteInfo = mDNSResponderHelper;
+		};
+		03067D850C849CC30022BE1F /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 03067D640C83A3700022BE1F;
+			remoteInfo = "Build Some";
+		};
+		2130257012400E9300AC839F /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = FFA572650AF190F10055A0F1;
+			remoteInfo = SystemLibrariesDynamic;
+		};
+		2141DCFC123FFB7D0086D23E /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 2141DCF8123FFB5D0086D23E;
+			remoteInfo = SystemLibraries;
+		};
+		2141DD0D123FFC960086D23E /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 2141DD0B123FFC7F0086D23E;
+			remoteInfo = SystemLibrariesStatic;
+		};
+		215FFB18124002C100470DE1 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 2141DD1C123FFCDB0086D23E;
+			remoteInfo = libdns_sd_static;
+		};
+		215FFB1A124002C700470DE1 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 2141DD23123FFD0F0086D23E;
+			remoteInfo = libdns_sd_debug_static;
+		};
+		215FFB1C124002CC00470DE1 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 2141DD29123FFD2C0086D23E;
+			remoteInfo = libdns_sd_profile_static;
+		};
+		217A4C48138EE14C000A5BA8 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 213FB21712028A7A002B3A08;
+			remoteInfo = BonjourEvents;
+		};
+		4AE471690EAFF83800A6C5AD /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 4AE471670EAFF81900A6C5AD;
+			remoteInfo = dns_sd.jar;
+		};
+		84C5B3401665544B00C324A8 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 84C5B3341665529800C324A8;
+			remoteInfo = dns_services;
+		};
+		D284BF2B0ADD815A0027CCDF /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = D284BEBF0ADD80A20027CCDF;
+			remoteInfo = dnsextd;
+		};
+		D284BF2D0ADD81600027CCDF /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = D284BEDB0ADD80A70027CCDF;
+			remoteInfo = ddnswriteconfig;
+		};
+		D284BF2F0ADD81630027CCDF /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = D284BEEA0ADD80B00027CCDF;
+			remoteInfo = PreferencePane;
+		};
+		FFA572680AF190FF0055A0F1 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = FFB765830AEED9C700583A2C;
+			remoteInfo = libdns_sd;
+		};
+		FFA5726A0AF191010055A0F1 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = FFA572300AF18F1C0055A0F1;
+			remoteInfo = "libdns_sd debug";
+		};
+		FFA5726C0AF191020055A0F1 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+			proxyType = 1;
+			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 */;
+			proxyType = 1;
+			remoteGlobalIDString = 00AD62BB032D7A0C0CCA2C71;
+			remoteInfo = "Build Main";
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		4A7B9E7F14FDA21B00B84CC1 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 8;
+			dstPath = /usr/local/OpenSourceVersions;
+			dstSubfolderSpec = 0;
+			files = (
+				4A7B9E8014FDA25000B84CC1 /* mDNSResponder.plist in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+		4A7B9E8114FDA25500B84CC1 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 8;
+			dstPath = /usr/local/OpenSourceLicenses;
+			dstSubfolderSpec = 0;
+			files = (
+				4A7B9E8214FDA26C00B84CC1 /* mDNSResponder.txt in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+		4AAE0C5A0C68E6EC003882A5 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 8;
+			dstPath = /usr/share/man/man8;
+			dstSubfolderSpec = 0;
+			files = (
+				4AAE0C9A0C68EA81003882A5 /* mDNSResponderHelper.8 in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+		72FB545D166D5FB00090B2D9 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 12;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8418673D15AB8BFF00BB7F70 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 8;
+			dstPath = /private/etc/asl/;
+			dstSubfolderSpec = 0;
+			files = (
+				8418673E15AB8C2D00BB7F70 /* com.apple.networking.mDNSResponder in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+		D284BE6A0ADD80740027CCDF /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 8;
+			dstPath = /usr/share/man/man8;
+			dstSubfolderSpec = 0;
+			files = (
+				D284BE6B0ADD80740027CCDF /* mDNSResponder.8 in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+		D284BEAB0ADD80920027CCDF /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 8;
+			dstPath = /usr/share/man/man1;
+			dstSubfolderSpec = 0;
+			files = (
+				D284BEAC0ADD80920027CCDF /* dns-sd.1 in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+		D284BED40ADD80A20027CCDF /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 8;
+			dstPath = /usr/share/man/man8;
+			dstSubfolderSpec = 0;
+			files = (
+				D284BED50ADD80A20027CCDF /* dnsextd.8 in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+		FFFF8F770C32F0FD00722979 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 8;
+			dstPath = /private/etc;
+			dstSubfolderSpec = 0;
+			files = (
+				FFFF8F810C3307C400722979 /* dnsextd.conf in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		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>"; };
+		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>"; };
+		2120ABD416B71614007089B6 /* CUPolicy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CUPolicy.c; sourceTree = "<group>"; };
+		2124FA2B1471E98C0021D7BB /* nsec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nsec.h; path = ../mDNSCore/nsec.h; sourceTree = "<group>"; };
+		2124FA2F1471E9B50021D7BB /* dnssec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dnssec.h; path = ../mDNSCore/dnssec.h; sourceTree = "<group>"; };
+		2124FA321471E9DE0021D7BB /* nsec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nsec.c; path = ../mDNSCore/nsec.c; sourceTree = "<group>"; };
+		2127A47515C3C7B900A857FC /* nsec3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nsec3.c; path = ../mDNSCore/nsec3.c; sourceTree = "<group>"; };
+		2127A47615C3C7B900A857FC /* nsec3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nsec3.h; path = ../mDNSCore/nsec3.h; sourceTree = "<group>"; };
+		213BDC6C147319F400000896 /* dnssec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnssec.c; path = ../mDNSCore/dnssec.c; sourceTree = "<group>"; };
+		213FB21812028A7A002B3A08 /* BonjourEvents.plugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BonjourEvents.plugin; sourceTree = BUILT_PRODUCTS_DIR; };
+		213FB22C12028B53002B3A08 /* BonjourEvents.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BonjourEvents.c; sourceTree = "<group>"; };
+		213FB22D12028B53002B3A08 /* BonjourEvents-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "BonjourEvents-Info.plist"; sourceTree = "<group>"; };
+		2141DD1D123FFCDB0086D23E /* libdns_sd.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdns_sd.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		2141DD24123FFD0F0086D23E /* libdns_sd_debug.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdns_sd_debug.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		2141DD2A123FFD2C0086D23E /* libdns_sd_profile.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdns_sd_profile.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		216D9ACD1720C9F5008066E1 /* VPNService.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = VPNService.c; sourceTree = "<group>"; };
+		218E8E4F156D8C0300720DA0 /* dnsproxy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnsproxy.c; path = ../mDNSCore/dnsproxy.c; sourceTree = "<group>"; };
+		218E8E50156D8C0300720DA0 /* dnsproxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dnsproxy.h; path = ../mDNSCore/dnsproxy.h; sourceTree = "<group>"; };
+		219D5541149ED645004464AE /* libxml2.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.2.dylib; path = SDKs/MacOSX10.8.sdk/usr/lib/libxml2.2.dylib; sourceTree = DEVELOPER_DIR; };
+		21A57F4A145B2AE100939099 /* CryptoAlg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = CryptoAlg.c; path = ../mDNSCore/CryptoAlg.c; sourceTree = "<group>"; };
+		21A57F4B145B2AE100939099 /* CryptoAlg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CryptoAlg.h; path = ../mDNSCore/CryptoAlg.h; sourceTree = "<group>"; };
+		21A57F51145B2B1400939099 /* CryptoSupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CryptoSupport.c; sourceTree = "<group>"; };
+		21A57F52145B2B1400939099 /* CryptoSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoSupport.h; sourceTree = "<group>"; };
+		21DD8FBD161E9A250033C8F8 /* anonymous.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = anonymous.c; path = ../mDNSCore/anonymous.c; sourceTree = "<group>"; };
+		21DD8FBE161E9A250033C8F8 /* anonymous.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = anonymous.h; path = ../mDNSCore/anonymous.h; sourceTree = "<group>"; };
+		21DED43415702C0F0060B6B9 /* DNSProxySupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DNSProxySupport.c; sourceTree = "<group>"; };
+		21F432971134AA6800581B69 /* WebFilterDNS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebFilterDNS.framework; path = /System/Library/PrivateFrameworks/WebFilterDNS.framework; sourceTree = "<absolute>"; };
+		2E0405EB0C3190DC00F13B59 /* helpermsg.defs */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.mig; path = helpermsg.defs; 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>"; };
+		2E0406CA0C31E9AD00F13B59 /* helper-main.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "helper-main.c"; sourceTree = "<group>"; };
+		2E35528F0C3A95C100CA1CB7 /* helper-error.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "helper-error.h"; sourceTree = "<group>"; };
+		2E8165F60C59835F00485EB2 /* libipsec.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libipsec.dylib; path = /usr/lib/libipsec.dylib; sourceTree = "<absolute>"; };
+		2E96A5250C39BE480087C4D2 /* helper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = helper.h; sourceTree = "<group>"; };
+		2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "helper-stubs.c"; sourceTree = "<group>"; };
+		2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "helpermsg-types.h"; sourceTree = "<group>"; };
+		2EDC5E720C39EA640092701B /* helper-server.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "helper-server.h"; sourceTree = "<group>"; };
+		3F347CF5185D57CD00367B40 /* base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = "<group>"; };
+		4A2E69DD0F5475A3004A87B0 /* uds_daemon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = uds_daemon.h; path = ../mDNSShared/uds_daemon.h; sourceTree = SOURCE_ROOT; };
+		4A3600DF0F34F8CD00453EFB /* DeviceToDeviceManager.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DeviceToDeviceManager.framework; path = /System/Library/PrivateFrameworks/DeviceToDeviceManager.framework; sourceTree = "<absolute>"; };
+		4A7B9E7C14FDA19F00B84CC1 /* mDNSResponder.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = mDNSResponder.txt; sourceTree = "<group>"; };
+		4A7B9E7E14FDA1BB00B84CC1 /* mDNSResponder.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = mDNSResponder.plist; sourceTree = "<group>"; };
+		4A8202510C56C36500DDFD48 /* ipsec_strerror.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipsec_strerror.h; sourceTree = "<group>"; };
+		4A8202520C56C36500DDFD48 /* libpfkey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libpfkey.h; sourceTree = "<group>"; };
+		4A8202530C56C36600DDFD48 /* pfkey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pfkey.c; sourceTree = "<group>"; };
+		4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mDNSResponderHelper.8; sourceTree = SOURCE_ROOT; };
+		4ADB5F230F6AB9F400B95BF3 /* helper-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "helper-entitlements.plist"; sourceTree = "<group>"; };
+		4BD2B638134FE09F002B96D5 /* P2PPacketFilter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = P2PPacketFilter.c; sourceTree = "<group>"; };
+		4BD2B639134FE09F002B96D5 /* P2PPacketFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = P2PPacketFilter.h; sourceTree = "<group>"; };
+		654BE64F02B63B93000001D1 /* mDNSEmbeddedAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mDNSEmbeddedAPI.h; path = ../mDNSCore/mDNSEmbeddedAPI.h; sourceTree = "<group>"; };
+		654BE65002B63B93000001D1 /* mDNSDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mDNSDebug.h; path = ../mDNSCore/mDNSDebug.h; sourceTree = "<group>"; };
+		65713D46025A293200000109 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = /System/Library/Frameworks/SystemConfiguration.framework; sourceTree = "<absolute>"; };
+		6575FBE9022EAF5A00000109 /* mDNS.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; name = mDNS.c; path = ../mDNSCore/mDNS.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
+		6575FBEB022EAF7200000109 /* mDNSMacOSX.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = mDNSMacOSX.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
+		6575FBEC022EAF7200000109 /* daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = daemon.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
+		6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscoveryDefines.h; sourceTree = "<group>"; };
+		6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = DNSServiceDiscoveryReply.defs; sourceTree = "<group>"; };
+		6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = DNSServiceDiscoveryRequest.defs; sourceTree = "<group>"; };
+		6575FC20022EB7AA00000109 /* SamplemDNSClient.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.c; path = SamplemDNSClient.c; sourceTree = SOURCE_ROOT; tabWidth = 4; usesTabs = 0; };
+		72FB545A166D5F960090B2D9 /* dnsctl.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dnsctl.c; path = ../Clients/dnsctl.c; sourceTree = "<group>"; };
+		72FB545F166D5FB00090B2D9 /* dnsctl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dnsctl; sourceTree = BUILT_PRODUCTS_DIR; };
+		7F18A9F60587CEF6001880B3 /* DNSCommon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = DNSCommon.c; path = ../mDNSCore/DNSCommon.c; sourceTree = SOURCE_ROOT; };
+		7F18A9F70587CEF6001880B3 /* uDNS.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = uDNS.c; path = ../mDNSCore/uDNS.c; sourceTree = SOURCE_ROOT; };
+		7F461DB5062DBF2900672BF3 /* DNSDigest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = DNSDigest.c; path = ../mDNSCore/DNSDigest.c; sourceTree = SOURCE_ROOT; };
+		7F869685066EE02400D2A2DC /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = "<absolute>"; };
+		7FC8F9D406D14E66007E879D /* LegacyNATTraversal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = LegacyNATTraversal.c; sourceTree = SOURCE_ROOT; };
+		8415A6561897109000BDBA26 /* libdns_services.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libdns_services.dylib; path = ../../../../../../../usr/lib/libdns_services.dylib; sourceTree = "<group>"; };
+		8418673A15AB8B6900BB7F70 /* com.apple.networking.mDNSResponder */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.networking.mDNSResponder; sourceTree = "<group>"; };
+		8418673C15AB8B8000BB7F70 /* mDNSResponderLogging.mobileconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = mDNSResponderLogging.mobileconfig; sourceTree = "<group>"; };
+		848DA5C6165477E000D2E8B4 /* xpc_services.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xpc_services.c; path = Private/xpc_services.c; sourceTree = "<group>"; };
+		848DA5C9165477EB00D2E8B4 /* xpc_services.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xpc_services.h; path = Private/xpc_services.h; sourceTree = "<group>"; };
+		848DA5D516547F7200D2E8B4 /* dns_xpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_xpc.h; path = Private/dns_xpc.h; sourceTree = "<group>"; };
+		84C5B3351665529800C324A8 /* libdns_services_mdns.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libdns_services_mdns.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_mdns.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_services_mdns.h; path = Private/dns_services_mdns.h; sourceTree = "<group>"; };
+		D284BE730ADD80740027CCDF /* mDNSResponder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mDNSResponder; sourceTree = BUILT_PRODUCTS_DIR; };
+		D284BE950ADD80800027CCDF /* mDNSResponder.debug */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mDNSResponder.debug; 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; };
+		D284C04D0ADD95D30027CCDF /* Info-PreferencePane.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "Info-PreferencePane.plist"; path = "PreferencePane/Info-PreferencePane.plist"; sourceTree = "<group>"; };
+		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; };
+		DB2CC4450662DD1100335AB3 /* DNSRecord.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSRecord.java; path = ../mDNSShared/Java/DNSRecord.java; sourceTree = SOURCE_ROOT; };
+		DB2CC4460662DD1100335AB3 /* DNSSD.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSSD.java; path = ../mDNSShared/Java/DNSSD.java; sourceTree = SOURCE_ROOT; };
+		DB2CC4470662DD1100335AB3 /* DNSSDException.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSSDException.java; path = ../mDNSShared/Java/DNSSDException.java; sourceTree = SOURCE_ROOT; };
+		DB2CC4480662DD1100335AB3 /* DNSSDRegistration.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSSDRegistration.java; path = ../mDNSShared/Java/DNSSDRegistration.java; sourceTree = SOURCE_ROOT; };
+		DB2CC4490662DD1100335AB3 /* DNSSDService.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DNSSDService.java; path = ../mDNSShared/Java/DNSSDService.java; sourceTree = SOURCE_ROOT; };
+		DB2CC44A0662DD1100335AB3 /* DomainListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = DomainListener.java; path = ../mDNSShared/Java/DomainListener.java; sourceTree = SOURCE_ROOT; };
+		DB2CC44B0662DD1100335AB3 /* JNISupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = JNISupport.c; path = ../mDNSShared/Java/JNISupport.c; sourceTree = SOURCE_ROOT; };
+		DB2CC44C0662DD1100335AB3 /* QueryListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = QueryListener.java; path = ../mDNSShared/Java/QueryListener.java; sourceTree = SOURCE_ROOT; };
+		DB2CC44D0662DD1100335AB3 /* RegisterListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = RegisterListener.java; path = ../mDNSShared/Java/RegisterListener.java; sourceTree = SOURCE_ROOT; };
+		DB2CC44E0662DD1100335AB3 /* ResolveListener.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = ResolveListener.java; path = ../mDNSShared/Java/ResolveListener.java; sourceTree = SOURCE_ROOT; };
+		DB2CC44F0662DD1100335AB3 /* TXTRecord.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; name = TXTRecord.java; path = ../mDNSShared/Java/TXTRecord.java; sourceTree = SOURCE_ROOT; };
+		DB2CC4680662DFF500335AB3 /* JavaVM.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaVM.framework; path = /System/Library/Frameworks/JavaVM.framework; sourceTree = "<absolute>"; };
+		DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mDNSDebug.c; path = ../mDNSShared/mDNSDebug.c; sourceTree = SOURCE_ROOT; };
+		DBAAFE2C057E8F660085CAD0 /* GenLinkedList.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GenLinkedList.c; path = ../mDNSShared/GenLinkedList.c; sourceTree = SOURCE_ROOT; };
+		F525E72804AA167501F1CF4D /* uds_daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = uds_daemon.c; path = ../mDNSShared/uds_daemon.c; sourceTree = SOURCE_ROOT; };
+		F5E11B5A04A28126019798ED /* dnssd_ipc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dnssd_ipc.c; path = ../mDNSShared/dnssd_ipc.c; sourceTree = SOURCE_ROOT; };
+		F5E11B5B04A28126019798ED /* dnssd_ipc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dnssd_ipc.h; path = ../mDNSShared/dnssd_ipc.h; sourceTree = SOURCE_ROOT; };
+		FF08480607CEB8E800AE6769 /* inprogress.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = inprogress.tiff; path = PreferencePane/Artwork/inprogress.tiff; sourceTree = SOURCE_ROOT; };
+		FF13FFEA0A5DA44A00897C81 /* dnsextd_lexer.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; name = dnsextd_lexer.l; path = ../mDNSShared/dnsextd_lexer.l; sourceTree = SOURCE_ROOT; };
+		FF13FFEC0A5DA45500897C81 /* dnsextd_parser.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; name = dnsextd_parser.y; path = ../mDNSShared/dnsextd_parser.y; sourceTree = SOURCE_ROOT; };
+		FF1C919D07021D77001048AB /* dns-sd.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = "dns-sd.1"; path = "../mDNSShared/dns-sd.1"; sourceTree = SOURCE_ROOT; };
+		FF1C919F07021E3F001048AB /* dns-sd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "dns-sd.c"; path = "../Clients/dns-sd.c"; sourceTree = SOURCE_ROOT; };
+		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; };
+		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; };
+		FFA572390AF18F1C0055A0F1 /* libsystem_dnssd_debug.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_dnssd_debug.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		FFA572450AF18F450055A0F1 /* libsystem_dnssd_profile.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libsystem_dnssd_profile.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DNSServiceDiscovery.c; sourceTree = "<group>"; };
+		FFA572600AF1908D0055A0F1 /* DNSServiceDiscovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNSServiceDiscovery.h; sourceTree = "<group>"; };
+		FFA572630AF190C20055A0F1 /* dns_sd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dns_sd.h; path = ../mDNSShared/dns_sd.h; sourceTree = SOURCE_ROOT; };
+		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>"; };
+		FFFB0DB407B43D2700B88D48 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+		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 */
+		213FB21612028A7A002B3A08 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				213FB23D12028C5A002B3A08 /* CoreFoundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2141DD1B123FFCDB0086D23E /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2141DD22123FFD0F0086D23E /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2141DD28123FFD2C0086D23E /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2E0405EE0C31955500F13B59 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				FFB437150EB165BD00E17C68 /* IOKit.framework in Frameworks */,
+				2E0406150C3197CB00F13B59 /* libbsm.dylib in Frameworks */,
+				2E04070A0C31EEEC00F13B59 /* CoreFoundation.framework in Frameworks */,
+				2E04070B0C31EEEC00F13B59 /* SystemConfiguration.framework in Frameworks */,
+				2E4D9B050C38C19500480551 /* Security.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		72FB545C166D5FB00090B2D9 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8415A6571897109000BDBA26 /* libdns_services.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		84C5B3321665529800C324A8 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BE640ADD80740027CCDF /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D284BE650ADD80740027CCDF /* CoreFoundation.framework in Frameworks */,
+				D284BE660ADD80740027CCDF /* SystemConfiguration.framework in Frameworks */,
+				D284BE670ADD80740027CCDF /* IOKit.framework in Frameworks */,
+				D284BE680ADD80740027CCDF /* Security.framework in Frameworks */,
+				219D5542149ED645004464AE /* libxml2.2.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BE8C0ADD80800027CCDF /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D284BE8D0ADD80800027CCDF /* CoreFoundation.framework in Frameworks */,
+				D284BE8E0ADD80800027CCDF /* SystemConfiguration.framework in Frameworks */,
+				D284BE8F0ADD80800027CCDF /* IOKit.framework in Frameworks */,
+				D284BE900ADD80800027CCDF /* Security.framework in Frameworks */,
+				219D5543149ED645004464AE /* libxml2.2.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEA90ADD80920027CCDF /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEB80ADD809A0027CCDF /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D284BEB90ADD809A0027CCDF /* JavaVM.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BECE0ADD80A20027CCDF /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D284BECF0ADD80A20027CCDF /* CoreFoundation.framework in Frameworks */,
+				D284BED00ADD80A20027CCDF /* SystemConfiguration.framework in Frameworks */,
+				D284BED10ADD80A20027CCDF /* IOKit.framework in Frameworks */,
+				D284BED20ADD80A20027CCDF /* Security.framework in Frameworks */,
+				2E8165F90C59838100485EB2 /* libipsec.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEDF0ADD80A70027CCDF /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D284BEE00ADD80A70027CCDF /* 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;
+			files = (
+				D284BF020ADD80B00027CCDF /* SystemConfiguration.framework in Frameworks */,
+				D284BF030ADD80B00027CCDF /* Security.framework in Frameworks */,
+				D284BF040ADD80B00027CCDF /* Cocoa.framework in Frameworks */,
+				D284BF050ADD80B00027CCDF /* PreferencePanes.framework in Frameworks */,
+				D284BF060ADD80B00027CCDF /* CoreFoundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		FFA572360AF18F1C0055A0F1 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		FFA572420AF18F450055A0F1 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		FFB765820AEED9C700583A2C /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		08FB7794FE84155DC02AAC07 /* mDNSResponder */ = {
+			isa = PBXGroup;
+			children = (
+				8415A6561897109000BDBA26 /* libdns_services.dylib */,
+				3F347CF5185D57CD00367B40 /* base.xcconfig */,
+				08FB7795FE84155DC02AAC07 /* mDNS Server Sources */,
+				6575FC1F022EB78C00000109 /* Command-Line Clients */,
+				213FB20912028902002B3A08 /* Bonjour Events Plugin */,
+				6575FBFE022EAFA800000109 /* MIG files */,
+				DB2CC4420662DCE500335AB3 /* Java Support */,
+				FFFB0DA407B43BED00B88D48 /* PreferencePane */,
+				08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
+				19C28FBDFE9D53C911CA2CBB /* Products */,
+			);
+			name = mDNSResponder;
+			sourceTree = "<group>";
+		};
+		08FB7795FE84155DC02AAC07 /* mDNS Server Sources */ = {
+			isa = PBXGroup;
+			children = (
+				84F4C08F188F04CF00D1E1DE /* dns_services_mdns.h */,
+				216D9ACD1720C9F5008066E1 /* VPNService.c */,
+				2120ABD416B71614007089B6 /* CUPolicy.c */,
+				72FB545A166D5F960090B2D9 /* dnsctl.c */,
+				84C5B339166553AF00C324A8 /* dns_services.c */,
+				848DA5D516547F7200D2E8B4 /* dns_xpc.h */,
+				848DA5C9165477EB00D2E8B4 /* xpc_services.h */,
+				848DA5C6165477E000D2E8B4 /* xpc_services.c */,
+				21070E5D16486B9000A69507 /* DNSSECSupport.c */,
+				21070E5E16486B9000A69507 /* DNSSECSupport.h */,
+				21DD8FBD161E9A250033C8F8 /* anonymous.c */,
+				21DD8FBE161E9A250033C8F8 /* anonymous.h */,
+				2127A47515C3C7B900A857FC /* nsec3.c */,
+				2127A47615C3C7B900A857FC /* nsec3.h */,
+				8418673C15AB8B8000BB7F70 /* mDNSResponderLogging.mobileconfig */,
+				8418673A15AB8B6900BB7F70 /* com.apple.networking.mDNSResponder */,
+				21DED43415702C0F0060B6B9 /* DNSProxySupport.c */,
+				218E8E4F156D8C0300720DA0 /* dnsproxy.c */,
+				218E8E50156D8C0300720DA0 /* dnsproxy.h */,
+				213BDC6C147319F400000896 /* dnssec.c */,
+				2124FA321471E9DE0021D7BB /* nsec.c */,
+				2124FA2F1471E9B50021D7BB /* dnssec.h */,
+				2124FA2B1471E98C0021D7BB /* nsec.h */,
+				21A57F51145B2B1400939099 /* CryptoSupport.c */,
+				21A57F52145B2B1400939099 /* CryptoSupport.h */,
+				21A57F4A145B2AE100939099 /* CryptoAlg.c */,
+				21A57F4B145B2AE100939099 /* CryptoAlg.h */,
+				4ADB5F230F6AB9F400B95BF3 /* helper-entitlements.plist */,
+				4A2E69DD0F5475A3004A87B0 /* uds_daemon.h */,
+				4AAE0C7A0C68E97F003882A5 /* mDNSResponderHelper.8 */,
+				2ECC11A50C4FEC3800CB1885 /* helpermsg-types.h */,
+				2E35528F0C3A95C100CA1CB7 /* helper-error.h */,
+				2E96A52D0C39C1A50087C4D2 /* helper-stubs.c */,
+				2EDC5E720C39EA640092701B /* helper-server.h */,
+				2E96A5250C39BE480087C4D2 /* helper.h */,
+				2E0405F40C3195F700F13B59 /* helper.c */,
+				2E0406CA0C31E9AD00F13B59 /* helper-main.c */,
+				4A8202510C56C36500DDFD48 /* ipsec_strerror.h */,
+				4A8202520C56C36500DDFD48 /* libpfkey.h */,
+				4A8202530C56C36600DDFD48 /* pfkey.c */,
+				7FC8F9D406D14E66007E879D /* LegacyNATTraversal.c */,
+				7F461DB5062DBF2900672BF3 /* DNSDigest.c */,
+				F525E72804AA167501F1CF4D /* uds_daemon.c */,
+				F5E11B5A04A28126019798ED /* dnssd_ipc.c */,
+				F5E11B5B04A28126019798ED /* dnssd_ipc.h */,
+				6575FBEC022EAF7200000109 /* daemon.c */,
+				6575FBE9022EAF5A00000109 /* mDNS.c */,
+				6575FBEB022EAF7200000109 /* mDNSMacOSX.c */,
+				654BE64F02B63B93000001D1 /* mDNSEmbeddedAPI.h */,
+				654BE65002B63B93000001D1 /* mDNSDebug.h */,
+				DBAAFE29057E8F4D0085CAD0 /* mDNSDebug.c */,
+				000753D303367C1C0CCA2C71 /* mDNSMacOSX.h */,
+				DBAAFE2C057E8F660085CAD0 /* GenLinkedList.c */,
+				FFCB6D73075D539900B8AF62 /* PlatformCommon.c */,
+				FF1C919D07021D77001048AB /* dns-sd.1 */,
+				FF485D5105632E0000130380 /* mDNSResponder.8 */,
+				FFF4F63A06CFE4DD00459EFD /* dnsextd.8 */,
+				FFFF8F800C3307AC00722979 /* dnsextd.conf */,
+				FF85880B0BD599F40080D89F /* mDNSResponder.sb */,
+				4A7B9E7C14FDA19F00B84CC1 /* mDNSResponder.txt */,
+				4A7B9E7E14FDA1BB00B84CC1 /* mDNSResponder.plist */,
+				7F18A9F60587CEF6001880B3 /* DNSCommon.c */,
+				7F18A9F70587CEF6001880B3 /* uDNS.c */,
+				FF25794606C9A8BF00376F7B /* dnsextd.c */,
+				FF13FFEA0A5DA44A00897C81 /* dnsextd_lexer.l */,
+				FF13FFEC0A5DA45500897C81 /* dnsextd_parser.y */,
+				FFFA38620AEEDB090065B80A /* dnssd_clientlib.c */,
+				FFFA38640AEEDB130065B80A /* dnssd_clientstub.c */,
+				FFA572600AF1908D0055A0F1 /* DNSServiceDiscovery.h */,
+				FFA572480AF18FCC0055A0F1 /* DNSServiceDiscovery.c */,
+				FFA572630AF190C20055A0F1 /* dns_sd.h */,
+				4BD2B638134FE09F002B96D5 /* P2PPacketFilter.c */,
+				4BD2B639134FE09F002B96D5 /* P2PPacketFilter.h */,
+			);
+			name = "mDNS Server Sources";
+			sourceTree = "<group>";
+		};
+		08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
+			isa = PBXGroup;
+			children = (
+				219D5541149ED645004464AE /* libxml2.2.dylib */,
+				4A3600DF0F34F8CD00453EFB /* DeviceToDeviceManager.framework */,
+				2E8165F60C59835F00485EB2 /* libipsec.dylib */,
+				65713D46025A293200000109 /* SystemConfiguration.framework */,
+				2E0406140C3197CB00F13B59 /* libbsm.dylib */,
+				7F869685066EE02400D2A2DC /* Security.framework */,
+				FFFB0DB407B43D2700B88D48 /* Foundation.framework */,
+				09AB6884FE841BABC02AAC07 /* CoreFoundation.framework */,
+				00CA213D02786FC30CCA2C71 /* IOKit.framework */,
+				DB2CC4680662DFF500335AB3 /* JavaVM.framework */,
+				FF2609FA07B4433800CE10E5 /* Cocoa.framework */,
+				FF260A1F07B4436900CE10E5 /* PreferencePanes.framework */,
+				21F432971134AA6800581B69 /* WebFilterDNS.framework */,
+			);
+			name = "External Frameworks and Libraries";
+			sourceTree = "<group>";
+		};
+		19C28FBDFE9D53C911CA2CBB /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				D284C04D0ADD95D30027CCDF /* Info-PreferencePane.plist */,
+				D284BE730ADD80740027CCDF /* mDNSResponder */,
+				D284BE950ADD80800027CCDF /* mDNSResponder.debug */,
+				D284BEB00ADD80920027CCDF /* dns-sd */,
+				D284BEBE0ADD809A0027CCDF /* libjdns_sd.jnilib */,
+				D284BED90ADD80A20027CCDF /* dnsextd */,
+				D284BEE80ADD80A70027CCDF /* ddnswriteconfig */,
+				D284BF0C0ADD80B00027CCDF /* Bonjour.prefPane */,
+				FFB765840AEED9C700583A2C /* libsystem_dnssd.dylib */,
+				FFA572390AF18F1C0055A0F1 /* libsystem_dnssd_debug.dylib */,
+				FFA572450AF18F450055A0F1 /* libsystem_dnssd_profile.dylib */,
+				2E0405F00C31955500F13B59 /* mDNSResponderHelper */,
+				213FB21812028A7A002B3A08 /* BonjourEvents.plugin */,
+				2141DD1D123FFCDB0086D23E /* libdns_sd.a */,
+				2141DD24123FFD0F0086D23E /* libdns_sd_debug.a */,
+				2141DD2A123FFD2C0086D23E /* libdns_sd_profile.a */,
+				84C5B3351665529800C324A8 /* libdns_services_mdns.dylib */,
+				72FB545F166D5FB00090B2D9 /* dnsctl */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		213FB20912028902002B3A08 /* Bonjour Events Plugin */ = {
+			isa = PBXGroup;
+			children = (
+				213FB22C12028B53002B3A08 /* BonjourEvents.c */,
+				213FB22D12028B53002B3A08 /* BonjourEvents-Info.plist */,
+			);
+			name = "Bonjour Events Plugin";
+			sourceTree = "<group>";
+		};
+		6575FBFE022EAFA800000109 /* MIG files */ = {
+			isa = PBXGroup;
+			children = (
+				2E0405EB0C3190DC00F13B59 /* helpermsg.defs */,
+				6575FBFF022EAFBA00000109 /* DNSServiceDiscoveryDefines.h */,
+				6575FC00022EAFBA00000109 /* DNSServiceDiscoveryReply.defs */,
+				6575FC01022EAFBA00000109 /* DNSServiceDiscoveryRequest.defs */,
+			);
+			name = "MIG files";
+			sourceTree = "<group>";
+		};
+		6575FC1F022EB78C00000109 /* Command-Line Clients */ = {
+			isa = PBXGroup;
+			children = (
+				6575FC20022EB7AA00000109 /* SamplemDNSClient.c */,
+				FF1C919F07021E3F001048AB /* dns-sd.c */,
+				FF5852100DD27BD300862BDF /* ClientCommon.c */,
+			);
+			name = "Command-Line Clients";
+			sourceTree = "<group>";
+		};
+		DB2CC4420662DCE500335AB3 /* Java Support */ = {
+			isa = PBXGroup;
+			children = (
+				DB2CC4430662DD1100335AB3 /* BaseListener.java */,
+				DB2CC4440662DD1100335AB3 /* BrowseListener.java */,
+				DB2CC4450662DD1100335AB3 /* DNSRecord.java */,
+				DB2CC4460662DD1100335AB3 /* DNSSD.java */,
+				DB2CC4470662DD1100335AB3 /* DNSSDException.java */,
+				DB2CC4480662DD1100335AB3 /* DNSSDRegistration.java */,
+				DB2CC4490662DD1100335AB3 /* DNSSDService.java */,
+				DB2CC44A0662DD1100335AB3 /* DomainListener.java */,
+				DB2CC44B0662DD1100335AB3 /* JNISupport.c */,
+				DB2CC44C0662DD1100335AB3 /* QueryListener.java */,
+				DB2CC44D0662DD1100335AB3 /* RegisterListener.java */,
+				DB2CC44E0662DD1100335AB3 /* ResolveListener.java */,
+				DB2CC44F0662DD1100335AB3 /* TXTRecord.java */,
+				FF2C5FB00A48B8680066DA11 /* DNSSDRecordRegistrar.java */,
+				FF2C5FB20A48B86E0066DA11 /* RegisterRecordListener.java */,
+			);
+			name = "Java Support";
+			sourceTree = "<group>";
+		};
+		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 */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		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 */,
+				FF260A2307B4463400CE10E5 /* Resources */,
+			);
+			path = PreferencePane;
+			sourceTree = SOURCE_ROOT;
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		2141DD19123FFCDB0086D23E /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2141DD20123FFD0F0086D23E /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2141DD26123FFD2C0086D23E /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2EC8F8ED0C39CCCA003C9C48 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2EC8F8EC0C39CCAC003C9C48 /* helper.h in Headers */,
+				2EDC5E730C39EA640092701B /* helper-server.h in Headers */,
+				2E3552920C3A95C100CA1CB7 /* helper-error.h in Headers */,
+				2ECC11A80C4FEC3800CB1885 /* helpermsg-types.h in Headers */,
+				2E8165E80C5980E300485EB2 /* libpfkey.h in Headers */,
+				2E8165EA0C5980F700485EB2 /* ipsec_strerror.h in Headers */,
+				4BD2B63B134FE09F002B96D5 /* P2PPacketFilter.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		84C5B3331665529800C324A8 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				84F4C090188F050200D1E1DE /* dns_services_mdns.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BE520ADD80740027CCDF /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D284BE530ADD80740027CCDF /* DNSServiceDiscoveryDefines.h in Headers */,
+				D284BE540ADD80740027CCDF /* dnssd_ipc.h in Headers */,
+				2E96A5260C39BE480087C4D2 /* helper.h in Headers */,
+				2EDC5E750C39EA640092701B /* helper-server.h in Headers */,
+				2E3552900C3A95C100CA1CB7 /* helper-error.h in Headers */,
+				2ECC11A60C4FEC3800CB1885 /* helpermsg-types.h in Headers */,
+				21A57F4E145B2AE100939099 /* CryptoAlg.h in Headers */,
+				21A57F55145B2B1400939099 /* CryptoSupport.h in Headers */,
+				2124FA2C1471E98C0021D7BB /* nsec.h in Headers */,
+				2124FA301471E9B50021D7BB /* dnssec.h in Headers */,
+				218E8E53156D8C0300720DA0 /* dnsproxy.h in Headers */,
+				2127A47915C3C7B900A857FC /* nsec3.h in Headers */,
+				21DD8FC1161E9A250033C8F8 /* anonymous.h in Headers */,
+				21070E6116486B9000A69507 /* DNSSECSupport.h in Headers */,
+				848DA5CA165477EB00D2E8B4 /* xpc_services.h in Headers */,
+				848DA5D616547F7200D2E8B4 /* dns_xpc.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BE770ADD80800027CCDF /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D284BE780ADD80800027CCDF /* DNSServiceDiscoveryDefines.h in Headers */,
+				D284BE790ADD80800027CCDF /* dnssd_ipc.h in Headers */,
+				D284BE7A0ADD80800027CCDF /* mDNSEmbeddedAPI.h in Headers */,
+				D284BE7B0ADD80800027CCDF /* mDNSDebug.h in Headers */,
+				D284BE7C0ADD80800027CCDF /* mDNSMacOSX.h in Headers */,
+				2E96A5270C39BE480087C4D2 /* helper.h in Headers */,
+				2EDC5E740C39EA640092701B /* helper-server.h in Headers */,
+				2E3552910C3A95C100CA1CB7 /* helper-error.h in Headers */,
+				2ECC11A70C4FEC3800CB1885 /* helpermsg-types.h in Headers */,
+				21A57F4F145B2AE100939099 /* CryptoAlg.h in Headers */,
+				21A57F56145B2B1400939099 /* CryptoSupport.h in Headers */,
+				2124FA2D1471E98C0021D7BB /* nsec.h in Headers */,
+				2124FA311471E9B50021D7BB /* dnssec.h in Headers */,
+				218E8E54156D8C0300720DA0 /* dnsproxy.h in Headers */,
+				2127A47A15C3C7B900A857FC /* nsec3.h in Headers */,
+				21DD8FC2161E9A250033C8F8 /* anonymous.h in Headers */,
+				21070E6216486B9000A69507 /* DNSSECSupport.h in Headers */,
+				848DA5CB165477EB00D2E8B4 /* xpc_services.h in Headers */,
+				848DA5D716547F7200D2E8B4 /* dns_xpc.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEA60ADD80920027CCDF /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEB50ADD809A0027CCDF /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEC20ADD80A20027CCDF /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2E35529D0C3A9E7600CA1CB7 /* helper-error.h in Headers */,
+				2E35529F0C3A9E7600CA1CB7 /* helper.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEDC0ADD80A70027CCDF /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEED0ADD80B00027CCDF /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		FFA572310AF18F1C0055A0F1 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		FFA5723D0AF18F450055A0F1 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		FFB765800AEED9C700583A2C /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXLegacyTarget section */
+		4AE471670EAFF81900A6C5AD /* dns_sd.jar */ = {
+			isa = PBXLegacyTarget;
+			buildArgumentsString = "-f ${SRCROOT}/../mDNSPosix/Makefile OBJDIR=${CONFIGURATION_TEMP_DIR}/dns_sd.jar.build BUILDDIR=${BUILT_PRODUCTS_DIR} SHAREDDIR=${SRCROOT}/../mDNSShared os=x JavaForXcode_$(ACTION)";
+			buildConfigurationList = 4AE471770EAFF84000A6C5AD /* Build configuration list for PBXLegacyTarget "dns_sd.jar" */;
+			buildPhases = (
+			);
+			buildToolPath = /usr/bin/make;
+			buildWorkingDirectory = "";
+			comments = "Multiplatform .jar file that implements Java interface to DNS-SD";
+			dependencies = (
+			);
+			name = dns_sd.jar;
+			passBuildSettingsInEnvironment = 1;
+			productName = dns_sd.jar;
+		};
+/* End PBXLegacyTarget section */
+
+/* Begin PBXNativeTarget section */
+		213FB21712028A7A002B3A08 /* BonjourEvents */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 213FB21B12028A7C002B3A08 /* Build configuration list for PBXNativeTarget "BonjourEvents" */;
+			buildPhases = (
+				213FB21412028A7A002B3A08 /* Resources */,
+				213FB21512028A7A002B3A08 /* Sources */,
+				213FB21612028A7A002B3A08 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = BonjourEvents;
+			productName = BonjourEvents;
+			productReference = 213FB21812028A7A002B3A08 /* BonjourEvents.plugin */;
+			productType = "com.apple.product-type.bundle";
+		};
+		2141DD1C123FFCDB0086D23E /* libdns_sd_static */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 2141DD1F123FFCF90086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_static" */;
+			buildPhases = (
+				2141DD19123FFCDB0086D23E /* Headers */,
+				2141DD1A123FFCDB0086D23E /* Sources */,
+				2141DD1B123FFCDB0086D23E /* Frameworks */,
+				2130256B12400DE600AC839F /* ShellScript */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = libdns_sd_static;
+			productName = libdns_sd_static;
+			productReference = 2141DD1D123FFCDB0086D23E /* libdns_sd.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		2141DD23123FFD0F0086D23E /* libdns_sd_debug_static */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 2141DD35123FFD3B0086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_debug_static" */;
+			buildPhases = (
+				2141DD20123FFD0F0086D23E /* Headers */,
+				2141DD21123FFD0F0086D23E /* Sources */,
+				2141DD22123FFD0F0086D23E /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = libdns_sd_debug_static;
+			productName = libdns_sd_debug_static;
+			productReference = 2141DD24123FFD0F0086D23E /* libdns_sd_debug.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		2141DD29123FFD2C0086D23E /* libdns_sd_profile_static */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 2141DD36123FFD3B0086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_profile_static" */;
+			buildPhases = (
+				2141DD26123FFD2C0086D23E /* Headers */,
+				2141DD27123FFD2C0086D23E /* Sources */,
+				2141DD28123FFD2C0086D23E /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = libdns_sd_profile_static;
+			productName = libdns_sd_profile_static;
+			productReference = 2141DD2A123FFD2C0086D23E /* libdns_sd_profile.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		2E0405EF0C31955500F13B59 /* mDNSResponderHelper */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 2E0405F30C31956600F13B59 /* Build configuration list for PBXNativeTarget "mDNSResponderHelper" */;
+			buildPhases = (
+				030BBED60CE11EEC00472F0C /* ShellScript */,
+				2EC8F8ED0C39CCCA003C9C48 /* Headers */,
+				2E0405ED0C31955500F13B59 /* Sources */,
+				2E0405EE0C31955500F13B59 /* Frameworks */,
+				4AAE0C5A0C68E6EC003882A5 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = mDNSResponderHelper;
+			productName = mDNSResponderHelper;
+			productReference = 2E0405F00C31955500F13B59 /* mDNSResponderHelper */;
+			productType = "com.apple.product-type.tool";
+		};
+		72FB545E166D5FB00090B2D9 /* dnsctl */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 72FB5465166D5FB00090B2D9 /* Build configuration list for PBXNativeTarget "dnsctl" */;
+			buildPhases = (
+				72FB545B166D5FB00090B2D9 /* Sources */,
+				72FB545C166D5FB00090B2D9 /* Frameworks */,
+				72FB545D166D5FB00090B2D9 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = dnsctl;
+			productName = dnsctl;
+			productReference = 72FB545F166D5FB00090B2D9 /* dnsctl */;
+			productType = "com.apple.product-type.tool";
+		};
+		84C5B3341665529800C324A8 /* dns_services */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 84C5B3361665529800C324A8 /* Build configuration list for PBXNativeTarget "dns_services" */;
+			buildPhases = (
+				84C5B3311665529800C324A8 /* Sources */,
+				84C5B3321665529800C324A8 /* Frameworks */,
+				84C5B3331665529800C324A8 /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = dns_services;
+			productName = dns_services;
+			productReference = 84C5B3351665529800C324A8 /* libdns_services_mdns.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		D284BE500ADD80740027CCDF /* mDNSResponder */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = D284BE6D0ADD80740027CCDF /* Build configuration list for PBXNativeTarget "mDNSResponder" */;
+			buildPhases = (
+				D284BE510ADD80740027CCDF /* ShellScript */,
+				D284BE520ADD80740027CCDF /* Headers */,
+				D284BE550ADD80740027CCDF /* Sources */,
+				D284BE640ADD80740027CCDF /* Frameworks */,
+				D284BE690ADD80740027CCDF /* Rez */,
+				D284BE6A0ADD80740027CCDF /* CopyFiles */,
+				4A7B9E7F14FDA21B00B84CC1 /* CopyFiles */,
+				4A7B9E8114FDA25500B84CC1 /* CopyFiles */,
+				D284BE6C0ADD80740027CCDF /* ShellScript */,
+				8418673D15AB8BFF00BB7F70 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = mDNSResponder;
+			productInstallPath = "${HOME}/bin";
+			productName = mDNSResponder;
+			productReference = D284BE730ADD80740027CCDF /* mDNSResponder */;
+			productType = "com.apple.product-type.tool";
+		};
+		D284BE750ADD80800027CCDF /* mDNSResponder debug */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = D284BE920ADD80800027CCDF /* Build configuration list for PBXNativeTarget "mDNSResponder debug" */;
+			buildPhases = (
+				D284BE760ADD80800027CCDF /* ShellScript */,
+				D284BE770ADD80800027CCDF /* Headers */,
+				D284BE7D0ADD80800027CCDF /* Sources */,
+				D284BE8C0ADD80800027CCDF /* Frameworks */,
+				D284BE910ADD80800027CCDF /* Rez */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "mDNSResponder debug";
+			productName = mDNSResponder;
+			productReference = D284BE950ADD80800027CCDF /* mDNSResponder.debug */;
+			productType = "com.apple.product-type.tool";
+		};
+		D284BEA50ADD80920027CCDF /* dns-sd tool */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = D284BEAD0ADD80920027CCDF /* Build configuration list for PBXNativeTarget "dns-sd tool" */;
+			buildPhases = (
+				D284BEA60ADD80920027CCDF /* Headers */,
+				D284BEA70ADD80920027CCDF /* Sources */,
+				D284BEA90ADD80920027CCDF /* Frameworks */,
+				D284BEAA0ADD80920027CCDF /* Rez */,
+				D284BEAB0ADD80920027CCDF /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "dns-sd tool";
+			productInstallPath = /usr/bin;
+			productName = "dns-sd command-line tool";
+			productReference = D284BEB00ADD80920027CCDF /* dns-sd */;
+			productType = "com.apple.product-type.tool";
+		};
+		D284BEB20ADD809A0027CCDF /* libjdns_sd.jnilib */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = D284BEBB0ADD809A0027CCDF /* Build configuration list for PBXNativeTarget "libjdns_sd.jnilib" */;
+			buildPhases = (
+				D284BEB50ADD809A0027CCDF /* Headers */,
+				D284BEB60ADD809A0027CCDF /* Sources */,
+				D284BEB80ADD809A0027CCDF /* Frameworks */,
+				D284BEBA0ADD809A0027CCDF /* Rez */,
+			);
+			buildRules = (
+			);
+			comments = "Platform-specific JNI library that bridges dns_sd.jar to <dns_sd.h>.";
+			dependencies = (
+				4AE4716A0EAFF83800A6C5AD /* PBXTargetDependency */,
+			);
+			name = libjdns_sd.jnilib;
+			productInstallPath = /usr/lib/java;
+			productName = libjdns_sd.jnilib;
+			productReference = D284BEBE0ADD809A0027CCDF /* libjdns_sd.jnilib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		D284BEBF0ADD80A20027CCDF /* dnsextd */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = D284BED60ADD80A20027CCDF /* Build configuration list for PBXNativeTarget "dnsextd" */;
+			buildPhases = (
+				D284BEC20ADD80A20027CCDF /* Headers */,
+				4A4EE3A413CB8E82005C624B /* Build yacc file into derived source files */,
+				D284BEC40ADD80A20027CCDF /* Sources */,
+				D284BECE0ADD80A20027CCDF /* Frameworks */,
+				D284BED40ADD80A20027CCDF /* CopyFiles */,
+				FFFF8F770C32F0FD00722979 /* CopyFiles */,
+				FF37FAAD0BC581780044A5CF /* ShellScript */,
+			);
+			buildRules = (
+				D284BFB80ADD8E510027CCDF /* PBXBuildRule */,
+				D284BF750ADD850C0027CCDF /* PBXBuildRule */,
+			);
+			dependencies = (
+			);
+			name = dnsextd;
+			productInstallPath = /usr/sbin;
+			productName = mDNSResponder;
+			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 */,
+				D284BEE40ADD80A70027CCDF /* Rez */,
+			);
+			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" */;
+			buildPhases = (
+				D284BEED0ADD80B00027CCDF /* Headers */,
+				D284BEEE0ADD80B00027CCDF /* Resources */,
+				D284BEFD0ADD80B00027CCDF /* Sources */,
+				D284BF010ADD80B00027CCDF /* Frameworks */,
+				D284BF070ADD80B00027CCDF /* Rez */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				FFAE66F9105F0CF100162116 /* PBXTargetDependency */,
+			);
+			name = PreferencePane;
+			productInstallPath = "${SYSTEM_LIBRARY_DIR}/PreferencePanes";
+			productName = PreferencePane;
+			productReference = D284BF0C0ADD80B00027CCDF /* Bonjour.prefPane */;
+			productType = "com.apple.product-type.bundle";
+		};
+		FFA572300AF18F1C0055A0F1 /* libdns_sd_debug_dynamic */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = FFA572370AF18F1C0055A0F1 /* Build configuration list for PBXNativeTarget "libdns_sd_debug_dynamic" */;
+			buildPhases = (
+				FFA572310AF18F1C0055A0F1 /* Headers */,
+				FFA572320AF18F1C0055A0F1 /* Sources */,
+				FFA572360AF18F1C0055A0F1 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = libdns_sd_debug_dynamic;
+			productName = libdns_sd.dylib;
+			productReference = FFA572390AF18F1C0055A0F1 /* libsystem_dnssd_debug.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		FFA5723C0AF18F450055A0F1 /* libdns_sd_profile_dynamic */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = FFA572430AF18F450055A0F1 /* Build configuration list for PBXNativeTarget "libdns_sd_profile_dynamic" */;
+			buildPhases = (
+				FFA5723D0AF18F450055A0F1 /* Headers */,
+				FFA5723E0AF18F450055A0F1 /* Sources */,
+				FFA572420AF18F450055A0F1 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = libdns_sd_profile_dynamic;
+			productName = libdns_sd.dylib;
+			productReference = FFA572450AF18F450055A0F1 /* libsystem_dnssd_profile.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		FFB765830AEED9C700583A2C /* libdns_sd_dynamic */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = FFB765890AEED9FB00583A2C /* Build configuration list for PBXNativeTarget "libdns_sd_dynamic" */;
+			buildPhases = (
+				FFB765800AEED9C700583A2C /* Headers */,
+				FFB765810AEED9C700583A2C /* Sources */,
+				FFB765820AEED9C700583A2C /* Frameworks */,
+				21DE714D115831CB00DD4BD1 /* ShellScript */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = libdns_sd_dynamic;
+			productName = libdns_sd.dylib;
+			productReference = FFB765840AEED9C700583A2C /* libsystem_dnssd.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		08FB7793FE84155DC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+			};
+			buildConfigurationList = D284BE2B0ADD78180027CCDF /* Build configuration list for PBXProject "mDNSResponder" */;
+			compatibilityVersion = "Xcode 3.1";
+			developmentRegion = English;
+			hasScannedForEncodings = 1;
+			knownRegions = (
+				English,
+				Japanese,
+				French,
+				German,
+			);
+			mainGroup = 08FB7794FE84155DC02AAC07 /* mDNSResponder */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				00AD62BB032D7A0C0CCA2C71 /* Build More */,
+				03067D640C83A3700022BE1F /* Build Some */,
+				FFB7657B0AEED96B00583A2C /* Build All */,
+				D284BE500ADD80740027CCDF /* mDNSResponder */,
+				D284BE750ADD80800027CCDF /* mDNSResponder debug */,
+				2E0405EF0C31955500F13B59 /* mDNSResponderHelper */,
+				D284BEA50ADD80920027CCDF /* dns-sd tool */,
+				4AE471670EAFF81900A6C5AD /* dns_sd.jar */,
+				D284BEB20ADD809A0027CCDF /* libjdns_sd.jnilib */,
+				D284BEBF0ADD80A20027CCDF /* dnsextd */,
+				D284BEDB0ADD80A70027CCDF /* ddnswriteconfig */,
+				D284BEEA0ADD80B00027CCDF /* PreferencePane */,
+				FFB765830AEED9C700583A2C /* libdns_sd_dynamic */,
+				FFA572300AF18F1C0055A0F1 /* libdns_sd_debug_dynamic */,
+				FFA5723C0AF18F450055A0F1 /* libdns_sd_profile_dynamic */,
+				FFA572650AF190F10055A0F1 /* SystemLibrariesDynamic */,
+				213FB21712028A7A002B3A08 /* BonjourEvents */,
+				2141DCF8123FFB5D0086D23E /* SystemLibraries */,
+				2141DD0B123FFC7F0086D23E /* SystemLibrariesStatic */,
+				2141DD1C123FFCDB0086D23E /* libdns_sd_static */,
+				2141DD23123FFD0F0086D23E /* libdns_sd_debug_static */,
+				2141DD29123FFD2C0086D23E /* libdns_sd_profile_static */,
+				84C5B3341665529800C324A8 /* dns_services */,
+				72FB545E166D5FB00090B2D9 /* dnsctl */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		213FB21412028A7A002B3A08 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEEE0ADD80B00027CCDF /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				3F347CF6185D57CD00367B40 /* base.xcconfig in Resources */,
+				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;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXRezBuildPhase section */
+		D284BE690ADD80740027CCDF /* Rez */ = {
+			isa = PBXRezBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BE910ADD80800027CCDF /* Rez */ = {
+			isa = PBXRezBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEAA0ADD80920027CCDF /* Rez */ = {
+			isa = PBXRezBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEBA0ADD809A0027CCDF /* Rez */ = {
+			isa = PBXRezBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEE40ADD80A70027CCDF /* Rez */ = {
+			isa = PBXRezBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BF070ADD80B00027CCDF /* Rez */ = {
+			isa = PBXRezBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXRezBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		030BBED60CE11EEC00472F0C /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			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";
+		};
+		2130256B12400DE600AC839F /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 8;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+			shellPath = /bin/sh;
+			shellScript = "DSTROOT=${DSTROOT}${INSTALL_PATH_PREFIX}\n\nmkdir -p \"$DSTROOT/usr/include\"\nsed 's/\\(^#define _DNS_SD_LIBDISPATCH \\)0$/\\1 1/' \"$SRCROOT/../mDNSShared/dns_sd.h\" > \"$DSTROOT/usr/include/dns_sd.h\"";
+		};
+		21DE714D115831CB00DD4BD1 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 8;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+			shellPath = /bin/sh;
+			shellScript = "DSTROOT=${DSTROOT}${INSTALL_PATH_PREFIX}\nmkdir -p \"$DSTROOT/usr/include\"\nsed 's/\\(^#define _DNS_SD_LIBDISPATCH \\)0$/\\1 1/' \"$SRCROOT/../mDNSShared/dns_sd.h\" > \"$DSTROOT/usr/include/dns_sd.h\"";
+		};
+		4A4EE3A413CB8E82005C624B /* Build yacc file into derived source files */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"$(SRCROOT)/../mDNSShared/dnsextd_parser.y",
+			);
+			name = "Build yacc file into derived source files";
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/dnsextd_parser.c",
+				"$(DERIVED_FILE_DIR)/dnsextd_parser.h",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "/usr/bin/bison -o ${SCRIPT_OUTPUT_FILE_0} -d ${SCRIPT_INPUT_FILE_0}";
+		};
+		D284BE510ADD80740027CCDF /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "if [ -e \"${SDKROOT}/usr/local/include/dnsinfo.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.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}/libdnsinfo.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n\nif [ -e \"${SDKROOT}/usr/include/sandbox.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nelse\necho \"#define MDNS_NO_SANDBOX 1\" > \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nfi\n\nif [ -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}/System/Library/Frameworks/IOKit.framework/PrivateHeaders/pwr_mgt/IOPMLibPrivate.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/IOKit\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt\"\ntouch \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt/IOPMLibPrivate.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/PrivateFrameworks/DeviceToDeviceManager.framework/Headers/DeviceToDeviceManager.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager\"\necho \"#define NO_D2D 1\" > \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager/DeviceToDeviceManager.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/PrivateFrameworks/WebFilterDNS.framework/Headers/WebFilterDNS.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS\"\necho \"#define NO_WCF 1\" > \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS/WebFilterDNS.h\"\nfi\n\nif [ -e \"${SDKROOT}/usr/local/include/AWACS.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/AWACS.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libAWACS.a\"\nelse\nec!
 ho \"#define NO_AWACS 1\" > \"${CONFIGURATION_TEMP_DIR}/AWACS.h\"\ntouch \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libAWACS.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\"\nfi\n";
+		};
+		D284BE6C0ADD80740027CCDF /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 8;
+			files = (
+			);
+			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}\" ] ; then\n  SANDBOXDST=\"${DSTROOT}/usr/local/share/sandbox/profiles/embedded/builtin\"\nelse\n  SANDBOXDST=\"${DSTROOT}/usr/share/sandbox\"\nfi\n(umask 022; mkdir -p -m 0755 \"$SANDBOXDST\")\ncp \"${SRCROOT}/mDNSResponder.sb\" \"${SANDBOXDST}/mDNSResponder.sb\"\n";
+		};
+		D284BE760ADD80800027CCDF /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "if [ -e \"${SDKROOT}/usr/local/include/dnsinfo.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.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}/libdnsinfo.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n\nif [ -e \"${SDKROOT}/usr/include/sandbox.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nelse\necho \"#define MDNS_NO_SANDBOX 1\" > \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nfi\n\nif [ -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}/System/Library/Frameworks/IOKit.framework/PrivateHeaders/pwr_mgt/IOPMLibPrivate.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/IOKit\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt\"\ntouch \"${CONFIGURATION_TEMP_DIR}/IOKit/pwr_mgt/IOPMLibPrivate.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/PrivateFrameworks/DeviceToDeviceManager.framework/Headers/DeviceToDeviceManager.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager\"\necho \"#define NO_D2D 1\" > \"${CONFIGURATION_TEMP_DIR}/DeviceToDeviceManager/DeviceToDeviceManager.h\"\nfi\n\nif [ -e \"${SDKROOT}/System/Library/PrivateFrameworks/WebFilterDNS.framework/Headers/WebFilterDNS.h\" ]\nthen\nrm -rf \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS\"\nelse\nmkdir -p \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS\"\necho \"#define NO_WCF 1\" > \"${CONFIGURATION_TEMP_DIR}/WebFilterDNS/WebFilterDNS.h\"\nfi\n\nif [ -e \"${SDKROOT}/usr/local/include/AWACS.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/AWACS.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libAWACS.a\"\nelse\nec!
 ho \"#define NO_AWACS 1\" > \"${CONFIGURATION_TEMP_DIR}/AWACS.h\"\ntouch \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libAWACS.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/AWACSempty.c\"\nfi";
+		};
+		FF045B6A0C7E4AA600448140 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 8;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+			shellPath = /bin/sh;
+			shellScript = "# Install plists to tell launchd how to start mDNSResponder and mDNSResponderHelper\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons\n\nif [ ! -z \"${IPHONEOS_DEPLOYMENT_TARGET}\" ] ; then\nplutil -convert binary1 ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponder.plist\nplutil -convert binary1 ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.mDNSResponderHelper.plist\nfi\n";
+		};
+		FF37FAAD0BC581780044A5CF /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 8;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+			shellPath = /bin/tcsh;
+			shellScript = "# Install plist to tell launchd how to start dnsextd\nmkdir -p ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons\ncp ${SRCROOT}/LaunchDaemonInfo.dnsextd.plist ${DSTROOT}${SYSTEM_LIBRARY_DIR}/LaunchDaemons/com.apple.dnsextd.plist\n";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		213FB21512028A7A002B3A08 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				213FB23C12028C4A002B3A08 /* BonjourEvents.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2141DD1A123FFCDB0086D23E /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				215FFAEE124000F900470DE1 /* dnssd_ipc.c in Sources */,
+				215FFAEF124000F900470DE1 /* dnssd_clientlib.c in Sources */,
+				215FFAF0124000F900470DE1 /* dnssd_clientstub.c in Sources */,
+				215FFAF1124000F900470DE1 /* DNSServiceDiscovery.c in Sources */,
+				215FFAF2124000F900470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */,
+				215FFAF3124000F900470DE1 /* DNSServiceDiscoveryReply.defs in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2141DD21123FFD0F0086D23E /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				215FFAF41240011800470DE1 /* dnssd_ipc.c in Sources */,
+				215FFAF51240011800470DE1 /* dnssd_clientlib.c in Sources */,
+				215FFAF61240011800470DE1 /* dnssd_clientstub.c in Sources */,
+				215FFAF71240011800470DE1 /* DNSServiceDiscovery.c in Sources */,
+				215FFAF81240011800470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */,
+				215FFAF91240011800470DE1 /* DNSServiceDiscoveryReply.defs in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2141DD27123FFD2C0086D23E /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				215FFAFA1240013400470DE1 /* dnssd_ipc.c in Sources */,
+				215FFAFB1240013400470DE1 /* dnssd_clientlib.c in Sources */,
+				215FFAFC1240013400470DE1 /* dnssd_clientstub.c in Sources */,
+				215FFAFD1240013400470DE1 /* DNSServiceDiscovery.c in Sources */,
+				215FFAFE1240013400470DE1 /* DNSServiceDiscoveryRequest.defs in Sources */,
+				215FFAFF1240013400470DE1 /* DNSServiceDiscoveryReply.defs in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		2E0405ED0C31955500F13B59 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				2E0405F50C3195F700F13B59 /* helper.c in Sources */,
+				2E0405F60C31961100F13B59 /* helpermsg.defs in Sources */,
+				2E96A51D0C39BDAC0087C4D2 /* helper-main.c in Sources */,
+				2E8165E90C5980EE00485EB2 /* pfkey.c in Sources */,
+				4BD2B63A134FE09F002B96D5 /* P2PPacketFilter.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		72FB545B166D5FB00090B2D9 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				72FB5467166D5FCA0090B2D9 /* dnsctl.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		84C5B3311665529800C324A8 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				84C5B33C166553F100C324A8 /* dns_services.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BE550ADD80740027CCDF /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D284BE560ADD80740027CCDF /* DNSServiceDiscoveryReply.defs in Sources */,
+				D284BE570ADD80740027CCDF /* DNSServiceDiscoveryRequest.defs in Sources */,
+				D284BE580ADD80740027CCDF /* mDNS.c in Sources */,
+				D284BE590ADD80740027CCDF /* uDNS.c in Sources */,
+				D284BE5A0ADD80740027CCDF /* DNSCommon.c in Sources */,
+				D284BE5B0ADD80740027CCDF /* DNSDigest.c in Sources */,
+				D284BE5D0ADD80740027CCDF /* mDNSDebug.c in Sources */,
+				D284BE5E0ADD80740027CCDF /* uds_daemon.c in Sources */,
+				D284BE5F0ADD80740027CCDF /* dnssd_ipc.c in Sources */,
+				D284BE600ADD80740027CCDF /* PlatformCommon.c in Sources */,
+				D284BE610ADD80740027CCDF /* mDNSMacOSX.c in Sources */,
+				D284BE620ADD80740027CCDF /* LegacyNATTraversal.c in Sources */,
+				D284BE630ADD80740027CCDF /* daemon.c in Sources */,
+				2E04061F0C3198B700F13B59 /* helpermsg.defs in Sources */,
+				2E96A5320C39C1A50087C4D2 /* helper-stubs.c in Sources */,
+				21A57F4C145B2AE100939099 /* CryptoAlg.c in Sources */,
+				21A57F53145B2B1400939099 /* CryptoSupport.c in Sources */,
+				2124FA331471E9DE0021D7BB /* nsec.c in Sources */,
+				213BDC6D147319F400000896 /* dnssec.c in Sources */,
+				218E8E51156D8C0300720DA0 /* dnsproxy.c in Sources */,
+				21DED43515702C0F0060B6B9 /* DNSProxySupport.c in Sources */,
+				216D9ACE1720C9F5008066E1 /* VPNService.c in Sources */,
+				2127A47715C3C7B900A857FC /* nsec3.c in Sources */,
+				21DD8FBF161E9A250033C8F8 /* anonymous.c in Sources */,
+				21070E5F16486B9000A69507 /* DNSSECSupport.c in Sources */,
+				848DA5C7165477E000D2E8B4 /* xpc_services.c in Sources */,
+				2120ABD516B71614007089B6 /* CUPolicy.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BE7D0ADD80800027CCDF /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D284BE7E0ADD80800027CCDF /* DNSServiceDiscoveryReply.defs in Sources */,
+				D284BE7F0ADD80800027CCDF /* DNSServiceDiscoveryRequest.defs in Sources */,
+				D284BE800ADD80800027CCDF /* mDNS.c in Sources */,
+				D284BE810ADD80800027CCDF /* uDNS.c in Sources */,
+				D284BE820ADD80800027CCDF /* DNSCommon.c in Sources */,
+				D284BE830ADD80800027CCDF /* DNSDigest.c in Sources */,
+				D284BE850ADD80800027CCDF /* mDNSDebug.c in Sources */,
+				D284BE860ADD80800027CCDF /* uds_daemon.c in Sources */,
+				D284BE870ADD80800027CCDF /* dnssd_ipc.c in Sources */,
+				D284BE880ADD80800027CCDF /* PlatformCommon.c in Sources */,
+				D284BE890ADD80800027CCDF /* mDNSMacOSX.c in Sources */,
+				D284BE8A0ADD80800027CCDF /* LegacyNATTraversal.c in Sources */,
+				D284BE8B0ADD80800027CCDF /* daemon.c in Sources */,
+				2E0406200C3198B700F13B59 /* helpermsg.defs in Sources */,
+				2E96A5300C39C1A50087C4D2 /* helper-stubs.c in Sources */,
+				21A57F4D145B2AE100939099 /* CryptoAlg.c in Sources */,
+				21A57F54145B2B1400939099 /* CryptoSupport.c in Sources */,
+				2124FA341471E9DE0021D7BB /* nsec.c in Sources */,
+				213BDC6E147319F400000896 /* dnssec.c in Sources */,
+				218E8E52156D8C0300720DA0 /* dnsproxy.c in Sources */,
+				21DED43615702C0F0060B6B9 /* DNSProxySupport.c in Sources */,
+				216D9ACF1720C9F5008066E1 /* VPNService.c in Sources */,
+				2127A47815C3C7B900A857FC /* nsec3.c in Sources */,
+				21DD8FC0161E9A250033C8F8 /* anonymous.c in Sources */,
+				21070E6016486B9000A69507 /* DNSSECSupport.c in Sources */,
+				848DA5C8165477E000D2E8B4 /* xpc_services.c in Sources */,
+				2120ABD616B71614007089B6 /* CUPolicy.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEA70ADD80920027CCDF /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D284BEA80ADD80920027CCDF /* dns-sd.c in Sources */,
+				FFF589B70E37F66800EF515C /* ClientCommon.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEB60ADD809A0027CCDF /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D284BEB70ADD809A0027CCDF /* JNISupport.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D284BEC40ADD80A20027CCDF /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				21DCD05C1461B23700702FC8 /* CryptoAlg.c in Sources */,
+				21DCD05D1461B23700702FC8 /* CryptoAlg.h in Sources */,
+				D284BEC50ADD80A20027CCDF /* DNSCommon.c in Sources */,
+				D284BEC60ADD80A20027CCDF /* DNSDigest.c in Sources */,
+				D284BEC70ADD80A20027CCDF /* dnsextd.c in Sources */,
+				D284BEC80ADD80A20027CCDF /* mDNSDebug.c in Sources */,
+				D284BEC90ADD80A20027CCDF /* GenLinkedList.c in Sources */,
+				D284BECA0ADD80A20027CCDF /* mDNSMacOSX.c in Sources */,
+				D284BECC0ADD80A20027CCDF /* dnsextd_parser.y in Sources */,
+				D284BECB0ADD80A20027CCDF /* dnsextd_lexer.l in Sources */,
+				D284BECD0ADD80A20027CCDF /* PlatformCommon.c in Sources */,
+				2EAE955A0C31F4D30021F738 /* helpermsg.defs in Sources */,
+				2E35529E0C3A9E7600CA1CB7 /* helper-stubs.c in Sources */,
+			);
+			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 */,
+				FFF589C10E37F67E00EF515C /* ClientCommon.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		FFA572320AF18F1C0055A0F1 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				FFA572330AF18F1C0055A0F1 /* dnssd_ipc.c in Sources */,
+				FFA572340AF18F1C0055A0F1 /* dnssd_clientlib.c in Sources */,
+				FFA572350AF18F1C0055A0F1 /* dnssd_clientstub.c in Sources */,
+				FFA5724A0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */,
+				FFC22AA40B00F42C00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */,
+				FFC22AA60B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		FFA5723E0AF18F450055A0F1 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				FFA5723F0AF18F450055A0F1 /* dnssd_ipc.c in Sources */,
+				FFA572400AF18F450055A0F1 /* dnssd_clientlib.c in Sources */,
+				FFA572410AF18F450055A0F1 /* dnssd_clientstub.c in Sources */,
+				FFA5724B0AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */,
+				FFC22AA30B00F42B00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */,
+				FFC22AA70B00F43100BAB070 /* DNSServiceDiscoveryReply.defs in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		FFB765810AEED9C700583A2C /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				FFFA38660AEEDB2B0065B80A /* dnssd_ipc.c in Sources */,
+				FFFA38630AEEDB090065B80A /* dnssd_clientlib.c in Sources */,
+				FFFA38650AEEDB130065B80A /* dnssd_clientstub.c in Sources */,
+				FFA572490AF18FCC0055A0F1 /* DNSServiceDiscovery.c in Sources */,
+				FFC22AA20B00F42A00BAB070 /* DNSServiceDiscoveryRequest.defs in Sources */,
+				FFC22AA50B00F43000BAB070 /* DNSServiceDiscoveryReply.defs in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		03067D680C83A3830022BE1F /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = D284BE500ADD80740027CCDF /* mDNSResponder */;
+			targetProxy = 03067D670C83A3830022BE1F /* PBXContainerItemProxy */;
+		};
+		03067D6A0C83A3890022BE1F /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = D284BE750ADD80800027CCDF /* mDNSResponder debug */;
+			targetProxy = 03067D690C83A3890022BE1F /* PBXContainerItemProxy */;
+		};
+		03067D6C0C83A3920022BE1F /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = D284BEA50ADD80920027CCDF /* dns-sd tool */;
+			targetProxy = 03067D6B0C83A3920022BE1F /* PBXContainerItemProxy */;
+		};
+		03067D6E0C83A39C0022BE1F /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 2E0405EF0C31955500F13B59 /* mDNSResponderHelper */;
+			targetProxy = 03067D6D0C83A39C0022BE1F /* PBXContainerItemProxy */;
+		};
+		03067D860C849CC30022BE1F /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 03067D640C83A3700022BE1F /* Build Some */;
+			targetProxy = 03067D850C849CC30022BE1F /* PBXContainerItemProxy */;
+		};
+		2130257112400E9300AC839F /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = FFA572650AF190F10055A0F1 /* SystemLibrariesDynamic */;
+			targetProxy = 2130257012400E9300AC839F /* PBXContainerItemProxy */;
+		};
+		2141DCFD123FFB7D0086D23E /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 2141DCF8123FFB5D0086D23E /* SystemLibraries */;
+			targetProxy = 2141DCFC123FFB7D0086D23E /* PBXContainerItemProxy */;
+		};
+		2141DD0E123FFC960086D23E /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 2141DD0B123FFC7F0086D23E /* SystemLibrariesStatic */;
+			targetProxy = 2141DD0D123FFC960086D23E /* PBXContainerItemProxy */;
+		};
+		215FFB19124002C100470DE1 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 2141DD1C123FFCDB0086D23E /* libdns_sd_static */;
+			targetProxy = 215FFB18124002C100470DE1 /* PBXContainerItemProxy */;
+		};
+		215FFB1B124002C700470DE1 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 2141DD23123FFD0F0086D23E /* libdns_sd_debug_static */;
+			targetProxy = 215FFB1A124002C700470DE1 /* PBXContainerItemProxy */;
+		};
+		215FFB1D124002CC00470DE1 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 2141DD29123FFD2C0086D23E /* libdns_sd_profile_static */;
+			targetProxy = 215FFB1C124002CC00470DE1 /* PBXContainerItemProxy */;
+		};
+		217A4C49138EE14C000A5BA8 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 213FB21712028A7A002B3A08 /* BonjourEvents */;
+			targetProxy = 217A4C48138EE14C000A5BA8 /* PBXContainerItemProxy */;
+		};
+		4AE4716A0EAFF83800A6C5AD /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 4AE471670EAFF81900A6C5AD /* dns_sd.jar */;
+			targetProxy = 4AE471690EAFF83800A6C5AD /* PBXContainerItemProxy */;
+		};
+		84C5B3411665544B00C324A8 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 84C5B3341665529800C324A8 /* dns_services */;
+			targetProxy = 84C5B3401665544B00C324A8 /* 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 */;
+			targetProxy = D284BF2F0ADD81630027CCDF /* PBXContainerItemProxy */;
+		};
+		FFA572690AF190FF0055A0F1 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = FFB765830AEED9C700583A2C /* libdns_sd_dynamic */;
+			targetProxy = FFA572680AF190FF0055A0F1 /* PBXContainerItemProxy */;
+		};
+		FFA5726B0AF191010055A0F1 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = FFA572300AF18F1C0055A0F1 /* libdns_sd_debug_dynamic */;
+			targetProxy = FFA5726A0AF191010055A0F1 /* PBXContainerItemProxy */;
+		};
+		FFA5726D0AF191020055A0F1 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			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 */;
+			targetProxy = FFB7657C0AEED97F00583A2C /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+		FF260A4807B4475600CE10E5 /* DNSServiceDiscoveryPref.nib */ = {
+			isa = PBXVariantGroup;
+			children = (
+				FF260A4907B4475600CE10E5 /* English */,
+			);
+			name = DNSServiceDiscoveryPref.nib;
+			path = PreferencePane;
+			sourceTree = SOURCE_ROOT;
+		};
+		FF260A4B07B4477F00CE10E5 /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				FF260A4C07B4477F00CE10E5 /* English */,
+			);
+			name = InfoPlist.strings;
+			path = PreferencePane;
+			sourceTree = SOURCE_ROOT;
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		03067D740C83A3CB0022BE1F /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_OPTIMIZATION_LEVEL = s;
+				PRODUCT_NAME = "Build Some";
+			};
+			name = Development;
+		};
+		213FB21A12028A7B002B3A08 /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				BUNDLE_LOADER = /usr/libexec/UserEventAgent;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_MODEL_TUNING = G5;
+				INFOPLIST_FILE = "BonjourEvents-Info.plist";
+				INSTALL_PATH_ACTUAL = /System/Library/UserEventPlugins/;
+				PREBINDING = NO;
+				PRODUCT_NAME = BonjourEvents;
+				PROVISIONING_PROFILE = "";
+				WRAPPER_EXTENSION = plugin;
+			};
+			name = Development;
+		};
+		2141DCF9123FFB5D0086D23E /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				PRODUCT_NAME = SystemLibraries;
+			};
+			name = Development;
+		};
+		2141DD0C123FFC7F0086D23E /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = s;
+				PRODUCT_NAME = SystemLibrariesStatic;
+			};
+			name = Development;
+		};
+		2141DD1E123FFCDB0086D23E /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(inherited)",
+					"__DARWIN_NON_CANCELABLE=1",
+				);
+				HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+				INSTALLHDRS_COPY_PHASE = YES;
+				INSTALLHDRS_SCRIPT_PHASE = YES;
+				INSTALL_PATH_ACTUAL = /usr/local/lib/system;
+				PREBINDING = NO;
+				PRODUCT_NAME = dns_sd;
+				"SKIP_INSTALL[sdk=iphonesimulator*]" = YES;
+			};
+			name = Development;
+		};
+		2141DD25123FFD100086D23E /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(inherited)",
+					"__DARWIN_NON_CANCELABLE=1",
+				);
+				HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+				INSTALL_PATH_ACTUAL = /usr/local/lib/system;
+				PREBINDING = NO;
+				PRODUCT_NAME = dns_sd_debug;
+				"SKIP_INSTALL[sdk=iphonesimulator*]" = YES;
+			};
+			name = Development;
+		};
+		2141DD2B123FFD2C0086D23E /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(inherited)",
+					"__DARWIN_NON_CANCELABLE=1",
+				);
+				HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+				INSTALL_PATH_ACTUAL = /usr/local/lib/system;
+				PREBINDING = NO;
+				PRODUCT_NAME = dns_sd_profile;
+				"SKIP_INSTALL[sdk=iphonesimulator*]" = YES;
+			};
+			name = Development;
+		};
+		2E0405F20C31955500F13B59 /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				"CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "helper-entitlements.plist";
+				CODE_SIGN_IDENTITY = "-";
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)";
+				CONFIGURATION_TEMP_DIR = "$(PROJECT_TEMP_DIR)";
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+				GCC_WARN_CHECK_SWITCH_STATEMENTS = NO;
+				HEADER_SEARCH_PATHS = (
+					"${CONFIGURATION_TEMP_DIR}",
+					"$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
+					"$(SDKROOT)/usr/local/include",
+				);
+				INSTALL_PATH = "";
+				"INSTALL_PATH[sdk=macosx*]" = "";
+				INSTALL_PATH_ACTUAL = /usr/sbin;
+				LD_MAP_FILE_PATH = "$(TARGET_TEMP_DIR)/$(PRODUCT_NAME)-LinkMap-$(CURRENT_VARIANT)-$(CURRENT_ARCH).txt";
+				LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
+				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				"OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = "$(inherited)";
+				OTHER_LDFLAGS = (
+					"$(inherited)",
+					"-lipsec",
+				);
+				"OTHER_LDFLAGS[sdk=macosx*][arch=*]" = (
+					"-lipsec",
+					"-Wl,-pie",
+				);
+				PREBINDING = NO;
+				PRODUCT_NAME = mDNSResponderHelper;
+				PROVISIONING_PROFILE = "";
+			};
+			name = Development;
+		};
+		4AE471680EAFF81900A6C5AD /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				PRODUCT_NAME = dns_sd.jar;
+			};
+			name = Development;
+		};
+		72FB5466166D5FB00090B2D9 /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+				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[sdk=*]" = "dnsctl-entitlements.plist";
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				GCC_OPTIMIZATION_LEVEL = s;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_STRICT_ALIASING = YES;
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_TREAT_WARNINGS_AS_ERRORS = 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_ACTUAL = /usr/bin;
+				MACOSX_DEPLOYMENT_TARGET = 10.9;
+				ONLY_ACTIVE_ARCH = NO;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE = "";
+				SDKROOT = macosx;
+			};
+			name = Development;
+		};
+		84C5B3371665529800C324A8 /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_PREFIX = lib;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				GCC_OPTIMIZATION_LEVEL = s;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_TREAT_WARNINGS_AS_ERRORS = 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_ACTUAL = /usr/lib;
+				MACOSX_DEPLOYMENT_TARGET = 10.8;
+				ONLY_ACTIVE_ARCH = NO;
+				PRODUCT_NAME = "$(TARGET_NAME)_mdns";
+				SDKROOT = macosx;
+			};
+			name = Development;
+		};
+		D284BE290ADD78180027CCDF /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				OTHER_CFLAGS = "";
+				OTHER_LDFLAGS = "";
+				OTHER_REZFLAGS = "";
+				PRODUCT_NAME = "Build All";
+				SECTORDER_FLAGS = "";
+			};
+			name = Development;
+		};
+		D284BE2C0ADD78180027CCDF /* Development */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 3F347CF5185D57CD00367B40 /* base.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)";
+				DEAD_CODE_STRIPPING = YES;
+				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",
+				);
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+				MVERS = "\"(Engineering Build)\"";
+				OTHER_CFLAGS = (
+					"-DUSE_SYSTEMCONFIGURATION_PRIVATE_HEADERS",
+					"-fwrapv",
+				);
+				"OTHER_LDFLAGS[sdk=macosx*]" = "";
+				PREBINDING = NO;
+				STRIP_STYLE = debugging;
+				WARNING_CFLAGS = (
+					"-W",
+					"-Wall",
+					"-Wmissing-prototypes",
+					"-Wno-four-char-constants",
+					"-Wno-unknown-pragmas",
+					"-Wshadow",
+				);
+				YACC_GENERATED_FILE_STEM = Standard;
+			};
+			name = Development;
+		};
+		D284BE6E0ADD80740027CCDF /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				"CODE_SIGN_ENTITLEMENTS[sdk=*]" = "mDNSResponder-entitlements.plist";
+				CODE_SIGN_IDENTITY = "-";
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+				);
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				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/",
+				);
+				INSTALL_PATH = "";
+				"INSTALL_PATH[sdk=macosx*]" = "";
+				INSTALL_PATH_ACTUAL = /usr/sbin;
+				LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
+				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				ORDER_FILE = "${SRCROOT}/mDNSResponder.order";
+				OTHER_CFLAGS = (
+					"$(inherited)",
+					"-no-cpp-precomp",
+				);
+				"OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = "$(inherited)";
+				OTHER_LDFLAGS = "";
+				"OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = (
+					"-Wl,-pie",
+					"-weak_framework",
+					DeviceToDeviceManager,
+					"-lMobileGestalt",
+					"-lcupolicy",
+				);
+				"OTHER_LDFLAGS[sdk=macosx*][arch=*]" = (
+					"-Wl,-pie",
+					"-lAWACS",
+					"-weak_framework",
+					WebFilterDNS,
+					"-weak_framework",
+					DeviceToDeviceManager,
+				);
+				"OTHER_LDFLAGS[sdk=macosx10.6][arch=*]" = "-lAWACS";
+				OTHER_REZFLAGS = "";
+				PRODUCT_NAME = mDNSResponder;
+				PROVISIONING_PROFILE = "";
+				REZ_EXECUTABLE = YES;
+			};
+			name = Development;
+		};
+		D284BE930ADD80800027CCDF /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(SDKROOT)/$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+				);
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_OPTIMIZATION_LEVEL = s;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(inherited)",
+					"MDNS_DEBUGMSGS=1",
+				);
+				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",
+				);
+				LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
+				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				OTHER_CFLAGS = (
+					"$(inherited)",
+					"-no-cpp-precomp",
+				);
+				OTHER_LDFLAGS = "";
+				"OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = (
+					"-Wl,-pie",
+					"-weak_framework",
+					DeviceToDeviceManager,
+					"-lMobileGestalt",
+					"-lcupolicy",
+				);
+				"OTHER_LDFLAGS[sdk=macosx*][arch=*]" = (
+					"-Wl,-pie",
+					"-lAWACS",
+					"-weak_framework",
+					WebFilterDNS,
+					"-weak_framework",
+					DeviceToDeviceManager,
+				);
+				"OTHER_LDFLAGS[sdk=macosx10.6][arch=*]" = "-lAWACS";
+				OTHER_REZFLAGS = "";
+				PRODUCT_NAME = mDNSResponder.debug;
+				REZ_EXECUTABLE = YES;
+				SECTORDER_FLAGS = (
+					"-sectorder",
+					__TEXT,
+					__text,
+					mDNSResponder.order,
+				);
+				SKIP_INSTALL = YES;
+			};
+			name = Development;
+		};
+		D284BEAE0ADD80920027CCDF /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				HEADER_SEARCH_PATHS = (
+					../mDNSShared,
+					"${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders",
+				);
+				INSTALL_PATH_ACTUAL = /usr/bin;
+				OTHER_CFLAGS = "-no-cpp-precomp";
+				OTHER_LDFLAGS = "";
+				OTHER_REZFLAGS = "";
+				PRODUCT_NAME = "dns-sd";
+				REZ_EXECUTABLE = YES;
+				SECTORDER_FLAGS = "";
+			};
+			name = Development;
+		};
+		D284BEBC0ADD809A0027CCDF /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				EXECUTABLE_EXTENSION = jnilib;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				HEADER_SEARCH_PATHS = (
+					../mDNSShared,
+					"${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/A/Headers",
+					"${SYSTEM_LIBRARY_DIR}/Frameworks/JavaVM.framework/Versions/1.3.1/Headers",
+					"${PROJECT_DERIVED_FILE_DIR}",
+				);
+				INSTALL_PATH_ACTUAL = /usr/lib/java;
+				LIBRARY_STYLE = DYNAMIC;
+				MACH_O_TYPE = mh_dylib;
+				OTHER_CFLAGS = "";
+				OTHER_LIBTOOL_FLAGS = "";
+				OTHER_REZFLAGS = "";
+				PRODUCT_NAME = libjdns_sd;
+				REZ_EXECUTABLE = YES;
+				SECTORDER_FLAGS = "";
+			};
+			name = Development;
+		};
+		D284BED70ADD80A20027CCDF /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				FRAMEWORK_SEARCH_PATHS = "";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				HEADER_SEARCH_PATHS = (
+					"${SYSTEM_LIBRARY_DIR}/Frameworks/System.framework/PrivateHeaders",
+					"${APPLE_INTERNAL_DEVELOPER_DIR}/Headers",
+					"${CONFIGURATION_TEMP_DIR}",
+					/System/Library/Frameworks/System.Framework/PrivateHeaders,
+				);
+				INSTALL_PATH_ACTUAL = /usr/sbin;
+				LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
+				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				OTHER_CFLAGS = (
+					"-no-cpp-precomp",
+					"-UAPPLE_OSX_mDNSResponder",
+				);
+				OTHER_LDFLAGS = "";
+				"OTHER_LDFLAGS[sdk=macosx*][arch=*]" = "-Wl,-pie";
+				PRODUCT_NAME = dnsextd;
+				SECTORDER_FLAGS = "";
+			};
+			name = Development;
+		};
+		D284BEE60ADD80A70027CCDF /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				INSTALL_PATH_ACTUAL = "/Library/Application Support/Bonjour";
+				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				OTHER_CFLAGS = "";
+				OTHER_LDFLAGS = "";
+				"OTHER_LDFLAGS[sdk=macosx*]" = "-Wl,-pie";
+				OTHER_REZFLAGS = "";
+				PRODUCT_NAME = ddnswriteconfig;
+				REZ_EXECUTABLE = YES;
+				SECTORDER_FLAGS = "";
+			};
+			name = Development;
+		};
+		D284BF090ADD80B00027CCDF /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				EXPORTED_SYMBOLS_FILE = "";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_OBJC_GC = supported;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				INFOPLIST_FILE = "PreferencePane/Info-PreferencePane.plist";
+				INSTALL_PATH_ACTUAL = /AppleInternal/Library/PreferencePanes;
+				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				OTHER_CFLAGS = "";
+				OTHER_LDFLAGS = "-twolevel_namespace";
+				OTHER_REZFLAGS = "";
+				PRODUCT_NAME = Bonjour;
+				SECTORDER_FLAGS = "";
+				WRAPPER_EXTENSION = prefPane;
+			};
+			name = Development;
+		};
+		FFA572380AF18F1C0055A0F1 /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				COPY_PHASE_STRIP = NO;
+				DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
+				EXECUTABLE_EXTENSION = dylib;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(inherited)",
+					"__DARWIN_NON_CANCELABLE=1",
+				);
+				HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+				INSTALL_PATH_ACTUAL = /usr/lib/system;
+				LINK_WITH_STANDARD_LIBRARIES = NO;
+				OTHER_LDFLAGS = (
+					"-Wl,-umbrella,System",
+					"-L/usr/lib/system",
+					"-ldyld",
+					"-lcompiler_rt",
+					"-lsystem_kernel",
+					"-lsystem_platform",
+					"-lsystem_pthread",
+					"-lsystem_malloc",
+					"-lsystem_c",
+					"-lsystem_blocks",
+					"-ldispatch",
+					"-llaunch",
+					"-lsystem_asl",
+				);
+				"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
+					"-Wl,-umbrella,System",
+					"-L/usr/lib/system",
+					"-ldyld_sim",
+					"-lcompiler_rt_sim",
+					"-lsystem_sim_c",
+					"-lsystem_sim_blocks",
+					"-ldispatch",
+					"-Wl,-upward-lSystem",
+				);
+				PRODUCT_NAME = libsystem_dnssd_debug;
+				"PRODUCT_NAME[sdk=iphonesimulator*]" = libsystem_sim_dnssd_debug;
+			};
+			name = Development;
+		};
+		FFA572440AF18F450055A0F1 /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				COPY_PHASE_STRIP = NO;
+				DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
+				EXECUTABLE_EXTENSION = dylib;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(inherited)",
+					"__DARWIN_NON_CANCELABLE=1",
+				);
+				GENERATE_PROFILING_CODE = YES;
+				HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+				INSTALL_PATH_ACTUAL = /usr/lib/system;
+				LINK_WITH_STANDARD_LIBRARIES = NO;
+				OTHER_LDFLAGS = (
+					"-Wl,-umbrella,System",
+					"-L/usr/lib/system",
+					"-ldyld",
+					"-lcompiler_rt",
+					"-lsystem_kernel",
+					"-lsystem_platform",
+					"-lsystem_pthread",
+					"-lsystem_malloc",
+					"-lsystem_c",
+					"-lsystem_blocks",
+					"-ldispatch",
+					"-llaunch",
+					"-lsystem_asl",
+				);
+				"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
+					"-Wl,-umbrella,System",
+					"-L/usr/lib/system",
+					"-ldyld_sim",
+					"-lcompiler_rt_sim",
+					"-lsystem_sim_c",
+					"-lsystem_sim_blocks",
+					"-ldispatch",
+					"-Wl,-upward-lSystem",
+				);
+				PRODUCT_NAME = libsystem_dnssd_profile;
+				"PRODUCT_NAME[sdk=iphonesimulator*]" = libsystem_sim_dnssd_profile;
+			};
+			name = Development;
+		};
+		FFA5726F0AF191200055A0F1 /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				PRODUCT_NAME = SystemLibrariesDynamic;
+			};
+			name = Development;
+		};
+		FFB7657F0AEED99D00583A2C /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				PRODUCT_NAME = "Build All";
+			};
+			name = Development;
+		};
+		FFB7658A0AEED9FB00583A2C /* Development */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "${BUILD_DIR}";
+				CONFIGURATION_TEMP_DIR = "${BUILD_DIR}/mDNSResponder.build";
+				COPY_PHASE_STRIP = NO;
+				DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
+				EXECUTABLE_EXTENSION = dylib;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"$(inherited)",
+					"__DARWIN_NON_CANCELABLE=1",
+				);
+				GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+				HEADER_SEARCH_PATHS = "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/";
+				INSTALLHDRS_COPY_PHASE = YES;
+				INSTALLHDRS_SCRIPT_PHASE = YES;
+				INSTALL_PATH_ACTUAL = /usr/lib/system;
+				LINK_WITH_STANDARD_LIBRARIES = NO;
+				OTHER_LDFLAGS = (
+					"-Wl,-umbrella,System",
+					"-L/usr/lib/system",
+					"-ldyld",
+					"-lcompiler_rt",
+					"-lsystem_kernel",
+					"-lsystem_platform",
+					"-lsystem_pthread",
+					"-lsystem_malloc",
+					"-lsystem_c",
+					"-lsystem_blocks",
+					"-ldispatch",
+					"-llaunch",
+					"-lsystem_asl",
+				);
+				"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
+					"-Wl,-umbrella,System",
+					"-L/usr/lib/system",
+					"-ldyld_sim",
+					"-lcompiler_rt_sim",
+					"-lsystem_sim_c",
+					"-lsystem_sim_blocks",
+					"-ldispatch",
+					"-Wl,-upward-lSystem",
+				);
+				PRODUCT_NAME = libsystem_dnssd;
+				"PRODUCT_NAME[sdk=iphonesimulator*]" = libsystem_sim_dnssd;
+			};
+			name = Development;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		03067D730C83A3CB0022BE1F /* Build configuration list for PBXAggregateTarget "Build Some" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				03067D740C83A3CB0022BE1F /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		213FB21B12028A7C002B3A08 /* Build configuration list for PBXNativeTarget "BonjourEvents" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				213FB21A12028A7B002B3A08 /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		2141DD08123FFB830086D23E /* Build configuration list for PBXAggregateTarget "SystemLibraries" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2141DCF9123FFB5D0086D23E /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		2141DD18123FFC990086D23E /* Build configuration list for PBXAggregateTarget "SystemLibrariesStatic" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2141DD0C123FFC7F0086D23E /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		2141DD1F123FFCF90086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_static" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2141DD1E123FFCDB0086D23E /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		2141DD35123FFD3B0086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_debug_static" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2141DD25123FFD100086D23E /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		2141DD36123FFD3B0086D23E /* Build configuration list for PBXNativeTarget "libdns_sd_profile_static" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2141DD2B123FFD2C0086D23E /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		2E0405F30C31956600F13B59 /* Build configuration list for PBXNativeTarget "mDNSResponderHelper" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2E0405F20C31955500F13B59 /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		4AE471770EAFF84000A6C5AD /* Build configuration list for PBXLegacyTarget "dns_sd.jar" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				4AE471680EAFF81900A6C5AD /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		72FB5465166D5FB00090B2D9 /* Build configuration list for PBXNativeTarget "dnsctl" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				72FB5466166D5FB00090B2D9 /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		84C5B3361665529800C324A8 /* Build configuration list for PBXNativeTarget "dns_services" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				84C5B3371665529800C324A8 /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		D284BE280ADD78180027CCDF /* Build configuration list for PBXAggregateTarget "Build More" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D284BE290ADD78180027CCDF /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		D284BE2B0ADD78180027CCDF /* Build configuration list for PBXProject "mDNSResponder" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D284BE2C0ADD78180027CCDF /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		D284BE6D0ADD80740027CCDF /* Build configuration list for PBXNativeTarget "mDNSResponder" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D284BE6E0ADD80740027CCDF /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		D284BE920ADD80800027CCDF /* Build configuration list for PBXNativeTarget "mDNSResponder debug" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D284BE930ADD80800027CCDF /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		D284BEAD0ADD80920027CCDF /* Build configuration list for PBXNativeTarget "dns-sd tool" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D284BEAE0ADD80920027CCDF /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		D284BEBB0ADD809A0027CCDF /* Build configuration list for PBXNativeTarget "libjdns_sd.jnilib" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D284BEBC0ADD809A0027CCDF /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		D284BED60ADD80A20027CCDF /* Build configuration list for PBXNativeTarget "dnsextd" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D284BED70ADD80A20027CCDF /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		D284BEE50ADD80A70027CCDF /* Build configuration list for PBXNativeTarget "ddnswriteconfig" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D284BEE60ADD80A70027CCDF /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		D284BF080ADD80B00027CCDF /* Build configuration list for PBXNativeTarget "PreferencePane" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				D284BF090ADD80B00027CCDF /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		FFA572370AF18F1C0055A0F1 /* Build configuration list for PBXNativeTarget "libdns_sd_debug_dynamic" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				FFA572380AF18F1C0055A0F1 /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		FFA572430AF18F450055A0F1 /* Build configuration list for PBXNativeTarget "libdns_sd_profile_dynamic" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				FFA572440AF18F450055A0F1 /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		FFA5726E0AF191200055A0F1 /* Build configuration list for PBXAggregateTarget "SystemLibrariesDynamic" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				FFA5726F0AF191200055A0F1 /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		FFB7657E0AEED99D00583A2C /* Build configuration list for PBXAggregateTarget "Build All" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				FFB7657F0AEED99D00583A2C /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+		FFB765890AEED9FB00583A2C /* Build configuration list for PBXNativeTarget "libdns_sd_dynamic" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				FFB7658A0AEED9FB00583A2C /* Development */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Development;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}

Deleted: vendor/apple/mDNSResponder/561.1.1/mDNSPosix/mDNSPosix.c
===================================================================
--- vendor/apple/mDNSResponder/dist/mDNSPosix/mDNSPosix.c	2014-06-30 23:58:12 UTC (rev 6706)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSPosix/mDNSPosix.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -1,1789 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2004 Apple Computer, 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 "mDNSEmbeddedAPI.h"           // Defines the interface provided to the client layer above
-#include "DNSCommon.h"
-#include "mDNSPosix.h"               // Defines the specific types needed to run mDNS on this platform
-#include "dns_sd.h"
-#include "dnssec.h"
-#include "nsec.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <stdarg.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <sys/select.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <time.h>                   // platform support for UTC time
-
-#if USES_NETLINK
-#include <asm/types.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#else // USES_NETLINK
-#include <net/route.h>
-#include <net/if.h>
-#endif // USES_NETLINK
-
-#include "mDNSUNP.h"
-#include "GenLinkedList.h"
-
-// ***************************************************************************
-// Structures
-
-// We keep a list of client-supplied event sources in PosixEventSource records
-struct PosixEventSource
-{
-    mDNSPosixEventCallback Callback;
-    void                        *Context;
-    int fd;
-    struct  PosixEventSource    *Next;
-};
-typedef struct PosixEventSource PosixEventSource;
-
-// Context record for interface change callback
-struct IfChangeRec
-{
-    int NotifySD;
-    mDNS *mDNS;
-};
-typedef struct IfChangeRec IfChangeRec;
-
-// Note that static data is initialized to zero in (modern) C.
-static fd_set gEventFDs;
-static int gMaxFD;                              // largest fd in gEventFDs
-static GenLinkedList gEventSources;             // linked list of PosixEventSource's
-static sigset_t gEventSignalSet;                // Signals which event loop listens for
-static sigset_t gEventSignals;                  // Signals which were received while inside loop
-
-// ***************************************************************************
-// Globals (for debugging)
-
-static int num_registered_interfaces = 0;
-static int num_pkts_accepted = 0;
-static int num_pkts_rejected = 0;
-
-// ***************************************************************************
-// Functions
-
-int gMDNSPlatformPosixVerboseLevel = 0;
-
-#define PosixErrorToStatus(errNum) ((errNum) == 0 ? mStatus_NoError : mStatus_UnknownErr)
-
-mDNSlocal void SockAddrTomDNSAddr(const struct sockaddr *const sa, mDNSAddr *ipAddr, mDNSIPPort *ipPort)
-{
-    switch (sa->sa_family)
-    {
-    case AF_INET:
-    {
-        struct sockaddr_in *sin          = (struct sockaddr_in*)sa;
-        ipAddr->type                     = mDNSAddrType_IPv4;
-        ipAddr->ip.v4.NotAnInteger       = sin->sin_addr.s_addr;
-        if (ipPort) ipPort->NotAnInteger = sin->sin_port;
-        break;
-    }
-
-#if HAVE_IPV6
-    case AF_INET6:
-    {
-        struct sockaddr_in6 *sin6        = (struct sockaddr_in6*)sa;
-#ifndef NOT_HAVE_SA_LEN
-        assert(sin6->sin6_len == sizeof(*sin6));
-#endif
-        ipAddr->type                     = mDNSAddrType_IPv6;
-        ipAddr->ip.v6                    = *(mDNSv6Addr*)&sin6->sin6_addr;
-        if (ipPort) ipPort->NotAnInteger = sin6->sin6_port;
-        break;
-    }
-#endif
-
-    default:
-        verbosedebugf("SockAddrTomDNSAddr: Uknown address family %d\n", sa->sa_family);
-        ipAddr->type = mDNSAddrType_None;
-        if (ipPort) ipPort->NotAnInteger = 0;
-        break;
-    }
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Send and Receive
-#endif
-
-// mDNS core calls this routine when it needs to send a packet.
-mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
-                                       mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, 
-                                       mDNSIPPort dstPort, mDNSBool useBackgroundTrafficClass)
-{
-    int err = 0;
-    struct sockaddr_storage to;
-    PosixNetworkInterface * thisIntf = (PosixNetworkInterface *)(InterfaceID);
-    int sendingsocket = -1;
-
-    (void)src;  // Will need to use this parameter once we implement mDNSPlatformUDPSocket/mDNSPlatformUDPClose
-    (void) useBackgroundTrafficClass;
-
-    assert(m != NULL);
-    assert(msg != NULL);
-    assert(end != NULL);
-    assert((((char *) end) - ((char *) msg)) > 0);
-
-    if (dstPort.NotAnInteger == 0)
-    {
-        LogMsg("mDNSPlatformSendUDP: Invalid argument -dstPort is set to 0");
-        return PosixErrorToStatus(EINVAL);
-    }
-    if (dst->type == mDNSAddrType_IPv4)
-    {
-        struct sockaddr_in *sin = (struct sockaddr_in*)&to;
-#ifndef NOT_HAVE_SA_LEN
-        sin->sin_len            = sizeof(*sin);
-#endif
-        sin->sin_family         = AF_INET;
-        sin->sin_port           = dstPort.NotAnInteger;
-        sin->sin_addr.s_addr    = dst->ip.v4.NotAnInteger;
-        sendingsocket           = thisIntf ? thisIntf->multicastSocket4 : m->p->unicastSocket4;
-    }
-
-#if HAVE_IPV6
-    else if (dst->type == mDNSAddrType_IPv6)
-    {
-        struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&to;
-        mDNSPlatformMemZero(sin6, sizeof(*sin6));
-#ifndef NOT_HAVE_SA_LEN
-        sin6->sin6_len            = sizeof(*sin6);
-#endif
-        sin6->sin6_family         = AF_INET6;
-        sin6->sin6_port           = dstPort.NotAnInteger;
-        sin6->sin6_addr           = *(struct in6_addr*)&dst->ip.v6;
-        sendingsocket             = thisIntf ? thisIntf->multicastSocket6 : m->p->unicastSocket6;
-    }
-#endif
-
-    if (sendingsocket >= 0)
-        err = sendto(sendingsocket, msg, (char*)end - (char*)msg, 0, (struct sockaddr *)&to, GET_SA_LEN(to));
-
-    if      (err > 0) err = 0;
-    else if (err < 0)
-    {
-        static int MessageCount = 0;
-        // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
-        if (!mDNSAddressIsAllDNSLinkGroup(dst))
-            if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
-
-        if (MessageCount < 1000)
-        {
-            MessageCount++;
-            if (thisIntf)
-                LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a on interface %#a/%s/%d",
-                       errno, strerror(errno), dst, &thisIntf->coreIntf.ip, thisIntf->intfName, thisIntf->index);
-            else
-                LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a", errno, strerror(errno), dst);
-        }
-    }
-
-    return PosixErrorToStatus(err);
-}
-
-// This routine is called when the main loop detects that data is available on a socket.
-mDNSlocal void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int skt)
-{
-    mDNSAddr senderAddr, destAddr;
-    mDNSIPPort senderPort;
-    ssize_t packetLen;
-    DNSMessage packet;
-    struct my_in_pktinfo packetInfo;
-    struct sockaddr_storage from;
-    socklen_t fromLen;
-    int flags;
-    mDNSu8 ttl;
-    mDNSBool reject;
-    const mDNSInterfaceID InterfaceID = intf ? intf->coreIntf.InterfaceID : NULL;
-
-    assert(m    != NULL);
-    assert(skt  >= 0);
-
-    fromLen = sizeof(from);
-    flags   = 0;
-    packetLen = recvfrom_flags(skt, &packet, sizeof(packet), &flags, (struct sockaddr *) &from, &fromLen, &packetInfo, &ttl);
-
-    if (packetLen >= 0)
-    {
-        SockAddrTomDNSAddr((struct sockaddr*)&from, &senderAddr, &senderPort);
-        SockAddrTomDNSAddr((struct sockaddr*)&packetInfo.ipi_addr, &destAddr, NULL);
-
-        // If we have broken IP_RECVDSTADDR functionality (so far
-        // I've only seen this on OpenBSD) then apply a hack to
-        // convince mDNS Core that this isn't a spoof packet.
-        // Basically what we do is check to see whether the
-        // packet arrived as a multicast and, if so, set its
-        // destAddr to the mDNS address.
-        //
-        // I must admit that I could just be doing something
-        // wrong on OpenBSD and hence triggering this problem
-        // but I'm at a loss as to how.
-        //
-        // If this platform doesn't have IP_PKTINFO or IP_RECVDSTADDR, then we have
-        // no way to tell the destination address or interface this packet arrived on,
-        // so all we can do is just assume it's a multicast
-
-        #if HAVE_BROKEN_RECVDSTADDR || (!defined(IP_PKTINFO) && !defined(IP_RECVDSTADDR))
-        if ((destAddr.NotAnInteger == 0) && (flags & MSG_MCAST))
-        {
-            destAddr.type = senderAddr.type;
-            if      (senderAddr.type == mDNSAddrType_IPv4) destAddr.ip.v4 = AllDNSLinkGroup_v4.ip.v4;
-            else if (senderAddr.type == mDNSAddrType_IPv6) destAddr.ip.v6 = AllDNSLinkGroup_v6.ip.v6;
-        }
-        #endif
-
-        // We only accept the packet if the interface on which it came
-        // in matches the interface associated with this socket.
-        // We do this match by name or by index, depending on which
-        // information is available.  recvfrom_flags sets the name
-        // to "" if the name isn't available, or the index to -1
-        // if the index is available.  This accomodates the various
-        // different capabilities of our target platforms.
-
-        reject = mDNSfalse;
-        if (!intf)
-        {
-            // Ignore multicasts accidentally delivered to our unicast receiving socket
-            if (mDNSAddrIsDNSMulticast(&destAddr)) packetLen = -1;
-        }
-        else
-        {
-            if      (packetInfo.ipi_ifname[0] != 0) reject = (strcmp(packetInfo.ipi_ifname, intf->intfName) != 0);
-            else if (packetInfo.ipi_ifindex != -1) reject = (packetInfo.ipi_ifindex != intf->index);
-
-            if (reject)
-            {
-                verbosedebugf("SocketDataReady ignored a packet from %#a to %#a on interface %s/%d expecting %#a/%s/%d/%d",
-                              &senderAddr, &destAddr, packetInfo.ipi_ifname, packetInfo.ipi_ifindex,
-                              &intf->coreIntf.ip, intf->intfName, intf->index, skt);
-                packetLen = -1;
-                num_pkts_rejected++;
-                if (num_pkts_rejected > (num_pkts_accepted + 1) * (num_registered_interfaces + 1) * 2)
-                {
-                    fprintf(stderr,
-                            "*** WARNING: Received %d packets; Accepted %d packets; Rejected %d packets because of interface mismatch\n",
-                            num_pkts_accepted + num_pkts_rejected, num_pkts_accepted, num_pkts_rejected);
-                    num_pkts_accepted = 0;
-                    num_pkts_rejected = 0;
-                }
-            }
-            else
-            {
-                verbosedebugf("SocketDataReady got a packet from %#a to %#a on interface %#a/%s/%d/%d",
-                              &senderAddr, &destAddr, &intf->coreIntf.ip, intf->intfName, intf->index, skt);
-                num_pkts_accepted++;
-            }
-        }
-    }
-
-    if (packetLen >= 0)
-        mDNSCoreReceive(m, &packet, (mDNSu8 *)&packet + packetLen,
-                        &senderAddr, senderPort, &destAddr, MulticastDNSPort, InterfaceID);
-}
-
-mDNSexport mDNSBool mDNSPlatformPeekUDP(mDNS *const m, UDPSocket *src)
-{
-    (void)m;    // unused
-    (void)src;  // unused
-    return mDNSfalse;
-}
-
-mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS * const m, TCPSocketFlags flags, mDNSIPPort * port, mDNSBool useBackgroundTrafficClass)
-{
-    (void)m;            // Unused
-    (void)flags;        // Unused
-    (void)port;         // Unused
-    (void)useBackgroundTrafficClass; // Unused
-    return NULL;
-}
-
-mDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd)
-{
-    (void)flags;        // Unused
-    (void)sd;           // Unused
-    return NULL;
-}
-
-mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
-{
-    (void)sock;         // Unused
-    return -1;
-}
-
-mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname, mDNSInterfaceID InterfaceID,
-                                          TCPConnectionCallback callback, void *context)
-{
-    (void)sock;         // Unused
-    (void)dst;          // Unused
-    (void)dstport;      // Unused
-    (void)hostname;     // Unused
-    (void)InterfaceID;  // Unused
-    (void)callback;     // Unused
-    (void)context;      // Unused
-    return(mStatus_UnsupportedErr);
-}
-
-mDNSexport void mDNSPlatformTCPCloseConnection(TCPSocket *sock)
-{
-    (void)sock;         // Unused
-}
-
-mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool * closed)
-{
-    (void)sock;         // Unused
-    (void)buf;          // Unused
-    (void)buflen;       // Unused
-    (void)closed;       // Unused
-    return 0;
-}
-
-mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len)
-{
-    (void)sock;         // Unused
-    (void)msg;          // Unused
-    (void)len;          // Unused
-    return 0;
-}
-
-mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS * const m, mDNSIPPort port)
-{
-    (void)m;            // Unused
-    (void)port;         // Unused
-    return NULL;
-}
-
-mDNSexport void           mDNSPlatformUDPClose(UDPSocket *sock)
-{
-    (void)sock;         // Unused
-}
-
-mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
-{
-    (void)m;            // Unused
-    (void)InterfaceID;          // Unused
-}
-
-mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
-{
-    (void)msg;          // Unused
-    (void)end;          // Unused
-    (void)InterfaceID;          // Unused
-}
-
-mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
-{
-    (void)m;            // Unused
-    (void)tpa;          // Unused
-    (void)tha;          // Unused
-    (void)InterfaceID;          // Unused
-}
-
-mDNSexport mStatus mDNSPlatformTLSSetupCerts(void)
-{
-    return(mStatus_UnsupportedErr);
-}
-
-mDNSexport void mDNSPlatformTLSTearDownCerts(void)
-{
-}
-
-mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason)
-{
-    (void) m;
-    (void) allowSleep;
-    (void) reason;
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - /etc/hosts support
-#endif
-
-mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-    (void)m;  // unused
-    (void)rr;
-    (void)result;
-}
-
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** DDNS Config Platform Functions
-#endif
-
-mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains,
-    DNameListElem **BrowseDomains, mDNSBool ackConfig)
-{
-    (void) m;
-    (void) setservers;
-    (void) fqdn;
-    (void) setsearch;
-    (void) RegDomains;
-    (void) BrowseDomains;
-    (void) ackConfig;
-
-    return mDNStrue;
-}
-
-mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS * const m, mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router)
-{
-    (void) m;
-    (void) v4;
-    (void) v6;
-    (void) router;
-
-    return mStatus_UnsupportedErr;
-}
-
-mDNSexport void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
-{
-    (void) dname;
-    (void) status;
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Init and Term
-#endif
-
-// This gets the current hostname, truncating it at the first dot if necessary
-mDNSlocal void GetUserSpecifiedRFC1034ComputerName(domainlabel *const namelabel)
-{
-    int len = 0;
-    gethostname((char *)(&namelabel->c[1]), MAX_DOMAIN_LABEL);
-    while (len < MAX_DOMAIN_LABEL && namelabel->c[len+1] && namelabel->c[len+1] != '.') len++;
-    namelabel->c[0] = len;
-}
-
-// On OS X this gets the text of the field labelled "Computer Name" in the Sharing Prefs Control Panel
-// Other platforms can either get the information from the appropriate place,
-// or they can alternatively just require all registering services to provide an explicit name
-mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
-{
-    // On Unix we have no better name than the host name, so we just use that.
-    GetUserSpecifiedRFC1034ComputerName(namelabel);
-}
-
-mDNSexport int ParseDNSServers(mDNS *m, const char *filePath)
-{
-    char line[256];
-    char nameserver[16];
-    char keyword[11];
-    int numOfServers = 0;
-    FILE *fp = fopen(filePath, "r");
-    if (fp == NULL) return -1;
-    while (fgets(line,sizeof(line),fp))
-    {
-        struct in_addr ina;
-        line[255]='\0';     // just to be safe
-        if (sscanf(line,"%10s %15s", keyword, nameserver) != 2) continue;   // it will skip whitespaces
-        if (strncasecmp(keyword,"nameserver",10)) continue;
-        if (inet_aton(nameserver, (struct in_addr *)&ina) != 0)
-        {
-            mDNSAddr DNSAddr;
-            DNSAddr.type = mDNSAddrType_IPv4;
-            DNSAddr.ip.v4.NotAnInteger = ina.s_addr;
-            mDNS_AddDNSServer(m, NULL, mDNSInterface_Any, 0, &DNSAddr, UnicastDNSPort, kScopeNone, 0, mDNSfalse, 0, mDNStrue, mDNStrue, mDNSfalse);
-            numOfServers++;
-        }
-    }
-    return (numOfServers > 0) ? 0 : -1;
-}
-
-// Searches the interface list looking for the named interface.
-// Returns a pointer to if it found, or NULL otherwise.
-mDNSlocal PosixNetworkInterface *SearchForInterfaceByName(mDNS *const m, const char *intfName)
-{
-    PosixNetworkInterface *intf;
-
-    assert(m != NULL);
-    assert(intfName != NULL);
-
-    intf = (PosixNetworkInterface*)(m->HostInterfaces);
-    while ((intf != NULL) && (strcmp(intf->intfName, intfName) != 0))
-        intf = (PosixNetworkInterface *)(intf->coreIntf.next);
-
-    return intf;
-}
-
-mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 index)
-{
-    PosixNetworkInterface *intf;
-
-    assert(m != NULL);
-
-    if (index == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
-    if (index == kDNSServiceInterfaceIndexP2P      ) return(mDNSInterface_P2P);
-    if (index == kDNSServiceInterfaceIndexAny      ) return(mDNSInterface_Any);
-
-    intf = (PosixNetworkInterface*)(m->HostInterfaces);
-    while ((intf != NULL) && (mDNSu32) intf->index != index)
-        intf = (PosixNetworkInterface *)(intf->coreIntf.next);
-
-    return (mDNSInterfaceID) intf;
-}
-
-mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange)
-{
-    PosixNetworkInterface *intf;
-    (void) suppressNetworkChange; // Unused
-
-    assert(m != NULL);
-
-    if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
-    if (id == mDNSInterface_P2P      ) return(kDNSServiceInterfaceIndexP2P);
-    if (id == mDNSInterface_Any      ) return(kDNSServiceInterfaceIndexAny);
-
-    intf = (PosixNetworkInterface*)(m->HostInterfaces);
-    while ((intf != NULL) && (mDNSInterfaceID) intf != id)
-        intf = (PosixNetworkInterface *)(intf->coreIntf.next);
-
-    return intf ? intf->index : 0;
-}
-
-// Frees the specified PosixNetworkInterface structure. The underlying
-// interface must have already been deregistered with the mDNS core.
-mDNSlocal void FreePosixNetworkInterface(PosixNetworkInterface *intf)
-{
-    assert(intf != NULL);
-    if (intf->intfName != NULL) free((void *)intf->intfName);
-    if (intf->multicastSocket4 != -1) assert(close(intf->multicastSocket4) == 0);
-#if HAVE_IPV6
-    if (intf->multicastSocket6 != -1) assert(close(intf->multicastSocket6) == 0);
-#endif
-    free(intf);
-}
-
-// Grab the first interface, deregister it, free it, and repeat until done.
-mDNSlocal void ClearInterfaceList(mDNS *const m)
-{
-    assert(m != NULL);
-
-    while (m->HostInterfaces)
-    {
-        PosixNetworkInterface *intf = (PosixNetworkInterface*)(m->HostInterfaces);
-        mDNS_DeregisterInterface(m, &intf->coreIntf, mDNSfalse);
-        if (gMDNSPlatformPosixVerboseLevel > 0) fprintf(stderr, "Deregistered interface %s\n", intf->intfName);
-        FreePosixNetworkInterface(intf);
-    }
-    num_registered_interfaces = 0;
-    num_pkts_accepted = 0;
-    num_pkts_rejected = 0;
-}
-
-// Sets up a send/receive socket.
-// If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
-// If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
-mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interfaceIndex, int *sktPtr)
-{
-    int err = 0;
-    static const int kOn = 1;
-    static const int kIntTwoFiveFive = 255;
-    static const unsigned char kByteTwoFiveFive = 255;
-    const mDNSBool JoinMulticastGroup = (port.NotAnInteger != 0);
-
-    (void) interfaceIndex;  // This parameter unused on plaforms that don't have IPv6
-    assert(intfAddr != NULL);
-    assert(sktPtr != NULL);
-    assert(*sktPtr == -1);
-
-    // Open the socket...
-    if      (intfAddr->sa_family == AF_INET) *sktPtr = socket(PF_INET,  SOCK_DGRAM, IPPROTO_UDP);
-#if HAVE_IPV6
-    else if (intfAddr->sa_family == AF_INET6) *sktPtr = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
-#endif
-    else return EINVAL;
-
-    if (*sktPtr < 0) { err = errno; perror((intfAddr->sa_family == AF_INET) ? "socket AF_INET" : "socket AF_INET6"); }
-
-    // ... with a shared UDP port, if it's for multicast receiving
-    if (err == 0 && port.NotAnInteger)
-    {
-        #if defined(SO_REUSEPORT)
-        err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEPORT, &kOn, sizeof(kOn));
-        #elif defined(SO_REUSEADDR)
-        err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
-        #else
-            #error This platform has no way to avoid address busy errors on multicast.
-        #endif
-        if (err < 0) { err = errno; perror("setsockopt - SO_REUSExxxx"); }
-    }
-
-    // We want to receive destination addresses and interface identifiers.
-    if (intfAddr->sa_family == AF_INET)
-    {
-        struct ip_mreq imr;
-        struct sockaddr_in bindAddr;
-        if (err == 0)
-        {
-            #if defined(IP_PKTINFO)                                 // Linux
-            err = setsockopt(*sktPtr, IPPROTO_IP, IP_PKTINFO, &kOn, sizeof(kOn));
-            if (err < 0) { err = errno; perror("setsockopt - IP_PKTINFO"); }
-            #elif defined(IP_RECVDSTADDR) || defined(IP_RECVIF)     // BSD and Solaris
-                #if defined(IP_RECVDSTADDR)
-            err = setsockopt(*sktPtr, IPPROTO_IP, IP_RECVDSTADDR, &kOn, sizeof(kOn));
-            if (err < 0) { err = errno; perror("setsockopt - IP_RECVDSTADDR"); }
-                #endif
-                #if defined(IP_RECVIF)
-            if (err == 0)
-            {
-                err = setsockopt(*sktPtr, IPPROTO_IP, IP_RECVIF, &kOn, sizeof(kOn));
-                if (err < 0) { err = errno; perror("setsockopt - IP_RECVIF"); }
-            }
-                #endif
-            #else
-                #warning This platform has no way to get the destination interface information -- will only work for single-homed hosts
-            #endif
-        }
-    #if defined(IP_RECVTTL)                                 // Linux
-        if (err == 0)
-        {
-            setsockopt(*sktPtr, IPPROTO_IP, IP_RECVTTL, &kOn, sizeof(kOn));
-            // We no longer depend on being able to get the received TTL, so don't worry if the option fails
-        }
-    #endif
-
-        // Add multicast group membership on this interface
-        if (err == 0 && JoinMulticastGroup)
-        {
-            imr.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
-            imr.imr_interface        = ((struct sockaddr_in*)intfAddr)->sin_addr;
-            err = setsockopt(*sktPtr, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr));
-            if (err < 0) { err = errno; perror("setsockopt - IP_ADD_MEMBERSHIP"); }
-        }
-
-        // Specify outgoing interface too
-        if (err == 0 && JoinMulticastGroup)
-        {
-            err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_IF, &((struct sockaddr_in*)intfAddr)->sin_addr, sizeof(struct in_addr));
-            if (err < 0) { err = errno; perror("setsockopt - IP_MULTICAST_IF"); }
-        }
-
-        // Per the mDNS spec, send unicast packets with TTL 255
-        if (err == 0)
-        {
-            err = setsockopt(*sktPtr, IPPROTO_IP, IP_TTL, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
-            if (err < 0) { err = errno; perror("setsockopt - IP_TTL"); }
-        }
-
-        // and multicast packets with TTL 255 too
-        // There's some debate as to whether IP_MULTICAST_TTL is an int or a byte so we just try both.
-        if (err == 0)
-        {
-            err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_TTL, &kByteTwoFiveFive, sizeof(kByteTwoFiveFive));
-            if (err < 0 && errno == EINVAL)
-                err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_TTL, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
-            if (err < 0) { err = errno; perror("setsockopt - IP_MULTICAST_TTL"); }
-        }
-
-        // And start listening for packets
-        if (err == 0)
-        {
-            bindAddr.sin_family      = AF_INET;
-            bindAddr.sin_port        = port.NotAnInteger;
-            bindAddr.sin_addr.s_addr = INADDR_ANY; // Want to receive multicasts AND unicasts on this socket
-            err = bind(*sktPtr, (struct sockaddr *) &bindAddr, sizeof(bindAddr));
-            if (err < 0) { err = errno; perror("bind"); fflush(stderr); }
-        }
-    }     // endif (intfAddr->sa_family == AF_INET)
-
-#if HAVE_IPV6
-    else if (intfAddr->sa_family == AF_INET6)
-    {
-        struct ipv6_mreq imr6;
-        struct sockaddr_in6 bindAddr6;
-    #if defined(IPV6_PKTINFO)
-        if (err == 0)
-        {
-            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_2292_PKTINFO, &kOn, sizeof(kOn));
-            if (err < 0) { err = errno; perror("setsockopt - IPV6_PKTINFO"); }
-        }
-    #else
-        #warning This platform has no way to get the destination interface information for IPv6 -- will only work for single-homed hosts
-    #endif
-    #if defined(IPV6_HOPLIMIT)
-        if (err == 0)
-        {
-            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_2292_HOPLIMIT, &kOn, sizeof(kOn));
-            if (err < 0) { err = errno; perror("setsockopt - IPV6_HOPLIMIT"); }
-        }
-    #endif
-
-        // Add multicast group membership on this interface
-        if (err == 0 && JoinMulticastGroup)
-        {
-            imr6.ipv6mr_multiaddr       = *(const struct in6_addr*)&AllDNSLinkGroup_v6.ip.v6;
-            imr6.ipv6mr_interface       = interfaceIndex;
-            //LogMsg("Joining %.16a on %d", &imr6.ipv6mr_multiaddr, imr6.ipv6mr_interface);
-            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_JOIN_GROUP, &imr6, sizeof(imr6));
-            if (err < 0)
-            {
-                err = errno;
-                verbosedebugf("IPV6_JOIN_GROUP %.16a on %d failed.\n", &imr6.ipv6mr_multiaddr, imr6.ipv6mr_interface);
-                perror("setsockopt - IPV6_JOIN_GROUP");
-            }
-        }
-
-        // Specify outgoing interface too
-        if (err == 0 && JoinMulticastGroup)
-        {
-            u_int multicast_if = interfaceIndex;
-            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_if, sizeof(multicast_if));
-            if (err < 0) { err = errno; perror("setsockopt - IPV6_MULTICAST_IF"); }
-        }
-
-        // We want to receive only IPv6 packets on this socket.
-        // Without this option, we may get IPv4 addresses as mapped addresses.
-        if (err == 0)
-        {
-            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_V6ONLY, &kOn, sizeof(kOn));
-            if (err < 0) { err = errno; perror("setsockopt - IPV6_V6ONLY"); }
-        }
-
-        // Per the mDNS spec, send unicast packets with TTL 255
-        if (err == 0)
-        {
-            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
-            if (err < 0) { err = errno; perror("setsockopt - IPV6_UNICAST_HOPS"); }
-        }
-
-        // and multicast packets with TTL 255 too
-        // There's some debate as to whether IPV6_MULTICAST_HOPS is an int or a byte so we just try both.
-        if (err == 0)
-        {
-            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kByteTwoFiveFive, sizeof(kByteTwoFiveFive));
-            if (err < 0 && errno == EINVAL)
-                err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
-            if (err < 0) { err = errno; perror("setsockopt - IPV6_MULTICAST_HOPS"); }
-        }
-
-        // And start listening for packets
-        if (err == 0)
-        {
-            mDNSPlatformMemZero(&bindAddr6, sizeof(bindAddr6));
-#ifndef NOT_HAVE_SA_LEN
-            bindAddr6.sin6_len         = sizeof(bindAddr6);
-#endif
-            bindAddr6.sin6_family      = AF_INET6;
-            bindAddr6.sin6_port        = port.NotAnInteger;
-            bindAddr6.sin6_flowinfo    = 0;
-            bindAddr6.sin6_addr        = in6addr_any; // Want to receive multicasts AND unicasts on this socket
-            bindAddr6.sin6_scope_id    = 0;
-            err = bind(*sktPtr, (struct sockaddr *) &bindAddr6, sizeof(bindAddr6));
-            if (err < 0) { err = errno; perror("bind"); fflush(stderr); }
-        }
-    }     // endif (intfAddr->sa_family == AF_INET6)
-#endif
-
-    // Set the socket to non-blocking.
-    if (err == 0)
-    {
-        err = fcntl(*sktPtr, F_GETFL, 0);
-        if (err < 0) err = errno;
-        else
-        {
-            err = fcntl(*sktPtr, F_SETFL, err | O_NONBLOCK);
-            if (err < 0) err = errno;
-        }
-    }
-
-    // Clean up
-    if (err != 0 && *sktPtr != -1) { assert(close(*sktPtr) == 0); *sktPtr = -1; }
-    assert((err == 0) == (*sktPtr != -1));
-    return err;
-}
-
-// Creates a PosixNetworkInterface for the interface whose IP address is
-// intfAddr and whose name is intfName and registers it with mDNS core.
-mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct sockaddr *intfMask, const char *intfName, int intfIndex)
-{
-    int err = 0;
-    PosixNetworkInterface *intf;
-    PosixNetworkInterface *alias = NULL;
-
-    assert(m != NULL);
-    assert(intfAddr != NULL);
-    assert(intfName != NULL);
-    assert(intfMask != NULL);
-
-    // Allocate the interface structure itself.
-    intf = (PosixNetworkInterface*)malloc(sizeof(*intf));
-    if (intf == NULL) { assert(0); err = ENOMEM; }
-
-    // And make a copy of the intfName.
-    if (err == 0)
-    {
-        intf->intfName = strdup(intfName);
-        if (intf->intfName == NULL) { assert(0); err = ENOMEM; }
-    }
-
-    if (err == 0)
-    {
-        // Set up the fields required by the mDNS core.
-        SockAddrTomDNSAddr(intfAddr, &intf->coreIntf.ip, NULL);
-        SockAddrTomDNSAddr(intfMask, &intf->coreIntf.mask, NULL);
-
-        //LogMsg("SetupOneInterface: %#a %#a",  &intf->coreIntf.ip,  &intf->coreIntf.mask);
-        strncpy(intf->coreIntf.ifname, intfName, sizeof(intf->coreIntf.ifname));
-        intf->coreIntf.ifname[sizeof(intf->coreIntf.ifname)-1] = 0;
-        intf->coreIntf.Advertise = m->AdvertiseLocalAddresses;
-        intf->coreIntf.McastTxRx = mDNStrue;
-
-        // Set up the extra fields in PosixNetworkInterface.
-        assert(intf->intfName != NULL);         // intf->intfName already set up above
-        intf->index                = intfIndex;
-        intf->multicastSocket4     = -1;
-#if HAVE_IPV6
-        intf->multicastSocket6     = -1;
-#endif
-        alias                      = SearchForInterfaceByName(m, intf->intfName);
-        if (alias == NULL) alias   = intf;
-        intf->coreIntf.InterfaceID = (mDNSInterfaceID)alias;
-
-        if (alias != intf)
-            debugf("SetupOneInterface: %s %#a is an alias of %#a", intfName, &intf->coreIntf.ip, &alias->coreIntf.ip);
-    }
-
-    // Set up the multicast socket
-    if (err == 0)
-    {
-        if (alias->multicastSocket4 == -1 && intfAddr->sa_family == AF_INET)
-            err = SetupSocket(intfAddr, MulticastDNSPort, intf->index, &alias->multicastSocket4);
-#if HAVE_IPV6
-        else if (alias->multicastSocket6 == -1 && intfAddr->sa_family == AF_INET6)
-            err = SetupSocket(intfAddr, MulticastDNSPort, intf->index, &alias->multicastSocket6);
-#endif
-    }
-
-    // If interface is a direct link, address record will be marked as kDNSRecordTypeKnownUnique
-    // and skip the probe phase of the probe/announce packet sequence.
-    intf->coreIntf.DirectLink = mDNSfalse;
-
-    // The interface is all ready to go, let's register it with the mDNS core.
-    if (err == 0)
-        err = mDNS_RegisterInterface(m, &intf->coreIntf, mDNSfalse);
-
-    // Clean up.
-    if (err == 0)
-    {
-        num_registered_interfaces++;
-        debugf("SetupOneInterface: %s %#a Registered", intf->intfName, &intf->coreIntf.ip);
-        if (gMDNSPlatformPosixVerboseLevel > 0)
-            fprintf(stderr, "Registered interface %s\n", intf->intfName);
-    }
-    else
-    {
-        // Use intfName instead of intf->intfName in the next line to avoid dereferencing NULL.
-        debugf("SetupOneInterface: %s %#a failed to register %d", intfName, &intf->coreIntf.ip, err);
-        if (intf) { FreePosixNetworkInterface(intf); intf = NULL; }
-    }
-
-    assert((err == 0) == (intf != NULL));
-
-    return err;
-}
-
-// Call get_ifi_info() to obtain a list of active interfaces and call SetupOneInterface() on each one.
-mDNSlocal int SetupInterfaceList(mDNS *const m)
-{
-    mDNSBool foundav4       = mDNSfalse;
-    int err            = 0;
-    struct ifi_info *intfList      = get_ifi_info(AF_INET, mDNStrue);
-    struct ifi_info *firstLoopback = NULL;
-
-    assert(m != NULL);
-    debugf("SetupInterfaceList");
-
-    if (intfList == NULL) err = ENOENT;
-
-#if HAVE_IPV6
-    if (err == 0)       /* Link the IPv6 list to the end of the IPv4 list */
-    {
-        struct ifi_info **p = &intfList;
-        while (*p) p = &(*p)->ifi_next;
-        *p = get_ifi_info(AF_INET6, mDNStrue);
-    }
-#endif
-
-    if (err == 0)
-    {
-        struct ifi_info *i = intfList;
-        while (i)
-        {
-            if (     ((i->ifi_addr->sa_family == AF_INET)
-#if HAVE_IPV6
-                      || (i->ifi_addr->sa_family == AF_INET6)
-#endif
-                      ) &&  (i->ifi_flags & IFF_UP) && !(i->ifi_flags & IFF_POINTOPOINT))
-            {
-                if (i->ifi_flags & IFF_LOOPBACK)
-                {
-                    if (firstLoopback == NULL)
-                        firstLoopback = i;
-                }
-                else
-                {
-                    if (SetupOneInterface(m, i->ifi_addr, i->ifi_netmask, i->ifi_name, i->ifi_index) == 0)
-                        if (i->ifi_addr->sa_family == AF_INET)
-                            foundav4 = mDNStrue;
-                }
-            }
-            i = i->ifi_next;
-        }
-
-        // If we found no normal interfaces but we did find a loopback interface, register the
-        // loopback interface.  This allows self-discovery if no interfaces are configured.
-        // Temporary workaround: Multicast loopback on IPv6 interfaces appears not to work.
-        // In the interim, we skip loopback interface only if we found at least one v4 interface to use
-        // if ((m->HostInterfaces == NULL) && (firstLoopback != NULL))
-        if (!foundav4 && firstLoopback)
-            (void) SetupOneInterface(m, firstLoopback->ifi_addr, firstLoopback->ifi_netmask, firstLoopback->ifi_name, firstLoopback->ifi_index);
-    }
-
-    // Clean up.
-    if (intfList != NULL) free_ifi_info(intfList);
-    return err;
-}
-
-#if USES_NETLINK
-
-// See <http://www.faqs.org/rfcs/rfc3549.html> for a description of NetLink
-
-// Open a socket that will receive interface change notifications
-mDNSlocal mStatus OpenIfNotifySocket(int *pFD)
-{
-    mStatus err = mStatus_NoError;
-    struct sockaddr_nl snl;
-    int sock;
-    int ret;
-
-    sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-    if (sock < 0)
-        return errno;
-
-    // Configure read to be non-blocking because inbound msg size is not known in advance
-    (void) fcntl(sock, F_SETFL, O_NONBLOCK);
-
-    /* Subscribe the socket to Link & IP addr notifications. */
-    mDNSPlatformMemZero(&snl, sizeof snl);
-    snl.nl_family = AF_NETLINK;
-    snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
-    ret = bind(sock, (struct sockaddr *) &snl, sizeof snl);
-    if (0 == ret)
-        *pFD = sock;
-    else
-        err = errno;
-
-    return err;
-}
-
-#if MDNS_DEBUGMSGS
-mDNSlocal void      PrintNetLinkMsg(const struct nlmsghdr *pNLMsg)
-{
-    const char *kNLMsgTypes[] = { "", "NLMSG_NOOP", "NLMSG_ERROR", "NLMSG_DONE", "NLMSG_OVERRUN" };
-    const char *kNLRtMsgTypes[] = { "RTM_NEWLINK", "RTM_DELLINK", "RTM_GETLINK", "RTM_NEWADDR", "RTM_DELADDR", "RTM_GETADDR" };
-
-    printf("nlmsghdr len=%d, type=%s, flags=0x%x\n", pNLMsg->nlmsg_len,
-           pNLMsg->nlmsg_type < RTM_BASE ? kNLMsgTypes[pNLMsg->nlmsg_type] : kNLRtMsgTypes[pNLMsg->nlmsg_type - RTM_BASE],
-           pNLMsg->nlmsg_flags);
-
-    if (RTM_NEWLINK <= pNLMsg->nlmsg_type && pNLMsg->nlmsg_type <= RTM_GETLINK)
-    {
-        struct ifinfomsg    *pIfInfo = (struct ifinfomsg*) NLMSG_DATA(pNLMsg);
-        printf("ifinfomsg family=%d, type=%d, index=%d, flags=0x%x, change=0x%x\n", pIfInfo->ifi_family,
-               pIfInfo->ifi_type, pIfInfo->ifi_index, pIfInfo->ifi_flags, pIfInfo->ifi_change);
-
-    }
-    else if (RTM_NEWADDR <= pNLMsg->nlmsg_type && pNLMsg->nlmsg_type <= RTM_GETADDR)
-    {
-        struct ifaddrmsg    *pIfAddr = (struct ifaddrmsg*) NLMSG_DATA(pNLMsg);
-        printf("ifaddrmsg family=%d, index=%d, flags=0x%x\n", pIfAddr->ifa_family,
-               pIfAddr->ifa_index, pIfAddr->ifa_flags);
-    }
-    printf("\n");
-}
-#endif
-
-mDNSlocal mDNSu32       ProcessRoutingNotification(int sd)
-// Read through the messages on sd and if any indicate that any interface records should
-// be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0.
-{
-    ssize_t readCount;
-    char buff[4096];
-    struct nlmsghdr         *pNLMsg = (struct nlmsghdr*) buff;
-    mDNSu32 result = 0;
-
-    // The structure here is more complex than it really ought to be because,
-    // unfortunately, there's no good way to size a buffer in advance large
-    // enough to hold all pending data and so avoid message fragmentation.
-    // (Note that FIONREAD is not supported on AF_NETLINK.)
-
-    readCount = read(sd, buff, sizeof buff);
-    while (1)
-    {
-        // Make sure we've got an entire nlmsghdr in the buffer, and payload, too.
-        // If not, discard already-processed messages in buffer and read more data.
-        if (((char*) &pNLMsg[1] > (buff + readCount)) ||    // i.e. *pNLMsg extends off end of buffer
-            ((char*) pNLMsg + pNLMsg->nlmsg_len > (buff + readCount)))
-        {
-            if (buff < (char*) pNLMsg)      // we have space to shuffle
-            {
-                // discard processed data
-                readCount -= ((char*) pNLMsg - buff);
-                memmove(buff, pNLMsg, readCount);
-                pNLMsg = (struct nlmsghdr*) buff;
-
-                // read more data
-                readCount += read(sd, buff + readCount, sizeof buff - readCount);
-                continue;                   // spin around and revalidate with new readCount
-            }
-            else
-                break;  // Otherwise message does not fit in buffer
-        }
-
-#if MDNS_DEBUGMSGS
-        PrintNetLinkMsg(pNLMsg);
-#endif
-
-        // Process the NetLink message
-        if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK)
-            result |= 1 << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index;
-        else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR)
-            result |= 1 << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index;
-
-        // Advance pNLMsg to the next message in the buffer
-        if ((pNLMsg->nlmsg_flags & NLM_F_MULTI) != 0 && pNLMsg->nlmsg_type != NLMSG_DONE)
-        {
-            ssize_t len = readCount - ((char*)pNLMsg - buff);
-            pNLMsg = NLMSG_NEXT(pNLMsg, len);
-        }
-        else
-            break;  // all done!
-    }
-
-    return result;
-}
-
-#else // USES_NETLINK
-
-// Open a socket that will receive interface change notifications
-mDNSlocal mStatus OpenIfNotifySocket(int *pFD)
-{
-    *pFD = socket(AF_ROUTE, SOCK_RAW, 0);
-
-    if (*pFD < 0)
-        return mStatus_UnknownErr;
-
-    // Configure read to be non-blocking because inbound msg size is not known in advance
-    (void) fcntl(*pFD, F_SETFL, O_NONBLOCK);
-
-    return mStatus_NoError;
-}
-
-#if MDNS_DEBUGMSGS
-mDNSlocal void      PrintRoutingSocketMsg(const struct ifa_msghdr *pRSMsg)
-{
-    const char *kRSMsgTypes[] = { "", "RTM_ADD", "RTM_DELETE", "RTM_CHANGE", "RTM_GET", "RTM_LOSING",
-                                  "RTM_REDIRECT", "RTM_MISS", "RTM_LOCK", "RTM_OLDADD", "RTM_OLDDEL", "RTM_RESOLVE",
-                                  "RTM_NEWADDR", "RTM_DELADDR", "RTM_IFINFO", "RTM_NEWMADDR", "RTM_DELMADDR" };
-
-    int index = pRSMsg->ifam_type == RTM_IFINFO ? ((struct if_msghdr*) pRSMsg)->ifm_index : pRSMsg->ifam_index;
-
-    printf("ifa_msghdr len=%d, type=%s, index=%d\n", pRSMsg->ifam_msglen, kRSMsgTypes[pRSMsg->ifam_type], index);
-}
-#endif
-
-mDNSlocal mDNSu32       ProcessRoutingNotification(int sd)
-// Read through the messages on sd and if any indicate that any interface records should
-// be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0.
-{
-    ssize_t readCount;
-    char buff[4096];
-    struct ifa_msghdr       *pRSMsg = (struct ifa_msghdr*) buff;
-    mDNSu32 result = 0;
-
-    readCount = read(sd, buff, sizeof buff);
-    if (readCount < (ssize_t) sizeof(struct ifa_msghdr))
-        return mStatus_UnsupportedErr;      // cannot decipher message
-
-#if MDNS_DEBUGMSGS
-    PrintRoutingSocketMsg(pRSMsg);
-#endif
-
-    // Process the message
-    if (pRSMsg->ifam_type == RTM_NEWADDR || pRSMsg->ifam_type == RTM_DELADDR ||
-        pRSMsg->ifam_type == RTM_IFINFO)
-    {
-        if (pRSMsg->ifam_type == RTM_IFINFO)
-            result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index;
-        else
-            result |= 1 << pRSMsg->ifam_index;
-    }
-
-    return result;
-}
-
-#endif // USES_NETLINK
-
-// Called when data appears on interface change notification socket
-mDNSlocal void InterfaceChangeCallback(int fd, short filter, void *context)
-{
-    IfChangeRec     *pChgRec = (IfChangeRec*) context;
-    fd_set readFDs;
-    mDNSu32 changedInterfaces = 0;
-    struct timeval zeroTimeout = { 0, 0 };
-
-    (void)fd; // Unused
-    (void)filter; // Unused
-
-    FD_ZERO(&readFDs);
-    FD_SET(pChgRec->NotifySD, &readFDs);
-
-    do
-    {
-        changedInterfaces |= ProcessRoutingNotification(pChgRec->NotifySD);
-    }
-    while (0 < select(pChgRec->NotifySD + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout));
-
-    // Currently we rebuild the entire interface list whenever any interface change is
-    // detected. If this ever proves to be a performance issue in a multi-homed
-    // configuration, more care should be paid to changedInterfaces.
-    if (changedInterfaces)
-        mDNSPlatformPosixRefreshInterfaceList(pChgRec->mDNS);
-}
-
-// Register with either a Routing Socket or RtNetLink to listen for interface changes.
-mDNSlocal mStatus WatchForInterfaceChange(mDNS *const m)
-{
-    mStatus err;
-    IfChangeRec *pChgRec;
-
-    pChgRec = (IfChangeRec*) mDNSPlatformMemAllocate(sizeof *pChgRec);
-    if (pChgRec == NULL)
-        return mStatus_NoMemoryErr;
-
-    pChgRec->mDNS = m;
-    err = OpenIfNotifySocket(&pChgRec->NotifySD);
-    if (err == 0)
-        err = mDNSPosixAddFDToEventLoop(pChgRec->NotifySD, InterfaceChangeCallback, pChgRec);
-
-    return err;
-}
-
-// Test to see if we're the first client running on UDP port 5353, by trying to bind to 5353 without using SO_REUSEPORT.
-// If we fail, someone else got here first. That's not a big problem; we can share the port for multicast responses --
-// we just need to be aware that we shouldn't expect to successfully receive unicast UDP responses.
-mDNSlocal mDNSBool mDNSPlatformInit_CanReceiveUnicast(void)
-{
-    int err;
-    int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-    struct sockaddr_in s5353;
-    s5353.sin_family      = AF_INET;
-    s5353.sin_port        = MulticastDNSPort.NotAnInteger;
-    s5353.sin_addr.s_addr = 0;
-    err = bind(s, (struct sockaddr *)&s5353, sizeof(s5353));
-    close(s);
-    if (err) debugf("No unicast UDP responses");
-    else debugf("Unicast UDP responses okay");
-    return(err == 0);
-}
-
-// mDNS core calls this routine to initialise the platform-specific data.
-mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
-{
-    int err = 0;
-    struct sockaddr sa;
-    assert(m != NULL);
-
-    if (mDNSPlatformInit_CanReceiveUnicast()) m->CanReceiveUnicastOn5353 = mDNStrue;
-
-    // Tell mDNS core the names of this machine.
-
-    // Set up the nice label
-    m->nicelabel.c[0] = 0;
-    GetUserSpecifiedFriendlyComputerName(&m->nicelabel);
-    if (m->nicelabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->nicelabel, "Computer");
-
-    // Set up the RFC 1034-compliant label
-    m->hostlabel.c[0] = 0;
-    GetUserSpecifiedRFC1034ComputerName(&m->hostlabel);
-    if (m->hostlabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->hostlabel, "Computer");
-
-    mDNS_SetFQDN(m);
-
-    sa.sa_family = AF_INET;
-    m->p->unicastSocket4 = -1;
-    if (err == mStatus_NoError) err = SetupSocket(&sa, zeroIPPort, 0, &m->p->unicastSocket4);
-#if HAVE_IPV6
-    sa.sa_family = AF_INET6;
-    m->p->unicastSocket6 = -1;
-    if (err == mStatus_NoError) err = SetupSocket(&sa, zeroIPPort, 0, &m->p->unicastSocket6);
-#endif
-
-    // Tell mDNS core about the network interfaces on this machine.
-    if (err == mStatus_NoError) err = SetupInterfaceList(m);
-
-    // Tell mDNS core about DNS Servers
-    mDNS_Lock(m);
-    if (err == mStatus_NoError) ParseDNSServers(m, uDNS_SERVERS_FILE);
-    mDNS_Unlock(m);
-
-    if (err == mStatus_NoError)
-    {
-        err = WatchForInterfaceChange(m);
-        // Failure to observe interface changes is non-fatal.
-        if (err != mStatus_NoError)
-        {
-            fprintf(stderr, "mDNS(%d) WARNING: Unable to detect interface changes (%d).\n", getpid(), err);
-            err = mStatus_NoError;
-        }
-    }
-
-    // We don't do asynchronous initialization on the Posix platform, so by the time
-    // we get here the setup will already have succeeded or failed.  If it succeeded,
-    // we should just call mDNSCoreInitComplete() immediately.
-    if (err == mStatus_NoError)
-        mDNSCoreInitComplete(m, mStatus_NoError);
-
-    return PosixErrorToStatus(err);
-}
-
-// mDNS core calls this routine to clean up the platform-specific data.
-// In our case all we need to do is to tear down every network interface.
-mDNSexport void mDNSPlatformClose(mDNS *const m)
-{
-    assert(m != NULL);
-    ClearInterfaceList(m);
-    if (m->p->unicastSocket4 != -1) assert(close(m->p->unicastSocket4) == 0);
-#if HAVE_IPV6
-    if (m->p->unicastSocket6 != -1) assert(close(m->p->unicastSocket6) == 0);
-#endif
-}
-
-mDNSexport mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m)
-{
-    int err;
-    ClearInterfaceList(m);
-    err = SetupInterfaceList(m);
-    return PosixErrorToStatus(err);
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Locking
-#endif
-
-// On the Posix platform, locking is a no-op because we only ever enter
-// mDNS core on the main thread.
-
-// mDNS core calls this routine when it wants to prevent
-// the platform from reentering mDNS core code.
-mDNSexport void    mDNSPlatformLock   (const mDNS *const m)
-{
-    (void) m;   // Unused
-}
-
-// mDNS core calls this routine when it release the lock taken by
-// mDNSPlatformLock and allow the platform to reenter mDNS core code.
-mDNSexport void    mDNSPlatformUnlock (const mDNS *const m)
-{
-    (void) m;   // Unused
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Strings
-#endif
-
-// mDNS core calls this routine to copy C strings.
-// On the Posix platform this maps directly to the ANSI C strcpy.
-mDNSexport void    mDNSPlatformStrCopy(void *dst, const void *src)
-{
-    strcpy((char *)dst, (char *)src);
-}
-
-// mDNS core calls this routine to get the length of a C string.
-// On the Posix platform this maps directly to the ANSI C strlen.
-mDNSexport mDNSu32  mDNSPlatformStrLen (const void *src)
-{
-    return strlen((char*)src);
-}
-
-// mDNS core calls this routine to copy memory.
-// On the Posix platform this maps directly to the ANSI C memcpy.
-mDNSexport void    mDNSPlatformMemCopy(void *dst, const void *src, mDNSu32 len)
-{
-    memcpy(dst, src, len);
-}
-
-// mDNS core calls this routine to test whether blocks of memory are byte-for-byte
-// identical. On the Posix platform this is a simple wrapper around ANSI C memcmp.
-mDNSexport mDNSBool mDNSPlatformMemSame(const void *dst, const void *src, mDNSu32 len)
-{
-    return memcmp(dst, src, len) == 0;
-}
-
-// If the caller wants to know the exact return of memcmp, then use this instead
-// of mDNSPlatformMemSame
-mDNSexport int mDNSPlatformMemCmp(const void *dst, const void *src, mDNSu32 len)
-{
-    return (memcmp(dst, src, len));
-}
-
-mDNSexport void mDNSPlatformQsort(void *base, int nel, int width, int (*compar)(const void *, const void *))
-{
-    return (qsort(base, nel, width, compar));
-}
-
-// DNSSEC stub functions
-mDNSexport void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *q)
-{
-    (void)m;
-    (void)dv;
-    (void)q;
-}
-
-mDNSexport mDNSBool AddNSECSForCacheRecord(mDNS *const m, CacheRecord *crlist, CacheRecord *negcr, mDNSu8 rcode)
-{
-    (void)m;
-    (void)crlist;
-    (void)negcr;
-    (void)rcode;
-    return mDNSfalse;
-}
-
-mDNSexport void BumpDNSSECStats(mDNS *const m, DNSSECStatsAction action, DNSSECStatsType type, mDNSu32 value)
-{
-    (void)m;
-    (void)action;
-    (void)type;
-    (void)value;
-}
-
-// Proxy stub functions
-mDNSexport mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit)
-{
-    (void) q;
-    (void) h;
-    (void) msg;
-    (void) ptr;
-    (void) limit;
-
-    return ptr;
-}
-
-mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[], mDNSu32 OpIf)
-{
-    (void) m;
-    (void) IpIfArr;
-    (void) OpIf;
-}
-
-mDNSexport void DNSProxyTerminate(mDNS *const m)
-{
-    (void) m;
-}
-
-// mDNS core calls this routine to clear blocks of memory.
-// On the Posix platform this is a simple wrapper around ANSI C memset.
-mDNSexport void    mDNSPlatformMemZero(void *dst, mDNSu32 len)
-{
-    memset(dst, 0, len);
-}
-
-mDNSexport void *  mDNSPlatformMemAllocate(mDNSu32 len) { return(malloc(len)); }
-mDNSexport void    mDNSPlatformMemFree    (void *mem)   { free(mem); }
-
-mDNSexport mDNSu32 mDNSPlatformRandomSeed(void)
-{
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    return(tv.tv_usec);
-}
-
-mDNSexport mDNSs32 mDNSPlatformOneSecond = 1024;
-
-mDNSexport mStatus mDNSPlatformTimeInit(void)
-{
-    // No special setup is required on Posix -- we just use gettimeofday();
-    // This is not really safe, because gettimeofday can go backwards if the user manually changes the date or time
-    // We should find a better way to do this
-    return(mStatus_NoError);
-}
-
-mDNSexport mDNSs32  mDNSPlatformRawTime()
-{
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-    // tv.tv_sec is seconds since 1st January 1970 (GMT, with no adjustment for daylight savings time)
-    // tv.tv_usec is microseconds since the start of this second (i.e. values 0 to 999999)
-    // We use the lower 22 bits of tv.tv_sec for the top 22 bits of our result
-    // and we multiply tv.tv_usec by 16 / 15625 to get a value in the range 0-1023 to go in the bottom 10 bits.
-    // This gives us a proper modular (cyclic) counter that has a resolution of roughly 1ms (actually 1/1024 second)
-    // and correctly cycles every 2^22 seconds (4194304 seconds = approx 48 days).
-    return((tv.tv_sec << 10) | (tv.tv_usec * 16 / 15625));
-}
-
-mDNSexport mDNSs32 mDNSPlatformUTC(void)
-{
-    return time(NULL);
-}
-
-mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
-{
-    (void) m;
-    (void) InterfaceID;
-    (void) EthAddr;
-    (void) IPAddr;
-    (void) iteration;
-}
-
-mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf)
-{
-    (void) rr;
-    (void) intf;
-
-    return 1;
-}
-
-mDNSexport mDNSBool mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf)
-{
-    (void) q;
-    (void) intf;
-
-    return 1;
-}
-
-// Used for debugging purposes. For now, just set the buffer to zero
-mDNSexport void mDNSPlatformFormatTime(unsigned long te, mDNSu8 *buf, int bufsize)
-{
-    (void) te;
-    if (bufsize) buf[0] = 0;
-}
-
-mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win)
-{
-    (void) sadd;    // Unused
-    (void) dadd;    // Unused
-    (void) lport;   // Unused
-    (void) rport;   // Unused
-    (void) seq;     // Unused
-    (void) ack;     // Unused
-    (void) win;     // Unused
-}
-
-mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti)
-{
-    (void) m;       // Unused
-    (void) laddr;   // Unused
-    (void) raddr;   // Unused
-    (void) lport;   // Unused
-    (void) rport;   // Unused
-    (void) mti;     // Unused
-
-    return mStatus_NoError;
-}
-
-mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr)
-{
-    (void) raddr; // Unused
-    (void) m;     // Unused
-
-    return mStatus_NoError;
-}
-
-mDNSexport mStatus    mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname)
-{
-    (void) spsaddr; // Unused
-    (void) ifname;  // Unused
-
-    return mStatus_NoError;
-}
-
-mDNSexport mStatus    mDNSPlatformClearSPSMACAddr(void)
-{
-    return mStatus_NoError;
-}
-
-mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
-{
-    (void) sock; // unused
- 
-    return (mDNSu16)-1;
-}
-
-mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
-{
-    (void) InterfaceID; // unused
-    
-    return mDNSfalse;
-}
-
-mDNSexport mDNSBool mDNSPlatformAllowPID(mDNS *const m, DNSQuestion *q)
-{
-    (void) m;
-    (void) q;
-    return mDNStrue;
-}
-
-mDNSexport mDNSs32 mDNSPlatformGetServiceID(mDNS *const m, DNSQuestion *q)
-{
-    (void) m;
-    (void) q;
-    return 0;
-}
-
-mDNSexport void mDNSPlatformSetDelegatePID(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q)
-{
-    (void) src;
-    (void) dst;
-    (void) q;
-}
-
-mDNSexport mDNSs32 mDNSPlatformGetPID()
-{
-    return 0;
-}
-
-mDNSlocal void mDNSPosixAddToFDSet(int *nfds, fd_set *readfds, int s)
-{
-    if (*nfds < s + 1) *nfds = s + 1;
-    FD_SET(s, readfds);
-}
-
-mDNSexport void mDNSPosixGetFDSet(mDNS *m, int *nfds, fd_set *readfds, struct timeval *timeout)
-{
-    mDNSs32 ticks;
-    struct timeval interval;
-
-    // 1. Call mDNS_Execute() to let mDNSCore do what it needs to do
-    mDNSs32 nextevent = mDNS_Execute(m);
-
-    // 2. Build our list of active file descriptors
-    PosixNetworkInterface *info = (PosixNetworkInterface *)(m->HostInterfaces);
-    if (m->p->unicastSocket4 != -1) mDNSPosixAddToFDSet(nfds, readfds, m->p->unicastSocket4);
-#if HAVE_IPV6
-    if (m->p->unicastSocket6 != -1) mDNSPosixAddToFDSet(nfds, readfds, m->p->unicastSocket6);
-#endif
-    while (info)
-    {
-        if (info->multicastSocket4 != -1) mDNSPosixAddToFDSet(nfds, readfds, info->multicastSocket4);
-#if HAVE_IPV6
-        if (info->multicastSocket6 != -1) mDNSPosixAddToFDSet(nfds, readfds, info->multicastSocket6);
-#endif
-        info = (PosixNetworkInterface *)(info->coreIntf.next);
-    }
-
-    // 3. Calculate the time remaining to the next scheduled event (in struct timeval format)
-    ticks = nextevent - mDNS_TimeNow(m);
-    if (ticks < 1) ticks = 1;
-    interval.tv_sec  = ticks >> 10;                     // The high 22 bits are seconds
-    interval.tv_usec = ((ticks & 0x3FF) * 15625) / 16;  // The low 10 bits are 1024ths
-
-    // 4. If client's proposed timeout is more than what we want, then reduce it
-    if (timeout->tv_sec > interval.tv_sec ||
-        (timeout->tv_sec == interval.tv_sec && timeout->tv_usec > interval.tv_usec))
-        *timeout = interval;
-}
-
-mDNSexport void mDNSPosixProcessFDSet(mDNS *const m, fd_set *readfds)
-{
-    PosixNetworkInterface *info;
-    assert(m       != NULL);
-    assert(readfds != NULL);
-    info = (PosixNetworkInterface *)(m->HostInterfaces);
-
-    if (m->p->unicastSocket4 != -1 && FD_ISSET(m->p->unicastSocket4, readfds))
-    {
-        FD_CLR(m->p->unicastSocket4, readfds);
-        SocketDataReady(m, NULL, m->p->unicastSocket4);
-    }
-#if HAVE_IPV6
-    if (m->p->unicastSocket6 != -1 && FD_ISSET(m->p->unicastSocket6, readfds))
-    {
-        FD_CLR(m->p->unicastSocket6, readfds);
-        SocketDataReady(m, NULL, m->p->unicastSocket6);
-    }
-#endif
-
-    while (info)
-    {
-        if (info->multicastSocket4 != -1 && FD_ISSET(info->multicastSocket4, readfds))
-        {
-            FD_CLR(info->multicastSocket4, readfds);
-            SocketDataReady(m, info, info->multicastSocket4);
-        }
-#if HAVE_IPV6
-        if (info->multicastSocket6 != -1 && FD_ISSET(info->multicastSocket6, readfds))
-        {
-            FD_CLR(info->multicastSocket6, readfds);
-            SocketDataReady(m, info, info->multicastSocket6);
-        }
-#endif
-        info = (PosixNetworkInterface *)(info->coreIntf.next);
-    }
-}
-
-// update gMaxFD
-mDNSlocal void  DetermineMaxEventFD(void)
-{
-    PosixEventSource    *iSource;
-
-    gMaxFD = 0;
-    for (iSource=(PosixEventSource*)gEventSources.Head; iSource; iSource = iSource->Next)
-        if (gMaxFD < iSource->fd)
-            gMaxFD = iSource->fd;
-}
-
-// Add a file descriptor to the set that mDNSPosixRunEventLoopOnce() listens to.
-mStatus mDNSPosixAddFDToEventLoop(int fd, mDNSPosixEventCallback callback, void *context)
-{
-    PosixEventSource    *newSource;
-
-    if (gEventSources.LinkOffset == 0)
-        InitLinkedList(&gEventSources, offsetof(PosixEventSource, Next));
-
-    if (fd >= (int) FD_SETSIZE || fd < 0)
-        return mStatus_UnsupportedErr;
-    if (callback == NULL)
-        return mStatus_BadParamErr;
-
-    newSource = (PosixEventSource*) malloc(sizeof *newSource);
-    if (NULL == newSource)
-        return mStatus_NoMemoryErr;
-
-    newSource->Callback = callback;
-    newSource->Context = context;
-    newSource->fd = fd;
-
-    AddToTail(&gEventSources, newSource);
-    FD_SET(fd, &gEventFDs);
-
-    DetermineMaxEventFD();
-
-    return mStatus_NoError;
-}
-
-// Remove a file descriptor from the set that mDNSPosixRunEventLoopOnce() listens to.
-mStatus mDNSPosixRemoveFDFromEventLoop(int fd)
-{
-    PosixEventSource    *iSource;
-
-    for (iSource=(PosixEventSource*)gEventSources.Head; iSource; iSource = iSource->Next)
-    {
-        if (fd == iSource->fd)
-        {
-            FD_CLR(fd, &gEventFDs);
-            RemoveFromList(&gEventSources, iSource);
-            free(iSource);
-            DetermineMaxEventFD();
-            return mStatus_NoError;
-        }
-    }
-    return mStatus_NoSuchNameErr;
-}
-
-// Simply note the received signal in gEventSignals.
-mDNSlocal void  NoteSignal(int signum)
-{
-    sigaddset(&gEventSignals, signum);
-}
-
-// Tell the event package to listen for signal and report it in mDNSPosixRunEventLoopOnce().
-mStatus mDNSPosixListenForSignalInEventLoop(int signum)
-{
-    struct sigaction action;
-    mStatus err;
-
-    mDNSPlatformMemZero(&action, sizeof action);        // more portable than member-wise assignment
-    action.sa_handler = NoteSignal;
-    err = sigaction(signum, &action, (struct sigaction*) NULL);
-
-    sigaddset(&gEventSignalSet, signum);
-
-    return err;
-}
-
-// Tell the event package to stop listening for signal in mDNSPosixRunEventLoopOnce().
-mStatus mDNSPosixIgnoreSignalInEventLoop(int signum)
-{
-    struct sigaction action;
-    mStatus err;
-
-    mDNSPlatformMemZero(&action, sizeof action);        // more portable than member-wise assignment
-    action.sa_handler = SIG_DFL;
-    err = sigaction(signum, &action, (struct sigaction*) NULL);
-
-    sigdelset(&gEventSignalSet, signum);
-
-    return err;
-}
-
-// Do a single pass through the attendent event sources and dispatch any found to their callbacks.
-// Return as soon as internal timeout expires, or a signal we're listening for is received.
-mStatus mDNSPosixRunEventLoopOnce(mDNS *m, const struct timeval *pTimeout,
-                                  sigset_t *pSignalsReceived, mDNSBool *pDataDispatched)
-{
-    fd_set listenFDs = gEventFDs;
-    int fdMax = 0, numReady;
-    struct timeval timeout = *pTimeout;
-
-    // Include the sockets that are listening to the wire in our select() set
-    mDNSPosixGetFDSet(m, &fdMax, &listenFDs, &timeout); // timeout may get modified
-    if (fdMax < gMaxFD)
-        fdMax = gMaxFD;
-
-    numReady = select(fdMax + 1, &listenFDs, (fd_set*) NULL, (fd_set*) NULL, &timeout);
-
-    // If any data appeared, invoke its callback
-    if (numReady > 0)
-    {
-        PosixEventSource    *iSource;
-
-        (void) mDNSPosixProcessFDSet(m, &listenFDs);    // call this first to process wire data for clients
-
-        for (iSource=(PosixEventSource*)gEventSources.Head; iSource; iSource = iSource->Next)
-        {
-            if (FD_ISSET(iSource->fd, &listenFDs))
-            {
-                iSource->Callback(iSource->fd, 0, iSource->Context);
-                break;  // in case callback removed elements from gEventSources
-            }
-        }
-        *pDataDispatched = mDNStrue;
-    }
-    else
-        *pDataDispatched = mDNSfalse;
-
-    (void) sigprocmask(SIG_BLOCK, &gEventSignalSet, (sigset_t*) NULL);
-    *pSignalsReceived = gEventSignals;
-    sigemptyset(&gEventSignals);
-    (void) sigprocmask(SIG_UNBLOCK, &gEventSignalSet, (sigset_t*) NULL);
-
-    return mStatus_NoError;
-}

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSPosix/mDNSPosix.c (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSPosix/mDNSPosix.c)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/mDNSPosix/mDNSPosix.c	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSPosix/mDNSPosix.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,1789 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2002-2004 Apple Computer, 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 "mDNSEmbeddedAPI.h"           // Defines the interface provided to the client layer above
+#include "DNSCommon.h"
+#include "mDNSPosix.h"               // Defines the specific types needed to run mDNS on this platform
+#include "dns_sd.h"
+#include "dnssec.h"
+#include "nsec.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/select.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <time.h>                   // platform support for UTC time
+
+#if USES_NETLINK
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#else // USES_NETLINK
+#include <net/route.h>
+#include <net/if.h>
+#endif // USES_NETLINK
+
+#include "mDNSUNP.h"
+#include "GenLinkedList.h"
+
+// ***************************************************************************
+// Structures
+
+// We keep a list of client-supplied event sources in PosixEventSource records
+struct PosixEventSource
+{
+    mDNSPosixEventCallback Callback;
+    void                        *Context;
+    int fd;
+    struct  PosixEventSource    *Next;
+};
+typedef struct PosixEventSource PosixEventSource;
+
+// Context record for interface change callback
+struct IfChangeRec
+{
+    int NotifySD;
+    mDNS *mDNS;
+};
+typedef struct IfChangeRec IfChangeRec;
+
+// Note that static data is initialized to zero in (modern) C.
+static fd_set gEventFDs;
+static int gMaxFD;                              // largest fd in gEventFDs
+static GenLinkedList gEventSources;             // linked list of PosixEventSource's
+static sigset_t gEventSignalSet;                // Signals which event loop listens for
+static sigset_t gEventSignals;                  // Signals which were received while inside loop
+
+// ***************************************************************************
+// Globals (for debugging)
+
+static int num_registered_interfaces = 0;
+static int num_pkts_accepted = 0;
+static int num_pkts_rejected = 0;
+
+// ***************************************************************************
+// Functions
+
+int gMDNSPlatformPosixVerboseLevel = 0;
+
+#define PosixErrorToStatus(errNum) ((errNum) == 0 ? mStatus_NoError : mStatus_UnknownErr)
+
+mDNSlocal void SockAddrTomDNSAddr(const struct sockaddr *const sa, mDNSAddr *ipAddr, mDNSIPPort *ipPort)
+{
+    switch (sa->sa_family)
+    {
+    case AF_INET:
+    {
+        struct sockaddr_in *sin          = (struct sockaddr_in*)sa;
+        ipAddr->type                     = mDNSAddrType_IPv4;
+        ipAddr->ip.v4.NotAnInteger       = sin->sin_addr.s_addr;
+        if (ipPort) ipPort->NotAnInteger = sin->sin_port;
+        break;
+    }
+
+#if HAVE_IPV6
+    case AF_INET6:
+    {
+        struct sockaddr_in6 *sin6        = (struct sockaddr_in6*)sa;
+#ifndef NOT_HAVE_SA_LEN
+        assert(sin6->sin6_len == sizeof(*sin6));
+#endif
+        ipAddr->type                     = mDNSAddrType_IPv6;
+        ipAddr->ip.v6                    = *(mDNSv6Addr*)&sin6->sin6_addr;
+        if (ipPort) ipPort->NotAnInteger = sin6->sin6_port;
+        break;
+    }
+#endif
+
+    default:
+        verbosedebugf("SockAddrTomDNSAddr: Uknown address family %d\n", sa->sa_family);
+        ipAddr->type = mDNSAddrType_None;
+        if (ipPort) ipPort->NotAnInteger = 0;
+        break;
+    }
+}
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark ***** Send and Receive
+#endif
+
+// mDNS core calls this routine when it needs to send a packet.
+mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
+                                       mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, 
+                                       mDNSIPPort dstPort, mDNSBool useBackgroundTrafficClass)
+{
+    int err = 0;
+    struct sockaddr_storage to;
+    PosixNetworkInterface * thisIntf = (PosixNetworkInterface *)(InterfaceID);
+    int sendingsocket = -1;
+
+    (void)src;  // Will need to use this parameter once we implement mDNSPlatformUDPSocket/mDNSPlatformUDPClose
+    (void) useBackgroundTrafficClass;
+
+    assert(m != NULL);
+    assert(msg != NULL);
+    assert(end != NULL);
+    assert((((char *) end) - ((char *) msg)) > 0);
+
+    if (dstPort.NotAnInteger == 0)
+    {
+        LogMsg("mDNSPlatformSendUDP: Invalid argument -dstPort is set to 0");
+        return PosixErrorToStatus(EINVAL);
+    }
+    if (dst->type == mDNSAddrType_IPv4)
+    {
+        struct sockaddr_in *sin = (struct sockaddr_in*)&to;
+#ifndef NOT_HAVE_SA_LEN
+        sin->sin_len            = sizeof(*sin);
+#endif
+        sin->sin_family         = AF_INET;
+        sin->sin_port           = dstPort.NotAnInteger;
+        sin->sin_addr.s_addr    = dst->ip.v4.NotAnInteger;
+        sendingsocket           = thisIntf ? thisIntf->multicastSocket4 : m->p->unicastSocket4;
+    }
+
+#if HAVE_IPV6
+    else if (dst->type == mDNSAddrType_IPv6)
+    {
+        struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&to;
+        mDNSPlatformMemZero(sin6, sizeof(*sin6));
+#ifndef NOT_HAVE_SA_LEN
+        sin6->sin6_len            = sizeof(*sin6);
+#endif
+        sin6->sin6_family         = AF_INET6;
+        sin6->sin6_port           = dstPort.NotAnInteger;
+        sin6->sin6_addr           = *(struct in6_addr*)&dst->ip.v6;
+        sendingsocket             = thisIntf ? thisIntf->multicastSocket6 : m->p->unicastSocket6;
+    }
+#endif
+
+    if (sendingsocket >= 0)
+        err = sendto(sendingsocket, msg, (char*)end - (char*)msg, 0, (struct sockaddr *)&to, GET_SA_LEN(to));
+
+    if      (err > 0) err = 0;
+    else if (err < 0)
+    {
+        static int MessageCount = 0;
+        // Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
+        if (!mDNSAddressIsAllDNSLinkGroup(dst))
+            if (errno == EHOSTDOWN || errno == ENETDOWN || errno == EHOSTUNREACH || errno == ENETUNREACH) return(mStatus_TransientErr);
+
+        if (MessageCount < 1000)
+        {
+            MessageCount++;
+            if (thisIntf)
+                LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a on interface %#a/%s/%d",
+                       errno, strerror(errno), dst, &thisIntf->coreIntf.ip, thisIntf->intfName, thisIntf->index);
+            else
+                LogMsg("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a", errno, strerror(errno), dst);
+        }
+    }
+
+    return PosixErrorToStatus(err);
+}
+
+// This routine is called when the main loop detects that data is available on a socket.
+mDNSlocal void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int skt)
+{
+    mDNSAddr senderAddr, destAddr;
+    mDNSIPPort senderPort;
+    ssize_t packetLen;
+    DNSMessage packet;
+    struct my_in_pktinfo packetInfo;
+    struct sockaddr_storage from;
+    socklen_t fromLen;
+    int flags;
+    mDNSu8 ttl;
+    mDNSBool reject;
+    const mDNSInterfaceID InterfaceID = intf ? intf->coreIntf.InterfaceID : NULL;
+
+    assert(m    != NULL);
+    assert(skt  >= 0);
+
+    fromLen = sizeof(from);
+    flags   = 0;
+    packetLen = recvfrom_flags(skt, &packet, sizeof(packet), &flags, (struct sockaddr *) &from, &fromLen, &packetInfo, &ttl);
+
+    if (packetLen >= 0)
+    {
+        SockAddrTomDNSAddr((struct sockaddr*)&from, &senderAddr, &senderPort);
+        SockAddrTomDNSAddr((struct sockaddr*)&packetInfo.ipi_addr, &destAddr, NULL);
+
+        // If we have broken IP_RECVDSTADDR functionality (so far
+        // I've only seen this on OpenBSD) then apply a hack to
+        // convince mDNS Core that this isn't a spoof packet.
+        // Basically what we do is check to see whether the
+        // packet arrived as a multicast and, if so, set its
+        // destAddr to the mDNS address.
+        //
+        // I must admit that I could just be doing something
+        // wrong on OpenBSD and hence triggering this problem
+        // but I'm at a loss as to how.
+        //
+        // If this platform doesn't have IP_PKTINFO or IP_RECVDSTADDR, then we have
+        // no way to tell the destination address or interface this packet arrived on,
+        // so all we can do is just assume it's a multicast
+
+        #if HAVE_BROKEN_RECVDSTADDR || (!defined(IP_PKTINFO) && !defined(IP_RECVDSTADDR))
+        if ((destAddr.NotAnInteger == 0) && (flags & MSG_MCAST))
+        {
+            destAddr.type = senderAddr.type;
+            if      (senderAddr.type == mDNSAddrType_IPv4) destAddr.ip.v4 = AllDNSLinkGroup_v4.ip.v4;
+            else if (senderAddr.type == mDNSAddrType_IPv6) destAddr.ip.v6 = AllDNSLinkGroup_v6.ip.v6;
+        }
+        #endif
+
+        // We only accept the packet if the interface on which it came
+        // in matches the interface associated with this socket.
+        // We do this match by name or by index, depending on which
+        // information is available.  recvfrom_flags sets the name
+        // to "" if the name isn't available, or the index to -1
+        // if the index is available.  This accomodates the various
+        // different capabilities of our target platforms.
+
+        reject = mDNSfalse;
+        if (!intf)
+        {
+            // Ignore multicasts accidentally delivered to our unicast receiving socket
+            if (mDNSAddrIsDNSMulticast(&destAddr)) packetLen = -1;
+        }
+        else
+        {
+            if      (packetInfo.ipi_ifname[0] != 0) reject = (strcmp(packetInfo.ipi_ifname, intf->intfName) != 0);
+            else if (packetInfo.ipi_ifindex != -1) reject = (packetInfo.ipi_ifindex != intf->index);
+
+            if (reject)
+            {
+                verbosedebugf("SocketDataReady ignored a packet from %#a to %#a on interface %s/%d expecting %#a/%s/%d/%d",
+                              &senderAddr, &destAddr, packetInfo.ipi_ifname, packetInfo.ipi_ifindex,
+                              &intf->coreIntf.ip, intf->intfName, intf->index, skt);
+                packetLen = -1;
+                num_pkts_rejected++;
+                if (num_pkts_rejected > (num_pkts_accepted + 1) * (num_registered_interfaces + 1) * 2)
+                {
+                    fprintf(stderr,
+                            "*** WARNING: Received %d packets; Accepted %d packets; Rejected %d packets because of interface mismatch\n",
+                            num_pkts_accepted + num_pkts_rejected, num_pkts_accepted, num_pkts_rejected);
+                    num_pkts_accepted = 0;
+                    num_pkts_rejected = 0;
+                }
+            }
+            else
+            {
+                verbosedebugf("SocketDataReady got a packet from %#a to %#a on interface %#a/%s/%d/%d",
+                              &senderAddr, &destAddr, &intf->coreIntf.ip, intf->intfName, intf->index, skt);
+                num_pkts_accepted++;
+            }
+        }
+    }
+
+    if (packetLen >= 0)
+        mDNSCoreReceive(m, &packet, (mDNSu8 *)&packet + packetLen,
+                        &senderAddr, senderPort, &destAddr, MulticastDNSPort, InterfaceID);
+}
+
+mDNSexport mDNSBool mDNSPlatformPeekUDP(mDNS *const m, UDPSocket *src)
+{
+    (void)m;    // unused
+    (void)src;  // unused
+    return mDNSfalse;
+}
+
+mDNSexport TCPSocket *mDNSPlatformTCPSocket(mDNS * const m, TCPSocketFlags flags, mDNSIPPort * port, mDNSBool useBackgroundTrafficClass)
+{
+    (void)m;            // Unused
+    (void)flags;        // Unused
+    (void)port;         // Unused
+    (void)useBackgroundTrafficClass; // Unused
+    return NULL;
+}
+
+mDNSexport TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd)
+{
+    (void)flags;        // Unused
+    (void)sd;           // Unused
+    return NULL;
+}
+
+mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
+{
+    (void)sock;         // Unused
+    return -1;
+}
+
+mDNSexport mStatus mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname, mDNSInterfaceID InterfaceID,
+                                          TCPConnectionCallback callback, void *context)
+{
+    (void)sock;         // Unused
+    (void)dst;          // Unused
+    (void)dstport;      // Unused
+    (void)hostname;     // Unused
+    (void)InterfaceID;  // Unused
+    (void)callback;     // Unused
+    (void)context;      // Unused
+    return(mStatus_UnsupportedErr);
+}
+
+mDNSexport void mDNSPlatformTCPCloseConnection(TCPSocket *sock)
+{
+    (void)sock;         // Unused
+}
+
+mDNSexport long mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool * closed)
+{
+    (void)sock;         // Unused
+    (void)buf;          // Unused
+    (void)buflen;       // Unused
+    (void)closed;       // Unused
+    return 0;
+}
+
+mDNSexport long mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len)
+{
+    (void)sock;         // Unused
+    (void)msg;          // Unused
+    (void)len;          // Unused
+    return 0;
+}
+
+mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS * const m, mDNSIPPort port)
+{
+    (void)m;            // Unused
+    (void)port;         // Unused
+    return NULL;
+}
+
+mDNSexport void           mDNSPlatformUDPClose(UDPSocket *sock)
+{
+    (void)sock;         // Unused
+}
+
+mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
+{
+    (void)m;            // Unused
+    (void)InterfaceID;          // Unused
+}
+
+mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
+{
+    (void)msg;          // Unused
+    (void)end;          // Unused
+    (void)InterfaceID;          // Unused
+}
+
+mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
+{
+    (void)m;            // Unused
+    (void)tpa;          // Unused
+    (void)tha;          // Unused
+    (void)InterfaceID;          // Unused
+}
+
+mDNSexport mStatus mDNSPlatformTLSSetupCerts(void)
+{
+    return(mStatus_UnsupportedErr);
+}
+
+mDNSexport void mDNSPlatformTLSTearDownCerts(void)
+{
+}
+
+mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason)
+{
+    (void) m;
+    (void) allowSleep;
+    (void) reason;
+}
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark -
+#pragma mark - /etc/hosts support
+#endif
+
+mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
+{
+    (void)m;  // unused
+    (void)rr;
+    (void)result;
+}
+
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark ***** DDNS Config Platform Functions
+#endif
+
+mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains,
+    DNameListElem **BrowseDomains, mDNSBool ackConfig)
+{
+    (void) m;
+    (void) setservers;
+    (void) fqdn;
+    (void) setsearch;
+    (void) RegDomains;
+    (void) BrowseDomains;
+    (void) ackConfig;
+
+    return mDNStrue;
+}
+
+mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS * const m, mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router)
+{
+    (void) m;
+    (void) v4;
+    (void) v6;
+    (void) router;
+
+    return mStatus_UnsupportedErr;
+}
+
+mDNSexport void mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
+{
+    (void) dname;
+    (void) status;
+}
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark ***** Init and Term
+#endif
+
+// This gets the current hostname, truncating it at the first dot if necessary
+mDNSlocal void GetUserSpecifiedRFC1034ComputerName(domainlabel *const namelabel)
+{
+    int len = 0;
+    gethostname((char *)(&namelabel->c[1]), MAX_DOMAIN_LABEL);
+    while (len < MAX_DOMAIN_LABEL && namelabel->c[len+1] && namelabel->c[len+1] != '.') len++;
+    namelabel->c[0] = len;
+}
+
+// On OS X this gets the text of the field labelled "Computer Name" in the Sharing Prefs Control Panel
+// Other platforms can either get the information from the appropriate place,
+// or they can alternatively just require all registering services to provide an explicit name
+mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
+{
+    // On Unix we have no better name than the host name, so we just use that.
+    GetUserSpecifiedRFC1034ComputerName(namelabel);
+}
+
+mDNSexport int ParseDNSServers(mDNS *m, const char *filePath)
+{
+    char line[256];
+    char nameserver[16];
+    char keyword[11];
+    int numOfServers = 0;
+    FILE *fp = fopen(filePath, "r");
+    if (fp == NULL) return -1;
+    while (fgets(line,sizeof(line),fp))
+    {
+        struct in_addr ina;
+        line[255]='\0';     // just to be safe
+        if (sscanf(line,"%10s %15s", keyword, nameserver) != 2) continue;   // it will skip whitespaces
+        if (strncasecmp(keyword,"nameserver",10)) continue;
+        if (inet_aton(nameserver, (struct in_addr *)&ina) != 0)
+        {
+            mDNSAddr DNSAddr;
+            DNSAddr.type = mDNSAddrType_IPv4;
+            DNSAddr.ip.v4.NotAnInteger = ina.s_addr;
+            mDNS_AddDNSServer(m, NULL, mDNSInterface_Any, 0, &DNSAddr, UnicastDNSPort, kScopeNone, 0, mDNSfalse, 0, mDNStrue, mDNStrue, mDNSfalse);
+            numOfServers++;
+        }
+    }
+    return (numOfServers > 0) ? 0 : -1;
+}
+
+// Searches the interface list looking for the named interface.
+// Returns a pointer to if it found, or NULL otherwise.
+mDNSlocal PosixNetworkInterface *SearchForInterfaceByName(mDNS *const m, const char *intfName)
+{
+    PosixNetworkInterface *intf;
+
+    assert(m != NULL);
+    assert(intfName != NULL);
+
+    intf = (PosixNetworkInterface*)(m->HostInterfaces);
+    while ((intf != NULL) && (strcmp(intf->intfName, intfName) != 0))
+        intf = (PosixNetworkInterface *)(intf->coreIntf.next);
+
+    return intf;
+}
+
+mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 index)
+{
+    PosixNetworkInterface *intf;
+
+    assert(m != NULL);
+
+    if (index == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
+    if (index == kDNSServiceInterfaceIndexP2P      ) return(mDNSInterface_P2P);
+    if (index == kDNSServiceInterfaceIndexAny      ) return(mDNSInterface_Any);
+
+    intf = (PosixNetworkInterface*)(m->HostInterfaces);
+    while ((intf != NULL) && (mDNSu32) intf->index != index)
+        intf = (PosixNetworkInterface *)(intf->coreIntf.next);
+
+    return (mDNSInterfaceID) intf;
+}
+
+mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange)
+{
+    PosixNetworkInterface *intf;
+    (void) suppressNetworkChange; // Unused
+
+    assert(m != NULL);
+
+    if (id == mDNSInterface_LocalOnly) return(kDNSServiceInterfaceIndexLocalOnly);
+    if (id == mDNSInterface_P2P      ) return(kDNSServiceInterfaceIndexP2P);
+    if (id == mDNSInterface_Any      ) return(kDNSServiceInterfaceIndexAny);
+
+    intf = (PosixNetworkInterface*)(m->HostInterfaces);
+    while ((intf != NULL) && (mDNSInterfaceID) intf != id)
+        intf = (PosixNetworkInterface *)(intf->coreIntf.next);
+
+    return intf ? intf->index : 0;
+}
+
+// Frees the specified PosixNetworkInterface structure. The underlying
+// interface must have already been deregistered with the mDNS core.
+mDNSlocal void FreePosixNetworkInterface(PosixNetworkInterface *intf)
+{
+    assert(intf != NULL);
+    if (intf->intfName != NULL) free((void *)intf->intfName);
+    if (intf->multicastSocket4 != -1) assert(close(intf->multicastSocket4) == 0);
+#if HAVE_IPV6
+    if (intf->multicastSocket6 != -1) assert(close(intf->multicastSocket6) == 0);
+#endif
+    free(intf);
+}
+
+// Grab the first interface, deregister it, free it, and repeat until done.
+mDNSlocal void ClearInterfaceList(mDNS *const m)
+{
+    assert(m != NULL);
+
+    while (m->HostInterfaces)
+    {
+        PosixNetworkInterface *intf = (PosixNetworkInterface*)(m->HostInterfaces);
+        mDNS_DeregisterInterface(m, &intf->coreIntf, mDNSfalse);
+        if (gMDNSPlatformPosixVerboseLevel > 0) fprintf(stderr, "Deregistered interface %s\n", intf->intfName);
+        FreePosixNetworkInterface(intf);
+    }
+    num_registered_interfaces = 0;
+    num_pkts_accepted = 0;
+    num_pkts_rejected = 0;
+}
+
+// Sets up a send/receive socket.
+// If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
+// If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
+mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interfaceIndex, int *sktPtr)
+{
+    int err = 0;
+    static const int kOn = 1;
+    static const int kIntTwoFiveFive = 255;
+    static const unsigned char kByteTwoFiveFive = 255;
+    const mDNSBool JoinMulticastGroup = (port.NotAnInteger != 0);
+
+    (void) interfaceIndex;  // This parameter unused on plaforms that don't have IPv6
+    assert(intfAddr != NULL);
+    assert(sktPtr != NULL);
+    assert(*sktPtr == -1);
+
+    // Open the socket...
+    if      (intfAddr->sa_family == AF_INET) *sktPtr = socket(PF_INET,  SOCK_DGRAM, IPPROTO_UDP);
+#if HAVE_IPV6
+    else if (intfAddr->sa_family == AF_INET6) *sktPtr = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+#endif
+    else return EINVAL;
+
+    if (*sktPtr < 0) { err = errno; perror((intfAddr->sa_family == AF_INET) ? "socket AF_INET" : "socket AF_INET6"); }
+
+    // ... with a shared UDP port, if it's for multicast receiving
+    if (err == 0 && port.NotAnInteger)
+    {
+        #if defined(SO_REUSEPORT)
+        err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEPORT, &kOn, sizeof(kOn));
+        #elif defined(SO_REUSEADDR)
+        err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
+        #else
+            #error This platform has no way to avoid address busy errors on multicast.
+        #endif
+        if (err < 0) { err = errno; perror("setsockopt - SO_REUSExxxx"); }
+    }
+
+    // We want to receive destination addresses and interface identifiers.
+    if (intfAddr->sa_family == AF_INET)
+    {
+        struct ip_mreq imr;
+        struct sockaddr_in bindAddr;
+        if (err == 0)
+        {
+            #if defined(IP_PKTINFO)                                 // Linux
+            err = setsockopt(*sktPtr, IPPROTO_IP, IP_PKTINFO, &kOn, sizeof(kOn));
+            if (err < 0) { err = errno; perror("setsockopt - IP_PKTINFO"); }
+            #elif defined(IP_RECVDSTADDR) || defined(IP_RECVIF)     // BSD and Solaris
+                #if defined(IP_RECVDSTADDR)
+            err = setsockopt(*sktPtr, IPPROTO_IP, IP_RECVDSTADDR, &kOn, sizeof(kOn));
+            if (err < 0) { err = errno; perror("setsockopt - IP_RECVDSTADDR"); }
+                #endif
+                #if defined(IP_RECVIF)
+            if (err == 0)
+            {
+                err = setsockopt(*sktPtr, IPPROTO_IP, IP_RECVIF, &kOn, sizeof(kOn));
+                if (err < 0) { err = errno; perror("setsockopt - IP_RECVIF"); }
+            }
+                #endif
+            #else
+                #warning This platform has no way to get the destination interface information -- will only work for single-homed hosts
+            #endif
+        }
+    #if defined(IP_RECVTTL)                                 // Linux
+        if (err == 0)
+        {
+            setsockopt(*sktPtr, IPPROTO_IP, IP_RECVTTL, &kOn, sizeof(kOn));
+            // We no longer depend on being able to get the received TTL, so don't worry if the option fails
+        }
+    #endif
+
+        // Add multicast group membership on this interface
+        if (err == 0 && JoinMulticastGroup)
+        {
+            imr.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
+            imr.imr_interface        = ((struct sockaddr_in*)intfAddr)->sin_addr;
+            err = setsockopt(*sktPtr, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr));
+            if (err < 0) { err = errno; perror("setsockopt - IP_ADD_MEMBERSHIP"); }
+        }
+
+        // Specify outgoing interface too
+        if (err == 0 && JoinMulticastGroup)
+        {
+            err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_IF, &((struct sockaddr_in*)intfAddr)->sin_addr, sizeof(struct in_addr));
+            if (err < 0) { err = errno; perror("setsockopt - IP_MULTICAST_IF"); }
+        }
+
+        // Per the mDNS spec, send unicast packets with TTL 255
+        if (err == 0)
+        {
+            err = setsockopt(*sktPtr, IPPROTO_IP, IP_TTL, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
+            if (err < 0) { err = errno; perror("setsockopt - IP_TTL"); }
+        }
+
+        // and multicast packets with TTL 255 too
+        // There's some debate as to whether IP_MULTICAST_TTL is an int or a byte so we just try both.
+        if (err == 0)
+        {
+            err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_TTL, &kByteTwoFiveFive, sizeof(kByteTwoFiveFive));
+            if (err < 0 && errno == EINVAL)
+                err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_TTL, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
+            if (err < 0) { err = errno; perror("setsockopt - IP_MULTICAST_TTL"); }
+        }
+
+        // And start listening for packets
+        if (err == 0)
+        {
+            bindAddr.sin_family      = AF_INET;
+            bindAddr.sin_port        = port.NotAnInteger;
+            bindAddr.sin_addr.s_addr = INADDR_ANY; // Want to receive multicasts AND unicasts on this socket
+            err = bind(*sktPtr, (struct sockaddr *) &bindAddr, sizeof(bindAddr));
+            if (err < 0) { err = errno; perror("bind"); fflush(stderr); }
+        }
+    }     // endif (intfAddr->sa_family == AF_INET)
+
+#if HAVE_IPV6
+    else if (intfAddr->sa_family == AF_INET6)
+    {
+        struct ipv6_mreq imr6;
+        struct sockaddr_in6 bindAddr6;
+    #if defined(IPV6_PKTINFO)
+        if (err == 0)
+        {
+            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_2292_PKTINFO, &kOn, sizeof(kOn));
+            if (err < 0) { err = errno; perror("setsockopt - IPV6_PKTINFO"); }
+        }
+    #else
+        #warning This platform has no way to get the destination interface information for IPv6 -- will only work for single-homed hosts
+    #endif
+    #if defined(IPV6_HOPLIMIT)
+        if (err == 0)
+        {
+            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_2292_HOPLIMIT, &kOn, sizeof(kOn));
+            if (err < 0) { err = errno; perror("setsockopt - IPV6_HOPLIMIT"); }
+        }
+    #endif
+
+        // Add multicast group membership on this interface
+        if (err == 0 && JoinMulticastGroup)
+        {
+            imr6.ipv6mr_multiaddr       = *(const struct in6_addr*)&AllDNSLinkGroup_v6.ip.v6;
+            imr6.ipv6mr_interface       = interfaceIndex;
+            //LogMsg("Joining %.16a on %d", &imr6.ipv6mr_multiaddr, imr6.ipv6mr_interface);
+            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_JOIN_GROUP, &imr6, sizeof(imr6));
+            if (err < 0)
+            {
+                err = errno;
+                verbosedebugf("IPV6_JOIN_GROUP %.16a on %d failed.\n", &imr6.ipv6mr_multiaddr, imr6.ipv6mr_interface);
+                perror("setsockopt - IPV6_JOIN_GROUP");
+            }
+        }
+
+        // Specify outgoing interface too
+        if (err == 0 && JoinMulticastGroup)
+        {
+            u_int multicast_if = interfaceIndex;
+            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_if, sizeof(multicast_if));
+            if (err < 0) { err = errno; perror("setsockopt - IPV6_MULTICAST_IF"); }
+        }
+
+        // We want to receive only IPv6 packets on this socket.
+        // Without this option, we may get IPv4 addresses as mapped addresses.
+        if (err == 0)
+        {
+            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_V6ONLY, &kOn, sizeof(kOn));
+            if (err < 0) { err = errno; perror("setsockopt - IPV6_V6ONLY"); }
+        }
+
+        // Per the mDNS spec, send unicast packets with TTL 255
+        if (err == 0)
+        {
+            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
+            if (err < 0) { err = errno; perror("setsockopt - IPV6_UNICAST_HOPS"); }
+        }
+
+        // and multicast packets with TTL 255 too
+        // There's some debate as to whether IPV6_MULTICAST_HOPS is an int or a byte so we just try both.
+        if (err == 0)
+        {
+            err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kByteTwoFiveFive, sizeof(kByteTwoFiveFive));
+            if (err < 0 && errno == EINVAL)
+                err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
+            if (err < 0) { err = errno; perror("setsockopt - IPV6_MULTICAST_HOPS"); }
+        }
+
+        // And start listening for packets
+        if (err == 0)
+        {
+            mDNSPlatformMemZero(&bindAddr6, sizeof(bindAddr6));
+#ifndef NOT_HAVE_SA_LEN
+            bindAddr6.sin6_len         = sizeof(bindAddr6);
+#endif
+            bindAddr6.sin6_family      = AF_INET6;
+            bindAddr6.sin6_port        = port.NotAnInteger;
+            bindAddr6.sin6_flowinfo    = 0;
+            bindAddr6.sin6_addr        = in6addr_any; // Want to receive multicasts AND unicasts on this socket
+            bindAddr6.sin6_scope_id    = 0;
+            err = bind(*sktPtr, (struct sockaddr *) &bindAddr6, sizeof(bindAddr6));
+            if (err < 0) { err = errno; perror("bind"); fflush(stderr); }
+        }
+    }     // endif (intfAddr->sa_family == AF_INET6)
+#endif
+
+    // Set the socket to non-blocking.
+    if (err == 0)
+    {
+        err = fcntl(*sktPtr, F_GETFL, 0);
+        if (err < 0) err = errno;
+        else
+        {
+            err = fcntl(*sktPtr, F_SETFL, err | O_NONBLOCK);
+            if (err < 0) err = errno;
+        }
+    }
+
+    // Clean up
+    if (err != 0 && *sktPtr != -1) { assert(close(*sktPtr) == 0); *sktPtr = -1; }
+    assert((err == 0) == (*sktPtr != -1));
+    return err;
+}
+
+// Creates a PosixNetworkInterface for the interface whose IP address is
+// intfAddr and whose name is intfName and registers it with mDNS core.
+mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct sockaddr *intfMask, const char *intfName, int intfIndex)
+{
+    int err = 0;
+    PosixNetworkInterface *intf;
+    PosixNetworkInterface *alias = NULL;
+
+    assert(m != NULL);
+    assert(intfAddr != NULL);
+    assert(intfName != NULL);
+    assert(intfMask != NULL);
+
+    // Allocate the interface structure itself.
+    intf = (PosixNetworkInterface*)malloc(sizeof(*intf));
+    if (intf == NULL) { assert(0); err = ENOMEM; }
+
+    // And make a copy of the intfName.
+    if (err == 0)
+    {
+        intf->intfName = strdup(intfName);
+        if (intf->intfName == NULL) { assert(0); err = ENOMEM; }
+    }
+
+    if (err == 0)
+    {
+        // Set up the fields required by the mDNS core.
+        SockAddrTomDNSAddr(intfAddr, &intf->coreIntf.ip, NULL);
+        SockAddrTomDNSAddr(intfMask, &intf->coreIntf.mask, NULL);
+
+        //LogMsg("SetupOneInterface: %#a %#a",  &intf->coreIntf.ip,  &intf->coreIntf.mask);
+        strncpy(intf->coreIntf.ifname, intfName, sizeof(intf->coreIntf.ifname));
+        intf->coreIntf.ifname[sizeof(intf->coreIntf.ifname)-1] = 0;
+        intf->coreIntf.Advertise = m->AdvertiseLocalAddresses;
+        intf->coreIntf.McastTxRx = mDNStrue;
+
+        // Set up the extra fields in PosixNetworkInterface.
+        assert(intf->intfName != NULL);         // intf->intfName already set up above
+        intf->index                = intfIndex;
+        intf->multicastSocket4     = -1;
+#if HAVE_IPV6
+        intf->multicastSocket6     = -1;
+#endif
+        alias                      = SearchForInterfaceByName(m, intf->intfName);
+        if (alias == NULL) alias   = intf;
+        intf->coreIntf.InterfaceID = (mDNSInterfaceID)alias;
+
+        if (alias != intf)
+            debugf("SetupOneInterface: %s %#a is an alias of %#a", intfName, &intf->coreIntf.ip, &alias->coreIntf.ip);
+    }
+
+    // Set up the multicast socket
+    if (err == 0)
+    {
+        if (alias->multicastSocket4 == -1 && intfAddr->sa_family == AF_INET)
+            err = SetupSocket(intfAddr, MulticastDNSPort, intf->index, &alias->multicastSocket4);
+#if HAVE_IPV6
+        else if (alias->multicastSocket6 == -1 && intfAddr->sa_family == AF_INET6)
+            err = SetupSocket(intfAddr, MulticastDNSPort, intf->index, &alias->multicastSocket6);
+#endif
+    }
+
+    // If interface is a direct link, address record will be marked as kDNSRecordTypeKnownUnique
+    // and skip the probe phase of the probe/announce packet sequence.
+    intf->coreIntf.DirectLink = mDNSfalse;
+
+    // The interface is all ready to go, let's register it with the mDNS core.
+    if (err == 0)
+        err = mDNS_RegisterInterface(m, &intf->coreIntf, mDNSfalse);
+
+    // Clean up.
+    if (err == 0)
+    {
+        num_registered_interfaces++;
+        debugf("SetupOneInterface: %s %#a Registered", intf->intfName, &intf->coreIntf.ip);
+        if (gMDNSPlatformPosixVerboseLevel > 0)
+            fprintf(stderr, "Registered interface %s\n", intf->intfName);
+    }
+    else
+    {
+        // Use intfName instead of intf->intfName in the next line to avoid dereferencing NULL.
+        debugf("SetupOneInterface: %s %#a failed to register %d", intfName, &intf->coreIntf.ip, err);
+        if (intf) { FreePosixNetworkInterface(intf); intf = NULL; }
+    }
+
+    assert((err == 0) == (intf != NULL));
+
+    return err;
+}
+
+// Call get_ifi_info() to obtain a list of active interfaces and call SetupOneInterface() on each one.
+mDNSlocal int SetupInterfaceList(mDNS *const m)
+{
+    mDNSBool foundav4       = mDNSfalse;
+    int err            = 0;
+    struct ifi_info *intfList      = get_ifi_info(AF_INET, mDNStrue);
+    struct ifi_info *firstLoopback = NULL;
+
+    assert(m != NULL);
+    debugf("SetupInterfaceList");
+
+    if (intfList == NULL) err = ENOENT;
+
+#if HAVE_IPV6
+    if (err == 0)       /* Link the IPv6 list to the end of the IPv4 list */
+    {
+        struct ifi_info **p = &intfList;
+        while (*p) p = &(*p)->ifi_next;
+        *p = get_ifi_info(AF_INET6, mDNStrue);
+    }
+#endif
+
+    if (err == 0)
+    {
+        struct ifi_info *i = intfList;
+        while (i)
+        {
+            if (     ((i->ifi_addr->sa_family == AF_INET)
+#if HAVE_IPV6
+                      || (i->ifi_addr->sa_family == AF_INET6)
+#endif
+                      ) &&  (i->ifi_flags & IFF_UP) && !(i->ifi_flags & IFF_POINTOPOINT))
+            {
+                if (i->ifi_flags & IFF_LOOPBACK)
+                {
+                    if (firstLoopback == NULL)
+                        firstLoopback = i;
+                }
+                else
+                {
+                    if (SetupOneInterface(m, i->ifi_addr, i->ifi_netmask, i->ifi_name, i->ifi_index) == 0)
+                        if (i->ifi_addr->sa_family == AF_INET)
+                            foundav4 = mDNStrue;
+                }
+            }
+            i = i->ifi_next;
+        }
+
+        // If we found no normal interfaces but we did find a loopback interface, register the
+        // loopback interface.  This allows self-discovery if no interfaces are configured.
+        // Temporary workaround: Multicast loopback on IPv6 interfaces appears not to work.
+        // In the interim, we skip loopback interface only if we found at least one v4 interface to use
+        // if ((m->HostInterfaces == NULL) && (firstLoopback != NULL))
+        if (!foundav4 && firstLoopback)
+            (void) SetupOneInterface(m, firstLoopback->ifi_addr, firstLoopback->ifi_netmask, firstLoopback->ifi_name, firstLoopback->ifi_index);
+    }
+
+    // Clean up.
+    if (intfList != NULL) free_ifi_info(intfList);
+    return err;
+}
+
+#if USES_NETLINK
+
+// See <http://www.faqs.org/rfcs/rfc3549.html> for a description of NetLink
+
+// Open a socket that will receive interface change notifications
+mDNSlocal mStatus OpenIfNotifySocket(int *pFD)
+{
+    mStatus err = mStatus_NoError;
+    struct sockaddr_nl snl;
+    int sock;
+    int ret;
+
+    sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+    if (sock < 0)
+        return errno;
+
+    // Configure read to be non-blocking because inbound msg size is not known in advance
+    (void) fcntl(sock, F_SETFL, O_NONBLOCK);
+
+    /* Subscribe the socket to Link & IP addr notifications. */
+    mDNSPlatformMemZero(&snl, sizeof snl);
+    snl.nl_family = AF_NETLINK;
+    snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
+    ret = bind(sock, (struct sockaddr *) &snl, sizeof snl);
+    if (0 == ret)
+        *pFD = sock;
+    else
+        err = errno;
+
+    return err;
+}
+
+#if MDNS_DEBUGMSGS
+mDNSlocal void      PrintNetLinkMsg(const struct nlmsghdr *pNLMsg)
+{
+    const char *kNLMsgTypes[] = { "", "NLMSG_NOOP", "NLMSG_ERROR", "NLMSG_DONE", "NLMSG_OVERRUN" };
+    const char *kNLRtMsgTypes[] = { "RTM_NEWLINK", "RTM_DELLINK", "RTM_GETLINK", "RTM_NEWADDR", "RTM_DELADDR", "RTM_GETADDR" };
+
+    printf("nlmsghdr len=%d, type=%s, flags=0x%x\n", pNLMsg->nlmsg_len,
+           pNLMsg->nlmsg_type < RTM_BASE ? kNLMsgTypes[pNLMsg->nlmsg_type] : kNLRtMsgTypes[pNLMsg->nlmsg_type - RTM_BASE],
+           pNLMsg->nlmsg_flags);
+
+    if (RTM_NEWLINK <= pNLMsg->nlmsg_type && pNLMsg->nlmsg_type <= RTM_GETLINK)
+    {
+        struct ifinfomsg    *pIfInfo = (struct ifinfomsg*) NLMSG_DATA(pNLMsg);
+        printf("ifinfomsg family=%d, type=%d, index=%d, flags=0x%x, change=0x%x\n", pIfInfo->ifi_family,
+               pIfInfo->ifi_type, pIfInfo->ifi_index, pIfInfo->ifi_flags, pIfInfo->ifi_change);
+
+    }
+    else if (RTM_NEWADDR <= pNLMsg->nlmsg_type && pNLMsg->nlmsg_type <= RTM_GETADDR)
+    {
+        struct ifaddrmsg    *pIfAddr = (struct ifaddrmsg*) NLMSG_DATA(pNLMsg);
+        printf("ifaddrmsg family=%d, index=%d, flags=0x%x\n", pIfAddr->ifa_family,
+               pIfAddr->ifa_index, pIfAddr->ifa_flags);
+    }
+    printf("\n");
+}
+#endif
+
+mDNSlocal mDNSu32       ProcessRoutingNotification(int sd)
+// Read through the messages on sd and if any indicate that any interface records should
+// be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0.
+{
+    ssize_t readCount;
+    char buff[4096];
+    struct nlmsghdr         *pNLMsg = (struct nlmsghdr*) buff;
+    mDNSu32 result = 0;
+
+    // The structure here is more complex than it really ought to be because,
+    // unfortunately, there's no good way to size a buffer in advance large
+    // enough to hold all pending data and so avoid message fragmentation.
+    // (Note that FIONREAD is not supported on AF_NETLINK.)
+
+    readCount = read(sd, buff, sizeof buff);
+    while (1)
+    {
+        // Make sure we've got an entire nlmsghdr in the buffer, and payload, too.
+        // If not, discard already-processed messages in buffer and read more data.
+        if (((char*) &pNLMsg[1] > (buff + readCount)) ||    // i.e. *pNLMsg extends off end of buffer
+            ((char*) pNLMsg + pNLMsg->nlmsg_len > (buff + readCount)))
+        {
+            if (buff < (char*) pNLMsg)      // we have space to shuffle
+            {
+                // discard processed data
+                readCount -= ((char*) pNLMsg - buff);
+                memmove(buff, pNLMsg, readCount);
+                pNLMsg = (struct nlmsghdr*) buff;
+
+                // read more data
+                readCount += read(sd, buff + readCount, sizeof buff - readCount);
+                continue;                   // spin around and revalidate with new readCount
+            }
+            else
+                break;  // Otherwise message does not fit in buffer
+        }
+
+#if MDNS_DEBUGMSGS
+        PrintNetLinkMsg(pNLMsg);
+#endif
+
+        // Process the NetLink message
+        if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK)
+            result |= 1 << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index;
+        else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR)
+            result |= 1 << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index;
+
+        // Advance pNLMsg to the next message in the buffer
+        if ((pNLMsg->nlmsg_flags & NLM_F_MULTI) != 0 && pNLMsg->nlmsg_type != NLMSG_DONE)
+        {
+            ssize_t len = readCount - ((char*)pNLMsg - buff);
+            pNLMsg = NLMSG_NEXT(pNLMsg, len);
+        }
+        else
+            break;  // all done!
+    }
+
+    return result;
+}
+
+#else // USES_NETLINK
+
+// Open a socket that will receive interface change notifications
+mDNSlocal mStatus OpenIfNotifySocket(int *pFD)
+{
+    *pFD = socket(AF_ROUTE, SOCK_RAW, 0);
+
+    if (*pFD < 0)
+        return mStatus_UnknownErr;
+
+    // Configure read to be non-blocking because inbound msg size is not known in advance
+    (void) fcntl(*pFD, F_SETFL, O_NONBLOCK);
+
+    return mStatus_NoError;
+}
+
+#if MDNS_DEBUGMSGS
+mDNSlocal void      PrintRoutingSocketMsg(const struct ifa_msghdr *pRSMsg)
+{
+    const char *kRSMsgTypes[] = { "", "RTM_ADD", "RTM_DELETE", "RTM_CHANGE", "RTM_GET", "RTM_LOSING",
+                                  "RTM_REDIRECT", "RTM_MISS", "RTM_LOCK", "RTM_OLDADD", "RTM_OLDDEL", "RTM_RESOLVE",
+                                  "RTM_NEWADDR", "RTM_DELADDR", "RTM_IFINFO", "RTM_NEWMADDR", "RTM_DELMADDR" };
+
+    int index = pRSMsg->ifam_type == RTM_IFINFO ? ((struct if_msghdr*) pRSMsg)->ifm_index : pRSMsg->ifam_index;
+
+    printf("ifa_msghdr len=%d, type=%s, index=%d\n", pRSMsg->ifam_msglen, kRSMsgTypes[pRSMsg->ifam_type], index);
+}
+#endif
+
+mDNSlocal mDNSu32       ProcessRoutingNotification(int sd)
+// Read through the messages on sd and if any indicate that any interface records should
+// be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0.
+{
+    ssize_t readCount;
+    char buff[4096];
+    struct ifa_msghdr       *pRSMsg = (struct ifa_msghdr*) buff;
+    mDNSu32 result = 0;
+
+    readCount = read(sd, buff, sizeof buff);
+    if (readCount < (ssize_t) sizeof(struct ifa_msghdr))
+        return mStatus_UnsupportedErr;      // cannot decipher message
+
+#if MDNS_DEBUGMSGS
+    PrintRoutingSocketMsg(pRSMsg);
+#endif
+
+    // Process the message
+    if (pRSMsg->ifam_type == RTM_NEWADDR || pRSMsg->ifam_type == RTM_DELADDR ||
+        pRSMsg->ifam_type == RTM_IFINFO)
+    {
+        if (pRSMsg->ifam_type == RTM_IFINFO)
+            result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index;
+        else
+            result |= 1 << pRSMsg->ifam_index;
+    }
+
+    return result;
+}
+
+#endif // USES_NETLINK
+
+// Called when data appears on interface change notification socket
+mDNSlocal void InterfaceChangeCallback(int fd, short filter, void *context)
+{
+    IfChangeRec     *pChgRec = (IfChangeRec*) context;
+    fd_set readFDs;
+    mDNSu32 changedInterfaces = 0;
+    struct timeval zeroTimeout = { 0, 0 };
+
+    (void)fd; // Unused
+    (void)filter; // Unused
+
+    FD_ZERO(&readFDs);
+    FD_SET(pChgRec->NotifySD, &readFDs);
+
+    do
+    {
+        changedInterfaces |= ProcessRoutingNotification(pChgRec->NotifySD);
+    }
+    while (0 < select(pChgRec->NotifySD + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout));
+
+    // Currently we rebuild the entire interface list whenever any interface change is
+    // detected. If this ever proves to be a performance issue in a multi-homed
+    // configuration, more care should be paid to changedInterfaces.
+    if (changedInterfaces)
+        mDNSPlatformPosixRefreshInterfaceList(pChgRec->mDNS);
+}
+
+// Register with either a Routing Socket or RtNetLink to listen for interface changes.
+mDNSlocal mStatus WatchForInterfaceChange(mDNS *const m)
+{
+    mStatus err;
+    IfChangeRec *pChgRec;
+
+    pChgRec = (IfChangeRec*) mDNSPlatformMemAllocate(sizeof *pChgRec);
+    if (pChgRec == NULL)
+        return mStatus_NoMemoryErr;
+
+    pChgRec->mDNS = m;
+    err = OpenIfNotifySocket(&pChgRec->NotifySD);
+    if (err == 0)
+        err = mDNSPosixAddFDToEventLoop(pChgRec->NotifySD, InterfaceChangeCallback, pChgRec);
+
+    return err;
+}
+
+// Test to see if we're the first client running on UDP port 5353, by trying to bind to 5353 without using SO_REUSEPORT.
+// If we fail, someone else got here first. That's not a big problem; we can share the port for multicast responses --
+// we just need to be aware that we shouldn't expect to successfully receive unicast UDP responses.
+mDNSlocal mDNSBool mDNSPlatformInit_CanReceiveUnicast(void)
+{
+    int err;
+    int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    struct sockaddr_in s5353;
+    s5353.sin_family      = AF_INET;
+    s5353.sin_port        = MulticastDNSPort.NotAnInteger;
+    s5353.sin_addr.s_addr = 0;
+    err = bind(s, (struct sockaddr *)&s5353, sizeof(s5353));
+    close(s);
+    if (err) debugf("No unicast UDP responses");
+    else debugf("Unicast UDP responses okay");
+    return(err == 0);
+}
+
+// mDNS core calls this routine to initialise the platform-specific data.
+mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
+{
+    int err = 0;
+    struct sockaddr sa;
+    assert(m != NULL);
+
+    if (mDNSPlatformInit_CanReceiveUnicast()) m->CanReceiveUnicastOn5353 = mDNStrue;
+
+    // Tell mDNS core the names of this machine.
+
+    // Set up the nice label
+    m->nicelabel.c[0] = 0;
+    GetUserSpecifiedFriendlyComputerName(&m->nicelabel);
+    if (m->nicelabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->nicelabel, "Computer");
+
+    // Set up the RFC 1034-compliant label
+    m->hostlabel.c[0] = 0;
+    GetUserSpecifiedRFC1034ComputerName(&m->hostlabel);
+    if (m->hostlabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->hostlabel, "Computer");
+
+    mDNS_SetFQDN(m);
+
+    sa.sa_family = AF_INET;
+    m->p->unicastSocket4 = -1;
+    if (err == mStatus_NoError) err = SetupSocket(&sa, zeroIPPort, 0, &m->p->unicastSocket4);
+#if HAVE_IPV6
+    sa.sa_family = AF_INET6;
+    m->p->unicastSocket6 = -1;
+    if (err == mStatus_NoError) err = SetupSocket(&sa, zeroIPPort, 0, &m->p->unicastSocket6);
+#endif
+
+    // Tell mDNS core about the network interfaces on this machine.
+    if (err == mStatus_NoError) err = SetupInterfaceList(m);
+
+    // Tell mDNS core about DNS Servers
+    mDNS_Lock(m);
+    if (err == mStatus_NoError) ParseDNSServers(m, uDNS_SERVERS_FILE);
+    mDNS_Unlock(m);
+
+    if (err == mStatus_NoError)
+    {
+        err = WatchForInterfaceChange(m);
+        // Failure to observe interface changes is non-fatal.
+        if (err != mStatus_NoError)
+        {
+            fprintf(stderr, "mDNS(%d) WARNING: Unable to detect interface changes (%d).\n", getpid(), err);
+            err = mStatus_NoError;
+        }
+    }
+
+    // We don't do asynchronous initialization on the Posix platform, so by the time
+    // we get here the setup will already have succeeded or failed.  If it succeeded,
+    // we should just call mDNSCoreInitComplete() immediately.
+    if (err == mStatus_NoError)
+        mDNSCoreInitComplete(m, mStatus_NoError);
+
+    return PosixErrorToStatus(err);
+}
+
+// mDNS core calls this routine to clean up the platform-specific data.
+// In our case all we need to do is to tear down every network interface.
+mDNSexport void mDNSPlatformClose(mDNS *const m)
+{
+    assert(m != NULL);
+    ClearInterfaceList(m);
+    if (m->p->unicastSocket4 != -1) assert(close(m->p->unicastSocket4) == 0);
+#if HAVE_IPV6
+    if (m->p->unicastSocket6 != -1) assert(close(m->p->unicastSocket6) == 0);
+#endif
+}
+
+mDNSexport mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m)
+{
+    int err;
+    ClearInterfaceList(m);
+    err = SetupInterfaceList(m);
+    return PosixErrorToStatus(err);
+}
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark ***** Locking
+#endif
+
+// On the Posix platform, locking is a no-op because we only ever enter
+// mDNS core on the main thread.
+
+// mDNS core calls this routine when it wants to prevent
+// the platform from reentering mDNS core code.
+mDNSexport void    mDNSPlatformLock   (const mDNS *const m)
+{
+    (void) m;   // Unused
+}
+
+// mDNS core calls this routine when it release the lock taken by
+// mDNSPlatformLock and allow the platform to reenter mDNS core code.
+mDNSexport void    mDNSPlatformUnlock (const mDNS *const m)
+{
+    (void) m;   // Unused
+}
+
+#if COMPILER_LIKES_PRAGMA_MARK
+#pragma mark ***** Strings
+#endif
+
+// mDNS core calls this routine to copy C strings.
+// On the Posix platform this maps directly to the ANSI C strcpy.
+mDNSexport void    mDNSPlatformStrCopy(void *dst, const void *src)
+{
+    strcpy((char *)dst, (char *)src);
+}
+
+// mDNS core calls this routine to get the length of a C string.
+// On the Posix platform this maps directly to the ANSI C strlen.
+mDNSexport mDNSu32  mDNSPlatformStrLen (const void *src)
+{
+    return strlen((char*)src);
+}
+
+// mDNS core calls this routine to copy memory.
+// On the Posix platform this maps directly to the ANSI C memcpy.
+mDNSexport void    mDNSPlatformMemCopy(void *dst, const void *src, mDNSu32 len)
+{
+    memcpy(dst, src, len);
+}
+
+// mDNS core calls this routine to test whether blocks of memory are byte-for-byte
+// identical. On the Posix platform this is a simple wrapper around ANSI C memcmp.
+mDNSexport mDNSBool mDNSPlatformMemSame(const void *dst, const void *src, mDNSu32 len)
+{
+    return memcmp(dst, src, len) == 0;
+}
+
+// If the caller wants to know the exact return of memcmp, then use this instead
+// of mDNSPlatformMemSame
+mDNSexport int mDNSPlatformMemCmp(const void *dst, const void *src, mDNSu32 len)
+{
+    return (memcmp(dst, src, len));
+}
+
+mDNSexport void mDNSPlatformQsort(void *base, int nel, int width, int (*compar)(const void *, const void *))
+{
+    return (qsort(base, nel, width, compar));
+}
+
+// DNSSEC stub functions
+mDNSexport void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *q)
+{
+    (void)m;
+    (void)dv;
+    (void)q;
+}
+
+mDNSexport mDNSBool AddNSECSForCacheRecord(mDNS *const m, CacheRecord *crlist, CacheRecord *negcr, mDNSu8 rcode)
+{
+    (void)m;
+    (void)crlist;
+    (void)negcr;
+    (void)rcode;
+    return mDNSfalse;
+}
+
+mDNSexport void BumpDNSSECStats(mDNS *const m, DNSSECStatsAction action, DNSSECStatsType type, mDNSu32 value)
+{
+    (void)m;
+    (void)action;
+    (void)type;
+    (void)value;
+}
+
+// Proxy stub functions
+mDNSexport mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit)
+{
+    (void) q;
+    (void) h;
+    (void) msg;
+    (void) ptr;
+    (void) limit;
+
+    return ptr;
+}
+
+mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[], mDNSu32 OpIf)
+{
+    (void) m;
+    (void) IpIfArr;
+    (void) OpIf;
+}
+
+mDNSexport void DNSProxyTerminate(mDNS *const m)
+{
+    (void) m;
+}
+
+// mDNS core calls this routine to clear blocks of memory.
+// On the Posix platform this is a simple wrapper around ANSI C memset.
+mDNSexport void    mDNSPlatformMemZero(void *dst, mDNSu32 len)
+{
+    memset(dst, 0, len);
+}
+
+mDNSexport void *  mDNSPlatformMemAllocate(mDNSu32 len) { return(malloc(len)); }
+mDNSexport void    mDNSPlatformMemFree    (void *mem)   { free(mem); }
+
+mDNSexport mDNSu32 mDNSPlatformRandomSeed(void)
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return(tv.tv_usec);
+}
+
+mDNSexport mDNSs32 mDNSPlatformOneSecond = 1024;
+
+mDNSexport mStatus mDNSPlatformTimeInit(void)
+{
+    // No special setup is required on Posix -- we just use gettimeofday();
+    // This is not really safe, because gettimeofday can go backwards if the user manually changes the date or time
+    // We should find a better way to do this
+    return(mStatus_NoError);
+}
+
+mDNSexport mDNSs32  mDNSPlatformRawTime()
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    // tv.tv_sec is seconds since 1st January 1970 (GMT, with no adjustment for daylight savings time)
+    // tv.tv_usec is microseconds since the start of this second (i.e. values 0 to 999999)
+    // We use the lower 22 bits of tv.tv_sec for the top 22 bits of our result
+    // and we multiply tv.tv_usec by 16 / 15625 to get a value in the range 0-1023 to go in the bottom 10 bits.
+    // This gives us a proper modular (cyclic) counter that has a resolution of roughly 1ms (actually 1/1024 second)
+    // and correctly cycles every 2^22 seconds (4194304 seconds = approx 48 days).
+    return((tv.tv_sec << 10) | (tv.tv_usec * 16 / 15625));
+}
+
+mDNSexport mDNSs32 mDNSPlatformUTC(void)
+{
+    return time(NULL);
+}
+
+mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
+{
+    (void) m;
+    (void) InterfaceID;
+    (void) EthAddr;
+    (void) IPAddr;
+    (void) iteration;
+}
+
+mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf)
+{
+    (void) rr;
+    (void) intf;
+
+    return 1;
+}
+
+mDNSexport mDNSBool mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf)
+{
+    (void) q;
+    (void) intf;
+
+    return 1;
+}
+
+// Used for debugging purposes. For now, just set the buffer to zero
+mDNSexport void mDNSPlatformFormatTime(unsigned long te, mDNSu8 *buf, int bufsize)
+{
+    (void) te;
+    if (bufsize) buf[0] = 0;
+}
+
+mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win)
+{
+    (void) sadd;    // Unused
+    (void) dadd;    // Unused
+    (void) lport;   // Unused
+    (void) rport;   // Unused
+    (void) seq;     // Unused
+    (void) ack;     // Unused
+    (void) win;     // Unused
+}
+
+mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti)
+{
+    (void) m;       // Unused
+    (void) laddr;   // Unused
+    (void) raddr;   // Unused
+    (void) lport;   // Unused
+    (void) rport;   // Unused
+    (void) mti;     // Unused
+
+    return mStatus_NoError;
+}
+
+mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr)
+{
+    (void) raddr; // Unused
+    (void) m;     // Unused
+
+    return mStatus_NoError;
+}
+
+mDNSexport mStatus    mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname)
+{
+    (void) spsaddr; // Unused
+    (void) ifname;  // Unused
+
+    return mStatus_NoError;
+}
+
+mDNSexport mStatus    mDNSPlatformClearSPSMACAddr(void)
+{
+    return mStatus_NoError;
+}
+
+mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
+{
+    (void) sock; // unused
+ 
+    return (mDNSu16)-1;
+}
+
+mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
+{
+    (void) InterfaceID; // unused
+    
+    return mDNSfalse;
+}
+
+mDNSexport mDNSBool mDNSPlatformAllowPID(mDNS *const m, DNSQuestion *q)
+{
+    (void) m;
+    (void) q;
+    return mDNStrue;
+}
+
+mDNSexport mDNSs32 mDNSPlatformGetServiceID(mDNS *const m, DNSQuestion *q)
+{
+    (void) m;
+    (void) q;
+    return -1;
+}
+
+mDNSexport void mDNSPlatformSetDelegatePID(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q)
+{
+    (void) src;
+    (void) dst;
+    (void) q;
+}
+
+mDNSexport mDNSs32 mDNSPlatformGetPID()
+{
+    return 0;
+}
+
+mDNSlocal void mDNSPosixAddToFDSet(int *nfds, fd_set *readfds, int s)
+{
+    if (*nfds < s + 1) *nfds = s + 1;
+    FD_SET(s, readfds);
+}
+
+mDNSexport void mDNSPosixGetFDSet(mDNS *m, int *nfds, fd_set *readfds, struct timeval *timeout)
+{
+    mDNSs32 ticks;
+    struct timeval interval;
+
+    // 1. Call mDNS_Execute() to let mDNSCore do what it needs to do
+    mDNSs32 nextevent = mDNS_Execute(m);
+
+    // 2. Build our list of active file descriptors
+    PosixNetworkInterface *info = (PosixNetworkInterface *)(m->HostInterfaces);
+    if (m->p->unicastSocket4 != -1) mDNSPosixAddToFDSet(nfds, readfds, m->p->unicastSocket4);
+#if HAVE_IPV6
+    if (m->p->unicastSocket6 != -1) mDNSPosixAddToFDSet(nfds, readfds, m->p->unicastSocket6);
+#endif
+    while (info)
+    {
+        if (info->multicastSocket4 != -1) mDNSPosixAddToFDSet(nfds, readfds, info->multicastSocket4);
+#if HAVE_IPV6
+        if (info->multicastSocket6 != -1) mDNSPosixAddToFDSet(nfds, readfds, info->multicastSocket6);
+#endif
+        info = (PosixNetworkInterface *)(info->coreIntf.next);
+    }
+
+    // 3. Calculate the time remaining to the next scheduled event (in struct timeval format)
+    ticks = nextevent - mDNS_TimeNow(m);
+    if (ticks < 1) ticks = 1;
+    interval.tv_sec  = ticks >> 10;                     // The high 22 bits are seconds
+    interval.tv_usec = ((ticks & 0x3FF) * 15625) / 16;  // The low 10 bits are 1024ths
+
+    // 4. If client's proposed timeout is more than what we want, then reduce it
+    if (timeout->tv_sec > interval.tv_sec ||
+        (timeout->tv_sec == interval.tv_sec && timeout->tv_usec > interval.tv_usec))
+        *timeout = interval;
+}
+
+mDNSexport void mDNSPosixProcessFDSet(mDNS *const m, fd_set *readfds)
+{
+    PosixNetworkInterface *info;
+    assert(m       != NULL);
+    assert(readfds != NULL);
+    info = (PosixNetworkInterface *)(m->HostInterfaces);
+
+    if (m->p->unicastSocket4 != -1 && FD_ISSET(m->p->unicastSocket4, readfds))
+    {
+        FD_CLR(m->p->unicastSocket4, readfds);
+        SocketDataReady(m, NULL, m->p->unicastSocket4);
+    }
+#if HAVE_IPV6
+    if (m->p->unicastSocket6 != -1 && FD_ISSET(m->p->unicastSocket6, readfds))
+    {
+        FD_CLR(m->p->unicastSocket6, readfds);
+        SocketDataReady(m, NULL, m->p->unicastSocket6);
+    }
+#endif
+
+    while (info)
+    {
+        if (info->multicastSocket4 != -1 && FD_ISSET(info->multicastSocket4, readfds))
+        {
+            FD_CLR(info->multicastSocket4, readfds);
+            SocketDataReady(m, info, info->multicastSocket4);
+        }
+#if HAVE_IPV6
+        if (info->multicastSocket6 != -1 && FD_ISSET(info->multicastSocket6, readfds))
+        {
+            FD_CLR(info->multicastSocket6, readfds);
+            SocketDataReady(m, info, info->multicastSocket6);
+        }
+#endif
+        info = (PosixNetworkInterface *)(info->coreIntf.next);
+    }
+}
+
+// update gMaxFD
+mDNSlocal void  DetermineMaxEventFD(void)
+{
+    PosixEventSource    *iSource;
+
+    gMaxFD = 0;
+    for (iSource=(PosixEventSource*)gEventSources.Head; iSource; iSource = iSource->Next)
+        if (gMaxFD < iSource->fd)
+            gMaxFD = iSource->fd;
+}
+
+// Add a file descriptor to the set that mDNSPosixRunEventLoopOnce() listens to.
+mStatus mDNSPosixAddFDToEventLoop(int fd, mDNSPosixEventCallback callback, void *context)
+{
+    PosixEventSource    *newSource;
+
+    if (gEventSources.LinkOffset == 0)
+        InitLinkedList(&gEventSources, offsetof(PosixEventSource, Next));
+
+    if (fd >= (int) FD_SETSIZE || fd < 0)
+        return mStatus_UnsupportedErr;
+    if (callback == NULL)
+        return mStatus_BadParamErr;
+
+    newSource = (PosixEventSource*) malloc(sizeof *newSource);
+    if (NULL == newSource)
+        return mStatus_NoMemoryErr;
+
+    newSource->Callback = callback;
+    newSource->Context = context;
+    newSource->fd = fd;
+
+    AddToTail(&gEventSources, newSource);
+    FD_SET(fd, &gEventFDs);
+
+    DetermineMaxEventFD();
+
+    return mStatus_NoError;
+}
+
+// Remove a file descriptor from the set that mDNSPosixRunEventLoopOnce() listens to.
+mStatus mDNSPosixRemoveFDFromEventLoop(int fd)
+{
+    PosixEventSource    *iSource;
+
+    for (iSource=(PosixEventSource*)gEventSources.Head; iSource; iSource = iSource->Next)
+    {
+        if (fd == iSource->fd)
+        {
+            FD_CLR(fd, &gEventFDs);
+            RemoveFromList(&gEventSources, iSource);
+            free(iSource);
+            DetermineMaxEventFD();
+            return mStatus_NoError;
+        }
+    }
+    return mStatus_NoSuchNameErr;
+}
+
+// Simply note the received signal in gEventSignals.
+mDNSlocal void  NoteSignal(int signum)
+{
+    sigaddset(&gEventSignals, signum);
+}
+
+// Tell the event package to listen for signal and report it in mDNSPosixRunEventLoopOnce().
+mStatus mDNSPosixListenForSignalInEventLoop(int signum)
+{
+    struct sigaction action;
+    mStatus err;
+
+    mDNSPlatformMemZero(&action, sizeof action);        // more portable than member-wise assignment
+    action.sa_handler = NoteSignal;
+    err = sigaction(signum, &action, (struct sigaction*) NULL);
+
+    sigaddset(&gEventSignalSet, signum);
+
+    return err;
+}
+
+// Tell the event package to stop listening for signal in mDNSPosixRunEventLoopOnce().
+mStatus mDNSPosixIgnoreSignalInEventLoop(int signum)
+{
+    struct sigaction action;
+    mStatus err;
+
+    mDNSPlatformMemZero(&action, sizeof action);        // more portable than member-wise assignment
+    action.sa_handler = SIG_DFL;
+    err = sigaction(signum, &action, (struct sigaction*) NULL);
+
+    sigdelset(&gEventSignalSet, signum);
+
+    return err;
+}
+
+// Do a single pass through the attendent event sources and dispatch any found to their callbacks.
+// Return as soon as internal timeout expires, or a signal we're listening for is received.
+mStatus mDNSPosixRunEventLoopOnce(mDNS *m, const struct timeval *pTimeout,
+                                  sigset_t *pSignalsReceived, mDNSBool *pDataDispatched)
+{
+    fd_set listenFDs = gEventFDs;
+    int fdMax = 0, numReady;
+    struct timeval timeout = *pTimeout;
+
+    // Include the sockets that are listening to the wire in our select() set
+    mDNSPosixGetFDSet(m, &fdMax, &listenFDs, &timeout); // timeout may get modified
+    if (fdMax < gMaxFD)
+        fdMax = gMaxFD;
+
+    numReady = select(fdMax + 1, &listenFDs, (fd_set*) NULL, (fd_set*) NULL, &timeout);
+
+    // If any data appeared, invoke its callback
+    if (numReady > 0)
+    {
+        PosixEventSource    *iSource;
+
+        (void) mDNSPosixProcessFDSet(m, &listenFDs);    // call this first to process wire data for clients
+
+        for (iSource=(PosixEventSource*)gEventSources.Head; iSource; iSource = iSource->Next)
+        {
+            if (FD_ISSET(iSource->fd, &listenFDs))
+            {
+                iSource->Callback(iSource->fd, 0, iSource->Context);
+                break;  // in case callback removed elements from gEventSources
+            }
+        }
+        *pDataDispatched = mDNStrue;
+    }
+    else
+        *pDataDispatched = mDNSfalse;
+
+    (void) sigprocmask(SIG_BLOCK, &gEventSignalSet, (sigset_t*) NULL);
+    *pSignalsReceived = gEventSignals;
+    sigemptyset(&gEventSignals);
+    (void) sigprocmask(SIG_UNBLOCK, &gEventSignalSet, (sigset_t*) NULL);
+
+    return mStatus_NoError;
+}

Deleted: vendor/apple/mDNSResponder/561.1.1/mDNSShared/dns_sd.h
===================================================================
--- vendor/apple/mDNSResponder/dist/mDNSShared/dns_sd.h	2014-06-30 23:58:12 UTC (rev 6706)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSShared/dns_sd.h	2015-03-20 01:14:52 UTC (rev 6985)
@@ -1,2657 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2013 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-/*! @header     DNS Service Discovery
- *
- * @discussion  This section describes the functions, callbacks, and data structures
- *              that make up the DNS Service Discovery API.
- *
- *              The DNS Service Discovery API is part of Bonjour, Apple's implementation
- *              of zero-configuration networking (ZEROCONF).
- *
- *              Bonjour allows you to register a network service, such as a
- *              printer or file server, so that it can be found by name or browsed
- *              for by service type and domain. Using Bonjour, applications can
- *              discover what services are available on the network, along with
- *              all the information -- such as name, IP address, and port --
- *              necessary to access a particular service.
- *
- *              In effect, Bonjour combines the functions of a local DNS server and
- *              AppleTalk. Bonjour allows applications to provide user-friendly printer
- *              and server browsing, among other things, over standard IP networks.
- *              This behavior is a result of combining protocols such as multicast and
- *              DNS to add new functionality to the network (such as multicast DNS).
- *
- *              Bonjour gives applications easy access to services over local IP
- *              networks without requiring the service or the application to support
- *              an AppleTalk or a Netbeui stack, and without requiring a DNS server
- *              for the local network.
- */
-
-
-/* _DNS_SD_H contains the mDNSResponder version number for this header file, formatted as follows:
- *   Major part of the build number * 10000 +
- *   minor part of the build number *   100
- * For example, Mac OS X 10.4.9 has mDNSResponder-108.4, which would be represented as
- * version 1080400. This allows C code to do simple greater-than and less-than comparisons:
- * e.g. an application that requires the DNSServiceGetProperty() call (new in mDNSResponder-126) can check:
- *
- *   #if _DNS_SD_H+0 >= 1260000
- *   ... some C code that calls DNSServiceGetProperty() ...
- *   #endif
- *
- * The version defined in this header file symbol allows for compile-time
- * checking, so that C code building with earlier versions of the header file
- * can avoid compile errors trying to use functions that aren't even defined
- * in those earlier versions. Similar checks may also be performed at run-time:
- *  => weak linking -- to avoid link failures if run with an earlier
- *     version of the library that's missing some desired symbol, or
- *  => DNSServiceGetProperty(DaemonVersion) -- to verify whether the running daemon
- *     ("system service" on Windows) meets some required minimum functionality level.
- */
-
-#ifndef _DNS_SD_H
-#define _DNS_SD_H 5410000
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-/* Set to 1 if libdispatch is supported
- * Note: May also be set by project and/or Makefile
- */
-#ifndef _DNS_SD_LIBDISPATCH
-#define _DNS_SD_LIBDISPATCH 0
-#endif /* ndef _DNS_SD_LIBDISPATCH */
-
-/* standard calling convention under Win32 is __stdcall */
-/* Note: When compiling Intel EFI (Extensible Firmware Interface) under MS Visual Studio, the */
-/* _WIN32 symbol is defined by the compiler even though it's NOT compiling code for Windows32 */
-#if defined(_WIN32) && !defined(EFI32) && !defined(EFI64)
-#define DNSSD_API __stdcall
-#else
-#define DNSSD_API
-#endif
-
-/* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */
-#if defined(__FreeBSD__) && (__FreeBSD__ < 5)
-#include <sys/types.h>
-
-/* Likewise, on Sun, standard integer types are in sys/types.h */
-#elif defined(__sun__)
-#include <sys/types.h>
-
-/* EFI does not have stdint.h, or anything else equivalent */
-#elif defined(EFI32) || defined(EFI64) || defined(EFIX64)
-#include "Tiano.h"
-#if !defined(_STDINT_H_)
-typedef UINT8 uint8_t;
-typedef INT8 int8_t;
-typedef UINT16 uint16_t;
-typedef INT16 int16_t;
-typedef UINT32 uint32_t;
-typedef INT32 int32_t;
-#endif
-/* Windows has its own differences */
-#elif defined(_WIN32)
-#include <windows.h>
-#define _UNUSED
-#ifndef _MSL_STDINT_H
-typedef UINT8 uint8_t;
-typedef INT8 int8_t;
-typedef UINT16 uint16_t;
-typedef INT16 int16_t;
-typedef UINT32 uint32_t;
-typedef INT32 int32_t;
-#endif
-
-/* All other Posix platforms use stdint.h */
-#else
-#include <stdint.h>
-#endif
-
-#if _DNS_SD_LIBDISPATCH
-#include <dispatch/dispatch.h>
-#endif
-
-/* DNSServiceRef, DNSRecordRef
- *
- * Opaque internal data types.
- * Note: client is responsible for serializing access to these structures if
- * they are shared between concurrent threads.
- */
-
-typedef struct _DNSServiceRef_t *DNSServiceRef;
-typedef struct _DNSRecordRef_t *DNSRecordRef;
-
-struct sockaddr;
-
-/*! @enum General flags
- * Most DNS-SD API functions and callbacks include a DNSServiceFlags parameter.
- * As a general rule, any given bit in the 32-bit flags field has a specific fixed meaning,
- * regardless of the function or callback being used. For any given function or callback,
- * typically only a subset of the possible flags are meaningful, and all others should be zero.
- * The discussion section for each API call describes which flags are valid for that call
- * and callback. In some cases, for a particular call, it may be that no flags are currently
- * defined, in which case the DNSServiceFlags parameter exists purely to allow future expansion.
- * In all cases, developers should expect that in future releases, it is possible that new flag
- * values will be defined, and write code with this in mind. For example, code that tests
- *     if (flags == kDNSServiceFlagsAdd) ...
- * will fail if, in a future release, another bit in the 32-bit flags field is also set.
- * The reliable way to test whether a particular bit is set is not with an equality test,
- * but with a bitwise mask:
- *     if (flags & kDNSServiceFlagsAdd) ...
- * With the exception of kDNSServiceFlagsValidate, each flag can be valid(be set) 
- * EITHER only as an input to one of the DNSService*() APIs OR only as an output
- * (provide status) through any of the callbacks used. For example, kDNSServiceFlagsAdd
- * can be set only as an output in the callback, whereas the kDNSServiceFlagsIncludeP2P
- * can be set only as an input to the DNSService*() APIs. See comments on kDNSServiceFlagsValidate  
- * defined in enum below.
- */
-enum
-{
-    kDNSServiceFlagsMoreComing          = 0x1,
-    /* MoreComing indicates to a callback that at least one more result is
-     * queued and will be delivered following immediately after this one.
-     * When the MoreComing flag is set, applications should not immediately
-     * update their UI, because this can result in a great deal of ugly flickering
-     * on the screen, and can waste a great deal of CPU time repeatedly updating
-     * the screen with content that is then immediately erased, over and over.
-     * Applications should wait until MoreComing is not set, and then
-     * update their UI when no more changes are imminent.
-     * When MoreComing is not set, that doesn't mean there will be no more
-     * answers EVER, just that there are no more answers immediately
-     * available right now at this instant. If more answers become available
-     * in the future they will be delivered as usual.
-     */
-
-    kDNSServiceFlagsAdd                 = 0x2,
-    kDNSServiceFlagsDefault             = 0x4,
-    /* Flags for domain enumeration and browse/query reply callbacks.
-     * "Default" applies only to enumeration and is only valid in
-     * conjunction with "Add". An enumeration callback with the "Add"
-     * flag NOT set indicates a "Remove", i.e. the domain is no longer
-     * valid.
-     */
-
-    kDNSServiceFlagsNoAutoRename        = 0x8,
-    /* Flag for specifying renaming behavior on name conflict when registering
-     * non-shared records. By default, name conflicts are automatically handled
-     * by renaming the service. NoAutoRename overrides this behavior - with this
-     * flag set, name conflicts will result in a callback. The NoAutorename flag
-     * is only valid if a name is explicitly specified when registering a service
-     * (i.e. the default name is not used.)
-     */
-
-    kDNSServiceFlagsShared              = 0x10,
-    kDNSServiceFlagsUnique              = 0x20,
-    /* Flag for registering individual records on a connected
-     * DNSServiceRef. Shared indicates that there may be multiple records
-     * with this name on the network (e.g. PTR records). Unique indicates that the
-     * record's name is to be unique on the network (e.g. SRV records).
-     */
-
-    kDNSServiceFlagsBrowseDomains       = 0x40,
-    kDNSServiceFlagsRegistrationDomains = 0x80,
-    /* Flags for specifying domain enumeration type in DNSServiceEnumerateDomains.
-     * BrowseDomains enumerates domains recommended for browsing, RegistrationDomains
-     * enumerates domains recommended for registration.
-     */
-
-    kDNSServiceFlagsLongLivedQuery      = 0x100,
-    /* Flag for creating a long-lived unicast query for the DNSServiceQueryRecord call. */
-
-    kDNSServiceFlagsAllowRemoteQuery    = 0x200,
-    /* Flag for creating a record for which we will answer remote queries
-     * (queries from hosts more than one hop away; hosts not directly connected to the local link).
-     */
-
-    kDNSServiceFlagsForceMulticast      = 0x400,
-    /* Flag for signifying that a query or registration should be performed exclusively via multicast
-     * DNS, even for a name in a domain (e.g. foo.apple.com.) that would normally imply unicast DNS.
-     */
-
-    kDNSServiceFlagsForce               = 0x800,    // This flag is deprecated.
-
-    kDNSServiceFlagsKnownUnique         = 0x800,
-    /* 
-     * Client guarantees that record names are unique, so we can skip sending out initial
-     * probe messages.  Standard name conflict resolution is still done if a conflict is discovered.
-     * Currently only valid for a DNSServiceRegister call.
-     */
-
-    kDNSServiceFlagsReturnIntermediates = 0x1000,
-    /* Flag for returning intermediate results.
-     * For example, if a query results in an authoritative NXDomain (name does not exist)
-     * then that result is returned to the client. However the query is not implicitly
-     * cancelled -- it remains active and if the answer subsequently changes
-     * (e.g. because a VPN tunnel is subsequently established) then that positive
-     * result will still be returned to the client.
-     * Similarly, if a query results in a CNAME record, then in addition to following
-     * the CNAME referral, the intermediate CNAME result is also returned to the client.
-     * When this flag is not set, NXDomain errors are not returned, and CNAME records
-     * are followed silently without informing the client of the intermediate steps.
-     * (In earlier builds this flag was briefly calledkDNSServiceFlagsReturnCNAME)
-     */
-
-    kDNSServiceFlagsNonBrowsable        = 0x2000,
-    /* A service registered with the NonBrowsable flag set can be resolved using
-     * DNSServiceResolve(), but will not be discoverable using DNSServiceBrowse().
-     * This is for cases where the name is actually a GUID; it is found by other means;
-     * there is no end-user benefit to browsing to find a long list of opaque GUIDs.
-     * Using the NonBrowsable flag creates SRV+TXT without the cost of also advertising
-     * an associated PTR record.
-     */
-
-    kDNSServiceFlagsShareConnection     = 0x4000,
-    /* For efficiency, clients that perform many concurrent operations may want to use a
-     * single Unix Domain Socket connection with the background daemon, instead of having a
-     * separate connection for each independent operation. To use this mode, clients first
-     * call DNSServiceCreateConnection(&MainRef) to initialize the main DNSServiceRef.
-     * For each subsequent operation that is to share that same connection, the client copies
-     * the MainRef, and then passes the address of that copy, setting the ShareConnection flag
-     * to tell the library that this DNSServiceRef is not a typical uninitialized DNSServiceRef;
-     * it's a copy of an existing DNSServiceRef whose connection information should be reused.
-     *
-     * For example:
-     *
-     * DNSServiceErrorType error;
-     * DNSServiceRef MainRef;
-     * error = DNSServiceCreateConnection(&MainRef);
-     * if (error) ...
-     * DNSServiceRef BrowseRef = MainRef;  // Important: COPY the primary DNSServiceRef first...
-     * error = DNSServiceBrowse(&BrowseRef, kDNSServiceFlagsShareConnection, ...); // then use the copy
-     * if (error) ...
-     * ...
-     * DNSServiceRefDeallocate(BrowseRef); // Terminate the browse operation
-     * DNSServiceRefDeallocate(MainRef);   // Terminate the shared connection
-     *
-     * Notes:
-     *
-     * 1. Collective kDNSServiceFlagsMoreComing flag
-     * When callbacks are invoked using a shared DNSServiceRef, the
-     * kDNSServiceFlagsMoreComing flag applies collectively to *all* active
-     * operations sharing the same parent DNSServiceRef. If the MoreComing flag is
-     * set it means that there are more results queued on this parent DNSServiceRef,
-     * but not necessarily more results for this particular callback function.
-     * The implication of this for client programmers is that when a callback
-     * is invoked with the MoreComing flag set, the code should update its
-     * internal data structures with the new result, and set a variable indicating
-     * that its UI needs to be updated. Then, later when a callback is eventually
-     * invoked with the MoreComing flag not set, the code should update *all*
-     * stale UI elements related to that shared parent DNSServiceRef that need
-     * updating, not just the UI elements related to the particular callback
-     * that happened to be the last one to be invoked.
-     *
-     * 2. Canceling operations and kDNSServiceFlagsMoreComing
-     * Whenever you cancel any operation for which you had deferred UI updates
-     * waiting because of a kDNSServiceFlagsMoreComing flag, you should perform
-     * those deferred UI updates. This is because, after cancelling the operation,
-     * you can no longer wait for a callback *without* MoreComing set, to tell
-     * you do perform your deferred UI updates (the operation has been canceled,
-     * so there will be no more callbacks). An implication of the collective
-     * kDNSServiceFlagsMoreComing flag for shared connections is that this
-     * guideline applies more broadly -- any time you cancel an operation on
-     * a shared connection, you should perform all deferred UI updates for all
-     * operations sharing that connection. This is because the MoreComing flag
-     * might have been referring to events coming for the operation you canceled,
-     * which will now not be coming because the operation has been canceled.
-     *
-     * 3. Only share DNSServiceRef's created with DNSServiceCreateConnection
-     * Calling DNSServiceCreateConnection(&ref) creates a special shareable DNSServiceRef.
-     * DNSServiceRef's created by other calls like DNSServiceBrowse() or DNSServiceResolve()
-     * cannot be shared by copying them and using kDNSServiceFlagsShareConnection.
-     *
-     * 4. Don't Double-Deallocate
-     * Calling DNSServiceRefDeallocate(ref) for a particular operation's DNSServiceRef terminates
-     * just that operation. Calling DNSServiceRefDeallocate(ref) for the main shared DNSServiceRef
-     * (the parent DNSServiceRef, originally created by DNSServiceCreateConnection(&ref))
-     * automatically terminates the shared connection and all operations that were still using it.
-     * After doing this, DO NOT then attempt to deallocate any remaining subordinate DNSServiceRef's.
-     * The memory used by those subordinate DNSServiceRef's has already been freed, so any attempt
-     * to do a DNSServiceRefDeallocate (or any other operation) on them will result in accesses
-     * to freed memory, leading to crashes or other equally undesirable results.
-     *
-     * 5. Thread Safety
-     * The dns_sd.h API does not presuppose any particular threading model, and consequently
-     * does no locking of its own (which would require linking some specific threading library).
-     * If client code calls API routines on the same DNSServiceRef concurrently
-     * from multiple threads, it is the client's responsibility to use a mutext
-     * lock or take similar appropriate precautions to serialize those calls.
-     */
-
-    kDNSServiceFlagsSuppressUnusable    = 0x8000,
-    /*
-     * This flag is meaningful only in DNSServiceQueryRecord which suppresses unusable queries on the
-     * wire. If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name)
-     * but this host has no routable IPv6 address, then the call will not try to look up IPv6 addresses
-     * for "hostname", since any addresses it found would be unlikely to be of any use anyway. Similarly,
-     * if this host has no routable IPv4 address, the call will not try to look up IPv4 addresses for
-     * "hostname".
-     */
-
-    kDNSServiceFlagsTimeout            = 0x10000,
-    /*
-     * When kDNServiceFlagsTimeout is passed to DNSServiceQueryRecord or DNSServiceGetAddrInfo, the query is
-     * stopped after a certain number of seconds have elapsed. The time at which the query will be stopped
-     * is determined by the system and cannot be configured by the user. The query will be stopped irrespective
-     * of whether a response was given earlier or not. When the query is stopped, the callback will be called
-     * with an error code of kDNSServiceErr_Timeout and a NULL sockaddr will be returned for DNSServiceGetAddrInfo
-     * and zero length rdata will be returned for DNSServiceQueryRecord.
-     */
-
-    kDNSServiceFlagsIncludeP2P          = 0x20000,
-    /*
-     * Include P2P interfaces when kDNSServiceInterfaceIndexAny is specified.
-     * By default, specifying kDNSServiceInterfaceIndexAny does not include P2P interfaces.
-     */
-
-    kDNSServiceFlagsWakeOnResolve      = 0x40000,
-    /*
-    * This flag is meaningful only in DNSServiceResolve. When set, it tries to send a magic packet
-    * to wake up the client.
-    */
-
-    kDNSServiceFlagsBackgroundTrafficClass  = 0x80000,
-    /*
-    * This flag is meaningful in DNSServiceBrowse, DNSServiceGetAddrInfo, DNSServiceQueryRecord, 
-    * and DNSServiceResolve. When set, it uses the background traffic 
-    * class for packets that service the request.
-    */
-
-    kDNSServiceFlagsIncludeAWDL      = 0x100000,
-   /*
-    * Include AWDL interface when kDNSServiceInterfaceIndexAny is specified.
-    */
-
-    kDNSServiceFlagsValidate               = 0x200000,
-   /*
-    * This flag is meaningful in DNSServiceGetAddrInfo and DNSServiceQueryRecord. This is the ONLY flag to be valid 
-    * as an input to the APIs and also an output through the callbacks in the APIs.
-    *
-    * When this flag is passed to DNSServiceQueryRecord and DNSServiceGetAddrInfo to resolve unicast names, 
-    * the response  will be validated using DNSSEC. The validation results are delivered using the flags field in 
-    * the callback and kDNSServiceFlagsValidate is marked in the flags to indicate that DNSSEC status is also available.
-    * When the callback is called to deliver the query results, the validation results may or may not be available. 
-    * If it is not delivered along with the results, the validation status is delivered when the validation completes.
-    * 
-    * When the validation results are delivered in the callback, it is indicated by marking the flags with
-    * kDNSServiceFlagsValidate and kDNSServiceFlagsAdd along with the DNSSEC status flags (described below) and a NULL
-    * sockaddr will be returned for DNSServiceGetAddrInfo and zero length rdata will be returned for DNSServiceQueryRecord.
-    * DNSSEC validation results are for the whole RRSet and not just individual records delivered in the callback. When
-    * kDNSServiceFlagsAdd is not set in the flags, applications should implicitly assume that the DNSSEC status of the 
-    * RRSet that has been delivered up until that point is not valid anymore, till another callback is called with
-    * kDNSServiceFlagsAdd and kDNSServiceFlagsValidate.
-    *
-    * The following four flags indicate the status of the DNSSEC validation and marked in the flags field of the callback.
-    * When any of the four flags is set, kDNSServiceFlagsValidate will also be set. To check the validation status, the 
-    * other applicable output flags should be masked. See kDNSServiceOutputFlags below.
-    */
-
-    kDNSServiceFlagsSecure                 = 0x200010,
-   /*
-    * The response has been validated by verifying all the signaures in the response and was able to
-    * build a successful authentication chain starting from a known trust anchor.   
-    */
-
-    kDNSServiceFlagsInsecure               = 0x200020,
-   /*
-    * A chain of trust cannot be built starting from a known trust anchor to the response.
-    */
-
-    kDNSServiceFlagsBogus                  = 0x200040,
-   /*
-    * If the response cannot be verified to be secure due to expired signatures, missing signatures etc.,
-    * then the results are considered to be bogus.
-    */
-
-    kDNSServiceFlagsIndeterminate          = 0x200080,
-   /*
-    * There is no valid trust anchor that can be used to determine whether a response is secure or not.
-    */
-
-    kDNSServiceFlagsUnicastResponse        = 0x400000,
-   /*
-    * Request unicast response to query.
-    */
-    kDNSServiceFlagsValidateOptional       = 0x800000,
-
-    /*
-     * This flag is identical to kDNSServiceFlagsValidate except for the case where the response
-     * cannot be validated. If this flag is set in DNSServiceQueryRecord or DNSServiceGetAddrInfo,
-     * the DNSSEC records will be requested for validation. If they cannot be received for some reason
-     * during the validation (e.g., zone is not signed, zone is signed but cannot be traced back to
-     * root, recursive server does not understand DNSSEC etc.), then this will fallback to the default
-     * behavior where the validation will not be performed and no DNSSEC results will be provided.
-     *
-     * If the zone is signed and there is a valid path to a known trust anchor configured in the system
-     * and the application requires DNSSEC validation irrespective of the DNSSEC awareness in the current
-     * network, then this option MUST not be used. This is only intended to be used during the transition
-     * period where the different nodes participating in the DNS resolution may not understand DNSSEC or
-     * managed properly (e.g. missing DS record) but still want to be able to resolve DNS successfully.
-     */
-
-    kDNSServiceFlagsWakeOnlyService        = 0x1000000,
-    /*
-     * This flag is meaningful only in DNSServiceRegister. When set, the service will not be registered
-     * with sleep proxy server during sleep.
-     */
-
-    kDNSServiceFlagsThresholdOne           = 0x2000000,
-    kDNSServiceFlagsThresholdFinder        = 0x4000000,
-    kDNSServiceFlagsThresholdReached       = kDNSServiceFlagsThresholdOne,
-    /*
-     * kDNSServiceFlagsThresholdOne is meaningful only in DNSServiceBrowse. When set,
-     * the system will stop issuing browse queries on the network once the number
-     * of answers returned is one or more.  It will issue queries on the network
-     * again if the number of answers drops to zero.
-     * This flag is for Apple internal use only. Third party developers
-     * should not rely on this behavior being supported in any given software release.
-     *
-     * kDNSServiceFlagsThresholdFinder is meaningful only in DNSServiceBrowse. When set,
-     * the system will stop issuing browse queries on the network once the number
-     * of answers has reached the threshold set for Finder.
-     * It will issue queries on the network again if the number of answers drops below
-     * this threshold.
-     * This flag is for Apple internal use only. Third party developers
-     * should not rely on this behavior being supported in any given software release.
-     *
-     * When kDNSServiceFlagsThresholdReached is set in the client callback add or remove event,
-     * it indicates that the browse answer threshold has been reached and no 
-     * browse requests will be generated on the network until the number of answers falls
-     * below the threshold value.  Add and remove events can still occur based
-     * on incoming Bonjour traffic observed by the system.
-     * The set of services return to the client is not guaranteed to represent the 
-     * entire set of services present on the network once the threshold has been reached.
-     *
-     * Note, while kDNSServiceFlagsThresholdReached and kDNSServiceFlagsThresholdOne
-     * have the same value, there  isn't a conflict because kDNSServiceFlagsThresholdReached
-     * is only set in the callbacks and kDNSServiceFlagsThresholdOne is only set on
-     * input to a DNSServiceBrowse call.
-     */
-};
-
-#define kDNSServiceOutputFlags (kDNSServiceFlagsValidate | kDNSServiceFlagsValidateOptional | kDNSServiceFlagsMoreComing | kDNSServiceFlagsAdd | kDNSServiceFlagsDefault)
-   /* All the output flags excluding the DNSSEC Status flags. Typically used to check DNSSEC Status */
-
-/* Possible protocol values */
-enum
-{
-    /* for DNSServiceGetAddrInfo() */
-    kDNSServiceProtocol_IPv4 = 0x01,
-    kDNSServiceProtocol_IPv6 = 0x02,
-    /* 0x04 and 0x08 reserved for future internetwork protocols */
-
-    /* for DNSServiceNATPortMappingCreate() */
-    kDNSServiceProtocol_UDP  = 0x10,
-    kDNSServiceProtocol_TCP  = 0x20
-                               /* 0x40 and 0x80 reserved for future transport protocols, e.g. SCTP [RFC 2960]
-                                * or DCCP [RFC 4340]. If future NAT gateways are created that support port
-                                * mappings for these protocols, new constants will be defined here.
-                                */
-};
-
-/*
- * The values for DNS Classes and Types are listed in RFC 1035, and are available
- * on every OS in its DNS header file. Unfortunately every OS does not have the
- * same header file containing DNS Class and Type constants, and the names of
- * the constants are not consistent. For example, BIND 8 uses "T_A",
- * BIND 9 uses "ns_t_a", Windows uses "DNS_TYPE_A", etc.
- * For this reason, these constants are also listed here, so that code using
- * the DNS-SD programming APIs can use these constants, so that the same code
- * can compile on all our supported platforms.
- */
-
-enum
-{
-    kDNSServiceClass_IN       = 1       /* Internet */
-};
-
-enum
-{
-    kDNSServiceType_A          = 1,      /* Host address. */
-    kDNSServiceType_NS         = 2,      /* Authoritative server. */
-    kDNSServiceType_MD         = 3,      /* Mail destination. */
-    kDNSServiceType_MF         = 4,      /* Mail forwarder. */
-    kDNSServiceType_CNAME      = 5,      /* Canonical name. */
-    kDNSServiceType_SOA        = 6,      /* Start of authority zone. */
-    kDNSServiceType_MB         = 7,      /* Mailbox domain name. */
-    kDNSServiceType_MG         = 8,      /* Mail group member. */
-    kDNSServiceType_MR         = 9,      /* Mail rename name. */
-    kDNSServiceType_NULL       = 10,     /* Null resource record. */
-    kDNSServiceType_WKS        = 11,     /* Well known service. */
-    kDNSServiceType_PTR        = 12,     /* Domain name pointer. */
-    kDNSServiceType_HINFO      = 13,     /* Host information. */
-    kDNSServiceType_MINFO      = 14,     /* Mailbox information. */
-    kDNSServiceType_MX         = 15,     /* Mail routing information. */
-    kDNSServiceType_TXT        = 16,     /* One or more text strings (NOT "zero or more..."). */
-    kDNSServiceType_RP         = 17,     /* Responsible person. */
-    kDNSServiceType_AFSDB      = 18,     /* AFS cell database. */
-    kDNSServiceType_X25        = 19,     /* X_25 calling address. */
-    kDNSServiceType_ISDN       = 20,     /* ISDN calling address. */
-    kDNSServiceType_RT         = 21,     /* Router. */
-    kDNSServiceType_NSAP       = 22,     /* NSAP address. */
-    kDNSServiceType_NSAP_PTR   = 23,     /* Reverse NSAP lookup (deprecated). */
-    kDNSServiceType_SIG        = 24,     /* Security signature. */
-    kDNSServiceType_KEY        = 25,     /* Security key. */
-    kDNSServiceType_PX         = 26,     /* X.400 mail mapping. */
-    kDNSServiceType_GPOS       = 27,     /* Geographical position (withdrawn). */
-    kDNSServiceType_AAAA       = 28,     /* IPv6 Address. */
-    kDNSServiceType_LOC        = 29,     /* Location Information. */
-    kDNSServiceType_NXT        = 30,     /* Next domain (security). */
-    kDNSServiceType_EID        = 31,     /* Endpoint identifier. */
-    kDNSServiceType_NIMLOC     = 32,     /* Nimrod Locator. */
-    kDNSServiceType_SRV        = 33,     /* Server Selection. */
-    kDNSServiceType_ATMA       = 34,     /* ATM Address */
-    kDNSServiceType_NAPTR      = 35,     /* Naming Authority PoinTeR */
-    kDNSServiceType_KX         = 36,     /* Key Exchange */
-    kDNSServiceType_CERT       = 37,     /* Certification record */
-    kDNSServiceType_A6         = 38,     /* IPv6 Address (deprecated) */
-    kDNSServiceType_DNAME      = 39,     /* Non-terminal DNAME (for IPv6) */
-    kDNSServiceType_SINK       = 40,     /* Kitchen sink (experimental) */
-    kDNSServiceType_OPT        = 41,     /* EDNS0 option (meta-RR) */
-    kDNSServiceType_APL        = 42,     /* Address Prefix List */
-    kDNSServiceType_DS         = 43,     /* Delegation Signer */
-    kDNSServiceType_SSHFP      = 44,     /* SSH Key Fingerprint */
-    kDNSServiceType_IPSECKEY   = 45,     /* IPSECKEY */
-    kDNSServiceType_RRSIG      = 46,     /* RRSIG */
-    kDNSServiceType_NSEC       = 47,     /* Denial of Existence */
-    kDNSServiceType_DNSKEY     = 48,     /* DNSKEY */
-    kDNSServiceType_DHCID      = 49,     /* DHCP Client Identifier */
-    kDNSServiceType_NSEC3      = 50,     /* Hashed Authenticated Denial of Existence */
-    kDNSServiceType_NSEC3PARAM = 51,     /* Hashed Authenticated Denial of Existence */
-
-    kDNSServiceType_HIP        = 55,     /* Host Identity Protocol */
-
-    kDNSServiceType_SPF        = 99,     /* Sender Policy Framework for E-Mail */
-    kDNSServiceType_UINFO      = 100,    /* IANA-Reserved */
-    kDNSServiceType_UID        = 101,    /* IANA-Reserved */
-    kDNSServiceType_GID        = 102,    /* IANA-Reserved */
-    kDNSServiceType_UNSPEC     = 103,    /* IANA-Reserved */
-
-    kDNSServiceType_TKEY       = 249,    /* Transaction key */
-    kDNSServiceType_TSIG       = 250,    /* Transaction signature. */
-    kDNSServiceType_IXFR       = 251,    /* Incremental zone transfer. */
-    kDNSServiceType_AXFR       = 252,    /* Transfer zone of authority. */
-    kDNSServiceType_MAILB      = 253,    /* Transfer mailbox records. */
-    kDNSServiceType_MAILA      = 254,    /* Transfer mail agent records. */
-    kDNSServiceType_ANY        = 255     /* Wildcard match. */
-};
-
-/* possible error code values */
-enum
-{
-    kDNSServiceErr_NoError                   = 0,
-    kDNSServiceErr_Unknown                   = -65537,  /* 0xFFFE FFFF */
-    kDNSServiceErr_NoSuchName                = -65538,
-    kDNSServiceErr_NoMemory                  = -65539,
-    kDNSServiceErr_BadParam                  = -65540,
-    kDNSServiceErr_BadReference              = -65541,
-    kDNSServiceErr_BadState                  = -65542,
-    kDNSServiceErr_BadFlags                  = -65543,
-    kDNSServiceErr_Unsupported               = -65544,
-    kDNSServiceErr_NotInitialized            = -65545,
-    kDNSServiceErr_AlreadyRegistered         = -65547,
-    kDNSServiceErr_NameConflict              = -65548,
-    kDNSServiceErr_Invalid                   = -65549,
-    kDNSServiceErr_Firewall                  = -65550,
-    kDNSServiceErr_Incompatible              = -65551,  /* client library incompatible with daemon */
-    kDNSServiceErr_BadInterfaceIndex         = -65552,
-    kDNSServiceErr_Refused                   = -65553,
-    kDNSServiceErr_NoSuchRecord              = -65554,
-    kDNSServiceErr_NoAuth                    = -65555,
-    kDNSServiceErr_NoSuchKey                 = -65556,
-    kDNSServiceErr_NATTraversal              = -65557,
-    kDNSServiceErr_DoubleNAT                 = -65558,
-    kDNSServiceErr_BadTime                   = -65559,  /* Codes up to here existed in Tiger */
-    kDNSServiceErr_BadSig                    = -65560,
-    kDNSServiceErr_BadKey                    = -65561,
-    kDNSServiceErr_Transient                 = -65562,
-    kDNSServiceErr_ServiceNotRunning         = -65563,  /* Background daemon not running */
-    kDNSServiceErr_NATPortMappingUnsupported = -65564,  /* NAT doesn't support PCP, NAT-PMP or UPnP */
-    kDNSServiceErr_NATPortMappingDisabled    = -65565,  /* NAT supports PCP, NAT-PMP or UPnP, but it's disabled by the administrator */
-    kDNSServiceErr_NoRouter                  = -65566,  /* No router currently configured (probably no network connectivity) */
-    kDNSServiceErr_PollingMode               = -65567,
-    kDNSServiceErr_Timeout                   = -65568
-
-                                               /* mDNS Error codes are in the range
-                                                * FFFE FF00 (-65792) to FFFE FFFF (-65537) */
-};
-
-/* Maximum length, in bytes, of a service name represented as a */
-/* literal C-String, including the terminating NULL at the end. */
-
-#define kDNSServiceMaxServiceName 64
-
-/* Maximum length, in bytes, of a domain name represented as an *escaped* C-String */
-/* including the final trailing dot, and the C-String terminating NULL at the end. */
-
-#define kDNSServiceMaxDomainName 1009
-
-/*
- * Notes on DNS Name Escaping
- *   -- or --
- * "Why is kDNSServiceMaxDomainName 1009, when the maximum legal domain name is 256 bytes?"
- *
- * All strings used in the DNS-SD APIs are UTF-8 strings. Apart from the exceptions noted below,
- * the APIs expect the strings to be properly escaped, using the conventional DNS escaping rules:
- *
- *   '\\' represents a single literal '\' in the name
- *   '\.' represents a single literal '.' in the name
- *   '\ddd', where ddd is a three-digit decimal value from 000 to 255,
- *        represents a single literal byte with that value.
- *   A bare unescaped '.' is a label separator, marking a boundary between domain and subdomain.
- *
- * The exceptions, that do not use escaping, are the routines where the full
- * DNS name of a resource is broken, for convenience, into servicename/regtype/domain.
- * In these routines, the "servicename" is NOT escaped. It does not need to be, since
- * it is, by definition, just a single literal string. Any characters in that string
- * represent exactly what they are. The "regtype" portion is, technically speaking,
- * escaped, but since legal regtypes are only allowed to contain letters, digits,
- * and hyphens, there is nothing to escape, so the issue is moot. The "domain"
- * portion is also escaped, though most domains in use on the public Internet
- * today, like regtypes, don't contain any characters that need to be escaped.
- * As DNS-SD becomes more popular, rich-text domains for service discovery will
- * become common, so software should be written to cope with domains with escaping.
- *
- * The servicename may be up to 63 bytes of UTF-8 text (not counting the C-String
- * terminating NULL at the end). The regtype is of the form _service._tcp or
- * _service._udp, where the "service" part is 1-15 characters, which may be
- * letters, digits, or hyphens. The domain part of the three-part name may be
- * any legal domain, providing that the resulting servicename+regtype+domain
- * name does not exceed 256 bytes.
- *
- * For most software, these issues are transparent. When browsing, the discovered
- * servicenames should simply be displayed as-is. When resolving, the discovered
- * servicename/regtype/domain are simply passed unchanged to DNSServiceResolve().
- * When a DNSServiceResolve() succeeds, the returned fullname is already in
- * the correct format to pass to standard system DNS APIs such as res_query().
- * For converting from servicename/regtype/domain to a single properly-escaped
- * full DNS name, the helper function DNSServiceConstructFullName() is provided.
- *
- * The following (highly contrived) example illustrates the escaping process.
- * Suppose you have an service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp"
- * in subdomain "4th. Floor" of subdomain "Building 2" of domain "apple.com."
- * The full (escaped) DNS name of this service's SRV record would be:
- * Dr\.\032Smith\\Dr\.\032Johnson._ftp._tcp.4th\.\032Floor.Building\0322.apple.com.
- */
-
-
-/*
- * Constants for specifying an interface index
- *
- * Specific interface indexes are identified via a 32-bit unsigned integer returned
- * by the if_nametoindex() family of calls.
- *
- * If the client passes 0 for interface index, that means "do the right thing",
- * which (at present) means, "if the name is in an mDNS local multicast domain
- * (e.g. 'local.', '254.169.in-addr.arpa.', '{8,9,A,B}.E.F.ip6.arpa.') then multicast
- * on all applicable interfaces, otherwise send via unicast to the appropriate
- * DNS server." Normally, most clients will use 0 for interface index to
- * automatically get the default sensible behaviour.
- *
- * If the client passes a positive interface index, then for multicast names that
- * indicates to do the operation only on that one interface. For unicast names the
- * interface index is ignored unless kDNSServiceFlagsForceMulticast is also set.
- *
- * If the client passes kDNSServiceInterfaceIndexLocalOnly when registering
- * a service, then that service will be found *only* by other local clients
- * on the same machine that are browsing using kDNSServiceInterfaceIndexLocalOnly
- * or kDNSServiceInterfaceIndexAny.
- * If a client has a 'private' service, accessible only to other processes
- * running on the same machine, this allows the client to advertise that service
- * in a way such that it does not inadvertently appear in service lists on
- * all the other machines on the network.
- *
- * If the client passes kDNSServiceInterfaceIndexLocalOnly when browsing
- * then it will find *all* records registered on that same local machine.
- * Clients explicitly wishing to discover *only* LocalOnly services can
- * accomplish this by inspecting the interfaceIndex of each service reported
- * to their DNSServiceBrowseReply() callback function, and discarding those
- * where the interface index is not kDNSServiceInterfaceIndexLocalOnly.
- *
- * kDNSServiceInterfaceIndexP2P is meaningful only in Browse, QueryRecord, Register,
- * and Resolve operations. It should not be used in other DNSService APIs.
- *
- * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceBrowse or
- *   DNSServiceQueryRecord, it restricts the operation to P2P.
- *
- * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceRegister, it is
- *   mapped internally to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P
- *   set.
- *
- * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceResolve, it is
- *   mapped internally to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P
- *   set, because resolving a P2P service may create and/or enable an interface whose 
- *   index is not known a priori. The resolve callback will indicate the index of the
- *   interface via which the service can be accessed.
- *
- * If applications pass kDNSServiceInterfaceIndexAny to DNSServiceBrowse
- * or DNSServiceQueryRecord, they must set the kDNSServiceFlagsIncludeP2P flag
- * to include P2P. In this case, if a service instance or the record being queried
- * is found over P2P, the resulting ADD event will indicate kDNSServiceInterfaceIndexP2P
- * as the interface index.
- */
-
-#define kDNSServiceInterfaceIndexAny 0
-#define kDNSServiceInterfaceIndexLocalOnly ((uint32_t)-1)
-#define kDNSServiceInterfaceIndexUnicast   ((uint32_t)-2)
-#define kDNSServiceInterfaceIndexP2P       ((uint32_t)-3)
-
-typedef uint32_t DNSServiceFlags;
-typedef uint32_t DNSServiceProtocol;
-typedef int32_t DNSServiceErrorType;
-
-
-/*********************************************************************************************
-*
-* Version checking
-*
-*********************************************************************************************/
-
-/* DNSServiceGetProperty() Parameters:
- *
- * property:        The requested property.
- *                  Currently the only property defined is kDNSServiceProperty_DaemonVersion.
- *
- * result:          Place to store result.
- *                  For retrieving DaemonVersion, this should be the address of a uint32_t.
- *
- * size:            Pointer to uint32_t containing size of the result location.
- *                  For retrieving DaemonVersion, this should be sizeof(uint32_t).
- *                  On return the uint32_t is updated to the size of the data returned.
- *                  For DaemonVersion, the returned size is always sizeof(uint32_t), but
- *                  future properties could be defined which return variable-sized results.
- *
- * return value:    Returns kDNSServiceErr_NoError on success, or kDNSServiceErr_ServiceNotRunning
- *                  if the daemon (or "system service" on Windows) is not running.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceGetProperty
-(
-    const char *property,  /* Requested property (i.e. kDNSServiceProperty_DaemonVersion) */
-    void       *result,    /* Pointer to place to store result */
-    uint32_t   *size       /* size of result location */
-);
-
-/*
- * When requesting kDNSServiceProperty_DaemonVersion, the result pointer must point
- * to a 32-bit unsigned integer, and the size parameter must be set to sizeof(uint32_t).
- *
- * On return, the 32-bit unsigned integer contains the version number, formatted as follows:
- *   Major part of the build number * 10000 +
- *   minor part of the build number *   100
- *
- * For example, Mac OS X 10.4.9 has mDNSResponder-108.4, which would be represented as
- * version 1080400. This allows applications to do simple greater-than and less-than comparisons:
- * e.g. an application that requires at least mDNSResponder-108.4 can check:
- *
- *   if (version >= 1080400) ...
- *
- * Example usage:
- *
- * uint32_t version;
- * uint32_t size = sizeof(version);
- * DNSServiceErrorType err = DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &version, &size);
- * if (!err) printf("Bonjour version is %d.%d\n", version / 10000, version / 100 % 100);
- */
-
-#define kDNSServiceProperty_DaemonVersion "DaemonVersion"
-
-
-// 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
- *                  mDNSResponder to send the DNS query on the wire.
- *
- * pid:             Process ID of the application that started the name resolution which triggered
- *                  mDNSResponder 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
-);
-
-/*********************************************************************************************
-*
-* Unix Domain Socket access, DNSServiceRef deallocation, and data processing functions
-*
-*********************************************************************************************/
-
-/* DNSServiceRefSockFD()
- *
- * Access underlying Unix domain socket for an initialized DNSServiceRef.
- * The DNS Service Discovery implementation uses this socket to communicate between the client and
- * the mDNSResponder daemon. The application MUST NOT directly read from or write to this socket.
- * Access to the socket is provided so that it can be used as a kqueue event source, a CFRunLoop
- * event source, in a select() loop, etc. When the underlying event management subsystem (kqueue/
- * select/CFRunLoop etc.) indicates to the client that data is available for reading on the
- * socket, the client should call DNSServiceProcessResult(), which will extract the daemon's
- * reply from the socket, and pass it to the appropriate application callback. By using a run
- * loop or select(), results from the daemon can be processed asynchronously. Alternatively,
- * a client can choose to fork a thread and have it loop calling "DNSServiceProcessResult(ref);"
- * If DNSServiceProcessResult() is called when no data is available for reading on the socket, it
- * will block until data does become available, and then process the data and return to the caller.
- * When data arrives on the socket, the client is responsible for calling DNSServiceProcessResult(ref)
- * in a timely fashion -- if the client allows a large backlog of data to build up the daemon
- * may terminate the connection.
- *
- * sdRef:           A DNSServiceRef initialized by any of the DNSService calls.
- *
- * return value:    The DNSServiceRef's underlying socket descriptor, or -1 on
- *                  error.
- */
-
-int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef);
-
-
-/* DNSServiceProcessResult()
- *
- * Read a reply from the daemon, calling the appropriate application callback. This call will
- * block until the daemon's response is received. Use DNSServiceRefSockFD() in
- * conjunction with a run loop or select() to determine the presence of a response from the
- * server before calling this function to process the reply without blocking. Call this function
- * at any point if it is acceptable to block until the daemon's response arrives. Note that the
- * client is responsible for ensuring that DNSServiceProcessResult() is called whenever there is
- * a reply from the daemon - the daemon may terminate its connection with a client that does not
- * process the daemon's responses.
- *
- * sdRef:           A DNSServiceRef initialized by any of the DNSService calls
- *                  that take a callback parameter.
- *
- * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns
- *                  an error code indicating the specific failure that occurred.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef);
-
-
-/* DNSServiceRefDeallocate()
- *
- * Terminate a connection with the daemon and free memory associated with the DNSServiceRef.
- * Any services or records registered with this DNSServiceRef will be deregistered. Any
- * Browse, Resolve, or Query operations called with this reference will be terminated.
- *
- * Note: If the reference's underlying socket is used in a run loop or select() call, it should
- * be removed BEFORE DNSServiceRefDeallocate() is called, as this function closes the reference's
- * socket.
- *
- * Note: If the reference was initialized with DNSServiceCreateConnection(), any DNSRecordRefs
- * created via this reference will be invalidated by this call - the resource records are
- * deregistered, and their DNSRecordRefs may not be used in subsequent functions. Similarly,
- * if the reference was initialized with DNSServiceRegister, and an extra resource record was
- * added to the service via DNSServiceAddRecord(), the DNSRecordRef created by the Add() call
- * is invalidated when this function is called - the DNSRecordRef may not be used in subsequent
- * functions.
- *
- * Note: This call is to be used only with the DNSServiceRef defined by this API.
- *
- * sdRef:           A DNSServiceRef initialized by any of the DNSService calls.
- *
- */
-
-void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef);
-
-
-/*********************************************************************************************
-*
-* Domain Enumeration
-*
-*********************************************************************************************/
-
-/* DNSServiceEnumerateDomains()
- *
- * Asynchronously enumerate domains available for browsing and registration.
- *
- * The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains
- * are to be found.
- *
- * Note that the names returned are (like all of DNS-SD) UTF-8 strings,
- * and are escaped using standard DNS escaping rules.
- * (See "Notes on DNS Name Escaping" earlier in this file for more details.)
- * A graphical browser displaying a hierarchical tree-structured view should cut
- * the names at the bare dots to yield individual labels, then de-escape each
- * label according to the escaping rules, and then display the resulting UTF-8 text.
- *
- * DNSServiceDomainEnumReply Callback Parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceEnumerateDomains().
- *
- * flags:           Possible values are:
- *                  kDNSServiceFlagsMoreComing
- *                  kDNSServiceFlagsAdd
- *                  kDNSServiceFlagsDefault
- *
- * interfaceIndex:  Specifies the interface on which the domain exists. (The index for a given
- *                  interface is determined via the if_nametoindex() family of calls.)
- *
- * errorCode:       Will be kDNSServiceErr_NoError (0) on success, otherwise indicates
- *                  the failure that occurred (other parameters are undefined if errorCode is nonzero).
- *
- * replyDomain:     The name of the domain.
- *
- * context:         The context pointer passed to DNSServiceEnumerateDomains.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceDomainEnumReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceErrorType errorCode,
-    const char                          *replyDomain,
-    void                                *context
-);
-
-
-/* DNSServiceEnumerateDomains() Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
- *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
- *                  and the enumeration operation will run indefinitely until the client
- *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * flags:           Possible values are:
- *                  kDNSServiceFlagsBrowseDomains to enumerate domains recommended for browsing.
- *                  kDNSServiceFlagsRegistrationDomains to enumerate domains recommended
- *                  for registration.
- *
- * interfaceIndex:  If non-zero, specifies the interface on which to look for domains.
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Most applications will pass 0 to enumerate domains on
- *                  all interfaces. See "Constants for specifying an interface index" for more details.
- *
- * callBack:        The function to be called when a domain is found or the call asynchronously
- *                  fails.
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is not invoked and the DNSServiceRef
- *                  is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceDomainEnumReply callBack,
-    void                                *context  /* may be NULL */
-);
-
-
-/*********************************************************************************************
-*
-*  Service Registration
-*
-*********************************************************************************************/
-
-/* Register a service that is discovered via Browse() and Resolve() calls.
- *
- * DNSServiceRegisterReply() Callback Parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceRegister().
- *
- * flags:           When a name is successfully registered, the callback will be
- *                  invoked with the kDNSServiceFlagsAdd flag set. When Wide-Area
- *                  DNS-SD is in use, it is possible for a single service to get
- *                  more than one success callback (e.g. one in the "local" multicast
- *                  DNS domain, and another in a wide-area unicast DNS domain).
- *                  If a successfully-registered name later suffers a name conflict
- *                  or similar problem and has to be deregistered, the callback will
- *                  be invoked with the kDNSServiceFlagsAdd flag not set. The callback
- *                  is *not* invoked in the case where the caller explicitly terminates
- *                  the service registration by calling DNSServiceRefDeallocate(ref);
- *
- * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
- *                  indicate the failure that occurred (including name conflicts,
- *                  if the kDNSServiceFlagsNoAutoRename flag was used when registering.)
- *                  Other parameters are undefined if errorCode is nonzero.
- *
- * name:            The service name registered (if the application did not specify a name in
- *                  DNSServiceRegister(), this indicates what name was automatically chosen).
- *
- * regtype:         The type of service registered, as it was passed to the callout.
- *
- * domain:          The domain on which the service was registered (if the application did not
- *                  specify a domain in DNSServiceRegister(), this indicates the default domain
- *                  on which the service was registered).
- *
- * context:         The context pointer that was passed to the callout.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceRegisterReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    DNSServiceErrorType errorCode,
-    const char                          *name,
-    const char                          *regtype,
-    const char                          *domain,
-    void                                *context
-);
-
-
-/* DNSServiceRegister() Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
- *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
- *                  and the registration will remain active indefinitely until the client
- *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * interfaceIndex:  If non-zero, specifies the interface on which to register the service
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Most applications will pass 0 to register on all
- *                  available interfaces. See "Constants for specifying an interface index" for more details.
- *
- * flags:           Indicates the renaming behavior on name conflict (most applications
- *                  will pass 0). See flag definitions above for details.
- *
- * name:            If non-NULL, specifies the service name to be registered.
- *                  Most applications will not specify a name, in which case the computer
- *                  name is used (this name is communicated to the client via the callback).
- *                  If a name is specified, it must be 1-63 bytes of UTF-8 text.
- *                  If the name is longer than 63 bytes it will be automatically truncated
- *                  to a legal length, unless the NoAutoRename flag is set,
- *                  in which case kDNSServiceErr_BadParam will be returned.
- *
- * regtype:         The service type followed by the protocol, separated by a dot
- *                  (e.g. "_ftp._tcp"). The service type must be an underscore, followed
- *                  by 1-15 characters, which may be letters, digits, or hyphens.
- *                  The transport protocol must be "_tcp" or "_udp". New service types
- *                  should be registered at <http://www.dns-sd.org/ServiceTypes.html>.
- *
- *                  Additional subtypes of the primary service type (where a service
- *                  type has defined subtypes) follow the primary service type in a
- *                  comma-separated list, with no additional spaces, e.g.
- *                      "_primarytype._tcp,_subtype1,_subtype2,_subtype3"
- *                  Subtypes provide a mechanism for filtered browsing: A client browsing
- *                  for "_primarytype._tcp" will discover all instances of this type;
- *                  a client browsing for "_primarytype._tcp,_subtype2" will discover only
- *                  those instances that were registered with "_subtype2" in their list of
- *                  registered subtypes.
- *
- *                  The subtype mechanism can be illustrated with some examples using the
- *                  dns-sd command-line tool:
- *
- *                  % dns-sd -R Simple _test._tcp "" 1001 &
- *                  % dns-sd -R Better _test._tcp,HasFeatureA "" 1002 &
- *                  % dns-sd -R Best   _test._tcp,HasFeatureA,HasFeatureB "" 1003 &
- *
- *                  Now:
- *                  % dns-sd -B _test._tcp             # will find all three services
- *                  % dns-sd -B _test._tcp,HasFeatureA # finds "Better" and "Best"
- *                  % dns-sd -B _test._tcp,HasFeatureB # finds only "Best"
- *
- *                  Subtype labels may be up to 63 bytes long, and may contain any eight-
- *                  bit byte values, including zero bytes. However, due to the nature of
- *                  using a C-string-based API, conventional DNS escaping must be used for
- *                  dots ('.'), commas (','), backslashes ('\') and zero bytes, as shown below:
- *
- *                  % dns-sd -R Test '_test._tcp,s\.one,s\,two,s\\three,s\000four' local 123
- *
- *                  When a service is registered, all the clients browsing for the registered
- *                  type ("regtype") will discover it. If the discovery should be
- *                  restricted to a smaller set of well known peers, the service can be
- *                  registered with additional data (group identifier) that is known
- *                  only to a smaller set of peers. The group identifier should follow primary
- *                  service type using a colon (":") as a delimeter. If subtypes are also present,
- *                  it should be given before the subtype as shown below.
- *
- *                  % dns-sd -R _test1 _http._tcp:mygroup1 local 1001 
- *                  % dns-sd -R _test2 _http._tcp:mygroup2 local 1001 
- *                  % dns-sd -R _test3 _http._tcp:mygroup3,HasFeatureA local 1001 
- *
- *                  Now:
- *                  % dns-sd -B _http._tcp:"mygroup1"                # will discover only test1
- *                  % dns-sd -B _http._tcp:"mygroup2"                # will discover only test2
- *                  % dns-sd -B _http._tcp:"mygroup3",HasFeatureA    # will discover only test3
- *                  
- *                  By specifying the group information, only the members of that group are
- *                  discovered.
- *
- *                  The group identifier itself is not sent in clear. Only a hash of the group
- *                  identifier is sent and the clients discover them anonymously. The group identifier
- *                  may be up to 256 bytes long and may contain any eight bit values except comma which
- *                  should be escaped.
- *
- * domain:          If non-NULL, specifies the domain on which to advertise the service.
- *                  Most applications will not specify a domain, instead automatically
- *                  registering in the default domain(s).
- *
- * host:            If non-NULL, specifies the SRV target host name. Most applications
- *                  will not specify a host, instead automatically using the machine's
- *                  default host name(s). Note that specifying a non-NULL host does NOT
- *                  create an address record for that host - the application is responsible
- *                  for ensuring that the appropriate address record exists, or creating it
- *                  via DNSServiceRegisterRecord().
- *
- * port:            The port, in network byte order, on which the service accepts connections.
- *                  Pass 0 for a "placeholder" service (i.e. a service that will not be discovered
- *                  by browsing, but will cause a name conflict if another client tries to
- *                  register that same name). Most clients will not use placeholder services.
- *
- * txtLen:          The length of the txtRecord, in bytes. Must be zero if the txtRecord is NULL.
- *
- * txtRecord:       The TXT record rdata. A non-NULL txtRecord MUST be a properly formatted DNS
- *                  TXT record, i.e. <length byte> <data> <length byte> <data> ...
- *                  Passing NULL for the txtRecord is allowed as a synonym for txtLen=1, txtRecord="",
- *                  i.e. it creates a TXT record of length one containing a single empty string.
- *                  RFC 1035 doesn't allow a TXT record to contain *zero* strings, so a single empty
- *                  string is the smallest legal DNS TXT record.
- *                  As with the other parameters, the DNSServiceRegister call copies the txtRecord
- *                  data; e.g. if you allocated the storage for the txtRecord parameter with malloc()
- *                  then you can safely free that memory right after the DNSServiceRegister call returns.
- *
- * callBack:        The function to be called when the registration completes or asynchronously
- *                  fails. The client MAY pass NULL for the callback -  The client will NOT be notified
- *                  of the default values picked on its behalf, and the client will NOT be notified of any
- *                  asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration
- *                  of the service. The client may NOT pass the NoAutoRename flag if the callback is NULL.
- *                  The client may still deregister the service at any time via DNSServiceRefDeallocate().
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSServiceRef
- *                  is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceRegister
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                          *name,         /* may be NULL */
-    const char                          *regtype,
-    const char                          *domain,       /* may be NULL */
-    const char                          *host,         /* may be NULL */
-    uint16_t port,                                     /* In network byte order */
-    uint16_t txtLen,
-    const void                          *txtRecord,    /* may be NULL */
-    DNSServiceRegisterReply callBack,                  /* may be NULL */
-    void                                *context       /* may be NULL */
-);
-
-
-/* DNSServiceAddRecord()
- *
- * Add a record to a registered service. The name of the record will be the same as the
- * registered service's name.
- * The record can later be updated or deregistered by passing the RecordRef initialized
- * by this function to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
- *
- * Note that the DNSServiceAddRecord/UpdateRecord/RemoveRecord are *NOT* thread-safe
- * with respect to a single DNSServiceRef. If you plan to have multiple threads
- * in your program simultaneously add, update, or remove records from the same
- * DNSServiceRef, then it's the caller's responsibility to use a mutext lock
- * or take similar appropriate precautions to serialize those calls.
- *
- * Parameters;
- *
- * sdRef:           A DNSServiceRef initialized by DNSServiceRegister().
- *
- * RecordRef:       A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this
- *                  call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
- *                  If the above DNSServiceRef is passed to DNSServiceRefDeallocate(), RecordRef is also
- *                  invalidated and may not be used further.
- *
- * flags:           Currently ignored, reserved for future use.
- *
- * rrtype:          The type of the record (e.g. kDNSServiceType_TXT, kDNSServiceType_SRV, etc)
- *
- * rdlen:           The length, in bytes, of the rdata.
- *
- * rdata:           The raw rdata to be contained in the added resource record.
- *
- * ttl:             The time to live of the resource record, in seconds.
- *                  Most clients should pass 0 to indicate that the system should
- *                  select a sensible default value.
- *
- * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns an
- *                  error code indicating the error that occurred (the RecordRef is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceAddRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef                        *RecordRef,
-    DNSServiceFlags flags,
-    uint16_t rrtype,
-    uint16_t rdlen,
-    const void                          *rdata,
-    uint32_t ttl
-);
-
-
-/* DNSServiceUpdateRecord
- *
- * Update a registered resource record. The record must either be:
- *   - The primary txt record of a service registered via DNSServiceRegister()
- *   - A record added to a registered service via DNSServiceAddRecord()
- *   - An individual record registered by DNSServiceRegisterRecord()
- *
- * Parameters:
- *
- * sdRef:           A DNSServiceRef that was initialized by DNSServiceRegister()
- *                  or DNSServiceCreateConnection().
- *
- * RecordRef:       A DNSRecordRef initialized by DNSServiceAddRecord, or NULL to update the
- *                  service's primary txt record.
- *
- * flags:           Currently ignored, reserved for future use.
- *
- * rdlen:           The length, in bytes, of the new rdata.
- *
- * rdata:           The new rdata to be contained in the updated resource record.
- *
- * ttl:             The time to live of the updated resource record, in seconds.
- *                  Most clients should pass 0 to indicate that the system should
- *                  select a sensible default value.
- *
- * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns an
- *                  error code indicating the error that occurred.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef RecordRef,                            /* may be NULL */
-    DNSServiceFlags flags,
-    uint16_t rdlen,
-    const void                          *rdata,
-    uint32_t ttl
-);
-
-
-/* DNSServiceRemoveRecord
- *
- * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister
- * an record registered individually via DNSServiceRegisterRecord().
- *
- * Parameters:
- *
- * sdRef:           A DNSServiceRef initialized by DNSServiceRegister() (if the
- *                  record being removed was registered via DNSServiceAddRecord()) or by
- *                  DNSServiceCreateConnection() (if the record being removed was registered via
- *                  DNSServiceRegisterRecord()).
- *
- * recordRef:       A DNSRecordRef initialized by a successful call to DNSServiceAddRecord()
- *                  or DNSServiceRegisterRecord().
- *
- * flags:           Currently ignored, reserved for future use.
- *
- * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns an
- *                  error code indicating the error that occurred.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef RecordRef,
-    DNSServiceFlags flags
-);
-
-
-/*********************************************************************************************
-*
-*  Service Discovery
-*
-*********************************************************************************************/
-
-/* Browse for instances of a service.
- *
- * DNSServiceBrowseReply() Parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceBrowse().
- *
- * flags:           Possible values are kDNSServiceFlagsMoreComing and kDNSServiceFlagsAdd.
- *                  See flag definitions for details.
- *
- * interfaceIndex:  The interface on which the service is advertised. This index should
- *                  be passed to DNSServiceResolve() when resolving the service.
- *
- * errorCode:       Will be kDNSServiceErr_NoError (0) on success, otherwise will
- *                  indicate the failure that occurred. Other parameters are undefined if
- *                  the errorCode is nonzero.
- *
- * serviceName:     The discovered service name. This name should be displayed to the user,
- *                  and stored for subsequent use in the DNSServiceResolve() call.
- *
- * regtype:         The service type, which is usually (but not always) the same as was passed
- *                  to DNSServiceBrowse(). One case where the discovered service type may
- *                  not be the same as the requested service type is when using subtypes:
- *                  The client may want to browse for only those ftp servers that allow
- *                  anonymous connections. The client will pass the string "_ftp._tcp,_anon"
- *                  to DNSServiceBrowse(), but the type of the service that's discovered
- *                  is simply "_ftp._tcp". The regtype for each discovered service instance
- *                  should be stored along with the name, so that it can be passed to
- *                  DNSServiceResolve() when the service is later resolved.
- *
- * domain:          The domain of the discovered service instance. This may or may not be the
- *                  same as the domain that was passed to DNSServiceBrowse(). The domain for each
- *                  discovered service instance should be stored along with the name, so that
- *                  it can be passed to DNSServiceResolve() when the service is later resolved.
- *
- * context:         The context pointer that was passed to the callout.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceBrowseReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceErrorType errorCode,
-    const char                          *serviceName,
-    const char                          *regtype,
-    const char                          *replyDomain,
-    void                                *context
-);
-
-
-/* DNSServiceBrowse() Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
- *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
- *                  and the browse operation will run indefinitely until the client
- *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * flags:           Currently ignored, reserved for future use.
- *
- * interfaceIndex:  If non-zero, specifies the interface on which to browse for services
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Most applications will pass 0 to browse on all available
- *                  interfaces. See "Constants for specifying an interface index" for more details.
- *
- * regtype:         The service type being browsed for followed by the protocol, separated by a
- *                  dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
- *                  A client may optionally specify a single subtype to perform filtered browsing:
- *                  e.g. browsing for "_primarytype._tcp,_subtype" will discover only those
- *                  instances of "_primarytype._tcp" that were registered specifying "_subtype"
- *                  in their list of registered subtypes. Additionally, a group identifier may
- *                  also be specified before the subtype e.g., _primarytype._tcp:GroupID, which
- *                  will discover only the members that register the service with GroupID. See
- *                  DNSServiceRegister for more details.
- *
- * domain:          If non-NULL, specifies the domain on which to browse for services.
- *                  Most applications will not specify a domain, instead browsing on the
- *                  default domain(s).
- *
- * callBack:        The function to be called when an instance of the service being browsed for
- *                  is found, or if the call asynchronously fails.
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is not invoked and the DNSServiceRef
- *                  is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceBrowse
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                          *regtype,
-    const char                          *domain,    /* may be NULL */
-    DNSServiceBrowseReply callBack,
-    void                                *context    /* may be NULL */
-);
-
-
-/* DNSServiceResolve()
- *
- * Resolve a service name discovered via DNSServiceBrowse() to a target host name, port number, and
- * txt record.
- *
- * Note: Applications should NOT use DNSServiceResolve() solely for txt record monitoring - use
- * DNSServiceQueryRecord() instead, as it is more efficient for this task.
- *
- * Note: When the desired results have been returned, the client MUST terminate the resolve by calling
- * DNSServiceRefDeallocate().
- *
- * Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record
- * and a single TXT record. To resolve non-standard services with multiple SRV or TXT records,
- * DNSServiceQueryRecord() should be used.
- *
- * DNSServiceResolveReply Callback Parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceResolve().
- *
- * flags:           Possible values: kDNSServiceFlagsMoreComing
- *
- * interfaceIndex:  The interface on which the service was resolved.
- *
- * errorCode:       Will be kDNSServiceErr_NoError (0) on success, otherwise will
- *                  indicate the failure that occurred. Other parameters are undefined if
- *                  the errorCode is nonzero.
- *
- * fullname:        The full service domain name, in the form <servicename>.<protocol>.<domain>.
- *                  (This name is escaped following standard DNS rules, making it suitable for
- *                  passing to standard system DNS APIs such as res_query(), or to the
- *                  special-purpose functions included in this API that take fullname parameters.
- *                  See "Notes on DNS Name Escaping" earlier in this file for more details.)
- *
- * hosttarget:      The target hostname of the machine providing the service. This name can
- *                  be passed to functions like gethostbyname() to identify the host's IP address.
- *
- * port:            The port, in network byte order, on which connections are accepted for this service.
- *
- * txtLen:          The length of the txt record, in bytes.
- *
- * txtRecord:       The service's primary txt record, in standard txt record format.
- *
- * context:         The context pointer that was passed to the callout.
- *
- * NOTE: In earlier versions of this header file, the txtRecord parameter was declared "const char *"
- * This is incorrect, since it contains length bytes which are values in the range 0 to 255, not -128 to +127.
- * Depending on your compiler settings, this change may cause signed/unsigned mismatch warnings.
- * These should be fixed by updating your own callback function definition to match the corrected
- * function signature using "const unsigned char *txtRecord". Making this change may also fix inadvertent
- * bugs in your callback function, where it could have incorrectly interpreted a length byte with value 250
- * as being -6 instead, with various bad consequences ranging from incorrect operation to software crashes.
- * If you need to maintain portable code that will compile cleanly with both the old and new versions of
- * this header file, you should update your callback function definition to use the correct unsigned value,
- * and then in the place where you pass your callback function to DNSServiceResolve(), use a cast to eliminate
- * the compiler warning, e.g.:
- *   DNSServiceResolve(sd, flags, index, name, regtype, domain, (DNSServiceResolveReply)MyCallback, context);
- * This will ensure that your code compiles cleanly without warnings (and more importantly, works correctly)
- * with both the old header and with the new corrected version.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceResolveReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceErrorType errorCode,
-    const char                          *fullname,
-    const char                          *hosttarget,
-    uint16_t port,                                   /* In network byte order */
-    uint16_t txtLen,
-    const unsigned char                 *txtRecord,
-    void                                *context
-);
-
-
-/* DNSServiceResolve() Parameters
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
- *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
- *                  and the resolve operation will run indefinitely until the client
- *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * flags:           Specifying kDNSServiceFlagsForceMulticast will cause query to be
- *                  performed with a link-local mDNS query, even if the name is an
- *                  apparently non-local name (i.e. a name not ending in ".local.")
- *
- * interfaceIndex:  The interface on which to resolve the service. If this resolve call is
- *                  as a result of a currently active DNSServiceBrowse() operation, then the
- *                  interfaceIndex should be the index reported in the DNSServiceBrowseReply
- *                  callback. If this resolve call is using information previously saved
- *                  (e.g. in a preference file) for later use, then use interfaceIndex 0, because
- *                  the desired service may now be reachable via a different physical interface.
- *                  See "Constants for specifying an interface index" for more details.
- *
- * name:            The name of the service instance to be resolved, as reported to the
- *                  DNSServiceBrowseReply() callback.
- *
- * regtype:         The type of the service instance to be resolved, as reported to the
- *                  DNSServiceBrowseReply() callback.
- *
- * domain:          The domain of the service instance to be resolved, as reported to the
- *                  DNSServiceBrowseReply() callback.
- *
- * callBack:        The function to be called when a result is found, or if the call
- *                  asynchronously fails.
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSServiceRef
- *                  is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceResolve
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                          *name,
-    const char                          *regtype,
-    const char                          *domain,
-    DNSServiceResolveReply callBack,
-    void                                *context  /* may be NULL */
-);
-
-
-/*********************************************************************************************
-*
-*  Querying Individual Specific Records
-*
-*********************************************************************************************/
-
-/* DNSServiceQueryRecord
- *
- * Query for an arbitrary DNS record.
- *
- * DNSServiceQueryRecordReply() Callback Parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceQueryRecord().
- *
- * flags:           Possible values are kDNSServiceFlagsMoreComing and
- *                  kDNSServiceFlagsAdd. The Add flag is NOT set for PTR records
- *                  with a ttl of 0, i.e. "Remove" events.
- *
- * interfaceIndex:  The interface on which the query was resolved (the index for a given
- *                  interface is determined via the if_nametoindex() family of calls).
- *                  See "Constants for specifying an interface index" for more details.
- *
- * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
- *                  indicate the failure that occurred. Other parameters are undefined if
- *                  errorCode is nonzero.
- *
- * fullname:        The resource record's full domain name.
- *
- * rrtype:          The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- * rrclass:         The class of the resource record (usually kDNSServiceClass_IN).
- *
- * rdlen:           The length, in bytes, of the resource record rdata.
- *
- * rdata:           The raw rdata of the resource record.
- *
- * ttl:             If the client wishes to cache the result for performance reasons,
- *                  the TTL indicates how long the client may legitimately hold onto
- *                  this result, in seconds. After the TTL expires, the client should
- *                  consider the result no longer valid, and if it requires this data
- *                  again, it should be re-fetched with a new query. Of course, this
- *                  only applies to clients that cancel the asynchronous operation when
- *                  they get a result. Clients that leave the asynchronous operation
- *                  running can safely assume that the data remains valid until they
- *                  get another callback telling them otherwise.
- *
- * context:         The context pointer that was passed to the callout.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceQueryRecordReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceErrorType errorCode,
-    const char                          *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void                          *rdata,
-    uint32_t ttl,
-    void                                *context
-);
-
-
-/* DNSServiceQueryRecord() Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
- *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
- *                  and the query operation will run indefinitely until the client
- *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * flags:           kDNSServiceFlagsForceMulticast or kDNSServiceFlagsLongLivedQuery.
- *                  Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast
- *                  query to a unicast DNS server that implements the protocol. This flag
- *                  has no effect on link-local multicast queries.
- *
- * interfaceIndex:  If non-zero, specifies the interface on which to issue the query
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Passing 0 causes the name to be queried for on all
- *                  interfaces. See "Constants for specifying an interface index" for more details.
- *
- * fullname:        The full domain name of the resource record to be queried for.
- *
- * rrtype:          The numerical type of the resource record to be queried for
- *                  (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- * rrclass:         The class of the resource record (usually kDNSServiceClass_IN).
- *
- * callBack:        The function to be called when a result is found, or if the call
- *                  asynchronously fails.
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSServiceRef
- *                  is not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                          *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    DNSServiceQueryRecordReply callBack,
-    void                                *context  /* may be NULL */
-);
-
-
-/*********************************************************************************************
-*
-*  Unified lookup of both IPv4 and IPv6 addresses for a fully qualified hostname
-*
-*********************************************************************************************/
-
-/* DNSServiceGetAddrInfo
- *
- * Queries for the IP address of a hostname by using either Multicast or Unicast DNS.
- *
- * DNSServiceGetAddrInfoReply() parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceGetAddrInfo().
- *
- * flags:           Possible values are kDNSServiceFlagsMoreComing and
- *                  kDNSServiceFlagsAdd.
- *
- * interfaceIndex:  The interface to which the answers pertain.
- *
- * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
- *                  indicate the failure that occurred.  Other parameters are
- *                  undefined if errorCode is nonzero.
- *
- * hostname:        The fully qualified domain name of the host to be queried for.
- *
- * address:         IPv4 or IPv6 address.
- *
- * ttl:             If the client wishes to cache the result for performance reasons,
- *                  the TTL indicates how long the client may legitimately hold onto
- *                  this result, in seconds. After the TTL expires, the client should
- *                  consider the result no longer valid, and if it requires this data
- *                  again, it should be re-fetched with a new query. Of course, this
- *                  only applies to clients that cancel the asynchronous operation when
- *                  they get a result. Clients that leave the asynchronous operation
- *                  running can safely assume that the data remains valid until they
- *                  get another callback telling them otherwise.
- *
- * context:         The context pointer that was passed to the callout.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceGetAddrInfoReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceErrorType errorCode,
-    const char                       *hostname,
-    const struct sockaddr            *address,
-    uint32_t ttl,
-    void                             *context
-);
-
-
-/* DNSServiceGetAddrInfo() Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds then it
- *                  initializes the DNSServiceRef, returns kDNSServiceErr_NoError, and the query
- *                  begins and will last indefinitely until the client terminates the query
- *                  by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * flags:           kDNSServiceFlagsForceMulticast or kDNSServiceFlagsLongLivedQuery.
- *                  Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast
- *                  query to a unicast DNS server that implements the protocol. This flag
- *                  has no effect on link-local multicast queries.
- *
- * interfaceIndex:  The interface on which to issue the query.  Passing 0 causes the query to be
- *                  sent on all active interfaces via Multicast or the primary interface via Unicast.
- *
- * protocol:        Pass in kDNSServiceProtocol_IPv4 to look up IPv4 addresses, or kDNSServiceProtocol_IPv6
- *                  to look up IPv6 addresses, or both to look up both kinds. If neither flag is
- *                  set, the system will apply an intelligent heuristic, which is (currently)
- *                  that it will attempt to look up both, except:
- *
- *                   * If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name)
- *                     but this host has no routable IPv6 address, then the call will not try to
- *                     look up IPv6 addresses for "hostname", since any addresses it found would be
- *                     unlikely to be of any use anyway. Similarly, if this host has no routable
- *                     IPv4 address, the call will not try to look up IPv4 addresses for "hostname".
- *
- * hostname:        The fully qualified domain name of the host to be queried for.
- *
- * callBack:        The function to be called when the query succeeds or fails asynchronously.
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo
-(
-    DNSServiceRef                    *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceProtocol protocol,
-    const char                       *hostname,
-    DNSServiceGetAddrInfoReply callBack,
-    void                             *context          /* may be NULL */
-);
-
-
-/*********************************************************************************************
-*
-*  Special Purpose Calls:
-*  DNSServiceCreateConnection(), DNSServiceRegisterRecord(), DNSServiceReconfirmRecord()
-*  (most applications will not use these)
-*
-*********************************************************************************************/
-
-/* DNSServiceCreateConnection()
- *
- * Create a connection to the daemon allowing efficient registration of
- * multiple individual records.
- *
- * Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. Deallocating
- *                  the reference (via DNSServiceRefDeallocate()) severs the
- *                  connection and deregisters all records registered on this connection.
- *
- * 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).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef);
-
-/* DNSServiceRegisterRecord
- *
- * Register an individual resource record on a connected DNSServiceRef.
- *
- * Note that name conflicts occurring for records registered via this call must be handled
- * by the client in the callback.
- *
- * DNSServiceRegisterRecordReply() parameters:
- *
- * sdRef:           The connected DNSServiceRef initialized by
- *                  DNSServiceCreateConnection().
- *
- * RecordRef:       The DNSRecordRef initialized by DNSServiceRegisterRecord(). If the above
- *                  DNSServiceRef is passed to DNSServiceRefDeallocate(), this DNSRecordRef is
- *                  invalidated, and may not be used further.
- *
- * flags:           Currently unused, reserved for future use.
- *
- * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
- *                  indicate the failure that occurred (including name conflicts.)
- *                  Other parameters are undefined if errorCode is nonzero.
- *
- * context:         The context pointer that was passed to the callout.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceRegisterRecordReply)
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef RecordRef,
-    DNSServiceFlags flags,
-    DNSServiceErrorType errorCode,
-    void                                *context
-);
-
-
-/* DNSServiceRegisterRecord() Parameters:
- *
- * sdRef:           A DNSServiceRef initialized by DNSServiceCreateConnection().
- *
- * RecordRef:       A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this
- *                  call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
- *                  (To deregister ALL records registered on a single connected DNSServiceRef
- *                  and deallocate each of their corresponding DNSServiceRecordRefs, call
- *                  DNSServiceRefDeallocate()).
- *
- * flags:           Possible values are kDNSServiceFlagsShared or kDNSServiceFlagsUnique
- *                  (see flag type definitions for details).
- *
- * interfaceIndex:  If non-zero, specifies the interface on which to register the record
- *                  (the index for a given interface is determined via the if_nametoindex()
- *                  family of calls.) Passing 0 causes the record to be registered on all interfaces.
- *                  See "Constants for specifying an interface index" for more details.
- *
- * fullname:        The full domain name of the resource record.
- *
- * rrtype:          The numerical type of the resource record (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- * rrclass:         The class of the resource record (usually kDNSServiceClass_IN)
- *
- * rdlen:           Length, in bytes, of the rdata.
- *
- * rdata:           A pointer to the raw rdata, as it is to appear in the DNS record.
- *
- * ttl:             The time to live of the resource record, in seconds.
- *                  Most clients should pass 0 to indicate that the system should
- *                  select a sensible default value.
- *
- * callBack:        The function to be called when a result is found, or if the call
- *                  asynchronously fails (e.g. because of a name conflict.)
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred (the callback is never invoked and the DNSRecordRef is
- *                  not initialized).
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef                        *RecordRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                          *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void                          *rdata,
-    uint32_t ttl,
-    DNSServiceRegisterRecordReply callBack,
-    void                                *context    /* may be NULL */
-);
-
-
-/* DNSServiceReconfirmRecord
- *
- * Instruct the daemon to verify the validity of a resource record that appears
- * to be out of date (e.g. because TCP connection to a service's target failed.)
- * Causes the record to be flushed from the daemon's cache (as well as all other
- * daemons' caches on the network) if the record is determined to be invalid.
- * Use this routine conservatively. Reconfirming a record necessarily consumes
- * network bandwidth, so this should not be done indiscriminately.
- *
- * Parameters:
- *
- * flags:           Not currently used.
- *
- * interfaceIndex:  Specifies the interface of the record in question.
- *                  The caller must specify the interface.
- *                  This API (by design) causes increased network traffic, so it requires
- *                  the caller to be precise about which record should be reconfirmed.
- *                  It is not possible to pass zero for the interface index to perform
- *                  a "wildcard" reconfirmation, where *all* matching records are reconfirmed.
- *
- * fullname:        The resource record's full domain name.
- *
- * rrtype:          The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
- *
- * rrclass:         The class of the resource record (usually kDNSServiceClass_IN).
- *
- * rdlen:           The length, in bytes, of the resource record rdata.
- *
- * rdata:           The raw rdata of the resource record.
- *
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
-(
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                         *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void                         *rdata
-);
-
-
-/*********************************************************************************************
-*
-*  NAT Port Mapping
-*
-*********************************************************************************************/
-
-/* DNSServiceNATPortMappingCreate
- *
- * Request a port mapping in the NAT gateway, which maps a port on the local machine
- * to an external port on the NAT. The NAT should support either PCP, NAT-PMP or the
- * UPnP/IGD protocol for this API to create a successful mapping. Note that this API
- * currently supports IPv4 addresses/mappings only. If the NAT gateway supports PCP and
- * returns an IPv6 address (incorrectly, since this API specifically requests IPv4
- * addresses), the DNSServiceNATPortMappingReply callback will be invoked with errorCode
- * kDNSServiceErr_NATPortMappingUnsupported.
- *
- * The port mapping will be renewed indefinitely until the client process exits, or
- * explicitly terminates the port mapping request by calling DNSServiceRefDeallocate().
- * The client callback will be invoked, informing the client of the NAT gateway's
- * external IP address and the external port that has been allocated for this client.
- * The client should then record this external IP address and port using whatever
- * directory service mechanism it is using to enable peers to connect to it.
- * (Clients advertising services using Wide-Area DNS-SD DO NOT need to use this API
- * -- when a client calls DNSServiceRegister() NAT mappings are automatically created
- * and the external IP address and port for the service are recorded in the global DNS.
- * Only clients using some directory mechanism other than Wide-Area DNS-SD need to use
- * this API to explicitly map their own ports.)
- *
- * It's possible that the client callback could be called multiple times, for example
- * if the NAT gateway's IP address changes, or if a configuration change results in a
- * different external port being mapped for this client. Over the lifetime of any long-lived
- * port mapping, the client should be prepared to handle these notifications of changes
- * in the environment, and should update its recorded address and/or port as appropriate.
- *
- * NOTE: There are two unusual aspects of how the DNSServiceNATPortMappingCreate API works,
- * which were intentionally designed to help simplify client code:
- *
- *  1. It's not an error to request a NAT mapping when the machine is not behind a NAT gateway.
- *     In other NAT mapping APIs, if you request a NAT mapping and the machine is not behind a NAT
- *     gateway, then the API returns an error code -- it can't get you a NAT mapping if there's no
- *     NAT gateway. The DNSServiceNATPortMappingCreate API takes a different view. Working out
- *     whether or not you need a NAT mapping can be tricky and non-obvious, particularly on
- *     a machine with multiple active network interfaces. Rather than make every client recreate
- *     this logic for deciding whether a NAT mapping is required, the PortMapping API does that
- *     work for you. If the client calls the PortMapping API when the machine already has a
- *     routable public IP address, then instead of complaining about it and giving an error,
- *     the PortMapping API just invokes your callback, giving the machine's public address
- *     and your own port number. This means you don't need to write code to work out whether
- *     your client needs to call the PortMapping API -- just call it anyway, and if it wasn't
- *     necessary, no harm is done:
- *
- *     - If the machine already has a routable public IP address, then your callback
- *       will just be invoked giving your own address and port.
- *     - If a NAT mapping is required and obtained, then your callback will be invoked
- *       giving you the external address and port.
- *     - If a NAT mapping is required but not obtained from the local NAT gateway,
- *       or the machine has no network connectivity, then your callback will be
- *       invoked giving zero address and port.
- *
- *  2. In other NAT mapping APIs, if a laptop computer is put to sleep and woken up on a new
- *     network, it's the client's job to notice this, and work out whether a NAT mapping
- *     is required on the new network, and make a new NAT mapping request if necessary.
- *     The DNSServiceNATPortMappingCreate API does this for you, automatically.
- *     The client just needs to make one call to the PortMapping API, and its callback will
- *     be invoked any time the mapping state changes. This property complements point (1) above.
- *     If the client didn't make a NAT mapping request just because it determined that one was
- *     not required at that particular moment in time, the client would then have to monitor
- *     for network state changes to determine if a NAT port mapping later became necessary.
- *     By unconditionally making a NAT mapping request, even when a NAT mapping not to be
- *     necessary, the PortMapping API will then begin monitoring network state changes on behalf of
- *     the client, and if a NAT mapping later becomes necessary, it will automatically create a NAT
- *     mapping and inform the client with a new callback giving the new address and port information.
- *
- * DNSServiceNATPortMappingReply() parameters:
- *
- * sdRef:           The DNSServiceRef initialized by DNSServiceNATPortMappingCreate().
- *
- * flags:           Currently unused, reserved for future use.
- *
- * interfaceIndex:  The interface through which the NAT gateway is reached.
- *
- * errorCode:       Will be kDNSServiceErr_NoError on success.
- *                  Will be kDNSServiceErr_DoubleNAT when the NAT gateway is itself behind one or
- *                  more layers of NAT, in which case the other parameters have the defined values.
- *                  For other failures, will indicate the failure that occurred, and the other
- *                  parameters are undefined.
- *
- * externalAddress: Four byte IPv4 address in network byte order.
- *
- * protocol:        Will be kDNSServiceProtocol_UDP or kDNSServiceProtocol_TCP or both.
- *
- * internalPort:    The port on the local machine that was mapped.
- *
- * externalPort:    The actual external port in the NAT gateway that was mapped.
- *                  This is likely to be different than the requested external port.
- *
- * ttl:             The lifetime of the NAT port mapping created on the gateway.
- *                  This controls how quickly stale mappings will be garbage-collected
- *                  if the client machine crashes, suffers a power failure, is disconnected
- *                  from the network, or suffers some other unfortunate demise which
- *                  causes it to vanish without explicitly removing its NAT port mapping.
- *                  It's possible that the ttl value will differ from the requested ttl value.
- *
- * context:         The context pointer that was passed to the callout.
- *
- */
-
-typedef void (DNSSD_API *DNSServiceNATPortMappingReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceErrorType errorCode,
-    uint32_t externalAddress,                           /* four byte IPv4 address in network byte order */
-    DNSServiceProtocol protocol,
-    uint16_t internalPort,                              /* In network byte order */
-    uint16_t externalPort,                              /* In network byte order and may be different than the requested port */
-    uint32_t ttl,                                       /* may be different than the requested ttl */
-    void                             *context
-);
-
-
-/* DNSServiceNATPortMappingCreate() Parameters:
- *
- * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds then it
- *                  initializes the DNSServiceRef, returns kDNSServiceErr_NoError, and the nat
- *                  port mapping will last indefinitely until the client terminates the port
- *                  mapping request by passing this DNSServiceRef to DNSServiceRefDeallocate().
- *
- * flags:           Currently ignored, reserved for future use.
- *
- * interfaceIndex:  The interface on which to create port mappings in a NAT gateway. Passing 0 causes
- *                  the port mapping request to be sent on the primary interface.
- *
- * protocol:        To request a port mapping, pass in kDNSServiceProtocol_UDP, or kDNSServiceProtocol_TCP,
- *                  or (kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP) to map both.
- *                  The local listening port number must also be specified in the internalPort parameter.
- *                  To just discover the NAT gateway's external IP address, pass zero for protocol,
- *                  internalPort, externalPort and ttl.
- *
- * internalPort:    The port number in network byte order on the local machine which is listening for packets.
- *
- * externalPort:    The requested external port in network byte order in the NAT gateway that you would
- *                  like to map to the internal port. Pass 0 if you don't care which external port is chosen for you.
- *
- * ttl:             The requested renewal period of the NAT port mapping, in seconds.
- *                  If the client machine crashes, suffers a power failure, is disconnected from
- *                  the network, or suffers some other unfortunate demise which causes it to vanish
- *                  unexpectedly without explicitly removing its NAT port mappings, then the NAT gateway
- *                  will garbage-collect old stale NAT port mappings when their lifetime expires.
- *                  Requesting a short TTL causes such orphaned mappings to be garbage-collected
- *                  more promptly, but consumes system resources and network bandwidth with
- *                  frequent renewal packets to keep the mapping from expiring.
- *                  Requesting a long TTL is more efficient on the network, but in the event of the
- *                  client vanishing, stale NAT port mappings will not be garbage-collected as quickly.
- *                  Most clients should pass 0 to use a system-wide default value.
- *
- * callBack:        The function to be called when the port mapping request succeeds or fails asynchronously.
- *
- * context:         An application context pointer which is passed to the callback function
- *                  (may be NULL).
- *
- * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
- *                  errors are delivered to the callback), otherwise returns an error code indicating
- *                  the error that occurred.
- *
- *                  If you don't actually want a port mapped, and are just calling the API
- *                  because you want to find out the NAT's external IP address (e.g. for UI
- *                  display) then pass zero for protocol, internalPort, externalPort and ttl.
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
-(
-    DNSServiceRef                    *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceProtocol protocol,                        /* TCP and/or UDP          */
-    uint16_t internalPort,                              /* network byte order      */
-    uint16_t externalPort,                              /* network byte order      */
-    uint32_t ttl,                                       /* time to live in seconds */
-    DNSServiceNATPortMappingReply callBack,
-    void                             *context           /* may be NULL             */
-);
-
-
-/*********************************************************************************************
-*
-*  General Utility Functions
-*
-*********************************************************************************************/
-
-/* DNSServiceConstructFullName()
- *
- * Concatenate a three-part domain name (as returned by the above callbacks) into a
- * properly-escaped full domain name. Note that callbacks in the above functions ALREADY ESCAPE
- * strings where necessary.
- *
- * Parameters:
- *
- * fullName:        A pointer to a buffer that where the resulting full domain name is to be written.
- *                  The buffer must be kDNSServiceMaxDomainName (1009) bytes in length to
- *                  accommodate the longest legal domain name without buffer overrun.
- *
- * service:         The service name - any dots or backslashes must NOT be escaped.
- *                  May be NULL (to construct a PTR record name, e.g.
- *                  "_ftp._tcp.apple.com.").
- *
- * regtype:         The service type followed by the protocol, separated by a dot
- *                  (e.g. "_ftp._tcp").
- *
- * domain:          The domain name, e.g. "apple.com.". Literal dots or backslashes,
- *                  if any, must be escaped, e.g. "1st\. Floor.apple.com."
- *
- * return value:    Returns kDNSServiceErr_NoError (0) on success, kDNSServiceErr_BadParam on error.
- *
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceConstructFullName
-(
-    char                            * const fullName,
-    const char                      * const service,      /* may be NULL */
-    const char                      * const regtype,
-    const char                      * const domain
-);
-
-
-/*********************************************************************************************
-*
-*   TXT Record Construction Functions
-*
-*********************************************************************************************/
-
-/*
- * A typical calling sequence for TXT record construction is something like:
- *
- * Client allocates storage for TXTRecord data (e.g. declare buffer on the stack)
- * TXTRecordCreate();
- * TXTRecordSetValue();
- * TXTRecordSetValue();
- * TXTRecordSetValue();
- * ...
- * DNSServiceRegister( ... TXTRecordGetLength(), TXTRecordGetBytesPtr() ... );
- * TXTRecordDeallocate();
- * Explicitly deallocate storage for TXTRecord data (if not allocated on the stack)
- */
-
-
-/* TXTRecordRef
- *
- * Opaque internal data type.
- * Note: Represents a DNS-SD TXT record.
- */
-
-typedef union _TXTRecordRef_t { char PrivateData[16]; char *ForceNaturalAlignment; } TXTRecordRef;
-
-
-/* TXTRecordCreate()
- *
- * Creates a new empty TXTRecordRef referencing the specified storage.
- *
- * If the buffer parameter is NULL, or the specified storage size is not
- * large enough to hold a key subsequently added using TXTRecordSetValue(),
- * then additional memory will be added as needed using malloc().
- *
- * On some platforms, when memory is low, malloc() may fail. In this
- * case, TXTRecordSetValue() will return kDNSServiceErr_NoMemory, and this
- * error condition will need to be handled as appropriate by the caller.
- *
- * You can avoid the need to handle this error condition if you ensure
- * that the storage you initially provide is large enough to hold all
- * the key/value pairs that are to be added to the record.
- * The caller can precompute the exact length required for all of the
- * key/value pairs to be added, or simply provide a fixed-sized buffer
- * known in advance to be large enough.
- * A no-value (key-only) key requires  (1 + key length) bytes.
- * A key with empty value requires     (1 + key length + 1) bytes.
- * A key with non-empty value requires (1 + key length + 1 + value length).
- * For most applications, DNS-SD TXT records are generally
- * less than 100 bytes, so in most cases a simple fixed-sized
- * 256-byte buffer will be more than sufficient.
- * Recommended size limits for DNS-SD TXT Records are discussed in
- * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
- *
- * Note: When passing parameters to and from these TXT record APIs,
- * the key name does not include the '=' character. The '=' character
- * is the separator between the key and value in the on-the-wire
- * packet format; it is not part of either the key or the value.
- *
- * txtRecord:       A pointer to an uninitialized TXTRecordRef.
- *
- * bufferLen:       The size of the storage provided in the "buffer" parameter.
- *
- * buffer:          Optional caller-supplied storage used to hold the TXTRecord data.
- *                  This storage must remain valid for as long as
- *                  the TXTRecordRef.
- */
-
-void DNSSD_API TXTRecordCreate
-(
-    TXTRecordRef     *txtRecord,
-    uint16_t bufferLen,
-    void             *buffer
-);
-
-
-/* TXTRecordDeallocate()
- *
- * Releases any resources allocated in the course of preparing a TXT Record
- * using TXTRecordCreate()/TXTRecordSetValue()/TXTRecordRemoveValue().
- * Ownership of the buffer provided in TXTRecordCreate() returns to the client.
- *
- * txtRecord:           A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- */
-
-void DNSSD_API TXTRecordDeallocate
-(
-    TXTRecordRef     *txtRecord
-);
-
-
-/* TXTRecordSetValue()
- *
- * Adds a key (optionally with value) to a TXTRecordRef. If the "key" already
- * exists in the TXTRecordRef, then the current value will be replaced with
- * the new value.
- * Keys may exist in four states with respect to a given TXT record:
- *  - Absent (key does not appear at all)
- *  - Present with no value ("key" appears alone)
- *  - Present with empty value ("key=" appears in TXT record)
- *  - Present with non-empty value ("key=value" appears in TXT record)
- * For more details refer to "Data Syntax for DNS-SD TXT Records" in
- * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
- *
- * txtRecord:       A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- * key:             A null-terminated string which only contains printable ASCII
- *                  values (0x20-0x7E), excluding '=' (0x3D). Keys should be
- *                  9 characters or fewer (not counting the terminating null).
- *
- * valueSize:       The size of the value.
- *
- * value:           Any binary value. For values that represent
- *                  textual data, UTF-8 is STRONGLY recommended.
- *                  For values that represent textual data, valueSize
- *                  should NOT include the terminating null (if any)
- *                  at the end of the string.
- *                  If NULL, then "key" will be added with no value.
- *                  If non-NULL but valueSize is zero, then "key=" will be
- *                  added with empty value.
- *
- * return value:    Returns kDNSServiceErr_NoError on success.
- *                  Returns kDNSServiceErr_Invalid if the "key" string contains
- *                  illegal characters.
- *                  Returns kDNSServiceErr_NoMemory if adding this key would
- *                  exceed the available storage.
- */
-
-DNSServiceErrorType DNSSD_API TXTRecordSetValue
-(
-    TXTRecordRef     *txtRecord,
-    const char       *key,
-    uint8_t valueSize,                 /* may be zero */
-    const void       *value            /* may be NULL */
-);
-
-
-/* TXTRecordRemoveValue()
- *
- * Removes a key from a TXTRecordRef. The "key" must be an
- * ASCII string which exists in the TXTRecordRef.
- *
- * txtRecord:       A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- * key:             A key name which exists in the TXTRecordRef.
- *
- * return value:    Returns kDNSServiceErr_NoError on success.
- *                  Returns kDNSServiceErr_NoSuchKey if the "key" does not
- *                  exist in the TXTRecordRef.
- */
-
-DNSServiceErrorType DNSSD_API TXTRecordRemoveValue
-(
-    TXTRecordRef     *txtRecord,
-    const char       *key
-);
-
-
-/* TXTRecordGetLength()
- *
- * Allows you to determine the length of the raw bytes within a TXTRecordRef.
- *
- * txtRecord:       A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- * return value:    Returns the size of the raw bytes inside a TXTRecordRef
- *                  which you can pass directly to DNSServiceRegister() or
- *                  to DNSServiceUpdateRecord().
- *                  Returns 0 if the TXTRecordRef is empty.
- */
-
-uint16_t DNSSD_API TXTRecordGetLength
-(
-    const TXTRecordRef *txtRecord
-);
-
-
-/* TXTRecordGetBytesPtr()
- *
- * Allows you to retrieve a pointer to the raw bytes within a TXTRecordRef.
- *
- * txtRecord:       A TXTRecordRef initialized by calling TXTRecordCreate().
- *
- * return value:    Returns a pointer to the raw bytes inside the TXTRecordRef
- *                  which you can pass directly to DNSServiceRegister() or
- *                  to DNSServiceUpdateRecord().
- */
-
-const void * DNSSD_API TXTRecordGetBytesPtr
-(
-    const TXTRecordRef *txtRecord
-);
-
-
-/*********************************************************************************************
-*
-*   TXT Record Parsing Functions
-*
-*********************************************************************************************/
-
-/*
- * A typical calling sequence for TXT record parsing is something like:
- *
- * Receive TXT record data in DNSServiceResolve() callback
- * if (TXTRecordContainsKey(txtLen, txtRecord, "key")) then do something
- * val1ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key1", &len1);
- * val2ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key2", &len2);
- * ...
- * memcpy(myval1, val1ptr, len1);
- * memcpy(myval2, val2ptr, len2);
- * ...
- * return;
- *
- * If you wish to retain the values after return from the DNSServiceResolve()
- * callback, then you need to copy the data to your own storage using memcpy()
- * or similar, as shown in the example above.
- *
- * If for some reason you need to parse a TXT record you built yourself
- * using the TXT record construction functions above, then you can do
- * that using TXTRecordGetLength and TXTRecordGetBytesPtr calls:
- * TXTRecordGetValue(TXTRecordGetLength(x), TXTRecordGetBytesPtr(x), key, &len);
- *
- * Most applications only fetch keys they know about from a TXT record and
- * ignore the rest.
- * However, some debugging tools wish to fetch and display all keys.
- * To do that, use the TXTRecordGetCount() and TXTRecordGetItemAtIndex() calls.
- */
-
-/* TXTRecordContainsKey()
- *
- * Allows you to determine if a given TXT Record contains a specified key.
- *
- * txtLen:          The size of the received TXT Record.
- *
- * txtRecord:       Pointer to the received TXT Record bytes.
- *
- * key:             A null-terminated ASCII string containing the key name.
- *
- * return value:    Returns 1 if the TXT Record contains the specified key.
- *                  Otherwise, it returns 0.
- */
-
-int DNSSD_API TXTRecordContainsKey
-(
-    uint16_t txtLen,
-    const void       *txtRecord,
-    const char       *key
-);
-
-
-/* TXTRecordGetValuePtr()
- *
- * Allows you to retrieve the value for a given key from a TXT Record.
- *
- * txtLen:          The size of the received TXT Record
- *
- * txtRecord:       Pointer to the received TXT Record bytes.
- *
- * key:             A null-terminated ASCII string containing the key name.
- *
- * valueLen:        On output, will be set to the size of the "value" data.
- *
- * return value:    Returns NULL if the key does not exist in this TXT record,
- *                  or exists with no value (to differentiate between
- *                  these two cases use TXTRecordContainsKey()).
- *                  Returns pointer to location within TXT Record bytes
- *                  if the key exists with empty or non-empty value.
- *                  For empty value, valueLen will be zero.
- *                  For non-empty value, valueLen will be length of value data.
- */
-
-const void * DNSSD_API TXTRecordGetValuePtr
-(
-    uint16_t txtLen,
-    const void       *txtRecord,
-    const char       *key,
-    uint8_t          *valueLen
-);
-
-
-/* TXTRecordGetCount()
- *
- * Returns the number of keys stored in the TXT Record. The count
- * can be used with TXTRecordGetItemAtIndex() to iterate through the keys.
- *
- * txtLen:          The size of the received TXT Record.
- *
- * txtRecord:       Pointer to the received TXT Record bytes.
- *
- * return value:    Returns the total number of keys in the TXT Record.
- *
- */
-
-uint16_t DNSSD_API TXTRecordGetCount
-(
-    uint16_t txtLen,
-    const void       *txtRecord
-);
-
-
-/* TXTRecordGetItemAtIndex()
- *
- * Allows you to retrieve a key name and value pointer, given an index into
- * a TXT Record. Legal index values range from zero to TXTRecordGetCount()-1.
- * It's also possible to iterate through keys in a TXT record by simply
- * calling TXTRecordGetItemAtIndex() repeatedly, beginning with index zero
- * and increasing until TXTRecordGetItemAtIndex() returns kDNSServiceErr_Invalid.
- *
- * On return:
- * For keys with no value, *value is set to NULL and *valueLen is zero.
- * For keys with empty value, *value is non-NULL and *valueLen is zero.
- * For keys with non-empty value, *value is non-NULL and *valueLen is non-zero.
- *
- * txtLen:          The size of the received TXT Record.
- *
- * txtRecord:       Pointer to the received TXT Record bytes.
- *
- * itemIndex:       An index into the TXT Record.
- *
- * keyBufLen:       The size of the string buffer being supplied.
- *
- * key:             A string buffer used to store the key name.
- *                  On return, the buffer contains a null-terminated C string
- *                  giving the key name. DNS-SD TXT keys are usually
- *                  9 characters or fewer. To hold the maximum possible
- *                  key name, the buffer should be 256 bytes long.
- *
- * valueLen:        On output, will be set to the size of the "value" data.
- *
- * value:           On output, *value is set to point to location within TXT
- *                  Record bytes that holds the value data.
- *
- * return value:    Returns kDNSServiceErr_NoError on success.
- *                  Returns kDNSServiceErr_NoMemory if keyBufLen is too short.
- *                  Returns kDNSServiceErr_Invalid if index is greater than
- *                  TXTRecordGetCount()-1.
- */
-
-DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
-(
-    uint16_t txtLen,
-    const void       *txtRecord,
-    uint16_t itemIndex,
-    uint16_t keyBufLen,
-    char             *key,
-    uint8_t          *valueLen,
-    const void       **value
-);
-
-#if _DNS_SD_LIBDISPATCH
-/*
- * DNSServiceSetDispatchQueue
- *
- * Allows you to schedule a DNSServiceRef on a serial dispatch queue for receiving asynchronous
- * callbacks.  It's the clients responsibility to ensure that the provided dispatch queue is running.
- *
- * A typical application that uses CFRunLoopRun or dispatch_main on its main thread will
- * usually schedule DNSServiceRefs on its main queue (which is always a serial queue)
- * using "DNSServiceSetDispatchQueue(sdref, dispatch_get_main_queue());"
- *
- * If there is any error during the processing of events, the application callback will
- * be called with an error code. For shared connections, each subordinate DNSServiceRef
- * will get its own error callback. Currently these error callbacks only happen
- * if the mDNSResponder daemon is manually terminated or crashes, and the error
- * code in this case is kDNSServiceErr_ServiceNotRunning. The application must call
- * DNSServiceRefDeallocate to free the DNSServiceRef when it gets such an error code.
- * These error callbacks are rare and should not normally happen on customer machines,
- * but application code should be written defensively to handle such error callbacks
- * gracefully if they occur.
- *
- * After using DNSServiceSetDispatchQueue on a DNSServiceRef, calling DNSServiceProcessResult
- * on the same DNSServiceRef will result in undefined behavior and should be avoided.
- *
- * Once the application successfully schedules a DNSServiceRef on a serial dispatch queue using
- * DNSServiceSetDispatchQueue, it cannot remove the DNSServiceRef from the dispatch queue, or use
- * DNSServiceSetDispatchQueue a second time to schedule the DNSServiceRef onto a different serial dispatch
- * queue. Once scheduled onto a dispatch queue a DNSServiceRef will deliver events to that queue until
- * the application no longer requires that operation and terminates it using DNSServiceRefDeallocate.
- *
- * service:         DNSServiceRef that was allocated and returned to the application, when the
- *                  application calls one of the DNSService API.
- *
- * queue:           dispatch queue where the application callback will be scheduled
- *
- * return value:    Returns kDNSServiceErr_NoError on success.
- *                  Returns kDNSServiceErr_NoMemory if it cannot create a dispatch source
- *                  Returns kDNSServiceErr_BadParam if the service param is invalid or the
- *                  queue param is invalid
- */
-
-DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue
-(
-    DNSServiceRef service,
-    dispatch_queue_t queue
-);
-#endif //_DNS_SD_LIBDISPATCH
-
-#if !defined(_WIN32)
-typedef void (DNSSD_API *DNSServiceSleepKeepaliveReply)
-(
-    DNSServiceRef sdRef,
-    DNSServiceErrorType errorCode,
-    void                                *context
-);
-DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    int fd,
-    unsigned int timeout,
-    DNSServiceSleepKeepaliveReply callBack,
-    void                                *context
-);
-#endif
-
-#ifdef APPLE_OSX_mDNSResponder
-/* DNSServiceCreateDelegateConnection()
- *
- * Create a delegate connection to the daemon allowing efficient registration of
- * multiple individual records.
- *
- * 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);
-#endif
-
-#ifdef __APPLE_API_PRIVATE
-
-#define kDNSServiceCompPrivateDNS   "PrivateDNS"
-#define kDNSServiceCompMulticastDNS "MulticastDNS"
-
-#endif //__APPLE_API_PRIVATE
-
-/* Some C compiler cleverness. We can make the compiler check certain things for us,
- * and report errors at compile-time if anything is wrong. The usual way to do this would
- * be to use a run-time "if" statement or the conventional run-time "assert" mechanism, but
- * then you don't find out what's wrong until you run the software. This way, if the assertion
- * condition is false, the array size is negative, and the complier complains immediately.
- */
-
-struct CompileTimeAssertionChecks_DNS_SD
-{
-    char assert0[(sizeof(union _TXTRecordRef_t) == 16) ? 1 : -1];
-};
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif  /* _DNS_SD_H */

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSShared/dns_sd.h (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSShared/dns_sd.h)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/mDNSShared/dns_sd.h	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSShared/dns_sd.h	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,2660 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2003-2013 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
+ *     contributors may be used to endorse or promote products derived from this
+ *     software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*! @header     DNS Service Discovery
+ *
+ * @discussion  This section describes the functions, callbacks, and data structures
+ *              that make up the DNS Service Discovery API.
+ *
+ *              The DNS Service Discovery API is part of Bonjour, Apple's implementation
+ *              of zero-configuration networking (ZEROCONF).
+ *
+ *              Bonjour allows you to register a network service, such as a
+ *              printer or file server, so that it can be found by name or browsed
+ *              for by service type and domain. Using Bonjour, applications can
+ *              discover what services are available on the network, along with
+ *              all the information -- such as name, IP address, and port --
+ *              necessary to access a particular service.
+ *
+ *              In effect, Bonjour combines the functions of a local DNS server and
+ *              AppleTalk. Bonjour allows applications to provide user-friendly printer
+ *              and server browsing, among other things, over standard IP networks.
+ *              This behavior is a result of combining protocols such as multicast and
+ *              DNS to add new functionality to the network (such as multicast DNS).
+ *
+ *              Bonjour gives applications easy access to services over local IP
+ *              networks without requiring the service or the application to support
+ *              an AppleTalk or a Netbeui stack, and without requiring a DNS server
+ *              for the local network.
+ */
+
+/* _DNS_SD_H contains the API version number for this header file
+ * The API version defined in this header file symbol allows for compile-time
+ * checking, so that C code building with earlier versions of the header file
+ * can avoid compile errors trying to use functions that aren't even defined
+ * in those earlier versions. Similar checks may also be performed at run-time:
+ *  => weak linking -- to avoid link failures if run with an earlier
+ *     version of the library that's missing some desired symbol, or
+ *  => DNSServiceGetProperty(DaemonVersion) -- to verify whether the running daemon
+ *     ("system service" on Windows) meets some required minimum functionality level.
+ */
+
+#ifndef _DNS_SD_H
+#define _DNS_SD_H 5610101
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* Set to 1 if libdispatch is supported
+ * Note: May also be set by project and/or Makefile
+ */
+#ifndef _DNS_SD_LIBDISPATCH
+#define _DNS_SD_LIBDISPATCH 0
+#endif /* ndef _DNS_SD_LIBDISPATCH */
+
+/* standard calling convention under Win32 is __stdcall */
+/* Note: When compiling Intel EFI (Extensible Firmware Interface) under MS Visual Studio, the */
+/* _WIN32 symbol is defined by the compiler even though it's NOT compiling code for Windows32 */
+#if defined(_WIN32) && !defined(EFI32) && !defined(EFI64)
+#define DNSSD_API __stdcall
+#else
+#define DNSSD_API
+#endif
+
+/* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */
+#if defined(__FreeBSD__) && (__FreeBSD__ < 5)
+#include <sys/types.h>
+
+/* Likewise, on Sun, standard integer types are in sys/types.h */
+#elif defined(__sun__)
+#include <sys/types.h>
+
+/* EFI does not have stdint.h, or anything else equivalent */
+#elif defined(EFI32) || defined(EFI64) || defined(EFIX64)
+#include "Tiano.h"
+#if !defined(_STDINT_H_)
+typedef UINT8 uint8_t;
+typedef INT8 int8_t;
+typedef UINT16 uint16_t;
+typedef INT16 int16_t;
+typedef UINT32 uint32_t;
+typedef INT32 int32_t;
+#endif
+/* Windows has its own differences */
+#elif defined(_WIN32)
+#include <windows.h>
+#define _UNUSED
+#ifndef _MSL_STDINT_H
+typedef UINT8 uint8_t;
+typedef INT8 int8_t;
+typedef UINT16 uint16_t;
+typedef INT16 int16_t;
+typedef UINT32 uint32_t;
+typedef INT32 int32_t;
+#endif
+
+/* All other Posix platforms use stdint.h */
+#else
+#include <stdint.h>
+#endif
+
+#if _DNS_SD_LIBDISPATCH
+#include <dispatch/dispatch.h>
+#endif
+
+/* DNSServiceRef, DNSRecordRef
+ *
+ * Opaque internal data types.
+ * Note: client is responsible for serializing access to these structures if
+ * they are shared between concurrent threads.
+ */
+
+typedef struct _DNSServiceRef_t *DNSServiceRef;
+typedef struct _DNSRecordRef_t *DNSRecordRef;
+
+struct sockaddr;
+
+/*! @enum General flags
+ * Most DNS-SD API functions and callbacks include a DNSServiceFlags parameter.
+ * As a general rule, any given bit in the 32-bit flags field has a specific fixed meaning,
+ * regardless of the function or callback being used. For any given function or callback,
+ * typically only a subset of the possible flags are meaningful, and all others should be zero.
+ * The discussion section for each API call describes which flags are valid for that call
+ * and callback. In some cases, for a particular call, it may be that no flags are currently
+ * defined, in which case the DNSServiceFlags parameter exists purely to allow future expansion.
+ * In all cases, developers should expect that in future releases, it is possible that new flag
+ * values will be defined, and write code with this in mind. For example, code that tests
+ *     if (flags == kDNSServiceFlagsAdd) ...
+ * will fail if, in a future release, another bit in the 32-bit flags field is also set.
+ * The reliable way to test whether a particular bit is set is not with an equality test,
+ * but with a bitwise mask:
+ *     if (flags & kDNSServiceFlagsAdd) ...
+ * With the exception of kDNSServiceFlagsValidate, each flag can be valid(be set) 
+ * EITHER only as an input to one of the DNSService*() APIs OR only as an output
+ * (provide status) through any of the callbacks used. For example, kDNSServiceFlagsAdd
+ * can be set only as an output in the callback, whereas the kDNSServiceFlagsIncludeP2P
+ * can be set only as an input to the DNSService*() APIs. See comments on kDNSServiceFlagsValidate  
+ * defined in enum below.
+ */
+enum
+{
+    kDNSServiceFlagsMoreComing          = 0x1,
+    /* MoreComing indicates to a callback that at least one more result is
+     * queued and will be delivered following immediately after this one.
+     * When the MoreComing flag is set, applications should not immediately
+     * update their UI, because this can result in a great deal of ugly flickering
+     * on the screen, and can waste a great deal of CPU time repeatedly updating
+     * the screen with content that is then immediately erased, over and over.
+     * Applications should wait until MoreComing is not set, and then
+     * update their UI when no more changes are imminent.
+     * When MoreComing is not set, that doesn't mean there will be no more
+     * answers EVER, just that there are no more answers immediately
+     * available right now at this instant. If more answers become available
+     * in the future they will be delivered as usual.
+     */
+
+    kDNSServiceFlagsAdd                 = 0x2,
+    kDNSServiceFlagsDefault             = 0x4,
+    /* Flags for domain enumeration and browse/query reply callbacks.
+     * "Default" applies only to enumeration and is only valid in
+     * conjunction with "Add". An enumeration callback with the "Add"
+     * flag NOT set indicates a "Remove", i.e. the domain is no longer
+     * valid.
+     */
+
+    kDNSServiceFlagsNoAutoRename        = 0x8,
+    /* Flag for specifying renaming behavior on name conflict when registering
+     * non-shared records. By default, name conflicts are automatically handled
+     * by renaming the service. NoAutoRename overrides this behavior - with this
+     * flag set, name conflicts will result in a callback. The NoAutorename flag
+     * is only valid if a name is explicitly specified when registering a service
+     * (i.e. the default name is not used.)
+     */
+
+    kDNSServiceFlagsShared              = 0x10,
+    kDNSServiceFlagsUnique              = 0x20,
+    /* Flag for registering individual records on a connected
+     * DNSServiceRef. Shared indicates that there may be multiple records
+     * with this name on the network (e.g. PTR records). Unique indicates that the
+     * record's name is to be unique on the network (e.g. SRV records).
+     */
+
+    kDNSServiceFlagsBrowseDomains       = 0x40,
+    kDNSServiceFlagsRegistrationDomains = 0x80,
+    /* Flags for specifying domain enumeration type in DNSServiceEnumerateDomains.
+     * BrowseDomains enumerates domains recommended for browsing, RegistrationDomains
+     * enumerates domains recommended for registration.
+     */
+
+    kDNSServiceFlagsLongLivedQuery      = 0x100,
+    /* Flag for creating a long-lived unicast query for the DNSServiceQueryRecord call. */
+
+    kDNSServiceFlagsAllowRemoteQuery    = 0x200,
+    /* Flag for creating a record for which we will answer remote queries
+     * (queries from hosts more than one hop away; hosts not directly connected to the local link).
+     */
+
+    kDNSServiceFlagsForceMulticast      = 0x400,
+    /* Flag for signifying that a query or registration should be performed exclusively via multicast
+     * DNS, even for a name in a domain (e.g. foo.apple.com.) that would normally imply unicast DNS.
+     */
+
+    kDNSServiceFlagsForce               = 0x800,    // This flag is deprecated.
+
+    kDNSServiceFlagsKnownUnique         = 0x800,
+    /* 
+     * Client guarantees that record names are unique, so we can skip sending out initial
+     * probe messages.  Standard name conflict resolution is still done if a conflict is discovered.
+     * Currently only valid for a DNSServiceRegister call.
+     */
+
+    kDNSServiceFlagsReturnIntermediates = 0x1000,
+    /* Flag for returning intermediate results.
+     * For example, if a query results in an authoritative NXDomain (name does not exist)
+     * then that result is returned to the client. However the query is not implicitly
+     * cancelled -- it remains active and if the answer subsequently changes
+     * (e.g. because a VPN tunnel is subsequently established) then that positive
+     * result will still be returned to the client.
+     * Similarly, if a query results in a CNAME record, then in addition to following
+     * the CNAME referral, the intermediate CNAME result is also returned to the client.
+     * When this flag is not set, NXDomain errors are not returned, and CNAME records
+     * are followed silently without informing the client of the intermediate steps.
+     * (In earlier builds this flag was briefly calledkDNSServiceFlagsReturnCNAME)
+     */
+
+    kDNSServiceFlagsNonBrowsable        = 0x2000,
+    /* A service registered with the NonBrowsable flag set can be resolved using
+     * DNSServiceResolve(), but will not be discoverable using DNSServiceBrowse().
+     * This is for cases where the name is actually a GUID; it is found by other means;
+     * there is no end-user benefit to browsing to find a long list of opaque GUIDs.
+     * Using the NonBrowsable flag creates SRV+TXT without the cost of also advertising
+     * an associated PTR record.
+     */
+
+    kDNSServiceFlagsShareConnection     = 0x4000,
+    /* For efficiency, clients that perform many concurrent operations may want to use a
+     * single Unix Domain Socket connection with the background daemon, instead of having a
+     * separate connection for each independent operation. To use this mode, clients first
+     * call DNSServiceCreateConnection(&MainRef) to initialize the main DNSServiceRef.
+     * For each subsequent operation that is to share that same connection, the client copies
+     * the MainRef, and then passes the address of that copy, setting the ShareConnection flag
+     * to tell the library that this DNSServiceRef is not a typical uninitialized DNSServiceRef;
+     * it's a copy of an existing DNSServiceRef whose connection information should be reused.
+     *
+     * For example:
+     *
+     * DNSServiceErrorType error;
+     * DNSServiceRef MainRef;
+     * error = DNSServiceCreateConnection(&MainRef);
+     * if (error) ...
+     * DNSServiceRef BrowseRef = MainRef;  // Important: COPY the primary DNSServiceRef first...
+     * error = DNSServiceBrowse(&BrowseRef, kDNSServiceFlagsShareConnection, ...); // then use the copy
+     * if (error) ...
+     * ...
+     * DNSServiceRefDeallocate(BrowseRef); // Terminate the browse operation
+     * DNSServiceRefDeallocate(MainRef);   // Terminate the shared connection
+     * Also see Point 4.(Don't Double-Deallocate if the MainRef has been Deallocated) in Notes below:
+     *
+     * Notes:
+     *
+     * 1. Collective kDNSServiceFlagsMoreComing flag
+     * When callbacks are invoked using a shared DNSServiceRef, the
+     * kDNSServiceFlagsMoreComing flag applies collectively to *all* active
+     * operations sharing the same parent DNSServiceRef. If the MoreComing flag is
+     * set it means that there are more results queued on this parent DNSServiceRef,
+     * but not necessarily more results for this particular callback function.
+     * The implication of this for client programmers is that when a callback
+     * is invoked with the MoreComing flag set, the code should update its
+     * internal data structures with the new result, and set a variable indicating
+     * that its UI needs to be updated. Then, later when a callback is eventually
+     * invoked with the MoreComing flag not set, the code should update *all*
+     * stale UI elements related to that shared parent DNSServiceRef that need
+     * updating, not just the UI elements related to the particular callback
+     * that happened to be the last one to be invoked.
+     *
+     * 2. Canceling operations and kDNSServiceFlagsMoreComing
+     * Whenever you cancel any operation for which you had deferred UI updates
+     * waiting because of a kDNSServiceFlagsMoreComing flag, you should perform
+     * those deferred UI updates. This is because, after cancelling the operation,
+     * you can no longer wait for a callback *without* MoreComing set, to tell
+     * you do perform your deferred UI updates (the operation has been canceled,
+     * so there will be no more callbacks). An implication of the collective
+     * kDNSServiceFlagsMoreComing flag for shared connections is that this
+     * guideline applies more broadly -- any time you cancel an operation on
+     * a shared connection, you should perform all deferred UI updates for all
+     * operations sharing that connection. This is because the MoreComing flag
+     * might have been referring to events coming for the operation you canceled,
+     * which will now not be coming because the operation has been canceled.
+     *
+     * 3. Only share DNSServiceRef's created with DNSServiceCreateConnection
+     * Calling DNSServiceCreateConnection(&ref) creates a special shareable DNSServiceRef.
+     * DNSServiceRef's created by other calls like DNSServiceBrowse() or DNSServiceResolve()
+     * cannot be shared by copying them and using kDNSServiceFlagsShareConnection.
+     *
+     * 4. Don't Double-Deallocate if the MainRef has been Deallocated
+     * Calling DNSServiceRefDeallocate(ref) for a particular operation's DNSServiceRef terminates
+     * just that operation. Calling DNSServiceRefDeallocate(ref) for the main shared DNSServiceRef
+     * (the parent DNSServiceRef, originally created by DNSServiceCreateConnection(&ref))
+     * automatically terminates the shared connection and all operations that were still using it.
+     * After doing this, DO NOT then attempt to deallocate any remaining subordinate DNSServiceRef's.
+     * The memory used by those subordinate DNSServiceRef's has already been freed, so any attempt
+     * to do a DNSServiceRefDeallocate (or any other operation) on them will result in accesses
+     * to freed memory, leading to crashes or other equally undesirable results.
+     *
+     * 5. Thread Safety
+     * The dns_sd.h API does not presuppose any particular threading model, and consequently
+     * does no locking of its own (which would require linking some specific threading library).
+     * If client code calls API routines on the same DNSServiceRef concurrently
+     * from multiple threads, it is the client's responsibility to use a mutext
+     * lock or take similar appropriate precautions to serialize those calls.
+     */
+
+    kDNSServiceFlagsSuppressUnusable    = 0x8000,
+    /*
+     * This flag is meaningful only in DNSServiceQueryRecord which suppresses unusable queries on the
+     * wire. If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name)
+     * but this host has no routable IPv6 address, then the call will not try to look up IPv6 addresses
+     * for "hostname", since any addresses it found would be unlikely to be of any use anyway. Similarly,
+     * if this host has no routable IPv4 address, the call will not try to look up IPv4 addresses for
+     * "hostname".
+     */
+
+    kDNSServiceFlagsTimeout            = 0x10000,
+    /*
+     * When kDNServiceFlagsTimeout is passed to DNSServiceQueryRecord or DNSServiceGetAddrInfo, the query is
+     * stopped after a certain number of seconds have elapsed. The time at which the query will be stopped
+     * is determined by the system and cannot be configured by the user. The query will be stopped irrespective
+     * of whether a response was given earlier or not. When the query is stopped, the callback will be called
+     * with an error code of kDNSServiceErr_Timeout and a NULL sockaddr will be returned for DNSServiceGetAddrInfo
+     * and zero length rdata will be returned for DNSServiceQueryRecord.
+     */
+
+    kDNSServiceFlagsIncludeP2P          = 0x20000,
+    /*
+     * Include P2P interfaces when kDNSServiceInterfaceIndexAny is specified.
+     * By default, specifying kDNSServiceInterfaceIndexAny does not include P2P interfaces.
+     */
+
+    kDNSServiceFlagsWakeOnResolve      = 0x40000,
+    /*
+    * This flag is meaningful only in DNSServiceResolve. When set, it tries to send a magic packet
+    * to wake up the client.
+    */
+
+    kDNSServiceFlagsBackgroundTrafficClass  = 0x80000,
+    /*
+    * This flag is meaningful for Unicast DNS queries. When set, it uses the background traffic 
+    * class for packets that service the request.
+    */
+
+    kDNSServiceFlagsIncludeAWDL      = 0x100000,
+   /*
+    * Include AWDL interface when kDNSServiceInterfaceIndexAny is specified.
+    */
+
+    kDNSServiceFlagsValidate               = 0x200000,
+   /*
+    * This flag is meaningful in DNSServiceGetAddrInfo and DNSServiceQueryRecord. This is the ONLY flag to be valid 
+    * as an input to the APIs and also an output through the callbacks in the APIs.
+    *
+    * When this flag is passed to DNSServiceQueryRecord and DNSServiceGetAddrInfo to resolve unicast names, 
+    * the response  will be validated using DNSSEC. The validation results are delivered using the flags field in 
+    * the callback and kDNSServiceFlagsValidate is marked in the flags to indicate that DNSSEC status is also available.
+    * When the callback is called to deliver the query results, the validation results may or may not be available. 
+    * If it is not delivered along with the results, the validation status is delivered when the validation completes.
+    * 
+    * When the validation results are delivered in the callback, it is indicated by marking the flags with
+    * kDNSServiceFlagsValidate and kDNSServiceFlagsAdd along with the DNSSEC status flags (described below) and a NULL
+    * sockaddr will be returned for DNSServiceGetAddrInfo and zero length rdata will be returned for DNSServiceQueryRecord.
+    * DNSSEC validation results are for the whole RRSet and not just individual records delivered in the callback. When
+    * kDNSServiceFlagsAdd is not set in the flags, applications should implicitly assume that the DNSSEC status of the 
+    * RRSet that has been delivered up until that point is not valid anymore, till another callback is called with
+    * kDNSServiceFlagsAdd and kDNSServiceFlagsValidate.
+    *
+    * The following four flags indicate the status of the DNSSEC validation and marked in the flags field of the callback.
+    * When any of the four flags is set, kDNSServiceFlagsValidate will also be set. To check the validation status, the 
+    * other applicable output flags should be masked. See kDNSServiceOutputFlags below.
+    */
+
+    kDNSServiceFlagsSecure                 = 0x200010,
+   /*
+    * The response has been validated by verifying all the signaures in the response and was able to
+    * build a successful authentication chain starting from a known trust anchor.   
+    */
+
+    kDNSServiceFlagsInsecure               = 0x200020,
+   /*
+    * A chain of trust cannot be built starting from a known trust anchor to the response.
+    */
+
+    kDNSServiceFlagsBogus                  = 0x200040,
+   /*
+    * If the response cannot be verified to be secure due to expired signatures, missing signatures etc.,
+    * then the results are considered to be bogus.
+    */
+
+    kDNSServiceFlagsIndeterminate          = 0x200080,
+   /*
+    * There is no valid trust anchor that can be used to determine whether a response is secure or not.
+    */
+
+    kDNSServiceFlagsUnicastResponse        = 0x400000,
+   /*
+    * Request unicast response to query.
+    */
+    kDNSServiceFlagsValidateOptional       = 0x800000,
+
+    /*
+     * This flag is identical to kDNSServiceFlagsValidate except for the case where the response
+     * cannot be validated. If this flag is set in DNSServiceQueryRecord or DNSServiceGetAddrInfo,
+     * the DNSSEC records will be requested for validation. If they cannot be received for some reason
+     * during the validation (e.g., zone is not signed, zone is signed but cannot be traced back to
+     * root, recursive server does not understand DNSSEC etc.), then this will fallback to the default
+     * behavior where the validation will not be performed and no DNSSEC results will be provided.
+     *
+     * If the zone is signed and there is a valid path to a known trust anchor configured in the system
+     * and the application requires DNSSEC validation irrespective of the DNSSEC awareness in the current
+     * network, then this option MUST not be used. This is only intended to be used during the transition
+     * period where the different nodes participating in the DNS resolution may not understand DNSSEC or
+     * managed properly (e.g. missing DS record) but still want to be able to resolve DNS successfully.
+     */
+
+    kDNSServiceFlagsWakeOnlyService        = 0x1000000,
+    /*
+     * This flag is meaningful only in DNSServiceRegister. When set, the service will not be registered
+     * with sleep proxy server during sleep.
+     */
+
+    kDNSServiceFlagsThresholdOne           = 0x2000000,
+    kDNSServiceFlagsThresholdFinder        = 0x4000000,
+    kDNSServiceFlagsThresholdReached       = kDNSServiceFlagsThresholdOne,
+    /*
+     * kDNSServiceFlagsThresholdOne is meaningful only in DNSServiceBrowse. When set,
+     * the system will stop issuing browse queries on the network once the number
+     * of answers returned is one or more.  It will issue queries on the network
+     * again if the number of answers drops to zero.
+     * This flag is for Apple internal use only. Third party developers
+     * should not rely on this behavior being supported in any given software release.
+     *
+     * kDNSServiceFlagsThresholdFinder is meaningful only in DNSServiceBrowse. When set,
+     * the system will stop issuing browse queries on the network once the number
+     * of answers has reached the threshold set for Finder.
+     * It will issue queries on the network again if the number of answers drops below
+     * this threshold.
+     * This flag is for Apple internal use only. Third party developers
+     * should not rely on this behavior being supported in any given software release.
+     *
+     * When kDNSServiceFlagsThresholdReached is set in the client callback add or remove event,
+     * it indicates that the browse answer threshold has been reached and no 
+     * browse requests will be generated on the network until the number of answers falls
+     * below the threshold value.  Add and remove events can still occur based
+     * on incoming Bonjour traffic observed by the system.
+     * The set of services return to the client is not guaranteed to represent the 
+     * entire set of services present on the network once the threshold has been reached.
+     *
+     * Note, while kDNSServiceFlagsThresholdReached and kDNSServiceFlagsThresholdOne
+     * have the same value, there  isn't a conflict because kDNSServiceFlagsThresholdReached
+     * is only set in the callbacks and kDNSServiceFlagsThresholdOne is only set on
+     * input to a DNSServiceBrowse call.
+     */
+     kDNSServiceFlagsDenyCellular           = 0x8000000,
+    /*
+     * This flag is meaningful only for Unicast DNS queries. When set, the kernel will restrict
+     * DNS resolutions on the cellular interface for that request.
+     */
+
+     kDNSServiceFlagsServiceIndex           = 0x10000000,
+    /*
+     * This flag is meaningful only for DNSServiceGetAddrInfo() for Unicast DNS queries.
+     * When set, DNSServiceGetAddrInfo() will interpret the "interfaceIndex" argument of the call
+     * as the "serviceIndex".
+     */
+
+     kDNSServiceFlagsDenyExpensive          = 0x20000000
+    /*
+     * This flag is meaningful only for Unicast DNS queries. When set, the kernel will restrict
+     * DNS resolutions on interfaces defined as expensive for that request.
+     */
+
+};
+
+#define kDNSServiceOutputFlags (kDNSServiceFlagsValidate | kDNSServiceFlagsValidateOptional | kDNSServiceFlagsMoreComing | kDNSServiceFlagsAdd | kDNSServiceFlagsDefault)
+   /* All the output flags excluding the DNSSEC Status flags. Typically used to check DNSSEC Status */
+
+/* Possible protocol values */
+enum
+{
+    /* for DNSServiceGetAddrInfo() */
+    kDNSServiceProtocol_IPv4 = 0x01,
+    kDNSServiceProtocol_IPv6 = 0x02,
+    /* 0x04 and 0x08 reserved for future internetwork protocols */
+
+    /* for DNSServiceNATPortMappingCreate() */
+    kDNSServiceProtocol_UDP  = 0x10,
+    kDNSServiceProtocol_TCP  = 0x20
+                               /* 0x40 and 0x80 reserved for future transport protocols, e.g. SCTP [RFC 2960]
+                                * or DCCP [RFC 4340]. If future NAT gateways are created that support port
+                                * mappings for these protocols, new constants will be defined here.
+                                */
+};
+
+/*
+ * The values for DNS Classes and Types are listed in RFC 1035, and are available
+ * on every OS in its DNS header file. Unfortunately every OS does not have the
+ * same header file containing DNS Class and Type constants, and the names of
+ * the constants are not consistent. For example, BIND 8 uses "T_A",
+ * BIND 9 uses "ns_t_a", Windows uses "DNS_TYPE_A", etc.
+ * For this reason, these constants are also listed here, so that code using
+ * the DNS-SD programming APIs can use these constants, so that the same code
+ * can compile on all our supported platforms.
+ */
+
+enum
+{
+    kDNSServiceClass_IN       = 1       /* Internet */
+};
+
+enum
+{
+    kDNSServiceType_A          = 1,      /* Host address. */
+    kDNSServiceType_NS         = 2,      /* Authoritative server. */
+    kDNSServiceType_MD         = 3,      /* Mail destination. */
+    kDNSServiceType_MF         = 4,      /* Mail forwarder. */
+    kDNSServiceType_CNAME      = 5,      /* Canonical name. */
+    kDNSServiceType_SOA        = 6,      /* Start of authority zone. */
+    kDNSServiceType_MB         = 7,      /* Mailbox domain name. */
+    kDNSServiceType_MG         = 8,      /* Mail group member. */
+    kDNSServiceType_MR         = 9,      /* Mail rename name. */
+    kDNSServiceType_NULL       = 10,     /* Null resource record. */
+    kDNSServiceType_WKS        = 11,     /* Well known service. */
+    kDNSServiceType_PTR        = 12,     /* Domain name pointer. */
+    kDNSServiceType_HINFO      = 13,     /* Host information. */
+    kDNSServiceType_MINFO      = 14,     /* Mailbox information. */
+    kDNSServiceType_MX         = 15,     /* Mail routing information. */
+    kDNSServiceType_TXT        = 16,     /* One or more text strings (NOT "zero or more..."). */
+    kDNSServiceType_RP         = 17,     /* Responsible person. */
+    kDNSServiceType_AFSDB      = 18,     /* AFS cell database. */
+    kDNSServiceType_X25        = 19,     /* X_25 calling address. */
+    kDNSServiceType_ISDN       = 20,     /* ISDN calling address. */
+    kDNSServiceType_RT         = 21,     /* Router. */
+    kDNSServiceType_NSAP       = 22,     /* NSAP address. */
+    kDNSServiceType_NSAP_PTR   = 23,     /* Reverse NSAP lookup (deprecated). */
+    kDNSServiceType_SIG        = 24,     /* Security signature. */
+    kDNSServiceType_KEY        = 25,     /* Security key. */
+    kDNSServiceType_PX         = 26,     /* X.400 mail mapping. */
+    kDNSServiceType_GPOS       = 27,     /* Geographical position (withdrawn). */
+    kDNSServiceType_AAAA       = 28,     /* IPv6 Address. */
+    kDNSServiceType_LOC        = 29,     /* Location Information. */
+    kDNSServiceType_NXT        = 30,     /* Next domain (security). */
+    kDNSServiceType_EID        = 31,     /* Endpoint identifier. */
+    kDNSServiceType_NIMLOC     = 32,     /* Nimrod Locator. */
+    kDNSServiceType_SRV        = 33,     /* Server Selection. */
+    kDNSServiceType_ATMA       = 34,     /* ATM Address */
+    kDNSServiceType_NAPTR      = 35,     /* Naming Authority PoinTeR */
+    kDNSServiceType_KX         = 36,     /* Key Exchange */
+    kDNSServiceType_CERT       = 37,     /* Certification record */
+    kDNSServiceType_A6         = 38,     /* IPv6 Address (deprecated) */
+    kDNSServiceType_DNAME      = 39,     /* Non-terminal DNAME (for IPv6) */
+    kDNSServiceType_SINK       = 40,     /* Kitchen sink (experimental) */
+    kDNSServiceType_OPT        = 41,     /* EDNS0 option (meta-RR) */
+    kDNSServiceType_APL        = 42,     /* Address Prefix List */
+    kDNSServiceType_DS         = 43,     /* Delegation Signer */
+    kDNSServiceType_SSHFP      = 44,     /* SSH Key Fingerprint */
+    kDNSServiceType_IPSECKEY   = 45,     /* IPSECKEY */
+    kDNSServiceType_RRSIG      = 46,     /* RRSIG */
+    kDNSServiceType_NSEC       = 47,     /* Denial of Existence */
+    kDNSServiceType_DNSKEY     = 48,     /* DNSKEY */
+    kDNSServiceType_DHCID      = 49,     /* DHCP Client Identifier */
+    kDNSServiceType_NSEC3      = 50,     /* Hashed Authenticated Denial of Existence */
+    kDNSServiceType_NSEC3PARAM = 51,     /* Hashed Authenticated Denial of Existence */
+
+    kDNSServiceType_HIP        = 55,     /* Host Identity Protocol */
+
+    kDNSServiceType_SPF        = 99,     /* Sender Policy Framework for E-Mail */
+    kDNSServiceType_UINFO      = 100,    /* IANA-Reserved */
+    kDNSServiceType_UID        = 101,    /* IANA-Reserved */
+    kDNSServiceType_GID        = 102,    /* IANA-Reserved */
+    kDNSServiceType_UNSPEC     = 103,    /* IANA-Reserved */
+
+    kDNSServiceType_TKEY       = 249,    /* Transaction key */
+    kDNSServiceType_TSIG       = 250,    /* Transaction signature. */
+    kDNSServiceType_IXFR       = 251,    /* Incremental zone transfer. */
+    kDNSServiceType_AXFR       = 252,    /* Transfer zone of authority. */
+    kDNSServiceType_MAILB      = 253,    /* Transfer mailbox records. */
+    kDNSServiceType_MAILA      = 254,    /* Transfer mail agent records. */
+    kDNSServiceType_ANY        = 255     /* Wildcard match. */
+};
+
+/* possible error code values */
+enum
+{
+    kDNSServiceErr_NoError                   = 0,
+    kDNSServiceErr_Unknown                   = -65537,  /* 0xFFFE FFFF */
+    kDNSServiceErr_NoSuchName                = -65538,
+    kDNSServiceErr_NoMemory                  = -65539,
+    kDNSServiceErr_BadParam                  = -65540,
+    kDNSServiceErr_BadReference              = -65541,
+    kDNSServiceErr_BadState                  = -65542,
+    kDNSServiceErr_BadFlags                  = -65543,
+    kDNSServiceErr_Unsupported               = -65544,
+    kDNSServiceErr_NotInitialized            = -65545,
+    kDNSServiceErr_AlreadyRegistered         = -65547,
+    kDNSServiceErr_NameConflict              = -65548,
+    kDNSServiceErr_Invalid                   = -65549,
+    kDNSServiceErr_Firewall                  = -65550,
+    kDNSServiceErr_Incompatible              = -65551,  /* client library incompatible with daemon */
+    kDNSServiceErr_BadInterfaceIndex         = -65552,
+    kDNSServiceErr_Refused                   = -65553,
+    kDNSServiceErr_NoSuchRecord              = -65554,
+    kDNSServiceErr_NoAuth                    = -65555,
+    kDNSServiceErr_NoSuchKey                 = -65556,
+    kDNSServiceErr_NATTraversal              = -65557,
+    kDNSServiceErr_DoubleNAT                 = -65558,
+    kDNSServiceErr_BadTime                   = -65559,  /* Codes up to here existed in Tiger */
+    kDNSServiceErr_BadSig                    = -65560,
+    kDNSServiceErr_BadKey                    = -65561,
+    kDNSServiceErr_Transient                 = -65562,
+    kDNSServiceErr_ServiceNotRunning         = -65563,  /* Background daemon not running */
+    kDNSServiceErr_NATPortMappingUnsupported = -65564,  /* NAT doesn't support PCP, NAT-PMP or UPnP */
+    kDNSServiceErr_NATPortMappingDisabled    = -65565,  /* NAT supports PCP, NAT-PMP or UPnP, but it's disabled by the administrator */
+    kDNSServiceErr_NoRouter                  = -65566,  /* No router currently configured (probably no network connectivity) */
+    kDNSServiceErr_PollingMode               = -65567,
+    kDNSServiceErr_Timeout                   = -65568
+
+                                               /* mDNS Error codes are in the range
+                                                * FFFE FF00 (-65792) to FFFE FFFF (-65537) */
+};
+
+/* Maximum length, in bytes, of a service name represented as a */
+/* literal C-String, including the terminating NULL at the end. */
+
+#define kDNSServiceMaxServiceName 64
+
+/* Maximum length, in bytes, of a domain name represented as an *escaped* C-String */
+/* including the final trailing dot, and the C-String terminating NULL at the end. */
+
+#define kDNSServiceMaxDomainName 1009
+
+/*
+ * Notes on DNS Name Escaping
+ *   -- or --
+ * "Why is kDNSServiceMaxDomainName 1009, when the maximum legal domain name is 256 bytes?"
+ *
+ * All strings used in the DNS-SD APIs are UTF-8 strings. Apart from the exceptions noted below,
+ * the APIs expect the strings to be properly escaped, using the conventional DNS escaping rules:
+ *
+ *   '\\' represents a single literal '\' in the name
+ *   '\.' represents a single literal '.' in the name
+ *   '\ddd', where ddd is a three-digit decimal value from 000 to 255,
+ *        represents a single literal byte with that value.
+ *   A bare unescaped '.' is a label separator, marking a boundary between domain and subdomain.
+ *
+ * The exceptions, that do not use escaping, are the routines where the full
+ * DNS name of a resource is broken, for convenience, into servicename/regtype/domain.
+ * In these routines, the "servicename" is NOT escaped. It does not need to be, since
+ * it is, by definition, just a single literal string. Any characters in that string
+ * represent exactly what they are. The "regtype" portion is, technically speaking,
+ * escaped, but since legal regtypes are only allowed to contain letters, digits,
+ * and hyphens, there is nothing to escape, so the issue is moot. The "domain"
+ * portion is also escaped, though most domains in use on the public Internet
+ * today, like regtypes, don't contain any characters that need to be escaped.
+ * As DNS-SD becomes more popular, rich-text domains for service discovery will
+ * become common, so software should be written to cope with domains with escaping.
+ *
+ * The servicename may be up to 63 bytes of UTF-8 text (not counting the C-String
+ * terminating NULL at the end). The regtype is of the form _service._tcp or
+ * _service._udp, where the "service" part is 1-15 characters, which may be
+ * letters, digits, or hyphens. The domain part of the three-part name may be
+ * any legal domain, providing that the resulting servicename+regtype+domain
+ * name does not exceed 256 bytes.
+ *
+ * For most software, these issues are transparent. When browsing, the discovered
+ * servicenames should simply be displayed as-is. When resolving, the discovered
+ * servicename/regtype/domain are simply passed unchanged to DNSServiceResolve().
+ * When a DNSServiceResolve() succeeds, the returned fullname is already in
+ * the correct format to pass to standard system DNS APIs such as res_query().
+ * For converting from servicename/regtype/domain to a single properly-escaped
+ * full DNS name, the helper function DNSServiceConstructFullName() is provided.
+ *
+ * The following (highly contrived) example illustrates the escaping process.
+ * Suppose you have an service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp"
+ * in subdomain "4th. Floor" of subdomain "Building 2" of domain "apple.com."
+ * The full (escaped) DNS name of this service's SRV record would be:
+ * Dr\.\032Smith\\Dr\.\032Johnson._ftp._tcp.4th\.\032Floor.Building\0322.apple.com.
+ */
+
+
+/*
+ * Constants for specifying an interface index
+ *
+ * Specific interface indexes are identified via a 32-bit unsigned integer returned
+ * by the if_nametoindex() family of calls.
+ *
+ * If the client passes 0 for interface index, that means "do the right thing",
+ * which (at present) means, "if the name is in an mDNS local multicast domain
+ * (e.g. 'local.', '254.169.in-addr.arpa.', '{8,9,A,B}.E.F.ip6.arpa.') then multicast
+ * on all applicable interfaces, otherwise send via unicast to the appropriate
+ * DNS server." Normally, most clients will use 0 for interface index to
+ * automatically get the default sensible behaviour.
+ *
+ * If the client passes a positive interface index, then for multicast names that
+ * indicates to do the operation only on that one interface. For unicast names the
+ * interface index is ignored unless kDNSServiceFlagsForceMulticast is also set.
+ *
+ * If the client passes kDNSServiceInterfaceIndexLocalOnly when registering
+ * a service, then that service will be found *only* by other local clients
+ * on the same machine that are browsing using kDNSServiceInterfaceIndexLocalOnly
+ * or kDNSServiceInterfaceIndexAny.
+ * If a client has a 'private' service, accessible only to other processes
+ * running on the same machine, this allows the client to advertise that service
+ * in a way such that it does not inadvertently appear in service lists on
+ * all the other machines on the network.
+ *
+ * If the client passes kDNSServiceInterfaceIndexLocalOnly when browsing
+ * then it will find *all* records registered on that same local machine.
+ * Clients explicitly wishing to discover *only* LocalOnly services can
+ * accomplish this by inspecting the interfaceIndex of each service reported
+ * to their DNSServiceBrowseReply() callback function, and discarding those
+ * where the interface index is not kDNSServiceInterfaceIndexLocalOnly.
+ *
+ * kDNSServiceInterfaceIndexP2P is meaningful only in Browse, QueryRecord, Register,
+ * and Resolve operations. It should not be used in other DNSService APIs.
+ *
+ * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceBrowse or
+ *   DNSServiceQueryRecord, it restricts the operation to P2P.
+ *
+ * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceRegister, it is
+ *   mapped internally to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P
+ *   set.
+ *
+ * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceResolve, it is
+ *   mapped internally to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P
+ *   set, because resolving a P2P service may create and/or enable an interface whose 
+ *   index is not known a priori. The resolve callback will indicate the index of the
+ *   interface via which the service can be accessed.
+ *
+ * If applications pass kDNSServiceInterfaceIndexAny to DNSServiceBrowse
+ * or DNSServiceQueryRecord, they must set the kDNSServiceFlagsIncludeP2P flag
+ * to include P2P. In this case, if a service instance or the record being queried
+ * is found over P2P, the resulting ADD event will indicate kDNSServiceInterfaceIndexP2P
+ * as the interface index.
+ */
+
+#define kDNSServiceInterfaceIndexAny 0
+#define kDNSServiceInterfaceIndexLocalOnly ((uint32_t)-1)
+#define kDNSServiceInterfaceIndexUnicast   ((uint32_t)-2)
+#define kDNSServiceInterfaceIndexP2P       ((uint32_t)-3)
+
+typedef uint32_t DNSServiceFlags;
+typedef uint32_t DNSServiceProtocol;
+typedef int32_t DNSServiceErrorType;
+
+
+/*********************************************************************************************
+*
+* Version checking
+*
+*********************************************************************************************/
+
+/* DNSServiceGetProperty() Parameters:
+ *
+ * property:        The requested property.
+ *                  Currently the only property defined is kDNSServiceProperty_DaemonVersion.
+ *
+ * result:          Place to store result.
+ *                  For retrieving DaemonVersion, this should be the address of a uint32_t.
+ *
+ * size:            Pointer to uint32_t containing size of the result location.
+ *                  For retrieving DaemonVersion, this should be sizeof(uint32_t).
+ *                  On return the uint32_t is updated to the size of the data returned.
+ *                  For DaemonVersion, the returned size is always sizeof(uint32_t), but
+ *                  future properties could be defined which return variable-sized results.
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success, or kDNSServiceErr_ServiceNotRunning
+ *                  if the daemon (or "system service" on Windows) is not running.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceGetProperty
+(
+    const char *property,  /* Requested property (i.e. kDNSServiceProperty_DaemonVersion) */
+    void       *result,    /* Pointer to place to store result */
+    uint32_t   *size       /* size of result location */
+);
+
+/*
+ * When requesting kDNSServiceProperty_DaemonVersion, the result pointer must point
+ * to a 32-bit unsigned integer, and the size parameter must be set to sizeof(uint32_t).
+ *
+ * On return, the 32-bit unsigned integer contains the API version number
+ *
+ * For example, Mac OS X 10.4.9 has API version 1080400.
+ * This allows applications to do simple greater-than and less-than comparisons:
+ * e.g. an application that requires at least API version 1080400 can check:
+ *   if (version >= 1080400) ...
+ *
+ * Example usage:
+ * uint32_t version;
+ * uint32_t size = sizeof(version);
+ * DNSServiceErrorType err = DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &version, &size);
+ * if (!err) printf("DNS_SD API version is %d.%d\n", version / 10000, version / 100 % 100);
+ */
+
+#define kDNSServiceProperty_DaemonVersion "DaemonVersion"
+
+
+// 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
+);
+
+/*********************************************************************************************
+*
+* Unix Domain Socket access, DNSServiceRef deallocation, and data processing functions
+*
+*********************************************************************************************/
+
+/* DNSServiceRefSockFD()
+ *
+ * Access underlying Unix domain socket for an initialized DNSServiceRef.
+ * The DNS Service Discovery implementation uses this socket to communicate between the client and
+ * the daemon. The application MUST NOT directly read from or write to this socket.
+ * Access to the socket is provided so that it can be used as a kqueue event source, a CFRunLoop
+ * event source, in a select() loop, etc. When the underlying event management subsystem (kqueue/
+ * select/CFRunLoop etc.) indicates to the client that data is available for reading on the
+ * socket, the client should call DNSServiceProcessResult(), which will extract the daemon's
+ * reply from the socket, and pass it to the appropriate application callback. By using a run
+ * loop or select(), results from the daemon can be processed asynchronously. Alternatively,
+ * a client can choose to fork a thread and have it loop calling "DNSServiceProcessResult(ref);"
+ * If DNSServiceProcessResult() is called when no data is available for reading on the socket, it
+ * will block until data does become available, and then process the data and return to the caller.
+ * The application is reponsible for checking the return value of DNSServiceProcessResult() to determine
+ * if the socket is valid and if it should continue to process data on the socket.
+ * When data arrives on the socket, the client is responsible for calling DNSServiceProcessResult(ref)
+ * in a timely fashion -- if the client allows a large backlog of data to build up the daemon
+ * may terminate the connection.
+ *
+ * sdRef:           A DNSServiceRef initialized by any of the DNSService calls.
+ *
+ * return value:    The DNSServiceRef's underlying socket descriptor, or -1 on
+ *                  error.
+ */
+
+int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef);
+
+
+/* DNSServiceProcessResult()
+ *
+ * Read a reply from the daemon, calling the appropriate application callback. This call will
+ * block until the daemon's response is received. Use DNSServiceRefSockFD() in
+ * conjunction with a run loop or select() to determine the presence of a response from the
+ * server before calling this function to process the reply without blocking. Call this function
+ * at any point if it is acceptable to block until the daemon's response arrives. Note that the
+ * client is responsible for ensuring that DNSServiceProcessResult() is called whenever there is
+ * a reply from the daemon - the daemon may terminate its connection with a client that does not
+ * process the daemon's responses.
+ *
+ * sdRef:           A DNSServiceRef initialized by any of the DNSService calls
+ *                  that take a callback parameter.
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns
+ *                  an error code indicating the specific failure that occurred.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef);
+
+
+/* DNSServiceRefDeallocate()
+ *
+ * Terminate a connection with the daemon and free memory associated with the DNSServiceRef.
+ * Any services or records registered with this DNSServiceRef will be deregistered. Any
+ * Browse, Resolve, or Query operations called with this reference will be terminated.
+ *
+ * Note: If the reference's underlying socket is used in a run loop or select() call, it should
+ * be removed BEFORE DNSServiceRefDeallocate() is called, as this function closes the reference's
+ * socket.
+ *
+ * Note: If the reference was initialized with DNSServiceCreateConnection(), any DNSRecordRefs
+ * created via this reference will be invalidated by this call - the resource records are
+ * deregistered, and their DNSRecordRefs may not be used in subsequent functions. Similarly,
+ * if the reference was initialized with DNSServiceRegister, and an extra resource record was
+ * added to the service via DNSServiceAddRecord(), the DNSRecordRef created by the Add() call
+ * is invalidated when this function is called - the DNSRecordRef may not be used in subsequent
+ * functions.
+ *
+ * Note: This call is to be used only with the DNSServiceRef defined by this API.
+ *
+ * sdRef:           A DNSServiceRef initialized by any of the DNSService calls.
+ *
+ */
+
+void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef);
+
+
+/*********************************************************************************************
+*
+* Domain Enumeration
+*
+*********************************************************************************************/
+
+/* DNSServiceEnumerateDomains()
+ *
+ * Asynchronously enumerate domains available for browsing and registration.
+ *
+ * The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains
+ * are to be found.
+ *
+ * Note that the names returned are (like all of DNS-SD) UTF-8 strings,
+ * and are escaped using standard DNS escaping rules.
+ * (See "Notes on DNS Name Escaping" earlier in this file for more details.)
+ * A graphical browser displaying a hierarchical tree-structured view should cut
+ * the names at the bare dots to yield individual labels, then de-escape each
+ * label according to the escaping rules, and then display the resulting UTF-8 text.
+ *
+ * DNSServiceDomainEnumReply Callback Parameters:
+ *
+ * sdRef:           The DNSServiceRef initialized by DNSServiceEnumerateDomains().
+ *
+ * flags:           Possible values are:
+ *                  kDNSServiceFlagsMoreComing
+ *                  kDNSServiceFlagsAdd
+ *                  kDNSServiceFlagsDefault
+ *
+ * interfaceIndex:  Specifies the interface on which the domain exists. (The index for a given
+ *                  interface is determined via the if_nametoindex() family of calls.)
+ *
+ * errorCode:       Will be kDNSServiceErr_NoError (0) on success, otherwise indicates
+ *                  the failure that occurred (other parameters are undefined if errorCode is nonzero).
+ *
+ * replyDomain:     The name of the domain.
+ *
+ * context:         The context pointer passed to DNSServiceEnumerateDomains.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceDomainEnumReply)
+(
+    DNSServiceRef sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    DNSServiceErrorType errorCode,
+    const char                          *replyDomain,
+    void                                *context
+);
+
+
+/* DNSServiceEnumerateDomains() Parameters:
+ *
+ * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ *                  and the enumeration operation will run indefinitely until the client
+ *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags:           Possible values are:
+ *                  kDNSServiceFlagsBrowseDomains to enumerate domains recommended for browsing.
+ *                  kDNSServiceFlagsRegistrationDomains to enumerate domains recommended
+ *                  for registration.
+ *
+ * interfaceIndex:  If non-zero, specifies the interface on which to look for domains.
+ *                  (the index for a given interface is determined via the if_nametoindex()
+ *                  family of calls.) Most applications will pass 0 to enumerate domains on
+ *                  all interfaces. See "Constants for specifying an interface index" for more details.
+ *
+ * callBack:        The function to be called when a domain is found or the call asynchronously
+ *                  fails.
+ *
+ * context:         An application context pointer which is passed to the callback function
+ *                  (may be NULL).
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ *                  errors are delivered to the callback), otherwise returns an error code indicating
+ *                  the error that occurred (the callback is not invoked and the DNSServiceRef
+ *                  is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
+(
+    DNSServiceRef                       *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    DNSServiceDomainEnumReply callBack,
+    void                                *context  /* may be NULL */
+);
+
+
+/*********************************************************************************************
+*
+*  Service Registration
+*
+*********************************************************************************************/
+
+/* Register a service that is discovered via Browse() and Resolve() calls.
+ *
+ * DNSServiceRegisterReply() Callback Parameters:
+ *
+ * sdRef:           The DNSServiceRef initialized by DNSServiceRegister().
+ *
+ * flags:           When a name is successfully registered, the callback will be
+ *                  invoked with the kDNSServiceFlagsAdd flag set. When Wide-Area
+ *                  DNS-SD is in use, it is possible for a single service to get
+ *                  more than one success callback (e.g. one in the "local" multicast
+ *                  DNS domain, and another in a wide-area unicast DNS domain).
+ *                  If a successfully-registered name later suffers a name conflict
+ *                  or similar problem and has to be deregistered, the callback will
+ *                  be invoked with the kDNSServiceFlagsAdd flag not set. The callback
+ *                  is *not* invoked in the case where the caller explicitly terminates
+ *                  the service registration by calling DNSServiceRefDeallocate(ref);
+ *
+ * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
+ *                  indicate the failure that occurred (including name conflicts,
+ *                  if the kDNSServiceFlagsNoAutoRename flag was used when registering.)
+ *                  Other parameters are undefined if errorCode is nonzero.
+ *
+ * name:            The service name registered (if the application did not specify a name in
+ *                  DNSServiceRegister(), this indicates what name was automatically chosen).
+ *
+ * regtype:         The type of service registered, as it was passed to the callout.
+ *
+ * domain:          The domain on which the service was registered (if the application did not
+ *                  specify a domain in DNSServiceRegister(), this indicates the default domain
+ *                  on which the service was registered).
+ *
+ * context:         The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceRegisterReply)
+(
+    DNSServiceRef sdRef,
+    DNSServiceFlags flags,
+    DNSServiceErrorType errorCode,
+    const char                          *name,
+    const char                          *regtype,
+    const char                          *domain,
+    void                                *context
+);
+
+
+/* DNSServiceRegister() Parameters:
+ *
+ * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ *                  and the registration will remain active indefinitely until the client
+ *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * interfaceIndex:  If non-zero, specifies the interface on which to register the service
+ *                  (the index for a given interface is determined via the if_nametoindex()
+ *                  family of calls.) Most applications will pass 0 to register on all
+ *                  available interfaces. See "Constants for specifying an interface index" for more details.
+ *
+ * flags:           Indicates the renaming behavior on name conflict (most applications
+ *                  will pass 0). See flag definitions above for details.
+ *
+ * name:            If non-NULL, specifies the service name to be registered.
+ *                  Most applications will not specify a name, in which case the computer
+ *                  name is used (this name is communicated to the client via the callback).
+ *                  If a name is specified, it must be 1-63 bytes of UTF-8 text.
+ *                  If the name is longer than 63 bytes it will be automatically truncated
+ *                  to a legal length, unless the NoAutoRename flag is set,
+ *                  in which case kDNSServiceErr_BadParam will be returned.
+ *
+ * regtype:         The service type followed by the protocol, separated by a dot
+ *                  (e.g. "_ftp._tcp"). The service type must be an underscore, followed
+ *                  by 1-15 characters, which may be letters, digits, or hyphens.
+ *                  The transport protocol must be "_tcp" or "_udp". New service types
+ *                  should be registered at <http://www.dns-sd.org/ServiceTypes.html>.
+ *
+ *                  Additional subtypes of the primary service type (where a service
+ *                  type has defined subtypes) follow the primary service type in a
+ *                  comma-separated list, with no additional spaces, e.g.
+ *                      "_primarytype._tcp,_subtype1,_subtype2,_subtype3"
+ *                  Subtypes provide a mechanism for filtered browsing: A client browsing
+ *                  for "_primarytype._tcp" will discover all instances of this type;
+ *                  a client browsing for "_primarytype._tcp,_subtype2" will discover only
+ *                  those instances that were registered with "_subtype2" in their list of
+ *                  registered subtypes.
+ *
+ *                  The subtype mechanism can be illustrated with some examples using the
+ *                  dns-sd command-line tool:
+ *
+ *                  % dns-sd -R Simple _test._tcp "" 1001 &
+ *                  % dns-sd -R Better _test._tcp,HasFeatureA "" 1002 &
+ *                  % dns-sd -R Best   _test._tcp,HasFeatureA,HasFeatureB "" 1003 &
+ *
+ *                  Now:
+ *                  % dns-sd -B _test._tcp             # will find all three services
+ *                  % dns-sd -B _test._tcp,HasFeatureA # finds "Better" and "Best"
+ *                  % dns-sd -B _test._tcp,HasFeatureB # finds only "Best"
+ *
+ *                  Subtype labels may be up to 63 bytes long, and may contain any eight-
+ *                  bit byte values, including zero bytes. However, due to the nature of
+ *                  using a C-string-based API, conventional DNS escaping must be used for
+ *                  dots ('.'), commas (','), backslashes ('\') and zero bytes, as shown below:
+ *
+ *                  % dns-sd -R Test '_test._tcp,s\.one,s\,two,s\\three,s\000four' local 123
+ *
+ *                  When a service is registered, all the clients browsing for the registered
+ *                  type ("regtype") will discover it. If the discovery should be
+ *                  restricted to a smaller set of well known peers, the service can be
+ *                  registered with additional data (group identifier) that is known
+ *                  only to a smaller set of peers. The group identifier should follow primary
+ *                  service type using a colon (":") as a delimeter. If subtypes are also present,
+ *                  it should be given before the subtype as shown below.
+ *
+ *                  % dns-sd -R _test1 _http._tcp:mygroup1 local 1001 
+ *                  % dns-sd -R _test2 _http._tcp:mygroup2 local 1001 
+ *                  % dns-sd -R _test3 _http._tcp:mygroup3,HasFeatureA local 1001 
+ *
+ *                  Now:
+ *                  % dns-sd -B _http._tcp:"mygroup1"                # will discover only test1
+ *                  % dns-sd -B _http._tcp:"mygroup2"                # will discover only test2
+ *                  % dns-sd -B _http._tcp:"mygroup3",HasFeatureA    # will discover only test3
+ *                  
+ *                  By specifying the group information, only the members of that group are
+ *                  discovered.
+ *
+ *                  The group identifier itself is not sent in clear. Only a hash of the group
+ *                  identifier is sent and the clients discover them anonymously. The group identifier
+ *                  may be up to 256 bytes long and may contain any eight bit values except comma which
+ *                  should be escaped.
+ *
+ * domain:          If non-NULL, specifies the domain on which to advertise the service.
+ *                  Most applications will not specify a domain, instead automatically
+ *                  registering in the default domain(s).
+ *
+ * host:            If non-NULL, specifies the SRV target host name. Most applications
+ *                  will not specify a host, instead automatically using the machine's
+ *                  default host name(s). Note that specifying a non-NULL host does NOT
+ *                  create an address record for that host - the application is responsible
+ *                  for ensuring that the appropriate address record exists, or creating it
+ *                  via DNSServiceRegisterRecord().
+ *
+ * port:            The port, in network byte order, on which the service accepts connections.
+ *                  Pass 0 for a "placeholder" service (i.e. a service that will not be discovered
+ *                  by browsing, but will cause a name conflict if another client tries to
+ *                  register that same name). Most clients will not use placeholder services.
+ *
+ * txtLen:          The length of the txtRecord, in bytes. Must be zero if the txtRecord is NULL.
+ *
+ * txtRecord:       The TXT record rdata. A non-NULL txtRecord MUST be a properly formatted DNS
+ *                  TXT record, i.e. <length byte> <data> <length byte> <data> ...
+ *                  Passing NULL for the txtRecord is allowed as a synonym for txtLen=1, txtRecord="",
+ *                  i.e. it creates a TXT record of length one containing a single empty string.
+ *                  RFC 1035 doesn't allow a TXT record to contain *zero* strings, so a single empty
+ *                  string is the smallest legal DNS TXT record.
+ *                  As with the other parameters, the DNSServiceRegister call copies the txtRecord
+ *                  data; e.g. if you allocated the storage for the txtRecord parameter with malloc()
+ *                  then you can safely free that memory right after the DNSServiceRegister call returns.
+ *
+ * callBack:        The function to be called when the registration completes or asynchronously
+ *                  fails. The client MAY pass NULL for the callback -  The client will NOT be notified
+ *                  of the default values picked on its behalf, and the client will NOT be notified of any
+ *                  asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration
+ *                  of the service. The client may NOT pass the NoAutoRename flag if the callback is NULL.
+ *                  The client may still deregister the service at any time via DNSServiceRefDeallocate().
+ *
+ * context:         An application context pointer which is passed to the callback function
+ *                  (may be NULL).
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ *                  errors are delivered to the callback), otherwise returns an error code indicating
+ *                  the error that occurred (the callback is never invoked and the DNSServiceRef
+ *                  is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceRegister
+(
+    DNSServiceRef                       *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    const char                          *name,         /* may be NULL */
+    const char                          *regtype,
+    const char                          *domain,       /* may be NULL */
+    const char                          *host,         /* may be NULL */
+    uint16_t port,                                     /* In network byte order */
+    uint16_t txtLen,
+    const void                          *txtRecord,    /* may be NULL */
+    DNSServiceRegisterReply callBack,                  /* may be NULL */
+    void                                *context       /* may be NULL */
+);
+
+
+/* DNSServiceAddRecord()
+ *
+ * Add a record to a registered service. The name of the record will be the same as the
+ * registered service's name.
+ * The record can later be updated or deregistered by passing the RecordRef initialized
+ * by this function to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
+ *
+ * Note that the DNSServiceAddRecord/UpdateRecord/RemoveRecord are *NOT* thread-safe
+ * with respect to a single DNSServiceRef. If you plan to have multiple threads
+ * in your program simultaneously add, update, or remove records from the same
+ * DNSServiceRef, then it's the caller's responsibility to use a mutext lock
+ * or take similar appropriate precautions to serialize those calls.
+ *
+ * Parameters;
+ *
+ * sdRef:           A DNSServiceRef initialized by DNSServiceRegister().
+ *
+ * RecordRef:       A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this
+ *                  call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
+ *                  If the above DNSServiceRef is passed to DNSServiceRefDeallocate(), RecordRef is also
+ *                  invalidated and may not be used further.
+ *
+ * flags:           Currently ignored, reserved for future use.
+ *
+ * rrtype:          The type of the record (e.g. kDNSServiceType_TXT, kDNSServiceType_SRV, etc)
+ *
+ * rdlen:           The length, in bytes, of the rdata.
+ *
+ * rdata:           The raw rdata to be contained in the added resource record.
+ *
+ * ttl:             The time to live of the resource record, in seconds.
+ *                  Most clients should pass 0 to indicate that the system should
+ *                  select a sensible default value.
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns an
+ *                  error code indicating the error that occurred (the RecordRef is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceAddRecord
+(
+    DNSServiceRef sdRef,
+    DNSRecordRef                        *RecordRef,
+    DNSServiceFlags flags,
+    uint16_t rrtype,
+    uint16_t rdlen,
+    const void                          *rdata,
+    uint32_t ttl
+);
+
+
+/* DNSServiceUpdateRecord
+ *
+ * Update a registered resource record. The record must either be:
+ *   - The primary txt record of a service registered via DNSServiceRegister()
+ *   - A record added to a registered service via DNSServiceAddRecord()
+ *   - An individual record registered by DNSServiceRegisterRecord()
+ *
+ * Parameters:
+ *
+ * sdRef:           A DNSServiceRef that was initialized by DNSServiceRegister()
+ *                  or DNSServiceCreateConnection().
+ *
+ * RecordRef:       A DNSRecordRef initialized by DNSServiceAddRecord, or NULL to update the
+ *                  service's primary txt record.
+ *
+ * flags:           Currently ignored, reserved for future use.
+ *
+ * rdlen:           The length, in bytes, of the new rdata.
+ *
+ * rdata:           The new rdata to be contained in the updated resource record.
+ *
+ * ttl:             The time to live of the updated resource record, in seconds.
+ *                  Most clients should pass 0 to indicate that the system should
+ *                  select a sensible default value.
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns an
+ *                  error code indicating the error that occurred.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
+(
+    DNSServiceRef sdRef,
+    DNSRecordRef RecordRef,                            /* may be NULL */
+    DNSServiceFlags flags,
+    uint16_t rdlen,
+    const void                          *rdata,
+    uint32_t ttl
+);
+
+
+/* DNSServiceRemoveRecord
+ *
+ * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister
+ * an record registered individually via DNSServiceRegisterRecord().
+ *
+ * Parameters:
+ *
+ * sdRef:           A DNSServiceRef initialized by DNSServiceRegister() (if the
+ *                  record being removed was registered via DNSServiceAddRecord()) or by
+ *                  DNSServiceCreateConnection() (if the record being removed was registered via
+ *                  DNSServiceRegisterRecord()).
+ *
+ * recordRef:       A DNSRecordRef initialized by a successful call to DNSServiceAddRecord()
+ *                  or DNSServiceRegisterRecord().
+ *
+ * flags:           Currently ignored, reserved for future use.
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success, otherwise returns an
+ *                  error code indicating the error that occurred.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
+(
+    DNSServiceRef sdRef,
+    DNSRecordRef RecordRef,
+    DNSServiceFlags flags
+);
+
+
+/*********************************************************************************************
+*
+*  Service Discovery
+*
+*********************************************************************************************/
+
+/* Browse for instances of a service.
+ *
+ * DNSServiceBrowseReply() Parameters:
+ *
+ * sdRef:           The DNSServiceRef initialized by DNSServiceBrowse().
+ *
+ * flags:           Possible values are kDNSServiceFlagsMoreComing and kDNSServiceFlagsAdd.
+ *                  See flag definitions for details.
+ *
+ * interfaceIndex:  The interface on which the service is advertised. This index should
+ *                  be passed to DNSServiceResolve() when resolving the service.
+ *
+ * errorCode:       Will be kDNSServiceErr_NoError (0) on success, otherwise will
+ *                  indicate the failure that occurred. Other parameters are undefined if
+ *                  the errorCode is nonzero.
+ *
+ * serviceName:     The discovered service name. This name should be displayed to the user,
+ *                  and stored for subsequent use in the DNSServiceResolve() call.
+ *
+ * regtype:         The service type, which is usually (but not always) the same as was passed
+ *                  to DNSServiceBrowse(). One case where the discovered service type may
+ *                  not be the same as the requested service type is when using subtypes:
+ *                  The client may want to browse for only those ftp servers that allow
+ *                  anonymous connections. The client will pass the string "_ftp._tcp,_anon"
+ *                  to DNSServiceBrowse(), but the type of the service that's discovered
+ *                  is simply "_ftp._tcp". The regtype for each discovered service instance
+ *                  should be stored along with the name, so that it can be passed to
+ *                  DNSServiceResolve() when the service is later resolved.
+ *
+ * domain:          The domain of the discovered service instance. This may or may not be the
+ *                  same as the domain that was passed to DNSServiceBrowse(). The domain for each
+ *                  discovered service instance should be stored along with the name, so that
+ *                  it can be passed to DNSServiceResolve() when the service is later resolved.
+ *
+ * context:         The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceBrowseReply)
+(
+    DNSServiceRef sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    DNSServiceErrorType errorCode,
+    const char                          *serviceName,
+    const char                          *regtype,
+    const char                          *replyDomain,
+    void                                *context
+);
+
+
+/* DNSServiceBrowse() Parameters:
+ *
+ * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ *                  and the browse operation will run indefinitely until the client
+ *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags:           Currently ignored, reserved for future use.
+ *
+ * interfaceIndex:  If non-zero, specifies the interface on which to browse for services
+ *                  (the index for a given interface is determined via the if_nametoindex()
+ *                  family of calls.) Most applications will pass 0 to browse on all available
+ *                  interfaces. See "Constants for specifying an interface index" for more details.
+ *
+ * regtype:         The service type being browsed for followed by the protocol, separated by a
+ *                  dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
+ *                  A client may optionally specify a single subtype to perform filtered browsing:
+ *                  e.g. browsing for "_primarytype._tcp,_subtype" will discover only those
+ *                  instances of "_primarytype._tcp" that were registered specifying "_subtype"
+ *                  in their list of registered subtypes. Additionally, a group identifier may
+ *                  also be specified before the subtype e.g., _primarytype._tcp:GroupID, which
+ *                  will discover only the members that register the service with GroupID. See
+ *                  DNSServiceRegister for more details.
+ *
+ * domain:          If non-NULL, specifies the domain on which to browse for services.
+ *                  Most applications will not specify a domain, instead browsing on the
+ *                  default domain(s).
+ *
+ * callBack:        The function to be called when an instance of the service being browsed for
+ *                  is found, or if the call asynchronously fails.
+ *
+ * context:         An application context pointer which is passed to the callback function
+ *                  (may be NULL).
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ *                  errors are delivered to the callback), otherwise returns an error code indicating
+ *                  the error that occurred (the callback is not invoked and the DNSServiceRef
+ *                  is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceBrowse
+(
+    DNSServiceRef                       *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    const char                          *regtype,
+    const char                          *domain,    /* may be NULL */
+    DNSServiceBrowseReply callBack,
+    void                                *context    /* may be NULL */
+);
+
+
+/* DNSServiceResolve()
+ *
+ * Resolve a service name discovered via DNSServiceBrowse() to a target host name, port number, and
+ * txt record.
+ *
+ * Note: Applications should NOT use DNSServiceResolve() solely for txt record monitoring - use
+ * DNSServiceQueryRecord() instead, as it is more efficient for this task.
+ *
+ * Note: When the desired results have been returned, the client MUST terminate the resolve by calling
+ * DNSServiceRefDeallocate().
+ *
+ * Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record
+ * and a single TXT record. To resolve non-standard services with multiple SRV or TXT records,
+ * DNSServiceQueryRecord() should be used.
+ *
+ * DNSServiceResolveReply Callback Parameters:
+ *
+ * sdRef:           The DNSServiceRef initialized by DNSServiceResolve().
+ *
+ * flags:           Possible values: kDNSServiceFlagsMoreComing
+ *
+ * interfaceIndex:  The interface on which the service was resolved.
+ *
+ * errorCode:       Will be kDNSServiceErr_NoError (0) on success, otherwise will
+ *                  indicate the failure that occurred. Other parameters are undefined if
+ *                  the errorCode is nonzero.
+ *
+ * fullname:        The full service domain name, in the form <servicename>.<protocol>.<domain>.
+ *                  (This name is escaped following standard DNS rules, making it suitable for
+ *                  passing to standard system DNS APIs such as res_query(), or to the
+ *                  special-purpose functions included in this API that take fullname parameters.
+ *                  See "Notes on DNS Name Escaping" earlier in this file for more details.)
+ *
+ * hosttarget:      The target hostname of the machine providing the service. This name can
+ *                  be passed to functions like gethostbyname() to identify the host's IP address.
+ *
+ * port:            The port, in network byte order, on which connections are accepted for this service.
+ *
+ * txtLen:          The length of the txt record, in bytes.
+ *
+ * txtRecord:       The service's primary txt record, in standard txt record format.
+ *
+ * context:         The context pointer that was passed to the callout.
+ *
+ * NOTE: In earlier versions of this header file, the txtRecord parameter was declared "const char *"
+ * This is incorrect, since it contains length bytes which are values in the range 0 to 255, not -128 to +127.
+ * Depending on your compiler settings, this change may cause signed/unsigned mismatch warnings.
+ * These should be fixed by updating your own callback function definition to match the corrected
+ * function signature using "const unsigned char *txtRecord". Making this change may also fix inadvertent
+ * bugs in your callback function, where it could have incorrectly interpreted a length byte with value 250
+ * as being -6 instead, with various bad consequences ranging from incorrect operation to software crashes.
+ * If you need to maintain portable code that will compile cleanly with both the old and new versions of
+ * this header file, you should update your callback function definition to use the correct unsigned value,
+ * and then in the place where you pass your callback function to DNSServiceResolve(), use a cast to eliminate
+ * the compiler warning, e.g.:
+ *   DNSServiceResolve(sd, flags, index, name, regtype, domain, (DNSServiceResolveReply)MyCallback, context);
+ * This will ensure that your code compiles cleanly without warnings (and more importantly, works correctly)
+ * with both the old header and with the new corrected version.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceResolveReply)
+(
+    DNSServiceRef sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    DNSServiceErrorType errorCode,
+    const char                          *fullname,
+    const char                          *hosttarget,
+    uint16_t port,                                   /* In network byte order */
+    uint16_t txtLen,
+    const unsigned char                 *txtRecord,
+    void                                *context
+);
+
+
+/* DNSServiceResolve() Parameters
+ *
+ * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ *                  and the resolve operation will run indefinitely until the client
+ *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags:           Specifying kDNSServiceFlagsForceMulticast will cause query to be
+ *                  performed with a link-local mDNS query, even if the name is an
+ *                  apparently non-local name (i.e. a name not ending in ".local.")
+ *
+ * interfaceIndex:  The interface on which to resolve the service. If this resolve call is
+ *                  as a result of a currently active DNSServiceBrowse() operation, then the
+ *                  interfaceIndex should be the index reported in the DNSServiceBrowseReply
+ *                  callback. If this resolve call is using information previously saved
+ *                  (e.g. in a preference file) for later use, then use interfaceIndex 0, because
+ *                  the desired service may now be reachable via a different physical interface.
+ *                  See "Constants for specifying an interface index" for more details.
+ *
+ * name:            The name of the service instance to be resolved, as reported to the
+ *                  DNSServiceBrowseReply() callback.
+ *
+ * regtype:         The type of the service instance to be resolved, as reported to the
+ *                  DNSServiceBrowseReply() callback.
+ *
+ * domain:          The domain of the service instance to be resolved, as reported to the
+ *                  DNSServiceBrowseReply() callback.
+ *
+ * callBack:        The function to be called when a result is found, or if the call
+ *                  asynchronously fails.
+ *
+ * context:         An application context pointer which is passed to the callback function
+ *                  (may be NULL).
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ *                  errors are delivered to the callback), otherwise returns an error code indicating
+ *                  the error that occurred (the callback is never invoked and the DNSServiceRef
+ *                  is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceResolve
+(
+    DNSServiceRef                       *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    const char                          *name,
+    const char                          *regtype,
+    const char                          *domain,
+    DNSServiceResolveReply callBack,
+    void                                *context  /* may be NULL */
+);
+
+
+/*********************************************************************************************
+*
+*  Querying Individual Specific Records
+*
+*********************************************************************************************/
+
+/* DNSServiceQueryRecord
+ *
+ * Query for an arbitrary DNS record.
+ *
+ * DNSServiceQueryRecordReply() Callback Parameters:
+ *
+ * sdRef:           The DNSServiceRef initialized by DNSServiceQueryRecord().
+ *
+ * flags:           Possible values are kDNSServiceFlagsMoreComing and
+ *                  kDNSServiceFlagsAdd. The Add flag is NOT set for PTR records
+ *                  with a ttl of 0, i.e. "Remove" events.
+ *
+ * interfaceIndex:  The interface on which the query was resolved (the index for a given
+ *                  interface is determined via the if_nametoindex() family of calls).
+ *                  See "Constants for specifying an interface index" for more details.
+ *
+ * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
+ *                  indicate the failure that occurred. Other parameters are undefined if
+ *                  errorCode is nonzero.
+ *
+ * fullname:        The resource record's full domain name.
+ *
+ * rrtype:          The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
+ *
+ * rrclass:         The class of the resource record (usually kDNSServiceClass_IN).
+ *
+ * rdlen:           The length, in bytes, of the resource record rdata.
+ *
+ * rdata:           The raw rdata of the resource record.
+ *
+ * ttl:             If the client wishes to cache the result for performance reasons,
+ *                  the TTL indicates how long the client may legitimately hold onto
+ *                  this result, in seconds. After the TTL expires, the client should
+ *                  consider the result no longer valid, and if it requires this data
+ *                  again, it should be re-fetched with a new query. Of course, this
+ *                  only applies to clients that cancel the asynchronous operation when
+ *                  they get a result. Clients that leave the asynchronous operation
+ *                  running can safely assume that the data remains valid until they
+ *                  get another callback telling them otherwise.
+ *
+ * context:         The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceQueryRecordReply)
+(
+    DNSServiceRef sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    DNSServiceErrorType errorCode,
+    const char                          *fullname,
+    uint16_t rrtype,
+    uint16_t rrclass,
+    uint16_t rdlen,
+    const void                          *rdata,
+    uint32_t ttl,
+    void                                *context
+);
+
+
+/* DNSServiceQueryRecord() Parameters:
+ *
+ * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ *                  and the query operation will run indefinitely until the client
+ *                  terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags:           kDNSServiceFlagsForceMulticast or kDNSServiceFlagsLongLivedQuery.
+ *                  Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast
+ *                  query to a unicast DNS server that implements the protocol. This flag
+ *                  has no effect on link-local multicast queries.
+ *
+ * interfaceIndex:  If non-zero, specifies the interface on which to issue the query
+ *                  (the index for a given interface is determined via the if_nametoindex()
+ *                  family of calls.) Passing 0 causes the name to be queried for on all
+ *                  interfaces. See "Constants for specifying an interface index" for more details.
+ *
+ * fullname:        The full domain name of the resource record to be queried for.
+ *
+ * rrtype:          The numerical type of the resource record to be queried for
+ *                  (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
+ *
+ * rrclass:         The class of the resource record (usually kDNSServiceClass_IN).
+ *
+ * callBack:        The function to be called when a result is found, or if the call
+ *                  asynchronously fails.
+ *
+ * context:         An application context pointer which is passed to the callback function
+ *                  (may be NULL).
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ *                  errors are delivered to the callback), otherwise returns an error code indicating
+ *                  the error that occurred (the callback is never invoked and the DNSServiceRef
+ *                  is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
+(
+    DNSServiceRef                       *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    const char                          *fullname,
+    uint16_t rrtype,
+    uint16_t rrclass,
+    DNSServiceQueryRecordReply callBack,
+    void                                *context  /* may be NULL */
+);
+
+
+/*********************************************************************************************
+*
+*  Unified lookup of both IPv4 and IPv6 addresses for a fully qualified hostname
+*
+*********************************************************************************************/
+
+/* DNSServiceGetAddrInfo
+ *
+ * Queries for the IP address of a hostname by using either Multicast or Unicast DNS.
+ *
+ * DNSServiceGetAddrInfoReply() parameters:
+ *
+ * sdRef:           The DNSServiceRef initialized by DNSServiceGetAddrInfo().
+ *
+ * flags:           Possible values are kDNSServiceFlagsMoreComing and
+ *                  kDNSServiceFlagsAdd.
+ *
+ * interfaceIndex:  The interface to which the answers pertain.
+ *
+ * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
+ *                  indicate the failure that occurred.  Other parameters are
+ *                  undefined if errorCode is nonzero.
+ *
+ * hostname:        The fully qualified domain name of the host to be queried for.
+ *
+ * address:         IPv4 or IPv6 address.
+ *
+ * ttl:             If the client wishes to cache the result for performance reasons,
+ *                  the TTL indicates how long the client may legitimately hold onto
+ *                  this result, in seconds. After the TTL expires, the client should
+ *                  consider the result no longer valid, and if it requires this data
+ *                  again, it should be re-fetched with a new query. Of course, this
+ *                  only applies to clients that cancel the asynchronous operation when
+ *                  they get a result. Clients that leave the asynchronous operation
+ *                  running can safely assume that the data remains valid until they
+ *                  get another callback telling them otherwise.
+ *
+ * context:         The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceGetAddrInfoReply)
+(
+    DNSServiceRef sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    DNSServiceErrorType errorCode,
+    const char                       *hostname,
+    const struct sockaddr            *address,
+    uint32_t ttl,
+    void                             *context
+);
+
+
+/* DNSServiceGetAddrInfo() Parameters:
+ *
+ * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds then it
+ *                  initializes the DNSServiceRef, returns kDNSServiceErr_NoError, and the query
+ *                  begins and will last indefinitely until the client terminates the query
+ *                  by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags:           kDNSServiceFlagsForceMulticast
+ *
+ * interfaceIndex:  The interface on which to issue the query.  Passing 0 causes the query to be
+ *                  sent on all active interfaces via Multicast or the primary interface via Unicast.
+ *
+ * protocol:        Pass in kDNSServiceProtocol_IPv4 to look up IPv4 addresses, or kDNSServiceProtocol_IPv6
+ *                  to look up IPv6 addresses, or both to look up both kinds. If neither flag is
+ *                  set, the system will apply an intelligent heuristic, which is (currently)
+ *                  that it will attempt to look up both, except:
+ *
+ *                   * If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name)
+ *                     but this host has no routable IPv6 address, then the call will not try to
+ *                     look up IPv6 addresses for "hostname", since any addresses it found would be
+ *                     unlikely to be of any use anyway. Similarly, if this host has no routable
+ *                     IPv4 address, the call will not try to look up IPv4 addresses for "hostname".
+ *
+ * hostname:        The fully qualified domain name of the host to be queried for.
+ *
+ * callBack:        The function to be called when the query succeeds or fails asynchronously.
+ *
+ * context:         An application context pointer which is passed to the callback function
+ *                  (may be NULL).
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ *                  errors are delivered to the callback), otherwise returns an error code indicating
+ *                  the error that occurred.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo
+(
+    DNSServiceRef                    *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    DNSServiceProtocol protocol,
+    const char                       *hostname,
+    DNSServiceGetAddrInfoReply callBack,
+    void                             *context          /* may be NULL */
+);
+
+
+/*********************************************************************************************
+*
+*  Special Purpose Calls:
+*  DNSServiceCreateConnection(), DNSServiceRegisterRecord(), DNSServiceReconfirmRecord()
+*  (most applications will not use these)
+*
+*********************************************************************************************/
+
+/* DNSServiceCreateConnection()
+ *
+ * Create a connection to the daemon allowing efficient registration of
+ * multiple individual records.
+ *
+ * Parameters:
+ *
+ * sdRef:           A pointer to an uninitialized DNSServiceRef. Deallocating
+ *                  the reference (via DNSServiceRefDeallocate()) severs the
+ *                  connection and deregisters all records registered on this connection.
+ *
+ * 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).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef);
+
+/* DNSServiceRegisterRecord
+ *
+ * Register an individual resource record on a connected DNSServiceRef.
+ *
+ * Note that name conflicts occurring for records registered via this call must be handled
+ * by the client in the callback.
+ *
+ * DNSServiceRegisterRecordReply() parameters:
+ *
+ * sdRef:           The connected DNSServiceRef initialized by
+ *                  DNSServiceCreateConnection().
+ *
+ * RecordRef:       The DNSRecordRef initialized by DNSServiceRegisterRecord(). If the above
+ *                  DNSServiceRef is passed to DNSServiceRefDeallocate(), this DNSRecordRef is
+ *                  invalidated, and may not be used further.
+ *
+ * flags:           Currently unused, reserved for future use.
+ *
+ * errorCode:       Will be kDNSServiceErr_NoError on success, otherwise will
+ *                  indicate the failure that occurred (including name conflicts.)
+ *                  Other parameters are undefined if errorCode is nonzero.
+ *
+ * context:         The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceRegisterRecordReply)
+(
+    DNSServiceRef sdRef,
+    DNSRecordRef RecordRef,
+    DNSServiceFlags flags,
+    DNSServiceErrorType errorCode,
+    void                                *context
+);
+
+
+/* DNSServiceRegisterRecord() Parameters:
+ *
+ * sdRef:           A DNSServiceRef initialized by DNSServiceCreateConnection().
+ *
+ * RecordRef:       A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this
+ *                  call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
+ *                  (To deregister ALL records registered on a single connected DNSServiceRef
+ *                  and deallocate each of their corresponding DNSServiceRecordRefs, call
+ *                  DNSServiceRefDeallocate()).
+ *
+ * flags:           Possible values are kDNSServiceFlagsShared or kDNSServiceFlagsUnique
+ *                  (see flag type definitions for details).
+ *
+ * interfaceIndex:  If non-zero, specifies the interface on which to register the record
+ *                  (the index for a given interface is determined via the if_nametoindex()
+ *                  family of calls.) Passing 0 causes the record to be registered on all interfaces.
+ *                  See "Constants for specifying an interface index" for more details.
+ *
+ * fullname:        The full domain name of the resource record.
+ *
+ * rrtype:          The numerical type of the resource record (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
+ *
+ * rrclass:         The class of the resource record (usually kDNSServiceClass_IN)
+ *
+ * rdlen:           Length, in bytes, of the rdata.
+ *
+ * rdata:           A pointer to the raw rdata, as it is to appear in the DNS record.
+ *
+ * ttl:             The time to live of the resource record, in seconds.
+ *                  Most clients should pass 0 to indicate that the system should
+ *                  select a sensible default value.
+ *
+ * callBack:        The function to be called when a result is found, or if the call
+ *                  asynchronously fails (e.g. because of a name conflict.)
+ *
+ * context:         An application context pointer which is passed to the callback function
+ *                  (may be NULL).
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ *                  errors are delivered to the callback), otherwise returns an error code indicating
+ *                  the error that occurred (the callback is never invoked and the DNSRecordRef is
+ *                  not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
+(
+    DNSServiceRef sdRef,
+    DNSRecordRef                        *RecordRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    const char                          *fullname,
+    uint16_t rrtype,
+    uint16_t rrclass,
+    uint16_t rdlen,
+    const void                          *rdata,
+    uint32_t ttl,
+    DNSServiceRegisterRecordReply callBack,
+    void                                *context    /* may be NULL */
+);
+
+
+/* DNSServiceReconfirmRecord
+ *
+ * Instruct the daemon to verify the validity of a resource record that appears
+ * to be out of date (e.g. because TCP connection to a service's target failed.)
+ * Causes the record to be flushed from the daemon's cache (as well as all other
+ * daemons' caches on the network) if the record is determined to be invalid.
+ * Use this routine conservatively. Reconfirming a record necessarily consumes
+ * network bandwidth, so this should not be done indiscriminately.
+ *
+ * Parameters:
+ *
+ * flags:           Not currently used.
+ *
+ * interfaceIndex:  Specifies the interface of the record in question.
+ *                  The caller must specify the interface.
+ *                  This API (by design) causes increased network traffic, so it requires
+ *                  the caller to be precise about which record should be reconfirmed.
+ *                  It is not possible to pass zero for the interface index to perform
+ *                  a "wildcard" reconfirmation, where *all* matching records are reconfirmed.
+ *
+ * fullname:        The resource record's full domain name.
+ *
+ * rrtype:          The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
+ *
+ * rrclass:         The class of the resource record (usually kDNSServiceClass_IN).
+ *
+ * rdlen:           The length, in bytes, of the resource record rdata.
+ *
+ * rdata:           The raw rdata of the resource record.
+ *
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
+(
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    const char                         *fullname,
+    uint16_t rrtype,
+    uint16_t rrclass,
+    uint16_t rdlen,
+    const void                         *rdata
+);
+
+
+/*********************************************************************************************
+*
+*  NAT Port Mapping
+*
+*********************************************************************************************/
+
+/* DNSServiceNATPortMappingCreate
+ *
+ * Request a port mapping in the NAT gateway, which maps a port on the local machine
+ * to an external port on the NAT. The NAT should support either PCP, NAT-PMP or the
+ * UPnP/IGD protocol for this API to create a successful mapping. Note that this API
+ * currently supports IPv4 addresses/mappings only. If the NAT gateway supports PCP and
+ * returns an IPv6 address (incorrectly, since this API specifically requests IPv4
+ * addresses), the DNSServiceNATPortMappingReply callback will be invoked with errorCode
+ * kDNSServiceErr_NATPortMappingUnsupported.
+ *
+ * The port mapping will be renewed indefinitely until the client process exits, or
+ * explicitly terminates the port mapping request by calling DNSServiceRefDeallocate().
+ * The client callback will be invoked, informing the client of the NAT gateway's
+ * external IP address and the external port that has been allocated for this client.
+ * The client should then record this external IP address and port using whatever
+ * directory service mechanism it is using to enable peers to connect to it.
+ * (Clients advertising services using Wide-Area DNS-SD DO NOT need to use this API
+ * -- when a client calls DNSServiceRegister() NAT mappings are automatically created
+ * and the external IP address and port for the service are recorded in the global DNS.
+ * Only clients using some directory mechanism other than Wide-Area DNS-SD need to use
+ * this API to explicitly map their own ports.)
+ *
+ * It's possible that the client callback could be called multiple times, for example
+ * if the NAT gateway's IP address changes, or if a configuration change results in a
+ * different external port being mapped for this client. Over the lifetime of any long-lived
+ * port mapping, the client should be prepared to handle these notifications of changes
+ * in the environment, and should update its recorded address and/or port as appropriate.
+ *
+ * NOTE: There are two unusual aspects of how the DNSServiceNATPortMappingCreate API works,
+ * which were intentionally designed to help simplify client code:
+ *
+ *  1. It's not an error to request a NAT mapping when the machine is not behind a NAT gateway.
+ *     In other NAT mapping APIs, if you request a NAT mapping and the machine is not behind a NAT
+ *     gateway, then the API returns an error code -- it can't get you a NAT mapping if there's no
+ *     NAT gateway. The DNSServiceNATPortMappingCreate API takes a different view. Working out
+ *     whether or not you need a NAT mapping can be tricky and non-obvious, particularly on
+ *     a machine with multiple active network interfaces. Rather than make every client recreate
+ *     this logic for deciding whether a NAT mapping is required, the PortMapping API does that
+ *     work for you. If the client calls the PortMapping API when the machine already has a
+ *     routable public IP address, then instead of complaining about it and giving an error,
+ *     the PortMapping API just invokes your callback, giving the machine's public address
+ *     and your own port number. This means you don't need to write code to work out whether
+ *     your client needs to call the PortMapping API -- just call it anyway, and if it wasn't
+ *     necessary, no harm is done:
+ *
+ *     - If the machine already has a routable public IP address, then your callback
+ *       will just be invoked giving your own address and port.
+ *     - If a NAT mapping is required and obtained, then your callback will be invoked
+ *       giving you the external address and port.
+ *     - If a NAT mapping is required but not obtained from the local NAT gateway,
+ *       or the machine has no network connectivity, then your callback will be
+ *       invoked giving zero address and port.
+ *
+ *  2. In other NAT mapping APIs, if a laptop computer is put to sleep and woken up on a new
+ *     network, it's the client's job to notice this, and work out whether a NAT mapping
+ *     is required on the new network, and make a new NAT mapping request if necessary.
+ *     The DNSServiceNATPortMappingCreate API does this for you, automatically.
+ *     The client just needs to make one call to the PortMapping API, and its callback will
+ *     be invoked any time the mapping state changes. This property complements point (1) above.
+ *     If the client didn't make a NAT mapping request just because it determined that one was
+ *     not required at that particular moment in time, the client would then have to monitor
+ *     for network state changes to determine if a NAT port mapping later became necessary.
+ *     By unconditionally making a NAT mapping request, even when a NAT mapping not to be
+ *     necessary, the PortMapping API will then begin monitoring network state changes on behalf of
+ *     the client, and if a NAT mapping later becomes necessary, it will automatically create a NAT
+ *     mapping and inform the client with a new callback giving the new address and port information.
+ *
+ * DNSServiceNATPortMappingReply() parameters:
+ *
+ * sdRef:           The DNSServiceRef initialized by DNSServiceNATPortMappingCreate().
+ *
+ * flags:           Currently unused, reserved for future use.
+ *
+ * interfaceIndex:  The interface through which the NAT gateway is reached.
+ *
+ * errorCode:       Will be kDNSServiceErr_NoError on success.
+ *                  Will be kDNSServiceErr_DoubleNAT when the NAT gateway is itself behind one or
+ *                  more layers of NAT, in which case the other parameters have the defined values.
+ *                  For other failures, will indicate the failure that occurred, and the other
+ *                  parameters are undefined.
+ *
+ * externalAddress: Four byte IPv4 address in network byte order.
+ *
+ * protocol:        Will be kDNSServiceProtocol_UDP or kDNSServiceProtocol_TCP or both.
+ *
+ * internalPort:    The port on the local machine that was mapped.
+ *
+ * externalPort:    The actual external port in the NAT gateway that was mapped.
+ *                  This is likely to be different than the requested external port.
+ *
+ * ttl:             The lifetime of the NAT port mapping created on the gateway.
+ *                  This controls how quickly stale mappings will be garbage-collected
+ *                  if the client machine crashes, suffers a power failure, is disconnected
+ *                  from the network, or suffers some other unfortunate demise which
+ *                  causes it to vanish without explicitly removing its NAT port mapping.
+ *                  It's possible that the ttl value will differ from the requested ttl value.
+ *
+ * context:         The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceNATPortMappingReply)
+(
+    DNSServiceRef sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    DNSServiceErrorType errorCode,
+    uint32_t externalAddress,                           /* four byte IPv4 address in network byte order */
+    DNSServiceProtocol protocol,
+    uint16_t internalPort,                              /* In network byte order */
+    uint16_t externalPort,                              /* In network byte order and may be different than the requested port */
+    uint32_t ttl,                                       /* may be different than the requested ttl */
+    void                             *context
+);
+
+
+/* DNSServiceNATPortMappingCreate() Parameters:
+ *
+ * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds then it
+ *                  initializes the DNSServiceRef, returns kDNSServiceErr_NoError, and the nat
+ *                  port mapping will last indefinitely until the client terminates the port
+ *                  mapping request by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags:           Currently ignored, reserved for future use.
+ *
+ * interfaceIndex:  The interface on which to create port mappings in a NAT gateway. Passing 0 causes
+ *                  the port mapping request to be sent on the primary interface.
+ *
+ * protocol:        To request a port mapping, pass in kDNSServiceProtocol_UDP, or kDNSServiceProtocol_TCP,
+ *                  or (kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP) to map both.
+ *                  The local listening port number must also be specified in the internalPort parameter.
+ *                  To just discover the NAT gateway's external IP address, pass zero for protocol,
+ *                  internalPort, externalPort and ttl.
+ *
+ * internalPort:    The port number in network byte order on the local machine which is listening for packets.
+ *
+ * externalPort:    The requested external port in network byte order in the NAT gateway that you would
+ *                  like to map to the internal port. Pass 0 if you don't care which external port is chosen for you.
+ *
+ * ttl:             The requested renewal period of the NAT port mapping, in seconds.
+ *                  If the client machine crashes, suffers a power failure, is disconnected from
+ *                  the network, or suffers some other unfortunate demise which causes it to vanish
+ *                  unexpectedly without explicitly removing its NAT port mappings, then the NAT gateway
+ *                  will garbage-collect old stale NAT port mappings when their lifetime expires.
+ *                  Requesting a short TTL causes such orphaned mappings to be garbage-collected
+ *                  more promptly, but consumes system resources and network bandwidth with
+ *                  frequent renewal packets to keep the mapping from expiring.
+ *                  Requesting a long TTL is more efficient on the network, but in the event of the
+ *                  client vanishing, stale NAT port mappings will not be garbage-collected as quickly.
+ *                  Most clients should pass 0 to use a system-wide default value.
+ *
+ * callBack:        The function to be called when the port mapping request succeeds or fails asynchronously.
+ *
+ * context:         An application context pointer which is passed to the callback function
+ *                  (may be NULL).
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ *                  errors are delivered to the callback), otherwise returns an error code indicating
+ *                  the error that occurred.
+ *
+ *                  If you don't actually want a port mapped, and are just calling the API
+ *                  because you want to find out the NAT's external IP address (e.g. for UI
+ *                  display) then pass zero for protocol, internalPort, externalPort and ttl.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
+(
+    DNSServiceRef                    *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    DNSServiceProtocol protocol,                        /* TCP and/or UDP          */
+    uint16_t internalPort,                              /* network byte order      */
+    uint16_t externalPort,                              /* network byte order      */
+    uint32_t ttl,                                       /* time to live in seconds */
+    DNSServiceNATPortMappingReply callBack,
+    void                             *context           /* may be NULL             */
+);
+
+
+/*********************************************************************************************
+*
+*  General Utility Functions
+*
+*********************************************************************************************/
+
+/* DNSServiceConstructFullName()
+ *
+ * Concatenate a three-part domain name (as returned by the above callbacks) into a
+ * properly-escaped full domain name. Note that callbacks in the above functions ALREADY ESCAPE
+ * strings where necessary.
+ *
+ * Parameters:
+ *
+ * fullName:        A pointer to a buffer that where the resulting full domain name is to be written.
+ *                  The buffer must be kDNSServiceMaxDomainName (1009) bytes in length to
+ *                  accommodate the longest legal domain name without buffer overrun.
+ *
+ * service:         The service name - any dots or backslashes must NOT be escaped.
+ *                  May be NULL (to construct a PTR record name, e.g.
+ *                  "_ftp._tcp.apple.com.").
+ *
+ * regtype:         The service type followed by the protocol, separated by a dot
+ *                  (e.g. "_ftp._tcp").
+ *
+ * domain:          The domain name, e.g. "apple.com.". Literal dots or backslashes,
+ *                  if any, must be escaped, e.g. "1st\. Floor.apple.com."
+ *
+ * return value:    Returns kDNSServiceErr_NoError (0) on success, kDNSServiceErr_BadParam on error.
+ *
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceConstructFullName
+(
+    char                            * const fullName,
+    const char                      * const service,      /* may be NULL */
+    const char                      * const regtype,
+    const char                      * const domain
+);
+
+
+/*********************************************************************************************
+*
+*   TXT Record Construction Functions
+*
+*********************************************************************************************/
+
+/*
+ * A typical calling sequence for TXT record construction is something like:
+ *
+ * Client allocates storage for TXTRecord data (e.g. declare buffer on the stack)
+ * TXTRecordCreate();
+ * TXTRecordSetValue();
+ * TXTRecordSetValue();
+ * TXTRecordSetValue();
+ * ...
+ * DNSServiceRegister( ... TXTRecordGetLength(), TXTRecordGetBytesPtr() ... );
+ * TXTRecordDeallocate();
+ * Explicitly deallocate storage for TXTRecord data (if not allocated on the stack)
+ */
+
+
+/* TXTRecordRef
+ *
+ * Opaque internal data type.
+ * Note: Represents a DNS-SD TXT record.
+ */
+
+typedef union _TXTRecordRef_t { char PrivateData[16]; char *ForceNaturalAlignment; } TXTRecordRef;
+
+
+/* TXTRecordCreate()
+ *
+ * Creates a new empty TXTRecordRef referencing the specified storage.
+ *
+ * If the buffer parameter is NULL, or the specified storage size is not
+ * large enough to hold a key subsequently added using TXTRecordSetValue(),
+ * then additional memory will be added as needed using malloc().
+ *
+ * On some platforms, when memory is low, malloc() may fail. In this
+ * case, TXTRecordSetValue() will return kDNSServiceErr_NoMemory, and this
+ * error condition will need to be handled as appropriate by the caller.
+ *
+ * You can avoid the need to handle this error condition if you ensure
+ * that the storage you initially provide is large enough to hold all
+ * the key/value pairs that are to be added to the record.
+ * The caller can precompute the exact length required for all of the
+ * key/value pairs to be added, or simply provide a fixed-sized buffer
+ * known in advance to be large enough.
+ * A no-value (key-only) key requires  (1 + key length) bytes.
+ * A key with empty value requires     (1 + key length + 1) bytes.
+ * A key with non-empty value requires (1 + key length + 1 + value length).
+ * For most applications, DNS-SD TXT records are generally
+ * less than 100 bytes, so in most cases a simple fixed-sized
+ * 256-byte buffer will be more than sufficient.
+ * Recommended size limits for DNS-SD TXT Records are discussed in
+ * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
+ *
+ * Note: When passing parameters to and from these TXT record APIs,
+ * the key name does not include the '=' character. The '=' character
+ * is the separator between the key and value in the on-the-wire
+ * packet format; it is not part of either the key or the value.
+ *
+ * txtRecord:       A pointer to an uninitialized TXTRecordRef.
+ *
+ * bufferLen:       The size of the storage provided in the "buffer" parameter.
+ *
+ * buffer:          Optional caller-supplied storage used to hold the TXTRecord data.
+ *                  This storage must remain valid for as long as
+ *                  the TXTRecordRef.
+ */
+
+void DNSSD_API TXTRecordCreate
+(
+    TXTRecordRef     *txtRecord,
+    uint16_t bufferLen,
+    void             *buffer
+);
+
+
+/* TXTRecordDeallocate()
+ *
+ * Releases any resources allocated in the course of preparing a TXT Record
+ * using TXTRecordCreate()/TXTRecordSetValue()/TXTRecordRemoveValue().
+ * Ownership of the buffer provided in TXTRecordCreate() returns to the client.
+ *
+ * txtRecord:           A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ */
+
+void DNSSD_API TXTRecordDeallocate
+(
+    TXTRecordRef     *txtRecord
+);
+
+
+/* TXTRecordSetValue()
+ *
+ * Adds a key (optionally with value) to a TXTRecordRef. If the "key" already
+ * exists in the TXTRecordRef, then the current value will be replaced with
+ * the new value.
+ * Keys may exist in four states with respect to a given TXT record:
+ *  - Absent (key does not appear at all)
+ *  - Present with no value ("key" appears alone)
+ *  - Present with empty value ("key=" appears in TXT record)
+ *  - Present with non-empty value ("key=value" appears in TXT record)
+ * For more details refer to "Data Syntax for DNS-SD TXT Records" in
+ * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
+ *
+ * txtRecord:       A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ * key:             A null-terminated string which only contains printable ASCII
+ *                  values (0x20-0x7E), excluding '=' (0x3D). Keys should be
+ *                  9 characters or fewer (not counting the terminating null).
+ *
+ * valueSize:       The size of the value.
+ *
+ * value:           Any binary value. For values that represent
+ *                  textual data, UTF-8 is STRONGLY recommended.
+ *                  For values that represent textual data, valueSize
+ *                  should NOT include the terminating null (if any)
+ *                  at the end of the string.
+ *                  If NULL, then "key" will be added with no value.
+ *                  If non-NULL but valueSize is zero, then "key=" will be
+ *                  added with empty value.
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success.
+ *                  Returns kDNSServiceErr_Invalid if the "key" string contains
+ *                  illegal characters.
+ *                  Returns kDNSServiceErr_NoMemory if adding this key would
+ *                  exceed the available storage.
+ */
+
+DNSServiceErrorType DNSSD_API TXTRecordSetValue
+(
+    TXTRecordRef     *txtRecord,
+    const char       *key,
+    uint8_t valueSize,                 /* may be zero */
+    const void       *value            /* may be NULL */
+);
+
+
+/* TXTRecordRemoveValue()
+ *
+ * Removes a key from a TXTRecordRef. The "key" must be an
+ * ASCII string which exists in the TXTRecordRef.
+ *
+ * txtRecord:       A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ * key:             A key name which exists in the TXTRecordRef.
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success.
+ *                  Returns kDNSServiceErr_NoSuchKey if the "key" does not
+ *                  exist in the TXTRecordRef.
+ */
+
+DNSServiceErrorType DNSSD_API TXTRecordRemoveValue
+(
+    TXTRecordRef     *txtRecord,
+    const char       *key
+);
+
+
+/* TXTRecordGetLength()
+ *
+ * Allows you to determine the length of the raw bytes within a TXTRecordRef.
+ *
+ * txtRecord:       A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ * return value:    Returns the size of the raw bytes inside a TXTRecordRef
+ *                  which you can pass directly to DNSServiceRegister() or
+ *                  to DNSServiceUpdateRecord().
+ *                  Returns 0 if the TXTRecordRef is empty.
+ */
+
+uint16_t DNSSD_API TXTRecordGetLength
+(
+    const TXTRecordRef *txtRecord
+);
+
+
+/* TXTRecordGetBytesPtr()
+ *
+ * Allows you to retrieve a pointer to the raw bytes within a TXTRecordRef.
+ *
+ * txtRecord:       A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ * return value:    Returns a pointer to the raw bytes inside the TXTRecordRef
+ *                  which you can pass directly to DNSServiceRegister() or
+ *                  to DNSServiceUpdateRecord().
+ */
+
+const void * DNSSD_API TXTRecordGetBytesPtr
+(
+    const TXTRecordRef *txtRecord
+);
+
+
+/*********************************************************************************************
+*
+*   TXT Record Parsing Functions
+*
+*********************************************************************************************/
+
+/*
+ * A typical calling sequence for TXT record parsing is something like:
+ *
+ * Receive TXT record data in DNSServiceResolve() callback
+ * if (TXTRecordContainsKey(txtLen, txtRecord, "key")) then do something
+ * val1ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key1", &len1);
+ * val2ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key2", &len2);
+ * ...
+ * memcpy(myval1, val1ptr, len1);
+ * memcpy(myval2, val2ptr, len2);
+ * ...
+ * return;
+ *
+ * If you wish to retain the values after return from the DNSServiceResolve()
+ * callback, then you need to copy the data to your own storage using memcpy()
+ * or similar, as shown in the example above.
+ *
+ * If for some reason you need to parse a TXT record you built yourself
+ * using the TXT record construction functions above, then you can do
+ * that using TXTRecordGetLength and TXTRecordGetBytesPtr calls:
+ * TXTRecordGetValue(TXTRecordGetLength(x), TXTRecordGetBytesPtr(x), key, &len);
+ *
+ * Most applications only fetch keys they know about from a TXT record and
+ * ignore the rest.
+ * However, some debugging tools wish to fetch and display all keys.
+ * To do that, use the TXTRecordGetCount() and TXTRecordGetItemAtIndex() calls.
+ */
+
+/* TXTRecordContainsKey()
+ *
+ * Allows you to determine if a given TXT Record contains a specified key.
+ *
+ * txtLen:          The size of the received TXT Record.
+ *
+ * txtRecord:       Pointer to the received TXT Record bytes.
+ *
+ * key:             A null-terminated ASCII string containing the key name.
+ *
+ * return value:    Returns 1 if the TXT Record contains the specified key.
+ *                  Otherwise, it returns 0.
+ */
+
+int DNSSD_API TXTRecordContainsKey
+(
+    uint16_t txtLen,
+    const void       *txtRecord,
+    const char       *key
+);
+
+
+/* TXTRecordGetValuePtr()
+ *
+ * Allows you to retrieve the value for a given key from a TXT Record.
+ *
+ * txtLen:          The size of the received TXT Record
+ *
+ * txtRecord:       Pointer to the received TXT Record bytes.
+ *
+ * key:             A null-terminated ASCII string containing the key name.
+ *
+ * valueLen:        On output, will be set to the size of the "value" data.
+ *
+ * return value:    Returns NULL if the key does not exist in this TXT record,
+ *                  or exists with no value (to differentiate between
+ *                  these two cases use TXTRecordContainsKey()).
+ *                  Returns pointer to location within TXT Record bytes
+ *                  if the key exists with empty or non-empty value.
+ *                  For empty value, valueLen will be zero.
+ *                  For non-empty value, valueLen will be length of value data.
+ */
+
+const void * DNSSD_API TXTRecordGetValuePtr
+(
+    uint16_t txtLen,
+    const void       *txtRecord,
+    const char       *key,
+    uint8_t          *valueLen
+);
+
+
+/* TXTRecordGetCount()
+ *
+ * Returns the number of keys stored in the TXT Record. The count
+ * can be used with TXTRecordGetItemAtIndex() to iterate through the keys.
+ *
+ * txtLen:          The size of the received TXT Record.
+ *
+ * txtRecord:       Pointer to the received TXT Record bytes.
+ *
+ * return value:    Returns the total number of keys in the TXT Record.
+ *
+ */
+
+uint16_t DNSSD_API TXTRecordGetCount
+(
+    uint16_t txtLen,
+    const void       *txtRecord
+);
+
+
+/* TXTRecordGetItemAtIndex()
+ *
+ * Allows you to retrieve a key name and value pointer, given an index into
+ * a TXT Record. Legal index values range from zero to TXTRecordGetCount()-1.
+ * It's also possible to iterate through keys in a TXT record by simply
+ * calling TXTRecordGetItemAtIndex() repeatedly, beginning with index zero
+ * and increasing until TXTRecordGetItemAtIndex() returns kDNSServiceErr_Invalid.
+ *
+ * On return:
+ * For keys with no value, *value is set to NULL and *valueLen is zero.
+ * For keys with empty value, *value is non-NULL and *valueLen is zero.
+ * For keys with non-empty value, *value is non-NULL and *valueLen is non-zero.
+ *
+ * txtLen:          The size of the received TXT Record.
+ *
+ * txtRecord:       Pointer to the received TXT Record bytes.
+ *
+ * itemIndex:       An index into the TXT Record.
+ *
+ * keyBufLen:       The size of the string buffer being supplied.
+ *
+ * key:             A string buffer used to store the key name.
+ *                  On return, the buffer contains a null-terminated C string
+ *                  giving the key name. DNS-SD TXT keys are usually
+ *                  9 characters or fewer. To hold the maximum possible
+ *                  key name, the buffer should be 256 bytes long.
+ *
+ * valueLen:        On output, will be set to the size of the "value" data.
+ *
+ * value:           On output, *value is set to point to location within TXT
+ *                  Record bytes that holds the value data.
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success.
+ *                  Returns kDNSServiceErr_NoMemory if keyBufLen is too short.
+ *                  Returns kDNSServiceErr_Invalid if index is greater than
+ *                  TXTRecordGetCount()-1.
+ */
+
+DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
+(
+    uint16_t txtLen,
+    const void       *txtRecord,
+    uint16_t itemIndex,
+    uint16_t keyBufLen,
+    char             *key,
+    uint8_t          *valueLen,
+    const void       **value
+);
+
+#if _DNS_SD_LIBDISPATCH
+/*
+ * DNSServiceSetDispatchQueue
+ *
+ * Allows you to schedule a DNSServiceRef on a serial dispatch queue for receiving asynchronous
+ * callbacks.  It's the clients responsibility to ensure that the provided dispatch queue is running.
+ *
+ * A typical application that uses CFRunLoopRun or dispatch_main on its main thread will
+ * usually schedule DNSServiceRefs on its main queue (which is always a serial queue)
+ * using "DNSServiceSetDispatchQueue(sdref, dispatch_get_main_queue());"
+ *
+ * If there is any error during the processing of events, the application callback will
+ * be called with an error code. For shared connections, each subordinate DNSServiceRef
+ * will get its own error callback. Currently these error callbacks only happen
+ * if the daemon is manually terminated or crashes, and the error
+ * code in this case is kDNSServiceErr_ServiceNotRunning. The application must call
+ * DNSServiceRefDeallocate to free the DNSServiceRef when it gets such an error code.
+ * These error callbacks are rare and should not normally happen on customer machines,
+ * but application code should be written defensively to handle such error callbacks
+ * gracefully if they occur.
+ *
+ * After using DNSServiceSetDispatchQueue on a DNSServiceRef, calling DNSServiceProcessResult
+ * on the same DNSServiceRef will result in undefined behavior and should be avoided.
+ *
+ * Once the application successfully schedules a DNSServiceRef on a serial dispatch queue using
+ * DNSServiceSetDispatchQueue, it cannot remove the DNSServiceRef from the dispatch queue, or use
+ * DNSServiceSetDispatchQueue a second time to schedule the DNSServiceRef onto a different serial dispatch
+ * queue. Once scheduled onto a dispatch queue a DNSServiceRef will deliver events to that queue until
+ * the application no longer requires that operation and terminates it using DNSServiceRefDeallocate.
+ *
+ * service:         DNSServiceRef that was allocated and returned to the application, when the
+ *                  application calls one of the DNSService API.
+ *
+ * queue:           dispatch queue where the application callback will be scheduled
+ *
+ * return value:    Returns kDNSServiceErr_NoError on success.
+ *                  Returns kDNSServiceErr_NoMemory if it cannot create a dispatch source
+ *                  Returns kDNSServiceErr_BadParam if the service param is invalid or the
+ *                  queue param is invalid
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue
+(
+    DNSServiceRef service,
+    dispatch_queue_t queue
+);
+#endif //_DNS_SD_LIBDISPATCH
+
+#if !defined(_WIN32)
+typedef void (DNSSD_API *DNSServiceSleepKeepaliveReply)
+(
+    DNSServiceRef sdRef,
+    DNSServiceErrorType errorCode,
+    void                                *context
+);
+DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive
+(
+    DNSServiceRef                       *sdRef,
+    DNSServiceFlags flags,
+    int fd,
+    unsigned int timeout,
+    DNSServiceSleepKeepaliveReply callBack,
+    void                                *context
+);
+#endif
+
+#ifdef APPLE_OSX_mDNSResponder
+/* DNSServiceCreateDelegateConnection()
+ *
+ * Create a delegate connection to the daemon allowing efficient registration of
+ * multiple individual records.
+ *
+ * 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);
+#endif
+
+#ifdef __APPLE_API_PRIVATE
+
+#define kDNSServiceCompPrivateDNS   "PrivateDNS"
+#define kDNSServiceCompMulticastDNS "MulticastDNS"
+
+#endif //__APPLE_API_PRIVATE
+
+/* Some C compiler cleverness. We can make the compiler check certain things for us,
+ * and report errors at compile-time if anything is wrong. The usual way to do this would
+ * be to use a run-time "if" statement or the conventional run-time "assert" mechanism, but
+ * then you don't find out what's wrong until you run the software. This way, if the assertion
+ * condition is false, the array size is negative, and the complier complains immediately.
+ */
+
+struct CompileTimeAssertionChecks_DNS_SD
+{
+    char assert0[(sizeof(union _TXTRecordRef_t) == 16) ? 1 : -1];
+};
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif  /* _DNS_SD_H */

Deleted: vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_clientstub.c
===================================================================
--- vendor/apple/mDNSResponder/dist/mDNSShared/dnssd_clientstub.c	2014-06-30 23:58:12 UTC (rev 6706)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_clientstub.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -1,2363 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <stdlib.h>
-
-#if APPLE_OSX_mDNSResponder
-#include <mach-o/dyld.h>
-#include <uuid/uuid.h>
-#include <TargetConditionals.h>
-#endif
-
-#include "dnssd_ipc.h"
-
-static int gDaemonErr = kDNSServiceErr_NoError;
-
-#if defined(_WIN32)
-
-    #define _SSIZE_T
-    #include <CommonServices.h>
-    #include <DebugServices.h>
-    #include <winsock2.h>
-    #include <ws2tcpip.h>
-    #include <windows.h>
-    #include <stdarg.h>
-    #include <stdio.h>
-
-    #define sockaddr_mdns sockaddr_in
-    #define AF_MDNS AF_INET
-
-// Disable warning: "'type cast' : from data pointer 'void *' to function pointer"
-    #pragma warning(disable:4055)
-
-// Disable warning: "nonstandard extension, function/data pointer conversion in expression"
-    #pragma warning(disable:4152)
-
-extern BOOL IsSystemServiceDisabled();
-
-    #define sleep(X) Sleep((X) * 1000)
-
-static int g_initWinsock = 0;
-    #define LOG_WARNING kDebugLevelWarning
-    #define LOG_INFO kDebugLevelInfo
-static void syslog( int priority, const char * message, ...)
-{
-    va_list args;
-    int len;
-    char * buffer;
-    DWORD err = WSAGetLastError();
-    (void) priority;
-    va_start( args, message );
-    len = _vscprintf( message, args ) + 1;
-    buffer = malloc( len * sizeof(char) );
-    if ( buffer ) { vsprintf( buffer, message, args ); OutputDebugString( buffer ); free( buffer ); }
-    WSASetLastError( err );
-}
-#else
-
-    #include <sys/fcntl.h>      // For O_RDWR etc.
-    #include <sys/time.h>
-    #include <sys/socket.h>
-    #include <syslog.h>
-
-    #define sockaddr_mdns sockaddr_un
-    #define AF_MDNS AF_LOCAL
-
-#endif
-
-// <rdar://problem/4096913> Specifies how many times we'll try and connect to the server.
-
-#define DNSSD_CLIENT_MAXTRIES 4
-
-// Uncomment the line below to use the old error return mechanism of creating a temporary named socket (e.g. in /var/tmp)
-//#define USE_NAMED_ERROR_RETURN_SOCKET 1
-
-// If the UDS client has not received a response from the daemon in 60 secs, it is unlikely to get one
-// Note: Timeout of 3 secs should be sufficient in normal scenarios, but 60 secs is chosen as a safeguard since
-// some clients may come up before mDNSResponder itself after a BOOT and on rare ocassions IOPM/Keychain/D2D calls
-// in mDNSResponder's INIT may take a much longer time to return
-#define DNSSD_CLIENT_TIMEOUT 60
-
-#ifndef CTL_PATH_PREFIX
-#define CTL_PATH_PREFIX "/var/tmp/dnssd_result_socket."
-#endif
-
-typedef struct
-{
-    ipc_msg_hdr ipc_hdr;
-    DNSServiceFlags cb_flags;
-    uint32_t cb_interface;
-    DNSServiceErrorType cb_err;
-} CallbackHeader;
-
-typedef struct _DNSServiceRef_t DNSServiceOp;
-typedef struct _DNSRecordRef_t DNSRecord;
-
-#if !defined(_WIN32)
-typedef struct
-{
-    void             *AppCallback;      // Client callback function and context
-    void             *AppContext;
-} SleepKAContext;
-#endif
-
-// client stub callback to process message from server and deliver results to client application
-typedef void (*ProcessReplyFn)(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *msg, const char *const end);
-
-#define ValidatorBits 0x12345678
-#define DNSServiceRefValid(X) (dnssd_SocketValid((X)->sockfd) && (((X)->sockfd ^ (X)->validator) == ValidatorBits))
-
-// When using kDNSServiceFlagsShareConnection, there is one primary _DNSServiceOp_t, and zero or more subordinates
-// For the primary, the 'next' field points to the first subordinate, and its 'next' field points to the next, and so on.
-// For the primary, the 'primary' field is NULL; for subordinates the 'primary' field points back to the associated primary
-//
-// _DNS_SD_LIBDISPATCH is defined where libdispatch/GCD is available. This does not mean that the application will use the
-// DNSServiceSetDispatchQueue API. Hence any new code guarded with _DNS_SD_LIBDISPATCH should still be backwards compatible.
-struct _DNSServiceRef_t
-{
-    DNSServiceOp     *next;             // For shared connection
-    DNSServiceOp     *primary;          // For shared connection
-    dnssd_sock_t sockfd;                // Connected socket between client and daemon
-    dnssd_sock_t validator;             // Used to detect memory corruption, double disposals, etc.
-    client_context_t uid;               // For shared connection requests, each subordinate DNSServiceRef has its own ID,
-                                        // unique within the scope of the same shared parent DNSServiceRef
-    uint32_t op;                        // request_op_t or reply_op_t
-    uint32_t max_index;                 // Largest assigned record index - 0 if no additional records registered
-    uint32_t logcounter;                // Counter used to control number of syslog messages we write
-    int              *moreptr;          // Set while DNSServiceProcessResult working on this particular DNSServiceRef
-    ProcessReplyFn ProcessReply;        // Function pointer to the code to handle received messages
-    void             *AppCallback;      // Client callback function and context
-    void             *AppContext;
-    DNSRecord        *rec;
-#if _DNS_SD_LIBDISPATCH
-    dispatch_source_t disp_source;
-    dispatch_queue_t disp_queue;
-#endif
-    void             *kacontext;
-};
-
-struct _DNSRecordRef_t
-{
-    DNSRecord       *recnext;
-    void *AppContext;
-    DNSServiceRegisterRecordReply AppCallback;
-    DNSRecordRef recref;
-    uint32_t record_index;  // index is unique to the ServiceDiscoveryRef
-    client_context_t uid;  // For demultiplexing multiple DNSServiceRegisterRecord calls
-    DNSServiceOp *sdr;
-};
-
-// Write len bytes. Return 0 on success, -1 on error
-static int write_all(dnssd_sock_t sd, char *buf, size_t len)
-{
-    // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
-    //if (send(sd, buf, len, MSG_WAITALL) != len) return -1;
-    while (len)
-    {
-        ssize_t num_written = send(sd, buf, (long)len, 0);
-        if (num_written < 0 || (size_t)num_written > len)
-        {
-            // Should never happen. If it does, it indicates some OS bug,
-            // or that the mDNSResponder daemon crashed (which should never happen).
-            #if !defined(__ppc__) && defined(SO_ISDEFUNCT)
-            int defunct;
-            socklen_t dlen = sizeof (defunct);
-            if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0)
-                syslog(LOG_WARNING, "dnssd_clientstub write_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
-            if (!defunct)
-                syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
-                       (long)num_written, (long)len,
-                       (num_written < 0) ? dnssd_errno                 : 0,
-                       (num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
-            else
-                syslog(LOG_INFO, "dnssd_clientstub write_all(%d) DEFUNCT", sd);
-            #else
-            syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
-                   (long)num_written, (long)len,
-                   (num_written < 0) ? dnssd_errno                 : 0,
-                   (num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
-            #endif
-            return -1;
-        }
-        buf += num_written;
-        len -= num_written;
-    }
-    return 0;
-}
-
-enum { read_all_success = 0, read_all_fail = -1, read_all_wouldblock = -2 };
-
-// Read len bytes. Return 0 on success, read_all_fail on error, or read_all_wouldblock for
-static int read_all(dnssd_sock_t sd, char *buf, int len)
-{
-    // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
-    //if (recv(sd, buf, len, MSG_WAITALL) != len) return -1;
-
-    while (len)
-    {
-        ssize_t num_read = recv(sd, buf, len, 0);
-        // It is valid to get an interrupted system call error e.g., somebody attaching
-        // in a debugger, retry without failing
-        if ((num_read < 0) && (errno == EINTR)) 
-        { 
-            syslog(LOG_INFO, "dnssd_clientstub read_all: EINTR continue"); 
-            continue; 
-        }
-        if ((num_read == 0) || (num_read < 0) || (num_read > len))
-        {
-            int printWarn = 0;
-            int defunct = 0;
-            // Should never happen. If it does, it indicates some OS bug,
-            // or that the mDNSResponder daemon crashed (which should never happen).
-#if defined(WIN32)
-            // <rdar://problem/7481776> Suppress logs for "A non-blocking socket operation
-            //                          could not be completed immediately"
-            if (WSAGetLastError() != WSAEWOULDBLOCK)
-                printWarn = 1;
-#endif
-#if !defined(__ppc__) && defined(SO_ISDEFUNCT)
-            {
-                socklen_t dlen = sizeof (defunct);
-                if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0)
-                    syslog(LOG_WARNING, "dnssd_clientstub read_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
-            }
-            if (!defunct)
-                printWarn = 1;
-#endif
-            if (printWarn)
-                syslog(LOG_WARNING, "dnssd_clientstub read_all(%d) failed %ld/%ld %d %s", sd,
-                       (long)num_read, (long)len,
-                       (num_read < 0) ? dnssd_errno                 : 0,
-                       (num_read < 0) ? dnssd_strerror(dnssd_errno) : "");
-            else if (defunct)
-                syslog(LOG_INFO, "dnssd_clientstub read_all(%d) DEFUNCT", sd);
-            return (num_read < 0 && dnssd_errno == dnssd_EWOULDBLOCK) ? read_all_wouldblock : read_all_fail;
-        }
-        buf += num_read;
-        len -= num_read;
-    }
-    return read_all_success;
-}
-
-// Returns 1 if more bytes remain to be read on socket descriptor sd, 0 otherwise
-static int more_bytes(dnssd_sock_t sd)
-{
-    struct timeval tv = { 0, 0 };
-    fd_set readfds;
-    fd_set *fs;
-    int ret;
-
-    if (sd < FD_SETSIZE)
-    {
-        fs = &readfds;
-        FD_ZERO(fs);
-    }
-    else
-    {
-        // Compute the number of integers needed for storing "sd". Internally fd_set is stored
-        // as an array of ints with one bit for each fd and hence we need to compute
-        // the number of ints needed rather than the number of bytes. If "sd" is 32, we need
-        // two ints and not just one.
-        int nfdbits = sizeof (int) * 8;
-        int nints = (sd/nfdbits) + 1;
-        fs = (fd_set *)calloc(nints, sizeof(int));
-        if (fs == NULL) 
-        { 
-            syslog(LOG_WARNING, "dnssd_clientstub more_bytes: malloc failed"); 
-            return 0; 
-        }
-    }
-    FD_SET(sd, fs);
-    ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv);
-    if (fs != &readfds) 
-        free(fs);
-    return (ret > 0);
-}
-
-// set_waitlimit() implements a timeout using select. It is called from deliver_request() before recv() OR accept()
-// to ensure the UDS clients are not blocked in these system calls indefinitely.
-// Note: Ideally one should never be blocked here, because it indicates either mDNSResponder daemon is not yet up/hung/
-// superbusy/crashed or some other OS bug. For eg: On Windows which suffers from 3rd party software 
-// (primarily 3rd party firewall software) interfering with proper functioning of the TCP protocol stack it is possible 
-// the next operation on this socket(recv/accept) is blocked since we depend on TCP to communicate with the system service.
-static int set_waitlimit(dnssd_sock_t sock, int timeout)
-{
-    // To prevent stack corruption since select does not work with timeout if fds > FD_SETSIZE(1024)
-    if (!gDaemonErr && sock < FD_SETSIZE)
-    {
-        struct timeval tv;
-        fd_set set;
-
-        FD_ZERO(&set);
-        FD_SET(sock, &set);
-        tv.tv_sec = timeout;
-        tv.tv_usec = 0;
-        if (!select((int)(sock + 1), &set, NULL, NULL, &tv))
-        {
-            // Ideally one should never hit this case: See comments before set_waitlimit()
-            syslog(LOG_WARNING, "dnssd_clientstub set_waitlimit:_daemon timed out (%d secs) without any response: Socket %d", timeout, sock);
-            gDaemonErr = kDNSServiceErr_Timeout;
-        }
-    }
-    return gDaemonErr;
-}
-
-/* create_hdr
- *
- * allocate and initialize an ipc message header. Value of len should initially be the
- * length of the data, and is set to the value of the data plus the header. data_start
- * is set to point to the beginning of the data section. SeparateReturnSocket should be
- * non-zero for calls that can't receive an immediate error return value on their primary
- * socket, and therefore require a separate return path for the error code result.
- * if zero, the path to a control socket is appended at the beginning of the message buffer.
- * data_start is set past this string.
- */
-static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int SeparateReturnSocket, DNSServiceOp *ref)
-{
-    char *msg = NULL;
-    ipc_msg_hdr *hdr;
-    int datalen;
-#if !defined(USE_TCP_LOOPBACK)
-    char ctrl_path[64] = "";    // "/var/tmp/dnssd_result_socket.xxxxxxxxxx-xxx-xxxxxx"
-#endif
-
-    if (SeparateReturnSocket)
-    {
-#if defined(USE_TCP_LOOPBACK)
-        *len += 2;  // Allocate space for two-byte port number
-#elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
-        struct timeval tv;
-        if (gettimeofday(&tv, NULL) < 0)
-        { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: gettimeofday failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); return NULL; }
-        sprintf(ctrl_path, "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(),
-                (unsigned long)(tv.tv_sec & 0xFFF), (unsigned long)(tv.tv_usec));
-        *len += strlen(ctrl_path) + 1;
-#else
-        *len += 1;      // Allocate space for single zero byte (empty C string)
-#endif
-    }
-
-    datalen = (int) *len;
-    *len += sizeof(ipc_msg_hdr);
-
-    // Write message to buffer
-    msg = malloc(*len);
-    if (!msg) { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: malloc failed"); return NULL; }
-
-    memset(msg, 0, *len);
-    hdr = (ipc_msg_hdr *)msg;
-    hdr->version                = VERSION;
-    hdr->datalen                = datalen;
-    hdr->ipc_flags              = 0;
-    hdr->op                     = op;
-    hdr->client_context         = ref->uid;
-    hdr->reg_index              = 0;
-    *data_start = msg + sizeof(ipc_msg_hdr);
-#if defined(USE_TCP_LOOPBACK)
-    // Put dummy data in for the port, since we don't know what it is yet.
-    // The data will get filled in before we send the message. This happens in deliver_request().
-    if (SeparateReturnSocket) put_uint16(0, data_start);
-#else
-    if (SeparateReturnSocket) put_string(ctrl_path, data_start);
-#endif
-    return hdr;
-}
-
-static void FreeDNSRecords(DNSServiceOp *sdRef)
-{
-    DNSRecord *rec = sdRef->rec;
-    while (rec)
-    {
-        DNSRecord *next = rec->recnext;
-        free(rec);
-        rec = next;
-    }
-}
-
-static void FreeDNSServiceOp(DNSServiceOp *x)
-{
-    // We don't use our DNSServiceRefValid macro here because if we're cleaning up after a socket() call failed
-    // then sockfd could legitimately contain a failing value (e.g. dnssd_InvalidSocket)
-    if ((x->sockfd ^ x->validator) != ValidatorBits)
-        syslog(LOG_WARNING, "dnssd_clientstub attempt to dispose invalid DNSServiceRef %p %08X %08X", x, x->sockfd, x->validator);
-    else
-    {
-        x->next         = NULL;
-        x->primary      = NULL;
-        x->sockfd       = dnssd_InvalidSocket;
-        x->validator    = 0xDDDDDDDD;
-        x->op           = request_op_none;
-        x->max_index    = 0;
-        x->logcounter   = 0;
-        x->moreptr      = NULL;
-        x->ProcessReply = NULL;
-        x->AppCallback  = NULL;
-        x->AppContext   = NULL;
-#if _DNS_SD_LIBDISPATCH
-        if (x->disp_source) dispatch_release(x->disp_source);
-        x->disp_source  = NULL;
-        x->disp_queue   = NULL;
-#endif
-        // DNSRecords may have been added to subordinate sdRef e.g., DNSServiceRegister/DNSServiceAddRecord
-        // or on the main sdRef e.g., DNSServiceCreateConnection/DNSServiveRegisterRecord. DNSRecords may have
-        // been freed if the application called DNSRemoveRecord
-        FreeDNSRecords(x);
-        if (x->kacontext)
-        {
-            free(x->kacontext);
-            x->kacontext = NULL;
-        }
-        free(x);
-    }
-}
-
-// Return a connected service ref (deallocate with DNSServiceRefDeallocate)
-static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags flags, uint32_t op, ProcessReplyFn ProcessReply, void *AppCallback, void *AppContext)
-{
-    int NumTries = 0;
-
-    dnssd_sockaddr_t saddr;
-    DNSServiceOp *sdr;
-
-    if (!ref) 
-    { 
-        syslog(LOG_WARNING, "dnssd_clientstub DNSService operation with NULL DNSServiceRef"); 
-        return kDNSServiceErr_BadParam; 
-    }
-
-    if (flags & kDNSServiceFlagsShareConnection)
-    {
-        if (!*ref)
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with NULL DNSServiceRef");
-            return kDNSServiceErr_BadParam;
-        }
-        if (!DNSServiceRefValid(*ref) || ((*ref)->op != connection_request && (*ref)->op != connection_delegate_request) || (*ref)->primary)
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with invalid DNSServiceRef %p %08X %08X op %d",
-                   (*ref), (*ref)->sockfd, (*ref)->validator, (*ref)->op);
-            *ref = NULL;
-            return kDNSServiceErr_BadReference;
-        }
-    }
-
-    #if defined(_WIN32)
-    if (!g_initWinsock)
-    {
-        WSADATA wsaData;
-        g_initWinsock = 1;
-        if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { *ref = NULL; return kDNSServiceErr_ServiceNotRunning; }
-    }
-    // <rdar://problem/4096913> If the system service is disabled, we only want to try to connect once
-    if (IsSystemServiceDisabled()) 
-        NumTries = DNSSD_CLIENT_MAXTRIES;
-    #endif
-
-    sdr = malloc(sizeof(DNSServiceOp));
-    if (!sdr) 
-    { 
-        syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: malloc failed"); 
-        *ref = NULL; 
-        return kDNSServiceErr_NoMemory; 
-    }
-    sdr->next          = NULL;
-    sdr->primary       = NULL;
-    sdr->sockfd        = dnssd_InvalidSocket;
-    sdr->validator     = sdr->sockfd ^ ValidatorBits;
-    sdr->op            = op;
-    sdr->max_index     = 0;
-    sdr->logcounter    = 0;
-    sdr->moreptr       = NULL;
-    sdr->uid.u32[0]    = 0;
-    sdr->uid.u32[1]    = 0;
-    sdr->ProcessReply  = ProcessReply;
-    sdr->AppCallback   = AppCallback;
-    sdr->AppContext    = AppContext;
-    sdr->rec           = NULL;
-#if _DNS_SD_LIBDISPATCH
-    sdr->disp_source   = NULL;
-    sdr->disp_queue    = NULL;
-#endif
-    sdr->kacontext     = NULL;
-
-    if (flags & kDNSServiceFlagsShareConnection)
-    {
-        DNSServiceOp **p = &(*ref)->next;       // Append ourselves to end of primary's list
-        while (*p) 
-            p = &(*p)->next;
-        *p = sdr;
-        // Preincrement counter before we use it -- it helps with debugging if we know the all-zeroes ID should never appear
-        if (++(*ref)->uid.u32[0] == 0) 
-            ++(*ref)->uid.u32[1];               // In parent DNSServiceOp increment UID counter
-        sdr->primary    = *ref;                 // Set our primary pointer
-        sdr->sockfd     = (*ref)->sockfd;       // Inherit primary's socket
-        sdr->validator  = (*ref)->validator;
-        sdr->uid        = (*ref)->uid;
-        //printf("ConnectToServer sharing socket %d\n", sdr->sockfd);
-    }
-    else
-    {
-        #ifdef SO_NOSIGPIPE
-        const unsigned long optval = 1;
-        #endif
-        *ref = NULL;
-        sdr->sockfd    = socket(AF_DNSSD, SOCK_STREAM, 0);
-        sdr->validator = sdr->sockfd ^ ValidatorBits;
-        if (!dnssd_SocketValid(sdr->sockfd))
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: socket failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
-            FreeDNSServiceOp(sdr);
-            return kDNSServiceErr_NoMemory;
-        }
-        #ifdef SO_NOSIGPIPE
-        // Some environments (e.g. OS X) support turning off SIGPIPE for a socket
-        if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0)
-            syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_NOSIGPIPE failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
-        #endif
-        #if defined(USE_TCP_LOOPBACK)
-        saddr.sin_family      = AF_INET;
-        saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
-        saddr.sin_port        = htons(MDNS_TCP_SERVERPORT);
-        #else
-        saddr.sun_family      = AF_LOCAL;
-        strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH);
-        #if !defined(__ppc__) && defined(SO_DEFUNCTOK)
-        {
-            int defunct = 1;
-            if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0)
-                syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
-        }
-        #endif
-        #endif
-        
-        while (1)
-        {
-            int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr));
-            if (!err)
-                break; // If we succeeded, return sdr
-            // If we failed, then it may be because the daemon is still launching.
-            // This can happen for processes that launch early in the boot process, while the
-            // daemon is still coming up. Rather than fail here, we wait 1 sec and try again.
-            // If, after DNSSD_CLIENT_MAXTRIES, we still can't connect to the daemon,
-            // then we give up and return a failure code.
-            if (++NumTries < DNSSD_CLIENT_MAXTRIES)
-            {
-                syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect()-> No of tries: %d", NumTries);  
-                sleep(1); // Sleep a bit, then try again
-            }
-            else 
-            {
-                syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect() failed Socket:%d Err:%d Errno:%d %s", 
-                        sdr->sockfd, err, dnssd_errno, dnssd_strerror(dnssd_errno));
-                dnssd_close(sdr->sockfd); 
-                FreeDNSServiceOp(sdr); 
-                return kDNSServiceErr_ServiceNotRunning; 
-            }
-        }
-        //printf("ConnectToServer opened socket %d\n", sdr->sockfd);
-    }
-
-    *ref = sdr;
-    return kDNSServiceErr_NoError;
-}
-
-#define deliver_request_bailout(MSG) \
-    do { syslog(LOG_WARNING, "dnssd_clientstub deliver_request: %s failed %d (%s)", (MSG), dnssd_errno, dnssd_strerror(dnssd_errno)); goto cleanup; } while(0)
-
-static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
-{
-    uint32_t datalen = hdr->datalen;    // We take a copy here because we're going to convert hdr->datalen to network byte order
-    #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
-    char *const data = (char *)hdr + sizeof(ipc_msg_hdr);
-    #endif
-    dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
-    DNSServiceErrorType err = kDNSServiceErr_Unknown;   // Default for the "goto cleanup" cases
-    int MakeSeparateReturnSocket = 0;
-
-    // Note: need to check hdr->op, not sdr->op.
-    // hdr->op contains the code for the specific operation we're currently doing, whereas sdr->op
-    // contains the original parent DNSServiceOp (e.g. for an add_record_request, hdr->op will be
-    // add_record_request but the parent sdr->op will be connection_request or reg_service_request)
-    if (sdr->primary ||
-        hdr->op == reg_record_request || hdr->op == add_record_request || hdr->op == update_record_request || hdr->op == remove_record_request)
-        MakeSeparateReturnSocket = 1;
-
-    if (!DNSServiceRefValid(sdr))
-    {
-        if (hdr)
-            free(hdr);
-        syslog(LOG_WARNING, "dnssd_clientstub deliver_request: invalid DNSServiceRef %p %08X %08X", sdr, sdr->sockfd, sdr->validator);
-        return kDNSServiceErr_BadReference;
-    }
-
-    if (!hdr) 
-    { 
-        syslog(LOG_WARNING, "dnssd_clientstub deliver_request: !hdr"); 
-        return kDNSServiceErr_Unknown;  
-    }
-
-    if (MakeSeparateReturnSocket)
-    {
-        #if defined(USE_TCP_LOOPBACK)
-        {
-            union { uint16_t s; u_char b[2]; } port;
-            dnssd_sockaddr_t caddr;
-            dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr);
-            listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
-            if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("TCP socket");
-
-            caddr.sin_family      = AF_INET;
-            caddr.sin_port        = 0;
-            caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
-            if (bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr)) < 0) deliver_request_bailout("TCP bind");
-            if (getsockname(listenfd, (struct sockaddr*) &caddr, &len)   < 0) deliver_request_bailout("TCP getsockname");
-            if (listen(listenfd, 1)                                      < 0) deliver_request_bailout("TCP listen");
-            port.s = caddr.sin_port;
-            data[0] = port.b[0];  // don't switch the byte order, as the
-            data[1] = port.b[1];  // daemon expects it in network byte order
-        }
-        #elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
-        {
-            mode_t mask;
-            int bindresult;
-            dnssd_sockaddr_t caddr;
-            listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
-            if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET socket");
-
-            caddr.sun_family = AF_LOCAL;
-            // According to Stevens (section 3.2), there is no portable way to
-            // determine whether sa_len is defined on a particular platform.
-            #ifndef NOT_HAVE_SA_LEN
-            caddr.sun_len = sizeof(struct sockaddr_un);
-            #endif
-            strcpy(caddr.sun_path, data);
-            mask = umask(0);
-            bindresult = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
-            umask(mask);
-            if (bindresult          < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET bind");
-            if (listen(listenfd, 1) < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET listen");
-        }
-        #else
-        {
-            dnssd_sock_t sp[2];
-            if (socketpair(AF_DNSSD, SOCK_STREAM, 0, sp) < 0) deliver_request_bailout("socketpair");
-            else
-            {
-                errsd    = sp[0];   // We'll read our four-byte error code from sp[0]
-                listenfd = sp[1];   // We'll send sp[1] to the daemon
-                #if !defined(__ppc__) && defined(SO_DEFUNCTOK)
-                {
-                    int defunct = 1;
-                    if (setsockopt(errsd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0)
-                        syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
-                }
-                #endif
-            }
-        }
-        #endif
-    }
-
-#if !defined(USE_TCP_LOOPBACK) && !defined(USE_NAMED_ERROR_RETURN_SOCKET)
-    // If we're going to make a separate error return socket, and pass it to the daemon
-    // using sendmsg, then we'll hold back one data byte to go with it.
-    // On some versions of Unix (including Leopard) sending a control message without
-    // any associated data does not work reliably -- e.g. one particular issue we ran
-    // into is that if the receiving program is in a kqueue loop waiting to be notified
-    // of the received message, it doesn't get woken up when the control message arrives.
-    if (MakeSeparateReturnSocket || sdr->op == send_bpf) 
-        datalen--;     // Okay to use sdr->op when checking for op == send_bpf
-#endif
-
-    // At this point, our listening socket is set up and waiting, if necessary, for the daemon to connect back to
-    ConvertHeaderBytes(hdr);
-    //syslog(LOG_WARNING, "dnssd_clientstub deliver_request writing %lu bytes", (unsigned long)(datalen + sizeof(ipc_msg_hdr)));
-    //if (MakeSeparateReturnSocket) syslog(LOG_WARNING, "dnssd_clientstub deliver_request name is %s", data);
-#if TEST_SENDING_ONE_BYTE_AT_A_TIME
-    unsigned int i;
-    for (i=0; i<datalen + sizeof(ipc_msg_hdr); i++)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub deliver_request writing %d", i);
-        if (write_all(sdr->sockfd, ((char *)hdr)+i, 1) < 0)
-        { syslog(LOG_WARNING, "write_all (byte %u) failed", i); goto cleanup; }
-        usleep(10000);
-    }
-#else
-    if (write_all(sdr->sockfd, (char *)hdr, datalen + sizeof(ipc_msg_hdr)) < 0)
-    {
-        // write_all already prints an error message if there is an error writing to
-        // the socket except for DEFUNCT. Logging here is unnecessary and also wrong
-        // in the case of DEFUNCT sockets
-        syslog(LOG_INFO, "dnssd_clientstub deliver_request ERROR: write_all(%d, %lu bytes) failed",
-               sdr->sockfd, (unsigned long)(datalen + sizeof(ipc_msg_hdr)));
-        goto cleanup;
-    }
-#endif
-
-    if (!MakeSeparateReturnSocket) 
-        errsd = sdr->sockfd;
-    if (MakeSeparateReturnSocket || sdr->op == send_bpf)    // Okay to use sdr->op when checking for op == send_bpf
-    {
-#if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
-        // At this point we may wait in accept for a few milliseconds waiting for the daemon to connect back to us,
-        // but that's okay -- the daemon should not take more than a few milliseconds to respond.
-        // set_waitlimit() ensures we do not block indefinitely just in case something is wrong
-        dnssd_sockaddr_t daddr;
-        dnssd_socklen_t len = sizeof(daddr);
-        if ((err = set_waitlimit(listenfd, DNSSD_CLIENT_TIMEOUT)) != kDNSServiceErr_NoError) 
-            goto cleanup;
-        errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
-        if (!dnssd_SocketValid(errsd)) 
-            deliver_request_bailout("accept");
-#else
-
-        struct iovec vec = { ((char *)hdr) + sizeof(ipc_msg_hdr) + datalen, 1 }; // Send the last byte along with the SCM_RIGHTS
-        struct msghdr msg;
-        struct cmsghdr *cmsg;
-        char cbuf[CMSG_SPACE(4 * sizeof(dnssd_sock_t))];
-
-        msg.msg_name       = 0;
-        msg.msg_namelen    = 0;
-        msg.msg_iov        = &vec;
-        msg.msg_iovlen     = 1;
-        msg.msg_flags      = 0;
-        if (MakeSeparateReturnSocket || sdr->op == send_bpf)    // Okay to use sdr->op when checking for op == send_bpf
-        {
-            if (sdr->op == send_bpf)
-            {
-                int i;
-                char p[12];     // Room for "/dev/bpf999" with terminating null
-                for (i=0; i<100; i++)
-                {
-                    snprintf(p, sizeof(p), "/dev/bpf%d", i);
-                    listenfd = open(p, O_RDWR, 0);
-                    //if (dnssd_SocketValid(listenfd)) syslog(LOG_WARNING, "Sending fd %d for %s", listenfd, p);
-                    if (!dnssd_SocketValid(listenfd) && dnssd_errno != EBUSY)
-                        syslog(LOG_WARNING, "Error opening %s %d (%s)", p, dnssd_errno, dnssd_strerror(dnssd_errno));
-                    if (dnssd_SocketValid(listenfd) || dnssd_errno != EBUSY) break;
-                }
-            }
-            msg.msg_control    = cbuf;
-            msg.msg_controllen = CMSG_LEN(sizeof(dnssd_sock_t));
-
-            cmsg = CMSG_FIRSTHDR(&msg);
-            cmsg->cmsg_len     = CMSG_LEN(sizeof(dnssd_sock_t));
-            cmsg->cmsg_level   = SOL_SOCKET;
-            cmsg->cmsg_type    = SCM_RIGHTS;
-            *((dnssd_sock_t *)CMSG_DATA(cmsg)) = listenfd;
-        }
-
-#if TEST_KQUEUE_CONTROL_MESSAGE_BUG
-        sleep(1);
-#endif
-
-#if DEBUG_64BIT_SCM_RIGHTS
-        syslog(LOG_WARNING, "dnssd_clientstub sendmsg read sd=%d write sd=%d %ld %ld %ld/%ld/%ld/%ld",
-               errsd, listenfd, sizeof(dnssd_sock_t), sizeof(void*),
-               sizeof(struct cmsghdr) + sizeof(dnssd_sock_t),
-               CMSG_LEN(sizeof(dnssd_sock_t)), (long)CMSG_SPACE(sizeof(dnssd_sock_t)),
-               (long)((char*)CMSG_DATA(cmsg) + 4 - cbuf));
-#endif // DEBUG_64BIT_SCM_RIGHTS
-
-        if (sendmsg(sdr->sockfd, &msg, 0) < 0)
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub deliver_request ERROR: sendmsg failed read sd=%d write sd=%d errno %d (%s)",
-                   errsd, listenfd, dnssd_errno, dnssd_strerror(dnssd_errno));
-            err = kDNSServiceErr_Incompatible;
-            goto cleanup;
-        }
-
-#if DEBUG_64BIT_SCM_RIGHTS
-        syslog(LOG_WARNING, "dnssd_clientstub sendmsg read sd=%d write sd=%d okay", errsd, listenfd);
-#endif // DEBUG_64BIT_SCM_RIGHTS
-
-#endif
-        // Close our end of the socketpair *before* calling read_all() to get the four-byte error code.
-        // Otherwise, if the daemon closes our socket (or crashes), we will have to wait for a timeout
-        // in read_all() because the socket is not closed (we still have an open reference to it)
-        // Note: listenfd is overwritten in the case of send_bpf above and that will be closed here
-        // for send_bpf operation.
-        dnssd_close(listenfd);
-        listenfd = dnssd_InvalidSocket; // Make sure we don't close it a second time in the cleanup handling below
-    }
-
-    // At this point we may wait in read_all for a few milliseconds waiting for the daemon to send us the error code,
-    // but that's okay -- the daemon should not take more than a few milliseconds to respond.
-    // set_waitlimit() ensures we do not block indefinitely just in case something is wrong
-    if (sdr->op == send_bpf)    // Okay to use sdr->op when checking for op == send_bpf
-        err = kDNSServiceErr_NoError;
-    else if ((err = set_waitlimit(errsd, DNSSD_CLIENT_TIMEOUT)) == kDNSServiceErr_NoError)
-    {
-        if (read_all(errsd, (char*)&err, (int)sizeof(err)) < 0)
-            err = kDNSServiceErr_ServiceNotRunning; // On failure read_all will have written a message to syslog for us
-        else
-            err = ntohl(err);
-    }
-    //syslog(LOG_WARNING, "dnssd_clientstub deliver_request: retrieved error code %d", err);
-
-cleanup:
-    if (MakeSeparateReturnSocket)
-    {
-        if (dnssd_SocketValid(listenfd)) dnssd_close(listenfd);
-        if (dnssd_SocketValid(errsd)) dnssd_close(errsd);
-#if defined(USE_NAMED_ERROR_RETURN_SOCKET)
-        // syslog(LOG_WARNING, "dnssd_clientstub deliver_request: removing UDS: %s", data);
-        if (unlink(data) != 0)
-            syslog(LOG_WARNING, "dnssd_clientstub WARNING: unlink(\"%s\") failed errno %d (%s)", data, dnssd_errno, dnssd_strerror(dnssd_errno));
-        // else syslog(LOG_WARNING, "dnssd_clientstub deliver_request: removed UDS: %s", data);
-#endif
-    }
-
-    free(hdr);
-    return err;
-}
-
-int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
-{
-    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with NULL DNSServiceRef"); return dnssd_InvalidSocket; }
-
-    if (!DNSServiceRefValid(sdRef))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with invalid DNSServiceRef %p %08X %08X",
-               sdRef, sdRef->sockfd, sdRef->validator);
-        return dnssd_InvalidSocket;
-    }
-
-    if (sdRef->primary)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD undefined for kDNSServiceFlagsShareConnection subordinate DNSServiceRef %p", sdRef);
-        return dnssd_InvalidSocket;
-    }
-
-    return (int) sdRef->sockfd;
-}
-
-#if _DNS_SD_LIBDISPATCH
-static void CallbackWithError(DNSServiceRef sdRef, DNSServiceErrorType error)
-{
-    DNSServiceOp *sdr = sdRef;
-    DNSServiceOp *sdrNext;
-    DNSRecord *rec;
-    DNSRecord *recnext;
-    int morebytes;
-
-    while (sdr)
-    {
-        // We can't touch the sdr after the callback as it can be deallocated in the callback
-        sdrNext = sdr->next;
-        morebytes = 1;
-        sdr->moreptr = &morebytes;
-        switch (sdr->op)
-        {
-        case resolve_request:
-            if (sdr->AppCallback) ((DNSServiceResolveReply)    sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL,    sdr->AppContext);
-            break;
-        case query_request:
-            if (sdr->AppCallback) ((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL, 0, sdr->AppContext);
-            break;
-        case addrinfo_request:
-            if (sdr->AppCallback) ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, NULL, 0,          sdr->AppContext);
-            break;
-        case browse_request:
-            if (sdr->AppCallback) ((DNSServiceBrowseReply)     sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, NULL,          sdr->AppContext);
-            break;
-        case reg_service_request:
-            if (sdr->AppCallback) ((DNSServiceRegisterReply)   sdr->AppCallback)(sdr, 0,    error, NULL, 0, NULL,          sdr->AppContext);
-            break;
-        case enumeration_request:
-            if (sdr->AppCallback) ((DNSServiceDomainEnumReply) sdr->AppCallback)(sdr, 0, 0, error, NULL,                   sdr->AppContext);
-            break;
-        case connection_request:
-        case connection_delegate_request:
-            // This means Register Record, walk the list of DNSRecords to do the callback
-            rec = sdr->rec;
-            while (rec)
-            {
-                recnext = rec->recnext;
-                if (rec->AppCallback) ((DNSServiceRegisterRecordReply)rec->AppCallback)(sdr, 0, 0, error, rec->AppContext);
-                // The Callback can call DNSServiceRefDeallocate which in turn frees sdr and all the records.
-                // Detect that and return early
-                if (!morebytes) {syslog(LOG_WARNING, "dnssdclientstub:Record: CallbackwithError morebytes zero"); return;}
-                rec = recnext;
-            }
-            break;
-        case port_mapping_request:
-            if (sdr->AppCallback) ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, 0, 0, error, 0, 0, 0, 0, 0, sdr->AppContext);
-            break;
-        default:
-            syslog(LOG_WARNING, "dnssd_clientstub CallbackWithError called with bad op %d", sdr->op);
-        }
-        // If DNSServiceRefDeallocate was called in the callback, morebytes will be zero. As the sdRef
-        // (and its subordinates) have been freed, we should not proceed further. Note that when we
-        // call the callback with a subordinate sdRef the application can call DNSServiceRefDeallocate
-        // on the main sdRef and DNSServiceRefDeallocate handles this case by walking all the sdRefs and
-        // clears the moreptr so that we can terminate here.
-        //
-        // If DNSServiceRefDeallocate was not called in the callback, then set moreptr to NULL so that
-        // we don't access the stack variable after we return from this function.
-        if (!morebytes) {syslog(LOG_WARNING, "dnssdclientstub:sdRef: CallbackwithError morebytes zero sdr %p", sdr); return;}
-        else {sdr->moreptr = NULL;}
-        sdr = sdrNext;
-    }
-}
-#endif // _DNS_SD_LIBDISPATCH
-
-// Handle reply from server, calling application client callback. If there is no reply
-// from the daemon on the socket contained in sdRef, the call will block.
-DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
-{
-    int morebytes = 0;
-
-    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
-
-    if (!DNSServiceRefValid(sdRef))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
-        return kDNSServiceErr_BadReference;
-    }
-
-    if (sdRef->primary)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult undefined for kDNSServiceFlagsShareConnection subordinate DNSServiceRef %p", sdRef);
-        return kDNSServiceErr_BadReference;
-    }
-
-    if (!sdRef->ProcessReply)
-    {
-        static int num_logs = 0;
-        if (num_logs < 10) syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with DNSServiceRef with no ProcessReply function");
-        if (num_logs < 1000) num_logs++;else sleep(1);
-        return kDNSServiceErr_BadReference;
-    }
-
-    do
-    {
-        CallbackHeader cbh;
-        char *data;
-
-        // return NoError on EWOULDBLOCK. This will handle the case
-        // where a non-blocking socket is told there is data, but it was a false positive.
-        // On error, read_all will write a message to syslog for us, so don't need to duplicate that here
-        // Note: If we want to properly support using non-blocking sockets in the future
-        int result = read_all(sdRef->sockfd, (void *)&cbh.ipc_hdr, sizeof(cbh.ipc_hdr));
-        if (result == read_all_fail)
-        {
-            // Set the ProcessReply to NULL before callback as the sdRef can get deallocated
-            // in the callback.
-            sdRef->ProcessReply = NULL;
-#if _DNS_SD_LIBDISPATCH
-            // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult
-            // is not called by the application and hence need to communicate the error. Cancel the
-            // source so that we don't get any more events
-            // Note: read_all fails if we could not read from the daemon which can happen if the
-            // daemon dies or the file descriptor is disconnected (defunct).
-            if (sdRef->disp_source)
-            {
-                dispatch_source_cancel(sdRef->disp_source);
-                dispatch_release(sdRef->disp_source);
-                sdRef->disp_source = NULL;
-                CallbackWithError(sdRef, kDNSServiceErr_ServiceNotRunning);
-            }
-#endif
-            // Don't touch sdRef anymore as it might have been deallocated
-            return kDNSServiceErr_ServiceNotRunning;
-        }
-        else if (result == read_all_wouldblock)
-        {
-            if (morebytes && sdRef->logcounter < 100)
-            {
-                sdRef->logcounter++;
-                syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult error: select indicated data was waiting but read_all returned EWOULDBLOCK");
-            }
-            return kDNSServiceErr_NoError;
-        }
-
-        ConvertHeaderBytes(&cbh.ipc_hdr);
-        if (cbh.ipc_hdr.version != VERSION)
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult daemon version %d does not match client version %d", cbh.ipc_hdr.version, VERSION);
-            sdRef->ProcessReply = NULL;
-            return kDNSServiceErr_Incompatible;
-        }
-
-        data = malloc(cbh.ipc_hdr.datalen);
-        if (!data) return kDNSServiceErr_NoMemory;
-        if (read_all(sdRef->sockfd, data, cbh.ipc_hdr.datalen) < 0) // On error, read_all will write a message to syslog for us
-        {
-            // Set the ProcessReply to NULL before callback as the sdRef can get deallocated
-            // in the callback.
-            sdRef->ProcessReply = NULL;
-#if _DNS_SD_LIBDISPATCH
-            // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult
-            // is not called by the application and hence need to communicate the error. Cancel the
-            // source so that we don't get any more events
-            if (sdRef->disp_source)
-            {
-                dispatch_source_cancel(sdRef->disp_source);
-                dispatch_release(sdRef->disp_source);
-                sdRef->disp_source = NULL;
-                CallbackWithError(sdRef, kDNSServiceErr_ServiceNotRunning);
-            }
-#endif
-            // Don't touch sdRef anymore as it might have been deallocated
-            free(data);
-            return kDNSServiceErr_ServiceNotRunning;
-        }
-        else
-        {
-            const char *ptr = data;
-            cbh.cb_flags     = get_flags     (&ptr, data + cbh.ipc_hdr.datalen);
-            cbh.cb_interface = get_uint32    (&ptr, data + cbh.ipc_hdr.datalen);
-            cbh.cb_err       = get_error_code(&ptr, data + cbh.ipc_hdr.datalen);
-
-            // CAUTION: We have to handle the case where the client calls DNSServiceRefDeallocate from within the callback function.
-            // To do this we set moreptr to point to morebytes. If the client does call DNSServiceRefDeallocate(),
-            // then that routine will clear morebytes for us, and cause us to exit our loop.
-            morebytes = more_bytes(sdRef->sockfd);
-            if (morebytes)
-            {
-                cbh.cb_flags |= kDNSServiceFlagsMoreComing;
-                sdRef->moreptr = &morebytes;
-            }
-            if (ptr) sdRef->ProcessReply(sdRef, &cbh, ptr, data + cbh.ipc_hdr.datalen);
-            // Careful code here:
-            // If morebytes is non-zero, that means we set sdRef->moreptr above, and the operation was not
-            // cancelled out from under us, so now we need to clear sdRef->moreptr so we don't leave a stray
-            // dangling pointer pointing to a long-gone stack variable.
-            // If morebytes is zero, then one of two thing happened:
-            // (a) morebytes was 0 above, so we didn't set sdRef->moreptr, so we don't need to clear it
-            // (b) morebytes was 1 above, and we set sdRef->moreptr, but the operation was cancelled (with DNSServiceRefDeallocate()),
-            //     so we MUST NOT try to dereference our stale sdRef pointer.
-            if (morebytes) sdRef->moreptr = NULL;
-        }
-        free(data);
-    } while (morebytes);
-
-    return kDNSServiceErr_NoError;
-}
-
-void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef)
-{
-    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefDeallocate called with NULL DNSServiceRef"); return; }
-
-    if (!DNSServiceRefValid(sdRef))     // Also verifies dnssd_SocketValid(sdRef->sockfd) for us too
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefDeallocate called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
-        return;
-    }
-
-    // If we're in the middle of a DNSServiceProcessResult() invocation for this DNSServiceRef, clear its morebytes flag to break it out of its while loop
-    if (sdRef->moreptr) *(sdRef->moreptr) = 0;
-
-    if (sdRef->primary)     // If this is a subordinate DNSServiceOp, just send a 'stop' command
-    {
-        DNSServiceOp **p = &sdRef->primary->next;
-        while (*p && *p != sdRef) p = &(*p)->next;
-        if (*p)
-        {
-            char *ptr;
-            size_t len = 0;
-            ipc_msg_hdr *hdr = create_hdr(cancel_request, &len, &ptr, 0, sdRef);
-            if (hdr)
-            {
-                ConvertHeaderBytes(hdr);
-                write_all(sdRef->sockfd, (char *)hdr, len);
-                free(hdr);
-            }
-            *p = sdRef->next;
-            FreeDNSServiceOp(sdRef);
-        }
-    }
-    else                    // else, make sure to terminate all subordinates as well
-    {
-#if _DNS_SD_LIBDISPATCH
-        // The cancel handler will close the fd if a dispatch source has been set
-        if (sdRef->disp_source)
-        {
-            // By setting the ProcessReply to NULL, we make sure that we never call
-            // the application callbacks ever, after returning from this function. We
-            // assume that DNSServiceRefDeallocate is called from the serial queue
-            // that was passed to DNSServiceSetDispatchQueue. Hence, dispatch_source_cancel
-            // should cancel all the blocks on the queue and hence there should be no more
-            // callbacks when we return from this function. Setting ProcessReply to NULL
-            // provides extra protection.
-            sdRef->ProcessReply = NULL;
-            dispatch_source_cancel(sdRef->disp_source);
-            dispatch_release(sdRef->disp_source);
-            sdRef->disp_source = NULL;
-        }
-        // if disp_queue is set, it means it used the DNSServiceSetDispatchQueue API. In that case,
-        // when the source was cancelled, the fd was closed in the handler. Currently the source
-        // is cancelled only when the mDNSResponder daemon dies
-        else if (!sdRef->disp_queue) dnssd_close(sdRef->sockfd);
-#else
-        dnssd_close(sdRef->sockfd);
-#endif
-        // Free DNSRecords added in DNSRegisterRecord if they have not
-        // been freed in DNSRemoveRecord
-        while (sdRef)
-        {
-            DNSServiceOp *p = sdRef;
-            sdRef = sdRef->next;
-            // When there is an error reading from the daemon e.g., bad fd, CallbackWithError
-            // is called which sets moreptr. It might set the moreptr on a subordinate sdRef
-            // but the application might call DNSServiceRefDeallocate with the main sdRef from
-            // the callback. Hence, when we loop through the subordinate sdRefs, we need
-            // to clear the moreptr so that CallbackWithError can terminate itself instead of
-            // walking through the freed sdRefs.
-            if (p->moreptr) *(p->moreptr) = 0;
-            FreeDNSServiceOp(p);
-        }
-    }
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceGetProperty(const char *property, void *result, uint32_t *size)
-{
-    char *ptr;
-    size_t len = strlen(property) + 1;
-    ipc_msg_hdr *hdr;
-    DNSServiceOp *tmp;
-    uint32_t actualsize;
-
-    DNSServiceErrorType err = ConnectToServer(&tmp, 0, getproperty_request, NULL, NULL, NULL);
-    if (err) return err;
-
-    hdr = create_hdr(getproperty_request, &len, &ptr, 0, tmp);
-    if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
-
-    put_string(property, &ptr);
-    err = deliver_request(hdr, tmp);        // Will free hdr for us
-    if (read_all(tmp->sockfd, (char*)&actualsize, (int)sizeof(actualsize)) < 0)
-    { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; }
-
-    actualsize = ntohl(actualsize);
-    if (read_all(tmp->sockfd, (char*)result, actualsize < *size ? actualsize : *size) < 0)
-    { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; }
-    DNSServiceRefDeallocate(tmp);
-
-    // Swap version result back to local process byte order
-    if (!strcmp(property, kDNSServiceProperty_DaemonVersion) && *size >= 4)
-        *(uint32_t*)result = ntohl(*(uint32_t*)result);
-
-    *size = actualsize;
-    return kDNSServiceErr_NoError;
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceGetPID(const uint16_t srcport, int32_t *pid)
-{
-    char *ptr;
-    ipc_msg_hdr *hdr;
-    DNSServiceOp *tmp;
-    size_t len = sizeof(int32_t);
-
-    DNSServiceErrorType err = ConnectToServer(&tmp, 0, getpid_request, NULL, NULL, NULL);
-    if (err)
-        return err;
-
-    hdr = create_hdr(getpid_request, &len, &ptr, 0, tmp);
-    if (!hdr)
-    {
-        DNSServiceRefDeallocate(tmp);
-        return kDNSServiceErr_NoMemory;
-    }
-
-    put_uint16(srcport, &ptr);
-    err = deliver_request(hdr, tmp);        // Will free hdr for us
-
-    if (read_all(tmp->sockfd, (char*)pid, sizeof(int32_t)) < 0)
-    {
-        DNSServiceRefDeallocate(tmp);
-        return kDNSServiceErr_ServiceNotRunning;
-    }
-
-    DNSServiceRefDeallocate(tmp);
-    return kDNSServiceErr_NoError;
-}
-
-static void handle_resolve_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *end)
-{
-    char fullname[kDNSServiceMaxDomainName];
-    char target[kDNSServiceMaxDomainName];
-    uint16_t txtlen;
-    union { uint16_t s; u_char b[2]; } port;
-    unsigned char *txtrecord;
-
-    get_string(&data, end, fullname, kDNSServiceMaxDomainName);
-    get_string(&data, end, target,   kDNSServiceMaxDomainName);
-    if (!data || data + 2 > end) goto fail;
-
-    port.b[0] = *data++;
-    port.b[1] = *data++;
-    txtlen = get_uint16(&data, end);
-    txtrecord = (unsigned char *)get_rdata(&data, end, txtlen);
-
-    if (!data) goto fail;
-    ((DNSServiceResolveReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, fullname, target, port.s, txtlen, txtrecord, sdr->AppContext);
-    return;
-    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-fail:
-    syslog(LOG_WARNING, "dnssd_clientstub handle_resolve_response: error reading result from daemon");
-}
-
-#if APPLE_OSX_mDNSResponder
-
-static int32_t libSystemVersion = 0;
-
-// Return true if the application linked against a version of libsystem where P2P
-// interfaces were included by default when using kDNSServiceInterfaceIndexAny.
-// Using 160.0.0 == 0xa00000 as the version threshold.
-static int includeP2PWithIndexAny()
-{
-    if (libSystemVersion == 0)
-        libSystemVersion = NSVersionOfLinkTimeLibrary("System");
-
-    if (libSystemVersion < 0xa00000)
-        return 1;
-    else
-        return 0;
-}
-
-#else   // APPLE_OSX_mDNSResponder
-
-// always return false for non Apple platforms
-static int includeP2PWithIndexAny()
-{
-    return 0;
-}
-
-#endif  // APPLE_OSX_mDNSResponder
-
-DNSServiceErrorType DNSSD_API DNSServiceResolve
-(
-    DNSServiceRef                 *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                    *name,
-    const char                    *regtype,
-    const char                    *domain,
-    DNSServiceResolveReply callBack,
-    void                          *context
-)
-{
-    char *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err;
-
-    if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam;
-
-    // Need a real InterfaceID for WakeOnResolve
-    if ((flags & kDNSServiceFlagsWakeOnResolve) != 0 &&
-        ((interfaceIndex == kDNSServiceInterfaceIndexAny) ||
-         (interfaceIndex == kDNSServiceInterfaceIndexLocalOnly) ||
-         (interfaceIndex == kDNSServiceInterfaceIndexUnicast) ||
-         (interfaceIndex == kDNSServiceInterfaceIndexP2P)))
-    {
-        return kDNSServiceErr_BadParam;
-    }
-
-    if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
-        flags |= kDNSServiceFlagsIncludeP2P;
-
-    err = ConnectToServer(sdRef, flags, resolve_request, handle_resolve_response, callBack, context);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    // Calculate total message length
-    len = sizeof(flags);
-    len += sizeof(interfaceIndex);
-    len += strlen(name) + 1;
-    len += strlen(regtype) + 1;
-    len += strlen(domain) + 1;
-
-    hdr = create_hdr(resolve_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_string(name, &ptr);
-    put_string(regtype, &ptr);
-    put_string(domain, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-static void handle_query_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
-{
-    uint32_t ttl;
-    char name[kDNSServiceMaxDomainName];
-    uint16_t rrtype, rrclass, rdlen;
-    const char *rdata;
-
-    get_string(&data, end, name, kDNSServiceMaxDomainName);
-    rrtype  = get_uint16(&data, end);
-    rrclass = get_uint16(&data, end);
-    rdlen   = get_uint16(&data, end);
-    rdata   = get_rdata(&data, end, rdlen);
-    ttl     = get_uint32(&data, end);
-
-    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_query_response: error reading result from daemon");
-    else ((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, name, rrtype, rrclass, rdlen, rdata, ttl, sdr->AppContext);
-    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
-(
-    DNSServiceRef              *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                 *name,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    DNSServiceQueryRecordReply callBack,
-    void                       *context
-)
-{
-    char *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err;
-
-    if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
-        flags |= kDNSServiceFlagsIncludeP2P;
-
-    err = ConnectToServer(sdRef, flags, query_request, handle_query_response, callBack, context);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    if (!name) name = "\0";
-
-    // Calculate total message length
-    len = sizeof(flags);
-    len += sizeof(uint32_t);  // interfaceIndex
-    len += strlen(name) + 1;
-    len += 2 * sizeof(uint16_t);  // rrtype, rrclass
-
-    hdr = create_hdr(query_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_string(name, &ptr);
-    put_uint16(rrtype, &ptr);
-    put_uint16(rrclass, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-static void handle_addrinfo_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
-{
-    char hostname[kDNSServiceMaxDomainName];
-    uint16_t rrtype, rrclass, rdlen;
-    const char *rdata;
-    uint32_t ttl;
-
-    get_string(&data, end, hostname, kDNSServiceMaxDomainName);
-    rrtype  = get_uint16(&data, end);
-    rrclass = get_uint16(&data, end);
-    rdlen   = get_uint16(&data, end);
-    rdata   = get_rdata (&data, end, rdlen);
-    ttl     = get_uint32(&data, end);
-
-    // We only generate client callbacks for A and AAAA results (including NXDOMAIN results for
-    // those types, if the client has requested those with the kDNSServiceFlagsReturnIntermediates).
-    // Other result types, specifically CNAME referrals, are not communicated to the client, because
-    // the DNSServiceGetAddrInfoReply interface doesn't have any meaningful way to communiate CNAME referrals.
-    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_addrinfo_response: error reading result from daemon");
-    else if (rrtype == kDNSServiceType_A || rrtype == kDNSServiceType_AAAA)
-    {
-        struct sockaddr_in sa4;
-        struct sockaddr_in6 sa6;
-        const struct sockaddr *const sa = (rrtype == kDNSServiceType_A) ? (struct sockaddr*)&sa4 : (struct sockaddr*)&sa6;
-        if (rrtype == kDNSServiceType_A)
-        {
-            memset(&sa4, 0, sizeof(sa4));
-            #ifndef NOT_HAVE_SA_LEN
-            sa4.sin_len = sizeof(struct sockaddr_in);
-            #endif
-            sa4.sin_family = AF_INET;
-            //  sin_port   = 0;
-            if (!cbh->cb_err) memcpy(&sa4.sin_addr, rdata, rdlen);
-        }
-        else
-        {
-            memset(&sa6, 0, sizeof(sa6));
-            #ifndef NOT_HAVE_SA_LEN
-            sa6.sin6_len = sizeof(struct sockaddr_in6);
-            #endif
-            sa6.sin6_family     = AF_INET6;
-            //  sin6_port     = 0;
-            //  sin6_flowinfo = 0;
-            //  sin6_scope_id = 0;
-            if (!cbh->cb_err)
-            {
-                memcpy(&sa6.sin6_addr, rdata, rdlen);
-                if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr)) sa6.sin6_scope_id = cbh->cb_interface;
-            }
-        }
-        // Validation results are always delivered separately from the actual results of the
-        // DNSServiceGetAddrInfo. Set the "addr" to NULL as per the documentation.
-        //
-        // Note: If we deliver validation results along with the "addr" in the future, we need
-        // a way to differentiate the negative response from validation-only response as both
-        // has zero address.
-        if (!(cbh->cb_flags & kDNSServiceFlagsValidate))
-            ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, hostname, sa, ttl, sdr->AppContext);
-        else
-            ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, hostname, NULL, 0, sdr->AppContext);
-        // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-    }
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo
-(
-    DNSServiceRef                    *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    uint32_t protocol,
-    const char                       *hostname,
-    DNSServiceGetAddrInfoReply callBack,
-    void                             *context          /* may be NULL */
-)
-{
-    char *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err;
-
-    if (!hostname) return kDNSServiceErr_BadParam;
-
-    err = ConnectToServer(sdRef, flags, addrinfo_request, handle_addrinfo_response, callBack, context);
-    if (err)
-    {
-         return err;    // On error ConnectToServer leaves *sdRef set to NULL
-    }
-
-    // Calculate total message length
-    len = sizeof(flags);
-    len += sizeof(uint32_t);      // interfaceIndex
-    len += sizeof(uint32_t);      // protocol
-    len += strlen(hostname) + 1;
-
-    hdr = create_hdr(addrinfo_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_uint32(protocol, &ptr);
-    put_string(hostname, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-static void handle_browse_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
-{
-    char replyName[256], replyType[kDNSServiceMaxDomainName], replyDomain[kDNSServiceMaxDomainName];
-    get_string(&data, end, replyName, 256);
-    get_string(&data, end, replyType, kDNSServiceMaxDomainName);
-    get_string(&data, end, replyDomain, kDNSServiceMaxDomainName);
-    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_browse_response: error reading result from daemon");
-    else ((DNSServiceBrowseReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, replyName, replyType, replyDomain, sdr->AppContext);
-    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceBrowse
-(
-    DNSServiceRef         *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char            *regtype,
-    const char            *domain,
-    DNSServiceBrowseReply callBack,
-    void                  *context
-)
-{
-    char *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err;
-
-    if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
-        flags |= kDNSServiceFlagsIncludeP2P;
-
-    err = ConnectToServer(sdRef, flags, browse_request, handle_browse_response, callBack, context);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    if (!domain) domain = "";
-    len = sizeof(flags);
-    len += sizeof(interfaceIndex);
-    len += strlen(regtype) + 1;
-    len += strlen(domain) + 1;
-
-    hdr = create_hdr(browse_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_string(regtype, &ptr);
-    put_string(domain, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain);
-DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain)
-{
-    DNSServiceOp *tmp;
-    char *ptr;
-    size_t len = sizeof(flags) + strlen(domain) + 1;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err = ConnectToServer(&tmp, 0, setdomain_request, NULL, NULL, NULL);
-    if (err) return err;
-
-    hdr = create_hdr(setdomain_request, &len, &ptr, 0, tmp);
-    if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_string(domain, &ptr);
-    err = deliver_request(hdr, tmp);        // Will free hdr for us
-    DNSServiceRefDeallocate(tmp);
-    return err;
-}
-
-static void handle_regservice_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
-{
-    char name[256], regtype[kDNSServiceMaxDomainName], domain[kDNSServiceMaxDomainName];
-    get_string(&data, end, name, 256);
-    get_string(&data, end, regtype, kDNSServiceMaxDomainName);
-    get_string(&data, end, domain,  kDNSServiceMaxDomainName);
-    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_regservice_response: error reading result from daemon");
-    else ((DNSServiceRegisterReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_err, name, regtype, domain, sdr->AppContext);
-    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceRegister
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                          *name,
-    const char                          *regtype,
-    const char                          *domain,
-    const char                          *host,
-    uint16_t PortInNetworkByteOrder,
-    uint16_t txtLen,
-    const void                          *txtRecord,
-    DNSServiceRegisterReply callBack,
-    void                                *context
-)
-{
-    char *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err;
-    union { uint16_t s; u_char b[2]; } port = { PortInNetworkByteOrder };
-
-    if (!name) name = "";
-    if (!regtype) return kDNSServiceErr_BadParam;
-    if (!domain) domain = "";
-    if (!host) host = "";
-    if (!txtRecord) txtRecord = (void*)"";
-
-    // No callback must have auto-rename
-    if (!callBack && (flags & kDNSServiceFlagsNoAutoRename)) return kDNSServiceErr_BadParam;
-
-    if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
-        flags |= kDNSServiceFlagsIncludeP2P;
-
-    err = ConnectToServer(sdRef, flags, reg_service_request, callBack ? handle_regservice_response : NULL, callBack, context);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    len = sizeof(DNSServiceFlags);
-    len += sizeof(uint32_t);  // interfaceIndex
-    len += strlen(name) + strlen(regtype) + strlen(domain) + strlen(host) + 4;
-    len += 2 * sizeof(uint16_t);  // port, txtLen
-    len += txtLen;
-
-    hdr = create_hdr(reg_service_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    // If it is going over a shared connection, then don't set the IPC_FLAGS_NOREPLY
-    // as it affects all the operations over the shared connection. This is not
-    // a normal case and hence receiving the response back from the daemon and
-    // discarding it in ConnectionResponse is okay.
-
-    if (!(flags & kDNSServiceFlagsShareConnection) && !callBack) hdr->ipc_flags |= IPC_FLAGS_NOREPLY;
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_string(name, &ptr);
-    put_string(regtype, &ptr);
-    put_string(domain, &ptr);
-    put_string(host, &ptr);
-    *ptr++ = port.b[0];
-    *ptr++ = port.b[1];
-    put_uint16(txtLen, &ptr);
-    put_rdata(txtLen, txtRecord, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-static void handle_enumeration_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
-{
-    char domain[kDNSServiceMaxDomainName];
-    get_string(&data, end, domain, kDNSServiceMaxDomainName);
-    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_enumeration_response: error reading result from daemon");
-    else ((DNSServiceDomainEnumReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, domain, sdr->AppContext);
-    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
-(
-    DNSServiceRef             *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    DNSServiceDomainEnumReply callBack,
-    void                      *context
-)
-{
-    char *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err;
-
-    int f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0;
-    int f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0;
-    if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
-
-    err = ConnectToServer(sdRef, flags, enumeration_request, handle_enumeration_response, callBack, context);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    len = sizeof(DNSServiceFlags);
-    len += sizeof(uint32_t);
-
-    hdr = create_hdr(enumeration_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-static void ConnectionResponse(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *const data, const char *const end)
-{
-    (void)data; // Unused
-
-    //printf("ConnectionResponse got %d\n", cbh->ipc_hdr.op);
-    if (cbh->ipc_hdr.op != reg_record_reply_op)
-    {
-        // When using kDNSServiceFlagsShareConnection, need to search the list of associated DNSServiceOps
-        // to find the one this response is intended for, and then call through to its ProcessReply handler.
-        // We start with our first subordinate DNSServiceRef -- don't want to accidentally match the parent DNSServiceRef.
-        DNSServiceOp *op = sdr->next;
-        while (op && (op->uid.u32[0] != cbh->ipc_hdr.client_context.u32[0] || op->uid.u32[1] != cbh->ipc_hdr.client_context.u32[1]))
-            op = op->next;
-        // Note: We may sometimes not find a matching DNSServiceOp, in the case where the client has
-        // cancelled the subordinate DNSServiceOp, but there are still messages in the pipeline from the daemon
-        if (op && op->ProcessReply) op->ProcessReply(op, cbh, data, end);
-        // WARNING: Don't touch op or sdr after this -- client may have called DNSServiceRefDeallocate
-        return;
-    }
-    else
-    {
-        DNSRecordRef rec;
-        for (rec = sdr->rec; rec; rec = rec->recnext)
-        {
-            if (rec->uid.u32[0] == cbh->ipc_hdr.client_context.u32[0] && rec->uid.u32[1] == cbh->ipc_hdr.client_context.u32[1])
-                break;
-        }
-        // The record might have been freed already and hence not an
-        // error if the record is not found.
-        if (!rec)
-        {
-            syslog(LOG_INFO, "ConnectionResponse: Record not found");
-            return;
-        }
-        if (rec->sdr != sdr)
-        {
-            syslog(LOG_WARNING, "ConnectionResponse: Record sdr mismatch: rec %p sdr %p", rec->sdr, sdr);
-            return;
-        }
-
-        if (sdr->op == connection_request || sdr->op == connection_delegate_request)
-        {
-            rec->AppCallback(rec->sdr, rec, cbh->cb_flags, cbh->cb_err, rec->AppContext);
-        }
-        else
-        {
-            syslog(LOG_WARNING, "dnssd_clientstub ConnectionResponse: sdr->op != connection_request");
-            rec->AppCallback(rec->sdr, rec, 0, kDNSServiceErr_Unknown, rec->AppContext);
-        }
-        // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-    }
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef)
-{
-    char *ptr;
-    size_t len = 0;
-    ipc_msg_hdr *hdr;
-    DNSServiceErrorType err = ConnectToServer(sdRef, 0, connection_request, ConnectionResponse, NULL, NULL);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    hdr = create_hdr(connection_request, &len, &ptr, 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-#if APPLE_OSX_mDNSResponder && !TARGET_IPHONE_SIMULATOR
-DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid)
-{
-    char *ptr;
-    size_t len = 0;
-    ipc_msg_hdr *hdr;
-
-    DNSServiceErrorType err = ConnectToServer(sdRef, 0, connection_delegate_request, ConnectionResponse, NULL, NULL);
-    if (err)
-    {
-         return err;    // On error ConnectToServer leaves *sdRef set to NULL
-    }
-
-    // Only one of the two options can be set. If pid is zero, uuid is used. 
-    // If both are specified only pid will be used. We send across the pid
-    // so that the daemon knows what to read from the socket.
-
-    len += sizeof(int32_t);
-
-    hdr = create_hdr(connection_delegate_request, &len, &ptr, 0, *sdRef);
-    if (!hdr)
-    {
-        DNSServiceRefDeallocate(*sdRef);
-        *sdRef = NULL;
-        return kDNSServiceErr_NoMemory;
-    }
-
-    if (pid && setsockopt((*sdRef)->sockfd, SOL_SOCKET, SO_DELEGATED, &pid, sizeof(pid)) == -1)
-    {  
-        // Free the hdr in case we return before calling deliver_request() 
-        if (hdr)
-            free(hdr);
-        DNSServiceRefDeallocate(*sdRef);
-        *sdRef = NULL;
-        return kDNSServiceErr_NoAuth;
-    }
-
-    if (!pid && setsockopt((*sdRef)->sockfd, SOL_SOCKET, SO_DELEGATED_UUID, uuid, sizeof(uuid_t)) == -1)
-    {
-        // Free the hdr in case we return before calling deliver_request()
-        if (hdr)
-            free(hdr);
-        DNSServiceRefDeallocate(*sdRef);
-        *sdRef = NULL;
-        return kDNSServiceErr_NoAuth;
-    }
-
-    put_uint32(pid, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err)
-    {
-        DNSServiceRefDeallocate(*sdRef);
-        *sdRef = NULL;
-    }
-    return err;
-}
-#elif TARGET_IPHONE_SIMULATOR // This hack is for Simulator platform only
-DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid)
-{
-    (void) pid;
-    (void) uuid;
-    return DNSServiceCreateConnection(sdRef);
-}
-#endif
-
-DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef                  *RecordRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char                    *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void                    *rdata,
-    uint32_t ttl,
-    DNSServiceRegisterRecordReply callBack,
-    void                          *context
-)
-{
-    char *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr = NULL;
-    DNSRecordRef rref = NULL;
-    DNSRecord **p;
-    int f1 = (flags & kDNSServiceFlagsShared) != 0;
-    int f2 = (flags & kDNSServiceFlagsUnique) != 0;
-    if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
-
-    if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
-        flags |= kDNSServiceFlagsIncludeP2P;
-
-    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
-
-    if (!DNSServiceRefValid(sdRef))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
-        return kDNSServiceErr_BadReference;
-    }
-
-    if (sdRef->op != connection_request && sdRef->op != connection_delegate_request)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with non-DNSServiceCreateConnection DNSServiceRef %p %d", sdRef, sdRef->op);
-        return kDNSServiceErr_BadReference;
-    }
-
-    *RecordRef = NULL;
-
-    len = sizeof(DNSServiceFlags);
-    len += 2 * sizeof(uint32_t);  // interfaceIndex, ttl
-    len += 3 * sizeof(uint16_t);  // rrtype, rrclass, rdlen
-    len += strlen(fullname) + 1;
-    len += rdlen;
-
-    // Bump up the uid. Normally for shared operations (kDNSServiceFlagsShareConnection), this
-    // is done in ConnectToServer. For DNSServiceRegisterRecord, ConnectToServer has already
-    // been called. As multiple DNSServiceRegisterRecords can be multiplexed over a single
-    // connection, we need a way to demultiplex the response so that the callback corresponding
-    // to the right DNSServiceRegisterRecord instance can be called. Use the same mechanism that
-    // is used by kDNSServiceFlagsShareConnection. create_hdr copies the uid value to ipc
-    // hdr->client_context which will be returned in the ipc response.
-    if (++sdRef->uid.u32[0] == 0)
-        ++sdRef->uid.u32[1];
-    hdr = create_hdr(reg_record_request, &len, &ptr, 1, sdRef);
-    if (!hdr) return kDNSServiceErr_NoMemory;
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_string(fullname, &ptr);
-    put_uint16(rrtype, &ptr);
-    put_uint16(rrclass, &ptr);
-    put_uint16(rdlen, &ptr);
-    put_rdata(rdlen, rdata, &ptr);
-    put_uint32(ttl, &ptr);
-
-    rref = malloc(sizeof(DNSRecord));
-    if (!rref) { free(hdr); return kDNSServiceErr_NoMemory; }
-    rref->AppContext = context;
-    rref->AppCallback = callBack;
-    rref->record_index = sdRef->max_index++;
-    rref->sdr = sdRef;
-    rref->recnext = NULL;
-    *RecordRef = rref;
-    // Remember the uid that we are sending across so that we can match
-    // when the response comes back.
-    rref->uid = sdRef->uid;
-    hdr->reg_index = rref->record_index;
-
-    p = &(sdRef)->rec;
-    while (*p) p = &(*p)->recnext;
-    *p = rref;
-
-    return deliver_request(hdr, sdRef);     // Will free hdr for us
-}
-
-// sdRef returned by DNSServiceRegister()
-DNSServiceErrorType DNSSD_API DNSServiceAddRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef    *RecordRef,
-    DNSServiceFlags flags,
-    uint16_t rrtype,
-    uint16_t rdlen,
-    const void      *rdata,
-    uint32_t ttl
-)
-{
-    ipc_msg_hdr *hdr;
-    size_t len = 0;
-    char *ptr;
-    DNSRecordRef rref;
-    DNSRecord **p;
-
-    if (!sdRef)     { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSServiceRef");        return kDNSServiceErr_BadParam; }
-    if (!RecordRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSRecordRef pointer"); return kDNSServiceErr_BadParam; }
-    if (sdRef->op != reg_service_request)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with non-DNSServiceRegister DNSServiceRef %p %d", sdRef, sdRef->op);
-        return kDNSServiceErr_BadReference;
-    }
-
-    if (!DNSServiceRefValid(sdRef))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
-        return kDNSServiceErr_BadReference;
-    }
-
-    *RecordRef = NULL;
-
-    len += 2 * sizeof(uint16_t);  // rrtype, rdlen
-    len += rdlen;
-    len += sizeof(uint32_t);
-    len += sizeof(DNSServiceFlags);
-
-    hdr = create_hdr(add_record_request, &len, &ptr, 1, sdRef);
-    if (!hdr) return kDNSServiceErr_NoMemory;
-    put_flags(flags, &ptr);
-    put_uint16(rrtype, &ptr);
-    put_uint16(rdlen, &ptr);
-    put_rdata(rdlen, rdata, &ptr);
-    put_uint32(ttl, &ptr);
-
-    rref = malloc(sizeof(DNSRecord));
-    if (!rref) { free(hdr); return kDNSServiceErr_NoMemory; }
-    rref->AppContext = NULL;
-    rref->AppCallback = NULL;
-    rref->record_index = sdRef->max_index++;
-    rref->sdr = sdRef;
-    rref->recnext = NULL;
-    *RecordRef = rref;
-    hdr->reg_index = rref->record_index;
-
-    p = &(sdRef)->rec;
-    while (*p) p = &(*p)->recnext;
-    *p = rref;
-
-    return deliver_request(hdr, sdRef);     // Will free hdr for us
-}
-
-// DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord
-DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef RecordRef,
-    DNSServiceFlags flags,
-    uint16_t rdlen,
-    const void      *rdata,
-    uint32_t ttl
-)
-{
-    ipc_msg_hdr *hdr;
-    size_t len = 0;
-    char *ptr;
-
-    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
-
-    if (!DNSServiceRefValid(sdRef))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
-        return kDNSServiceErr_BadReference;
-    }
-
-    // Note: RecordRef is allowed to be NULL
-
-    len += sizeof(uint16_t);
-    len += rdlen;
-    len += sizeof(uint32_t);
-    len += sizeof(DNSServiceFlags);
-
-    hdr = create_hdr(update_record_request, &len, &ptr, 1, sdRef);
-    if (!hdr) return kDNSServiceErr_NoMemory;
-    hdr->reg_index = RecordRef ? RecordRef->record_index : TXT_RECORD_INDEX;
-    put_flags(flags, &ptr);
-    put_uint16(rdlen, &ptr);
-    put_rdata(rdlen, rdata, &ptr);
-    put_uint32(ttl, &ptr);
-    return deliver_request(hdr, sdRef);     // Will free hdr for us
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
-(
-    DNSServiceRef sdRef,
-    DNSRecordRef RecordRef,
-    DNSServiceFlags flags
-)
-{
-    ipc_msg_hdr *hdr;
-    size_t len = 0;
-    char *ptr;
-    DNSServiceErrorType err;
-
-    if (!sdRef)            { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
-    if (!RecordRef)        { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with NULL DNSRecordRef");  return kDNSServiceErr_BadParam; }
-    if (!sdRef->max_index) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with bad DNSServiceRef");  return kDNSServiceErr_BadReference; }
-
-    if (!DNSServiceRefValid(sdRef))
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
-        return kDNSServiceErr_BadReference;
-    }
-
-    len += sizeof(flags);
-    hdr = create_hdr(remove_record_request, &len, &ptr, 1, sdRef);
-    if (!hdr) return kDNSServiceErr_NoMemory;
-    hdr->reg_index = RecordRef->record_index;
-    put_flags(flags, &ptr);
-    err = deliver_request(hdr, sdRef);      // Will free hdr for us
-    if (!err)
-    {
-        // This RecordRef could have been allocated in DNSServiceRegisterRecord or DNSServiceAddRecord.
-        // If so, delink from the list before freeing
-        DNSRecord **p = &sdRef->rec;
-        while (*p && *p != RecordRef) p = &(*p)->recnext;
-        if (*p) *p = RecordRef->recnext;
-        free(RecordRef);
-    }
-    return err;
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
-(
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    const char      *fullname,
-    uint16_t rrtype,
-    uint16_t rrclass,
-    uint16_t rdlen,
-    const void      *rdata
-)
-{
-    char *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    DNSServiceOp *tmp;
-
-    DNSServiceErrorType err = ConnectToServer(&tmp, flags, reconfirm_record_request, NULL, NULL, NULL);
-    if (err) return err;
-
-    len = sizeof(DNSServiceFlags);
-    len += sizeof(uint32_t);
-    len += strlen(fullname) + 1;
-    len += 3 * sizeof(uint16_t);
-    len += rdlen;
-    hdr = create_hdr(reconfirm_record_request, &len, &ptr, 0, tmp);
-    if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_string(fullname, &ptr);
-    put_uint16(rrtype, &ptr);
-    put_uint16(rrclass, &ptr);
-    put_uint16(rdlen, &ptr);
-    put_rdata(rdlen, rdata, &ptr);
-
-    err = deliver_request(hdr, tmp);        // Will free hdr for us
-    DNSServiceRefDeallocate(tmp);
-    return err;
-}
-
-
-static void handle_port_mapping_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
-{
-    union { uint32_t l; u_char b[4]; } addr;
-    uint8_t protocol;
-    union { uint16_t s; u_char b[2]; } internalPort;
-    union { uint16_t s; u_char b[2]; } externalPort;
-    uint32_t ttl;
-
-    if (!data || data + 13 > end) goto fail;
-
-    addr.b[0] = *data++;
-    addr.b[1] = *data++;
-    addr.b[2] = *data++;
-    addr.b[3] = *data++;
-    protocol          = *data++;
-    internalPort.b[0] = *data++;
-    internalPort.b[1] = *data++;
-    externalPort.b[0] = *data++;
-    externalPort.b[1] = *data++;
-    ttl               = get_uint32(&data, end);
-    if (!data) goto fail;
-
-    ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, addr.l, protocol, internalPort.s, externalPort.s, ttl, sdr->AppContext);
-    return;
-    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
-
-    fail :
-    syslog(LOG_WARNING, "dnssd_clientstub handle_port_mapping_response: error reading result from daemon");
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    uint32_t interfaceIndex,
-    uint32_t protocol,                                /* TCP and/or UDP */
-    uint16_t internalPortInNetworkByteOrder,
-    uint16_t externalPortInNetworkByteOrder,
-    uint32_t ttl,                                     /* time to live in seconds */
-    DNSServiceNATPortMappingReply callBack,
-    void                                *context      /* may be NULL */
-)
-{
-    char *ptr;
-    size_t len;
-    ipc_msg_hdr *hdr;
-    union { uint16_t s; u_char b[2]; } internalPort = { internalPortInNetworkByteOrder };
-    union { uint16_t s; u_char b[2]; } externalPort = { externalPortInNetworkByteOrder };
-
-    DNSServiceErrorType err = ConnectToServer(sdRef, flags, port_mapping_request, handle_port_mapping_response, callBack, context);
-    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
-
-    len = sizeof(flags);
-    len += sizeof(interfaceIndex);
-    len += sizeof(protocol);
-    len += sizeof(internalPort);
-    len += sizeof(externalPort);
-    len += sizeof(ttl);
-
-    hdr = create_hdr(port_mapping_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
-    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
-
-    put_flags(flags, &ptr);
-    put_uint32(interfaceIndex, &ptr);
-    put_uint32(protocol, &ptr);
-    *ptr++ = internalPort.b[0];
-    *ptr++ = internalPort.b[1];
-    *ptr++ = externalPort.b[0];
-    *ptr++ = externalPort.b[1];
-    put_uint32(ttl, &ptr);
-
-    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
-    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
-    return err;
-}
-
-#if _DNS_SD_LIBDISPATCH
-DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue
-(
-    DNSServiceRef service,
-    dispatch_queue_t queue
-)
-{
-    int dnssd_fd  = DNSServiceRefSockFD(service);
-    if (dnssd_fd == dnssd_InvalidSocket) return kDNSServiceErr_BadParam;
-    if (!queue)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub: DNSServiceSetDispatchQueue dispatch queue NULL");
-        return kDNSServiceErr_BadParam;
-    }
-    if (service->disp_queue)
-    {
-        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSetDispatchQueue dispatch queue set already");
-        return kDNSServiceErr_BadParam;
-    }
-    if (service->disp_source)
-    {
-        syslog(LOG_WARNING, "DNSServiceSetDispatchQueue dispatch source set already");
-        return kDNSServiceErr_BadParam;
-    }
-    service->disp_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, dnssd_fd, 0, queue);
-    if (!service->disp_source)
-    {
-        syslog(LOG_WARNING, "DNSServiceSetDispatchQueue dispatch_source_create failed");
-        return kDNSServiceErr_NoMemory;
-    }
-    service->disp_queue = queue;
-    dispatch_source_set_event_handler(service->disp_source, ^{DNSServiceProcessResult(service);});
-    dispatch_source_set_cancel_handler(service->disp_source, ^{dnssd_close(dnssd_fd);});
-    dispatch_resume(service->disp_source);
-    return kDNSServiceErr_NoError;
-}
-#endif // _DNS_SD_LIBDISPATCH
-
-#if !defined(_WIN32)
-
-static void DNSSD_API SleepKeepaliveCallback(DNSServiceRef sdRef, DNSRecordRef rec, const DNSServiceFlags flags,
-                                             DNSServiceErrorType errorCode, void *context)
-{
-    SleepKAContext *ka = (SleepKAContext *)context;
-    (void)rec;      // Unused
-    (void)flags;    // Unused
-
-    if (sdRef->kacontext != context)
-        syslog(LOG_WARNING, "SleepKeepaliveCallback context mismatch");
-
-    if (ka->AppCallback)
-        ((DNSServiceSleepKeepaliveReply)ka->AppCallback)(sdRef, errorCode, ka->AppContext);
-}
-
-DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive
-(
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags flags,
-    int fd,
-    unsigned int timeout,
-    DNSServiceSleepKeepaliveReply callBack,
-    void                                *context
-)
-{
-    char source_str[INET6_ADDRSTRLEN];
-    char target_str[INET6_ADDRSTRLEN];
-    struct sockaddr_storage lss;
-    struct sockaddr_storage rss;
-    socklen_t len1, len2;
-    unsigned int len, proxyreclen;
-    char buf[256];
-    DNSServiceErrorType err;
-    DNSRecordRef record = NULL;
-    char name[10];
-    char recname[128];
-    SleepKAContext *ka;
-    unsigned int i, unique;
-
-
-    (void) flags; //unused
-    if (!timeout) return kDNSServiceErr_BadParam;
-
-
-    len1 = sizeof(lss);
-    if (getsockname(fd, (struct sockaddr *)&lss, &len1) < 0)
-    {
-        syslog(LOG_WARNING, "DNSServiceSleepKeepalive: getsockname %d\n", errno);
-        return kDNSServiceErr_BadParam;
-    }
-
-    len2 = sizeof(rss);
-    if (getpeername(fd, (struct sockaddr *)&rss, &len2) < 0)
-    {
-        syslog(LOG_WARNING, "DNSServiceSleepKeepalive: getpeername %d\n", errno);
-        return kDNSServiceErr_BadParam;
-    }
-
-    if (len1 != len2)
-    {
-        syslog(LOG_WARNING, "DNSServiceSleepKeepalive local/remote info not same");
-        return kDNSServiceErr_Unknown;
-    }
-
-    unique = 0;
-    if (lss.ss_family == AF_INET)
-    {
-        struct sockaddr_in *sl = (struct sockaddr_in *)&lss;
-        struct sockaddr_in *sr = (struct sockaddr_in *)&rss;
-        unsigned char *ptr = (unsigned char *)&sl->sin_addr;
-
-        if (!inet_ntop(AF_INET, (const void *)&sr->sin_addr, target_str, sizeof (target_str)))
-        {
-            syslog(LOG_WARNING, "DNSServiceSleepKeepalive remote info failed %d", errno);
-            return kDNSServiceErr_Unknown;
-        }
-        if (!inet_ntop(AF_INET, (const void *)&sl->sin_addr, source_str, sizeof (source_str)))
-        {
-            syslog(LOG_WARNING, "DNSServiceSleepKeepalive local info failed %d", errno);
-            return kDNSServiceErr_Unknown;
-        }
-        // Sum of all bytes in the local address and port should result in a unique
-        // number in the local network
-        for (i = 0; i < sizeof(struct in_addr); i++)
-            unique += ptr[i];
-        unique += sl->sin_port;
-        len = snprintf(buf+1, sizeof(buf) - 1, "t=%u h=%s d=%s l=%u r=%u", timeout, source_str, target_str, ntohs(sl->sin_port), ntohs(sr->sin_port));
-    }
-    else
-    {
-        struct sockaddr_in6 *sl6 = (struct sockaddr_in6 *)&lss;
-        struct sockaddr_in6 *sr6 = (struct sockaddr_in6 *)&rss;
-        unsigned char *ptr = (unsigned char *)&sl6->sin6_addr;
-
-        if (!inet_ntop(AF_INET6, (const void *)&sr6->sin6_addr, target_str, sizeof (target_str)))
-        {
-            syslog(LOG_WARNING, "DNSServiceSleepKeepalive remote6 info failed %d", errno);
-            return kDNSServiceErr_Unknown;
-        }
-        if (!inet_ntop(AF_INET6, (const void *)&sl6->sin6_addr, source_str, sizeof (source_str)))
-        {
-            syslog(LOG_WARNING, "DNSServiceSleepKeepalive local6 info failed %d", errno);
-            return kDNSServiceErr_Unknown;
-        }
-        for (i = 0; i < sizeof(struct in6_addr); i++)
-            unique += ptr[i];
-        unique += sl6->sin6_port;
-        len = snprintf(buf+1, sizeof(buf) - 1, "t=%u H=%s D=%s l=%u r=%u", timeout, source_str, target_str, ntohs(sl6->sin6_port), ntohs(sr6->sin6_port));
-    }
-
-    if (len >= (sizeof(buf) - 1))
-    {
-        syslog(LOG_WARNING, "DNSServiceSleepKeepalive could not fit local/remote info");
-        return kDNSServiceErr_Unknown;
-    }
-    // Include the NULL byte also in the first byte. The total length of the record includes the
-    // first byte also.
-    buf[0] = len + 1;
-    proxyreclen = len + 2;
-
-    len = snprintf(name, sizeof(name), "%u", unique);
-    if (len >= sizeof(name))
-    {
-        syslog(LOG_WARNING, "DNSServiceSleepKeepalive could not fit unique");
-        return kDNSServiceErr_Unknown;
-    }
-
-    len = snprintf(recname, sizeof(recname), "%s.%s", name, "_keepalive._dns-sd._udp.local");
-    if (len >= sizeof(recname))
-    {
-        syslog(LOG_WARNING, "DNSServiceSleepKeepalive could not fit name");
-        return kDNSServiceErr_Unknown;
-    }
-
-    ka = malloc(sizeof(SleepKAContext));
-    if (!ka) return kDNSServiceErr_NoMemory;
-    ka->AppCallback = callBack;
-    ka->AppContext = context;
-
-    err = DNSServiceCreateConnection(sdRef);
-    if (err)
-    {
-        syslog(LOG_WARNING, "DNSServiceSleepKeepalive cannot create connection");
-        free(ka);
-        return err;
-    }
-
-    // we don't care about the "record". When sdRef gets deallocated later, it will be freed too
-    err = DNSServiceRegisterRecord(*sdRef, &record, kDNSServiceFlagsUnique, 0, recname,
-                                   kDNSServiceType_NULL,  kDNSServiceClass_IN, proxyreclen, buf,  kDNSServiceInterfaceIndexAny, SleepKeepaliveCallback, ka);
-    if (err)
-    {
-        syslog(LOG_WARNING, "DNSServiceSleepKeepalive cannot create connection");
-        free(ka);
-        return err;
-    }
-    (*sdRef)->kacontext = ka;
-    return kDNSServiceErr_NoError;
-}
-#endif

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_clientstub.c (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSShared/dnssd_clientstub.c)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_clientstub.c	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_clientstub.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,2370 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
+ *     contributors may be used to endorse or promote products derived from this
+ *     software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+
+#if APPLE_OSX_mDNSResponder
+#include <mach-o/dyld.h>
+#include <uuid/uuid.h>
+#include <TargetConditionals.h>
+#endif
+
+#include "dnssd_ipc.h"
+
+#if defined(_WIN32)
+
+    #define _SSIZE_T
+    #include <CommonServices.h>
+    #include <DebugServices.h>
+    #include <winsock2.h>
+    #include <ws2tcpip.h>
+    #include <windows.h>
+    #include <stdarg.h>
+    #include <stdio.h>
+
+    #define sockaddr_mdns sockaddr_in
+    #define AF_MDNS AF_INET
+
+// Disable warning: "'type cast' : from data pointer 'void *' to function pointer"
+    #pragma warning(disable:4055)
+
+// Disable warning: "nonstandard extension, function/data pointer conversion in expression"
+    #pragma warning(disable:4152)
+
+extern BOOL IsSystemServiceDisabled();
+
+    #define sleep(X) Sleep((X) * 1000)
+
+static int g_initWinsock = 0;
+    #define LOG_WARNING kDebugLevelWarning
+    #define LOG_INFO kDebugLevelInfo
+static void syslog( int priority, const char * message, ...)
+{
+    va_list args;
+    int len;
+    char * buffer;
+    DWORD err = WSAGetLastError();
+    (void) priority;
+    va_start( args, message );
+    len = _vscprintf( message, args ) + 1;
+    buffer = malloc( len * sizeof(char) );
+    if ( buffer ) { vsprintf( buffer, message, args ); OutputDebugString( buffer ); free( buffer ); }
+    WSASetLastError( err );
+}
+#else
+
+    #include <sys/fcntl.h>      // For O_RDWR etc.
+    #include <sys/time.h>
+    #include <sys/socket.h>
+    #include <syslog.h>
+
+    #define sockaddr_mdns sockaddr_un
+    #define AF_MDNS AF_LOCAL
+
+#endif
+
+// <rdar://problem/4096913> Specifies how many times we'll try and connect to the server.
+
+#define DNSSD_CLIENT_MAXTRIES 4
+
+// Uncomment the line below to use the old error return mechanism of creating a temporary named socket (e.g. in /var/tmp)
+//#define USE_NAMED_ERROR_RETURN_SOCKET 1
+
+// If the UDS client has not received a response from the daemon in 60 secs, it is unlikely to get one
+// Note: Timeout of 3 secs should be sufficient in normal scenarios, but 60 secs is chosen as a safeguard since
+// some clients may come up before mDNSResponder itself after a BOOT and on rare ocassions IOPM/Keychain/D2D calls
+// in mDNSResponder's INIT may take a much longer time to return
+#define DNSSD_CLIENT_TIMEOUT 60
+
+#ifndef CTL_PATH_PREFIX
+#define CTL_PATH_PREFIX "/var/tmp/dnssd_result_socket."
+#endif
+
+typedef struct
+{
+    ipc_msg_hdr ipc_hdr;
+    DNSServiceFlags cb_flags;
+    uint32_t cb_interface;
+    DNSServiceErrorType cb_err;
+} CallbackHeader;
+
+typedef struct _DNSServiceRef_t DNSServiceOp;
+typedef struct _DNSRecordRef_t DNSRecord;
+
+#if !defined(_WIN32)
+typedef struct
+{
+    void             *AppCallback;      // Client callback function and context
+    void             *AppContext;
+} SleepKAContext;
+#endif
+
+// client stub callback to process message from server and deliver results to client application
+typedef void (*ProcessReplyFn)(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *msg, const char *const end);
+
+#define ValidatorBits 0x12345678
+#define DNSServiceRefValid(X) (dnssd_SocketValid((X)->sockfd) && (((X)->sockfd ^ (X)->validator) == ValidatorBits))
+
+// When using kDNSServiceFlagsShareConnection, there is one primary _DNSServiceOp_t, and zero or more subordinates
+// For the primary, the 'next' field points to the first subordinate, and its 'next' field points to the next, and so on.
+// For the primary, the 'primary' field is NULL; for subordinates the 'primary' field points back to the associated primary
+//
+// _DNS_SD_LIBDISPATCH is defined where libdispatch/GCD is available. This does not mean that the application will use the
+// DNSServiceSetDispatchQueue API. Hence any new code guarded with _DNS_SD_LIBDISPATCH should still be backwards compatible.
+struct _DNSServiceRef_t
+{
+    DNSServiceOp     *next;             // For shared connection
+    DNSServiceOp     *primary;          // For shared connection
+    dnssd_sock_t sockfd;                // Connected socket between client and daemon
+    dnssd_sock_t validator;             // Used to detect memory corruption, double disposals, etc.
+    client_context_t uid;               // For shared connection requests, each subordinate DNSServiceRef has its own ID,
+                                        // unique within the scope of the same shared parent DNSServiceRef
+    uint32_t op;                        // request_op_t or reply_op_t
+    uint32_t max_index;                 // Largest assigned record index - 0 if no additional records registered
+    uint32_t logcounter;                // Counter used to control number of syslog messages we write
+    int              *moreptr;          // Set while DNSServiceProcessResult working on this particular DNSServiceRef
+    ProcessReplyFn ProcessReply;        // Function pointer to the code to handle received messages
+    void             *AppCallback;      // Client callback function and context
+    void             *AppContext;
+    DNSRecord        *rec;
+#if _DNS_SD_LIBDISPATCH
+    dispatch_source_t disp_source;
+    dispatch_queue_t disp_queue;
+#endif
+    void             *kacontext;
+};
+
+struct _DNSRecordRef_t
+{
+    DNSRecord       *recnext;
+    void *AppContext;
+    DNSServiceRegisterRecordReply AppCallback;
+    DNSRecordRef recref;
+    uint32_t record_index;  // index is unique to the ServiceDiscoveryRef
+    client_context_t uid;  // For demultiplexing multiple DNSServiceRegisterRecord calls
+    DNSServiceOp *sdr;
+};
+
+// Write len bytes. Return 0 on success, -1 on error
+static int write_all(dnssd_sock_t sd, char *buf, size_t len)
+{
+    // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
+    //if (send(sd, buf, len, MSG_WAITALL) != len) return -1;
+    while (len)
+    {
+        ssize_t num_written = send(sd, buf, (long)len, 0);
+        if (num_written < 0 || (size_t)num_written > len)
+        {
+            // Should never happen. If it does, it indicates some OS bug,
+            // or that the mDNSResponder daemon crashed (which should never happen).
+            #if !defined(__ppc__) && defined(SO_ISDEFUNCT)
+            int defunct;
+            socklen_t dlen = sizeof (defunct);
+            if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0)
+                syslog(LOG_WARNING, "dnssd_clientstub write_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
+            if (!defunct)
+                syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
+                       (long)num_written, (long)len,
+                       (num_written < 0) ? dnssd_errno                 : 0,
+                       (num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
+            else
+                syslog(LOG_INFO, "dnssd_clientstub write_all(%d) DEFUNCT", sd);
+            #else
+            syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd,
+                   (long)num_written, (long)len,
+                   (num_written < 0) ? dnssd_errno                 : 0,
+                   (num_written < 0) ? dnssd_strerror(dnssd_errno) : "");
+            #endif
+            return -1;
+        }
+        buf += num_written;
+        len -= num_written;
+    }
+    return 0;
+}
+
+enum { read_all_success = 0, read_all_fail = -1, read_all_wouldblock = -2 };
+
+// Read len bytes. Return 0 on success, read_all_fail on error, or read_all_wouldblock for
+static int read_all(dnssd_sock_t sd, char *buf, int len)
+{
+    // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead.
+    //if (recv(sd, buf, len, MSG_WAITALL) != len) return -1;
+
+    while (len)
+    {
+        ssize_t num_read = recv(sd, buf, len, 0);
+        // It is valid to get an interrupted system call error e.g., somebody attaching
+        // in a debugger, retry without failing
+        if ((num_read < 0) && (errno == EINTR)) 
+        { 
+            syslog(LOG_INFO, "dnssd_clientstub read_all: EINTR continue"); 
+            continue; 
+        }
+        if ((num_read == 0) || (num_read < 0) || (num_read > len))
+        {
+            int printWarn = 0;
+            int defunct = 0;
+            // Should never happen. If it does, it indicates some OS bug,
+            // or that the mDNSResponder daemon crashed (which should never happen).
+#if defined(WIN32)
+            // <rdar://problem/7481776> Suppress logs for "A non-blocking socket operation
+            //                          could not be completed immediately"
+            if (WSAGetLastError() != WSAEWOULDBLOCK)
+                printWarn = 1;
+#endif
+#if !defined(__ppc__) && defined(SO_ISDEFUNCT)
+            {
+                socklen_t dlen = sizeof (defunct);
+                if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0)
+                    syslog(LOG_WARNING, "dnssd_clientstub read_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
+            }
+            if (!defunct)
+                printWarn = 1;
+#endif
+            if (printWarn)
+                syslog(LOG_WARNING, "dnssd_clientstub read_all(%d) failed %ld/%ld %d %s", sd,
+                       (long)num_read, (long)len,
+                       (num_read < 0) ? dnssd_errno                 : 0,
+                       (num_read < 0) ? dnssd_strerror(dnssd_errno) : "");
+            else if (defunct)
+                syslog(LOG_INFO, "dnssd_clientstub read_all(%d) DEFUNCT", sd);
+            return (num_read < 0 && dnssd_errno == dnssd_EWOULDBLOCK) ? read_all_wouldblock : read_all_fail;
+        }
+        buf += num_read;
+        len -= num_read;
+    }
+    return read_all_success;
+}
+
+// Returns 1 if more bytes remain to be read on socket descriptor sd, 0 otherwise
+static int more_bytes(dnssd_sock_t sd)
+{
+    struct timeval tv = { 0, 0 };
+    fd_set readfds;
+    fd_set *fs;
+    int ret;
+
+    if (sd < FD_SETSIZE)
+    {
+        fs = &readfds;
+        FD_ZERO(fs);
+    }
+    else
+    {
+        // Compute the number of integers needed for storing "sd". Internally fd_set is stored
+        // as an array of ints with one bit for each fd and hence we need to compute
+        // the number of ints needed rather than the number of bytes. If "sd" is 32, we need
+        // two ints and not just one.
+        int nfdbits = sizeof (int) * 8;
+        int nints = (sd/nfdbits) + 1;
+        fs = (fd_set *)calloc(nints, sizeof(int));
+        if (fs == NULL) 
+        { 
+            syslog(LOG_WARNING, "dnssd_clientstub more_bytes: malloc failed"); 
+            return 0; 
+        }
+    }
+    FD_SET(sd, fs);
+    ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv);
+    if (fs != &readfds) 
+        free(fs);
+    return (ret > 0);
+}
+
+// set_waitlimit() implements a timeout using select. It is called from deliver_request() before recv() OR accept()
+// to ensure the UDS clients are not blocked in these system calls indefinitely.
+// Note: Ideally one should never be blocked here, because it indicates either mDNSResponder daemon is not yet up/hung/
+// superbusy/crashed or some other OS bug. For eg: On Windows which suffers from 3rd party software 
+// (primarily 3rd party firewall software) interfering with proper functioning of the TCP protocol stack it is possible 
+// the next operation on this socket(recv/accept) is blocked since we depend on TCP to communicate with the system service.
+static int set_waitlimit(dnssd_sock_t sock, int timeout)
+{
+    int gDaemonErr = kDNSServiceErr_NoError;
+
+    // To prevent stack corruption since select does not work with timeout if fds > FD_SETSIZE(1024)
+    if (!gDaemonErr && sock < FD_SETSIZE)
+    {
+        struct timeval tv;
+        fd_set set;
+
+        FD_ZERO(&set);
+        FD_SET(sock, &set);
+        tv.tv_sec = timeout;
+        tv.tv_usec = 0;
+        if (!select((int)(sock + 1), &set, NULL, NULL, &tv))
+        {
+            // Ideally one should never hit this case: See comments before set_waitlimit()
+            syslog(LOG_WARNING, "dnssd_clientstub set_waitlimit:_daemon timed out (%d secs) without any response: Socket %d", timeout, sock);
+            gDaemonErr = kDNSServiceErr_Timeout;
+        }
+    }
+    return gDaemonErr;
+}
+
+/* create_hdr
+ *
+ * allocate and initialize an ipc message header. Value of len should initially be the
+ * length of the data, and is set to the value of the data plus the header. data_start
+ * is set to point to the beginning of the data section. SeparateReturnSocket should be
+ * non-zero for calls that can't receive an immediate error return value on their primary
+ * socket, and therefore require a separate return path for the error code result.
+ * if zero, the path to a control socket is appended at the beginning of the message buffer.
+ * data_start is set past this string.
+ */
+static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int SeparateReturnSocket, DNSServiceOp *ref)
+{
+    char *msg = NULL;
+    ipc_msg_hdr *hdr;
+    int datalen;
+#if !defined(USE_TCP_LOOPBACK)
+    char ctrl_path[64] = "";    // "/var/tmp/dnssd_result_socket.xxxxxxxxxx-xxx-xxxxxx"
+#endif
+
+    if (SeparateReturnSocket)
+    {
+#if defined(USE_TCP_LOOPBACK)
+        *len += 2;  // Allocate space for two-byte port number
+#elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
+        struct timeval tv;
+        if (gettimeofday(&tv, NULL) < 0)
+        { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: gettimeofday failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); return NULL; }
+        sprintf(ctrl_path, "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(),
+                (unsigned long)(tv.tv_sec & 0xFFF), (unsigned long)(tv.tv_usec));
+        *len += strlen(ctrl_path) + 1;
+#else
+        *len += 1;      // Allocate space for single zero byte (empty C string)
+#endif
+    }
+
+    datalen = (int) *len;
+    *len += sizeof(ipc_msg_hdr);
+
+    // Write message to buffer
+    msg = malloc(*len);
+    if (!msg) { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: malloc failed"); return NULL; }
+
+    memset(msg, 0, *len);
+    hdr = (ipc_msg_hdr *)msg;
+    hdr->version                = VERSION;
+    hdr->datalen                = datalen;
+    hdr->ipc_flags              = 0;
+    hdr->op                     = op;
+    hdr->client_context         = ref->uid;
+    hdr->reg_index              = 0;
+    *data_start = msg + sizeof(ipc_msg_hdr);
+#if defined(USE_TCP_LOOPBACK)
+    // Put dummy data in for the port, since we don't know what it is yet.
+    // The data will get filled in before we send the message. This happens in deliver_request().
+    if (SeparateReturnSocket) put_uint16(0, data_start);
+#else
+    if (SeparateReturnSocket) put_string(ctrl_path, data_start);
+#endif
+    return hdr;
+}
+
+static void FreeDNSRecords(DNSServiceOp *sdRef)
+{
+    DNSRecord *rec = sdRef->rec;
+    while (rec)
+    {
+        DNSRecord *next = rec->recnext;
+        free(rec);
+        rec = next;
+    }
+}
+
+static void FreeDNSServiceOp(DNSServiceOp *x)
+{
+    // We don't use our DNSServiceRefValid macro here because if we're cleaning up after a socket() call failed
+    // then sockfd could legitimately contain a failing value (e.g. dnssd_InvalidSocket)
+    if ((x->sockfd ^ x->validator) != ValidatorBits)
+        syslog(LOG_WARNING, "dnssd_clientstub attempt to dispose invalid DNSServiceRef %p %08X %08X", x, x->sockfd, x->validator);
+    else
+    {
+        x->next         = NULL;
+        x->primary      = NULL;
+        x->sockfd       = dnssd_InvalidSocket;
+        x->validator    = 0xDDDDDDDD;
+        x->op           = request_op_none;
+        x->max_index    = 0;
+        x->logcounter   = 0;
+        x->moreptr      = NULL;
+        x->ProcessReply = NULL;
+        x->AppCallback  = NULL;
+        x->AppContext   = NULL;
+#if _DNS_SD_LIBDISPATCH
+        if (x->disp_source) dispatch_release(x->disp_source);
+        x->disp_source  = NULL;
+        x->disp_queue   = NULL;
+#endif
+        // DNSRecords may have been added to subordinate sdRef e.g., DNSServiceRegister/DNSServiceAddRecord
+        // or on the main sdRef e.g., DNSServiceCreateConnection/DNSServiveRegisterRecord. DNSRecords may have
+        // been freed if the application called DNSRemoveRecord
+        FreeDNSRecords(x);
+        if (x->kacontext)
+        {
+            free(x->kacontext);
+            x->kacontext = NULL;
+        }
+        free(x);
+    }
+}
+
+// Return a connected service ref (deallocate with DNSServiceRefDeallocate)
+static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags flags, uint32_t op, ProcessReplyFn ProcessReply, void *AppCallback, void *AppContext)
+{
+    int NumTries = 0;
+
+    dnssd_sockaddr_t saddr;
+    DNSServiceOp *sdr;
+
+    if (!ref) 
+    { 
+        syslog(LOG_WARNING, "dnssd_clientstub DNSService operation with NULL DNSServiceRef"); 
+        return kDNSServiceErr_BadParam; 
+    }
+
+    if (flags & kDNSServiceFlagsShareConnection)
+    {
+        if (!*ref)
+        {
+            syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with NULL DNSServiceRef");
+            return kDNSServiceErr_BadParam;
+        }
+        if (!DNSServiceRefValid(*ref) || ((*ref)->op != connection_request && (*ref)->op != connection_delegate_request) || (*ref)->primary)
+        {
+            syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with invalid DNSServiceRef %p %08X %08X op %d",
+                   (*ref), (*ref)->sockfd, (*ref)->validator, (*ref)->op);
+            *ref = NULL;
+            return kDNSServiceErr_BadReference;
+        }
+    }
+
+    #if defined(_WIN32)
+    if (!g_initWinsock)
+    {
+        WSADATA wsaData;
+        g_initWinsock = 1;
+        if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { *ref = NULL; return kDNSServiceErr_ServiceNotRunning; }
+    }
+    // <rdar://problem/4096913> If the system service is disabled, we only want to try to connect once
+    if (IsSystemServiceDisabled()) 
+        NumTries = DNSSD_CLIENT_MAXTRIES;
+    #endif
+
+    sdr = malloc(sizeof(DNSServiceOp));
+    if (!sdr) 
+    { 
+        syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: malloc failed"); 
+        *ref = NULL; 
+        return kDNSServiceErr_NoMemory; 
+    }
+    sdr->next          = NULL;
+    sdr->primary       = NULL;
+    sdr->sockfd        = dnssd_InvalidSocket;
+    sdr->validator     = sdr->sockfd ^ ValidatorBits;
+    sdr->op            = op;
+    sdr->max_index     = 0;
+    sdr->logcounter    = 0;
+    sdr->moreptr       = NULL;
+    sdr->uid.u32[0]    = 0;
+    sdr->uid.u32[1]    = 0;
+    sdr->ProcessReply  = ProcessReply;
+    sdr->AppCallback   = AppCallback;
+    sdr->AppContext    = AppContext;
+    sdr->rec           = NULL;
+#if _DNS_SD_LIBDISPATCH
+    sdr->disp_source   = NULL;
+    sdr->disp_queue    = NULL;
+#endif
+    sdr->kacontext     = NULL;
+
+    if (flags & kDNSServiceFlagsShareConnection)
+    {
+        DNSServiceOp **p = &(*ref)->next;       // Append ourselves to end of primary's list
+        while (*p) 
+            p = &(*p)->next;
+        *p = sdr;
+        // Preincrement counter before we use it -- it helps with debugging if we know the all-zeroes ID should never appear
+        if (++(*ref)->uid.u32[0] == 0) 
+            ++(*ref)->uid.u32[1];               // In parent DNSServiceOp increment UID counter
+        sdr->primary    = *ref;                 // Set our primary pointer
+        sdr->sockfd     = (*ref)->sockfd;       // Inherit primary's socket
+        sdr->validator  = (*ref)->validator;
+        sdr->uid        = (*ref)->uid;
+        //printf("ConnectToServer sharing socket %d\n", sdr->sockfd);
+    }
+    else
+    {
+        #ifdef SO_NOSIGPIPE
+        const unsigned long optval = 1;
+        #endif
+        #ifndef USE_TCP_LOOPBACK
+        char* uds_serverpath = getenv(MDNS_UDS_SERVERPATH_ENVVAR);
+        if (uds_serverpath == NULL)
+            uds_serverpath = MDNS_UDS_SERVERPATH;
+        #endif
+        *ref = NULL;
+        sdr->sockfd    = socket(AF_DNSSD, SOCK_STREAM, 0);
+        sdr->validator = sdr->sockfd ^ ValidatorBits;
+        if (!dnssd_SocketValid(sdr->sockfd))
+        {
+            syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: socket failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
+            FreeDNSServiceOp(sdr);
+            return kDNSServiceErr_NoMemory;
+        }
+        #ifdef SO_NOSIGPIPE
+        // Some environments (e.g. OS X) support turning off SIGPIPE for a socket
+        if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0)
+            syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_NOSIGPIPE failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
+        #endif
+        #if defined(USE_TCP_LOOPBACK)
+        saddr.sin_family      = AF_INET;
+        saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
+        saddr.sin_port        = htons(MDNS_TCP_SERVERPORT);
+        #else
+        saddr.sun_family      = AF_LOCAL;
+        strcpy(saddr.sun_path, uds_serverpath);
+        #if !defined(__ppc__) && defined(SO_DEFUNCTOK)
+        {
+            int defunct = 1;
+            if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0)
+                syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
+        }
+        #endif
+        #endif
+        
+        while (1)
+        {
+            int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr));
+            if (!err)
+                break; // If we succeeded, return sdr
+            // If we failed, then it may be because the daemon is still launching.
+            // This can happen for processes that launch early in the boot process, while the
+            // daemon is still coming up. Rather than fail here, we wait 1 sec and try again.
+            // If, after DNSSD_CLIENT_MAXTRIES, we still can't connect to the daemon,
+            // then we give up and return a failure code.
+            if (++NumTries < DNSSD_CLIENT_MAXTRIES)
+            {
+                syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect()-> No of tries: %d", NumTries);  
+                sleep(1); // Sleep a bit, then try again
+            }
+            else 
+            {
+                syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect() failed path:%s Socket:%d Err:%d Errno:%d %s", 
+                       uds_serverpath, sdr->sockfd, err, dnssd_errno, dnssd_strerror(dnssd_errno));
+                dnssd_close(sdr->sockfd); 
+                FreeDNSServiceOp(sdr); 
+                return kDNSServiceErr_ServiceNotRunning; 
+            }
+        }
+        //printf("ConnectToServer opened socket %d\n", sdr->sockfd);
+    }
+
+    *ref = sdr;
+    return kDNSServiceErr_NoError;
+}
+
+#define deliver_request_bailout(MSG) \
+    do { syslog(LOG_WARNING, "dnssd_clientstub deliver_request: %s failed %d (%s)", (MSG), dnssd_errno, dnssd_strerror(dnssd_errno)); goto cleanup; } while(0)
+
+static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
+{
+    uint32_t datalen = hdr->datalen;    // We take a copy here because we're going to convert hdr->datalen to network byte order
+    #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
+    char *const data = (char *)hdr + sizeof(ipc_msg_hdr);
+    #endif
+    dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket;
+    DNSServiceErrorType err = kDNSServiceErr_Unknown;   // Default for the "goto cleanup" cases
+    int MakeSeparateReturnSocket = 0;
+
+    // Note: need to check hdr->op, not sdr->op.
+    // hdr->op contains the code for the specific operation we're currently doing, whereas sdr->op
+    // contains the original parent DNSServiceOp (e.g. for an add_record_request, hdr->op will be
+    // add_record_request but the parent sdr->op will be connection_request or reg_service_request)
+    if (sdr->primary ||
+        hdr->op == reg_record_request || hdr->op == add_record_request || hdr->op == update_record_request || hdr->op == remove_record_request)
+        MakeSeparateReturnSocket = 1;
+
+    if (!DNSServiceRefValid(sdr))
+    {
+        if (hdr)
+            free(hdr);
+        syslog(LOG_WARNING, "dnssd_clientstub deliver_request: invalid DNSServiceRef %p %08X %08X", sdr, sdr->sockfd, sdr->validator);
+        return kDNSServiceErr_BadReference;
+    }
+
+    if (!hdr) 
+    { 
+        syslog(LOG_WARNING, "dnssd_clientstub deliver_request: !hdr"); 
+        return kDNSServiceErr_Unknown;  
+    }
+
+    if (MakeSeparateReturnSocket)
+    {
+        #if defined(USE_TCP_LOOPBACK)
+        {
+            union { uint16_t s; u_char b[2]; } port;
+            dnssd_sockaddr_t caddr;
+            dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr);
+            listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
+            if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("TCP socket");
+
+            caddr.sin_family      = AF_INET;
+            caddr.sin_port        = 0;
+            caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
+            if (bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr)) < 0) deliver_request_bailout("TCP bind");
+            if (getsockname(listenfd, (struct sockaddr*) &caddr, &len)   < 0) deliver_request_bailout("TCP getsockname");
+            if (listen(listenfd, 1)                                      < 0) deliver_request_bailout("TCP listen");
+            port.s = caddr.sin_port;
+            data[0] = port.b[0];  // don't switch the byte order, as the
+            data[1] = port.b[1];  // daemon expects it in network byte order
+        }
+        #elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
+        {
+            mode_t mask;
+            int bindresult;
+            dnssd_sockaddr_t caddr;
+            listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
+            if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET socket");
+
+            caddr.sun_family = AF_LOCAL;
+            // According to Stevens (section 3.2), there is no portable way to
+            // determine whether sa_len is defined on a particular platform.
+            #ifndef NOT_HAVE_SA_LEN
+            caddr.sun_len = sizeof(struct sockaddr_un);
+            #endif
+            strcpy(caddr.sun_path, data);
+            mask = umask(0);
+            bindresult = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
+            umask(mask);
+            if (bindresult          < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET bind");
+            if (listen(listenfd, 1) < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET listen");
+        }
+        #else
+        {
+            dnssd_sock_t sp[2];
+            if (socketpair(AF_DNSSD, SOCK_STREAM, 0, sp) < 0) deliver_request_bailout("socketpair");
+            else
+            {
+                errsd    = sp[0];   // We'll read our four-byte error code from sp[0]
+                listenfd = sp[1];   // We'll send sp[1] to the daemon
+                #if !defined(__ppc__) && defined(SO_DEFUNCTOK)
+                {
+                    int defunct = 1;
+                    if (setsockopt(errsd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0)
+                        syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno));
+                }
+                #endif
+            }
+        }
+        #endif
+    }
+
+#if !defined(USE_TCP_LOOPBACK) && !defined(USE_NAMED_ERROR_RETURN_SOCKET)
+    // If we're going to make a separate error return socket, and pass it to the daemon
+    // using sendmsg, then we'll hold back one data byte to go with it.
+    // On some versions of Unix (including Leopard) sending a control message without
+    // any associated data does not work reliably -- e.g. one particular issue we ran
+    // into is that if the receiving program is in a kqueue loop waiting to be notified
+    // of the received message, it doesn't get woken up when the control message arrives.
+    if (MakeSeparateReturnSocket || sdr->op == send_bpf) 
+        datalen--;     // Okay to use sdr->op when checking for op == send_bpf
+#endif
+
+    // At this point, our listening socket is set up and waiting, if necessary, for the daemon to connect back to
+    ConvertHeaderBytes(hdr);
+    //syslog(LOG_WARNING, "dnssd_clientstub deliver_request writing %lu bytes", (unsigned long)(datalen + sizeof(ipc_msg_hdr)));
+    //if (MakeSeparateReturnSocket) syslog(LOG_WARNING, "dnssd_clientstub deliver_request name is %s", data);
+#if TEST_SENDING_ONE_BYTE_AT_A_TIME
+    unsigned int i;
+    for (i=0; i<datalen + sizeof(ipc_msg_hdr); i++)
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub deliver_request writing %d", i);
+        if (write_all(sdr->sockfd, ((char *)hdr)+i, 1) < 0)
+        { syslog(LOG_WARNING, "write_all (byte %u) failed", i); goto cleanup; }
+        usleep(10000);
+    }
+#else
+    if (write_all(sdr->sockfd, (char *)hdr, datalen + sizeof(ipc_msg_hdr)) < 0)
+    {
+        // write_all already prints an error message if there is an error writing to
+        // the socket except for DEFUNCT. Logging here is unnecessary and also wrong
+        // in the case of DEFUNCT sockets
+        syslog(LOG_INFO, "dnssd_clientstub deliver_request ERROR: write_all(%d, %lu bytes) failed",
+               sdr->sockfd, (unsigned long)(datalen + sizeof(ipc_msg_hdr)));
+        goto cleanup;
+    }
+#endif
+
+    if (!MakeSeparateReturnSocket) 
+        errsd = sdr->sockfd;
+    if (MakeSeparateReturnSocket || sdr->op == send_bpf)    // Okay to use sdr->op when checking for op == send_bpf
+    {
+#if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET)
+        // At this point we may wait in accept for a few milliseconds waiting for the daemon to connect back to us,
+        // but that's okay -- the daemon should not take more than a few milliseconds to respond.
+        // set_waitlimit() ensures we do not block indefinitely just in case something is wrong
+        dnssd_sockaddr_t daddr;
+        dnssd_socklen_t len = sizeof(daddr);
+        if ((err = set_waitlimit(listenfd, DNSSD_CLIENT_TIMEOUT)) != kDNSServiceErr_NoError) 
+            goto cleanup;
+        errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
+        if (!dnssd_SocketValid(errsd)) 
+            deliver_request_bailout("accept");
+#else
+
+        struct iovec vec = { ((char *)hdr) + sizeof(ipc_msg_hdr) + datalen, 1 }; // Send the last byte along with the SCM_RIGHTS
+        struct msghdr msg;
+        struct cmsghdr *cmsg;
+        char cbuf[CMSG_SPACE(4 * sizeof(dnssd_sock_t))];
+
+        msg.msg_name       = 0;
+        msg.msg_namelen    = 0;
+        msg.msg_iov        = &vec;
+        msg.msg_iovlen     = 1;
+        msg.msg_flags      = 0;
+        if (MakeSeparateReturnSocket || sdr->op == send_bpf)    // Okay to use sdr->op when checking for op == send_bpf
+        {
+            if (sdr->op == send_bpf)
+            {
+                int i;
+                char p[12];     // Room for "/dev/bpf999" with terminating null
+                for (i=0; i<100; i++)
+                {
+                    snprintf(p, sizeof(p), "/dev/bpf%d", i);
+                    listenfd = open(p, O_RDWR, 0);
+                    //if (dnssd_SocketValid(listenfd)) syslog(LOG_WARNING, "Sending fd %d for %s", listenfd, p);
+                    if (!dnssd_SocketValid(listenfd) && dnssd_errno != EBUSY)
+                        syslog(LOG_WARNING, "Error opening %s %d (%s)", p, dnssd_errno, dnssd_strerror(dnssd_errno));
+                    if (dnssd_SocketValid(listenfd) || dnssd_errno != EBUSY) break;
+                }
+            }
+            msg.msg_control    = cbuf;
+            msg.msg_controllen = CMSG_LEN(sizeof(dnssd_sock_t));
+
+            cmsg = CMSG_FIRSTHDR(&msg);
+            cmsg->cmsg_len     = CMSG_LEN(sizeof(dnssd_sock_t));
+            cmsg->cmsg_level   = SOL_SOCKET;
+            cmsg->cmsg_type    = SCM_RIGHTS;
+            *((dnssd_sock_t *)CMSG_DATA(cmsg)) = listenfd;
+        }
+
+#if TEST_KQUEUE_CONTROL_MESSAGE_BUG
+        sleep(1);
+#endif
+
+#if DEBUG_64BIT_SCM_RIGHTS
+        syslog(LOG_WARNING, "dnssd_clientstub sendmsg read sd=%d write sd=%d %ld %ld %ld/%ld/%ld/%ld",
+               errsd, listenfd, sizeof(dnssd_sock_t), sizeof(void*),
+               sizeof(struct cmsghdr) + sizeof(dnssd_sock_t),
+               CMSG_LEN(sizeof(dnssd_sock_t)), (long)CMSG_SPACE(sizeof(dnssd_sock_t)),
+               (long)((char*)CMSG_DATA(cmsg) + 4 - cbuf));
+#endif // DEBUG_64BIT_SCM_RIGHTS
+
+        if (sendmsg(sdr->sockfd, &msg, 0) < 0)
+        {
+            syslog(LOG_WARNING, "dnssd_clientstub deliver_request ERROR: sendmsg failed read sd=%d write sd=%d errno %d (%s)",
+                   errsd, listenfd, dnssd_errno, dnssd_strerror(dnssd_errno));
+            err = kDNSServiceErr_Incompatible;
+            goto cleanup;
+        }
+
+#if DEBUG_64BIT_SCM_RIGHTS
+        syslog(LOG_WARNING, "dnssd_clientstub sendmsg read sd=%d write sd=%d okay", errsd, listenfd);
+#endif // DEBUG_64BIT_SCM_RIGHTS
+
+#endif
+        // Close our end of the socketpair *before* calling read_all() to get the four-byte error code.
+        // Otherwise, if the daemon closes our socket (or crashes), we will have to wait for a timeout
+        // in read_all() because the socket is not closed (we still have an open reference to it)
+        // Note: listenfd is overwritten in the case of send_bpf above and that will be closed here
+        // for send_bpf operation.
+        dnssd_close(listenfd);
+        listenfd = dnssd_InvalidSocket; // Make sure we don't close it a second time in the cleanup handling below
+    }
+
+    // At this point we may wait in read_all for a few milliseconds waiting for the daemon to send us the error code,
+    // but that's okay -- the daemon should not take more than a few milliseconds to respond.
+    // set_waitlimit() ensures we do not block indefinitely just in case something is wrong
+    if (sdr->op == send_bpf)    // Okay to use sdr->op when checking for op == send_bpf
+        err = kDNSServiceErr_NoError;
+    else if ((err = set_waitlimit(errsd, DNSSD_CLIENT_TIMEOUT)) == kDNSServiceErr_NoError)
+    {
+        if (read_all(errsd, (char*)&err, (int)sizeof(err)) < 0)
+            err = kDNSServiceErr_ServiceNotRunning; // On failure read_all will have written a message to syslog for us
+        else
+            err = ntohl(err);
+    }
+    //syslog(LOG_WARNING, "dnssd_clientstub deliver_request: retrieved error code %d", err);
+
+cleanup:
+    if (MakeSeparateReturnSocket)
+    {
+        if (dnssd_SocketValid(listenfd)) dnssd_close(listenfd);
+        if (dnssd_SocketValid(errsd)) dnssd_close(errsd);
+#if defined(USE_NAMED_ERROR_RETURN_SOCKET)
+        // syslog(LOG_WARNING, "dnssd_clientstub deliver_request: removing UDS: %s", data);
+        if (unlink(data) != 0)
+            syslog(LOG_WARNING, "dnssd_clientstub WARNING: unlink(\"%s\") failed errno %d (%s)", data, dnssd_errno, dnssd_strerror(dnssd_errno));
+        // else syslog(LOG_WARNING, "dnssd_clientstub deliver_request: removed UDS: %s", data);
+#endif
+    }
+
+    free(hdr);
+    return err;
+}
+
+int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef)
+{
+    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with NULL DNSServiceRef"); return dnssd_InvalidSocket; }
+
+    if (!DNSServiceRefValid(sdRef))
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with invalid DNSServiceRef %p %08X %08X",
+               sdRef, sdRef->sockfd, sdRef->validator);
+        return dnssd_InvalidSocket;
+    }
+
+    if (sdRef->primary)
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD undefined for kDNSServiceFlagsShareConnection subordinate DNSServiceRef %p", sdRef);
+        return dnssd_InvalidSocket;
+    }
+
+    return (int) sdRef->sockfd;
+}
+
+#if _DNS_SD_LIBDISPATCH
+static void CallbackWithError(DNSServiceRef sdRef, DNSServiceErrorType error)
+{
+    DNSServiceOp *sdr = sdRef;
+    DNSServiceOp *sdrNext;
+    DNSRecord *rec;
+    DNSRecord *recnext;
+    int morebytes;
+
+    while (sdr)
+    {
+        // We can't touch the sdr after the callback as it can be deallocated in the callback
+        sdrNext = sdr->next;
+        morebytes = 1;
+        sdr->moreptr = &morebytes;
+        switch (sdr->op)
+        {
+        case resolve_request:
+            if (sdr->AppCallback) ((DNSServiceResolveReply)    sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL,    sdr->AppContext);
+            break;
+        case query_request:
+            if (sdr->AppCallback) ((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL, 0, sdr->AppContext);
+            break;
+        case addrinfo_request:
+            if (sdr->AppCallback) ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, NULL, 0,          sdr->AppContext);
+            break;
+        case browse_request:
+            if (sdr->AppCallback) ((DNSServiceBrowseReply)     sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, NULL,          sdr->AppContext);
+            break;
+        case reg_service_request:
+            if (sdr->AppCallback) ((DNSServiceRegisterReply)   sdr->AppCallback)(sdr, 0,    error, NULL, 0, NULL,          sdr->AppContext);
+            break;
+        case enumeration_request:
+            if (sdr->AppCallback) ((DNSServiceDomainEnumReply) sdr->AppCallback)(sdr, 0, 0, error, NULL,                   sdr->AppContext);
+            break;
+        case connection_request:
+        case connection_delegate_request:
+            // This means Register Record, walk the list of DNSRecords to do the callback
+            rec = sdr->rec;
+            while (rec)
+            {
+                recnext = rec->recnext;
+                if (rec->AppCallback) ((DNSServiceRegisterRecordReply)rec->AppCallback)(sdr, 0, 0, error, rec->AppContext);
+                // The Callback can call DNSServiceRefDeallocate which in turn frees sdr and all the records.
+                // Detect that and return early
+                if (!morebytes) {syslog(LOG_WARNING, "dnssdclientstub:Record: CallbackwithError morebytes zero"); return;}
+                rec = recnext;
+            }
+            break;
+        case port_mapping_request:
+            if (sdr->AppCallback) ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, 0, 0, error, 0, 0, 0, 0, 0, sdr->AppContext);
+            break;
+        default:
+            syslog(LOG_WARNING, "dnssd_clientstub CallbackWithError called with bad op %d", sdr->op);
+        }
+        // If DNSServiceRefDeallocate was called in the callback, morebytes will be zero. As the sdRef
+        // (and its subordinates) have been freed, we should not proceed further. Note that when we
+        // call the callback with a subordinate sdRef the application can call DNSServiceRefDeallocate
+        // on the main sdRef and DNSServiceRefDeallocate handles this case by walking all the sdRefs and
+        // clears the moreptr so that we can terminate here.
+        //
+        // If DNSServiceRefDeallocate was not called in the callback, then set moreptr to NULL so that
+        // we don't access the stack variable after we return from this function.
+        if (!morebytes) {syslog(LOG_WARNING, "dnssdclientstub:sdRef: CallbackwithError morebytes zero sdr %p", sdr); return;}
+        else {sdr->moreptr = NULL;}
+        sdr = sdrNext;
+    }
+}
+#endif // _DNS_SD_LIBDISPATCH
+
+// Handle reply from server, calling application client callback. If there is no reply
+// from the daemon on the socket contained in sdRef, the call will block.
+DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef)
+{
+    int morebytes = 0;
+
+    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
+
+    if (!DNSServiceRefValid(sdRef))
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
+        return kDNSServiceErr_BadReference;
+    }
+
+    if (sdRef->primary)
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult undefined for kDNSServiceFlagsShareConnection subordinate DNSServiceRef %p", sdRef);
+        return kDNSServiceErr_BadReference;
+    }
+
+    if (!sdRef->ProcessReply)
+    {
+        static int num_logs = 0;
+        if (num_logs < 10) syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with DNSServiceRef with no ProcessReply function");
+        if (num_logs < 1000) num_logs++;else sleep(1);
+        return kDNSServiceErr_BadReference;
+    }
+
+    do
+    {
+        CallbackHeader cbh;
+        char *data;
+
+        // return NoError on EWOULDBLOCK. This will handle the case
+        // where a non-blocking socket is told there is data, but it was a false positive.
+        // On error, read_all will write a message to syslog for us, so don't need to duplicate that here
+        // Note: If we want to properly support using non-blocking sockets in the future
+        int result = read_all(sdRef->sockfd, (void *)&cbh.ipc_hdr, sizeof(cbh.ipc_hdr));
+        if (result == read_all_fail)
+        {
+            // Set the ProcessReply to NULL before callback as the sdRef can get deallocated
+            // in the callback.
+            sdRef->ProcessReply = NULL;
+#if _DNS_SD_LIBDISPATCH
+            // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult
+            // is not called by the application and hence need to communicate the error. Cancel the
+            // source so that we don't get any more events
+            // Note: read_all fails if we could not read from the daemon which can happen if the
+            // daemon dies or the file descriptor is disconnected (defunct).
+            if (sdRef->disp_source)
+            {
+                dispatch_source_cancel(sdRef->disp_source);
+                dispatch_release(sdRef->disp_source);
+                sdRef->disp_source = NULL;
+                CallbackWithError(sdRef, kDNSServiceErr_ServiceNotRunning);
+            }
+#endif
+            // Don't touch sdRef anymore as it might have been deallocated
+            return kDNSServiceErr_ServiceNotRunning;
+        }
+        else if (result == read_all_wouldblock)
+        {
+            if (morebytes && sdRef->logcounter < 100)
+            {
+                sdRef->logcounter++;
+                syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult error: select indicated data was waiting but read_all returned EWOULDBLOCK");
+            }
+            return kDNSServiceErr_NoError;
+        }
+
+        ConvertHeaderBytes(&cbh.ipc_hdr);
+        if (cbh.ipc_hdr.version != VERSION)
+        {
+            syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult daemon version %d does not match client version %d", cbh.ipc_hdr.version, VERSION);
+            sdRef->ProcessReply = NULL;
+            return kDNSServiceErr_Incompatible;
+        }
+
+        data = malloc(cbh.ipc_hdr.datalen);
+        if (!data) return kDNSServiceErr_NoMemory;
+        if (read_all(sdRef->sockfd, data, cbh.ipc_hdr.datalen) < 0) // On error, read_all will write a message to syslog for us
+        {
+            // Set the ProcessReply to NULL before callback as the sdRef can get deallocated
+            // in the callback.
+            sdRef->ProcessReply = NULL;
+#if _DNS_SD_LIBDISPATCH
+            // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult
+            // is not called by the application and hence need to communicate the error. Cancel the
+            // source so that we don't get any more events
+            if (sdRef->disp_source)
+            {
+                dispatch_source_cancel(sdRef->disp_source);
+                dispatch_release(sdRef->disp_source);
+                sdRef->disp_source = NULL;
+                CallbackWithError(sdRef, kDNSServiceErr_ServiceNotRunning);
+            }
+#endif
+            // Don't touch sdRef anymore as it might have been deallocated
+            free(data);
+            return kDNSServiceErr_ServiceNotRunning;
+        }
+        else
+        {
+            const char *ptr = data;
+            cbh.cb_flags     = get_flags     (&ptr, data + cbh.ipc_hdr.datalen);
+            cbh.cb_interface = get_uint32    (&ptr, data + cbh.ipc_hdr.datalen);
+            cbh.cb_err       = get_error_code(&ptr, data + cbh.ipc_hdr.datalen);
+
+            // CAUTION: We have to handle the case where the client calls DNSServiceRefDeallocate from within the callback function.
+            // To do this we set moreptr to point to morebytes. If the client does call DNSServiceRefDeallocate(),
+            // then that routine will clear morebytes for us, and cause us to exit our loop.
+            morebytes = more_bytes(sdRef->sockfd);
+            if (morebytes)
+            {
+                cbh.cb_flags |= kDNSServiceFlagsMoreComing;
+                sdRef->moreptr = &morebytes;
+            }
+            if (ptr) sdRef->ProcessReply(sdRef, &cbh, ptr, data + cbh.ipc_hdr.datalen);
+            // Careful code here:
+            // If morebytes is non-zero, that means we set sdRef->moreptr above, and the operation was not
+            // cancelled out from under us, so now we need to clear sdRef->moreptr so we don't leave a stray
+            // dangling pointer pointing to a long-gone stack variable.
+            // If morebytes is zero, then one of two thing happened:
+            // (a) morebytes was 0 above, so we didn't set sdRef->moreptr, so we don't need to clear it
+            // (b) morebytes was 1 above, and we set sdRef->moreptr, but the operation was cancelled (with DNSServiceRefDeallocate()),
+            //     so we MUST NOT try to dereference our stale sdRef pointer.
+            if (morebytes) sdRef->moreptr = NULL;
+        }
+        free(data);
+    } while (morebytes);
+
+    return kDNSServiceErr_NoError;
+}
+
+void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef)
+{
+    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefDeallocate called with NULL DNSServiceRef"); return; }
+
+    if (!DNSServiceRefValid(sdRef))     // Also verifies dnssd_SocketValid(sdRef->sockfd) for us too
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefDeallocate called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
+        return;
+    }
+
+    // If we're in the middle of a DNSServiceProcessResult() invocation for this DNSServiceRef, clear its morebytes flag to break it out of its while loop
+    if (sdRef->moreptr) *(sdRef->moreptr) = 0;
+
+    if (sdRef->primary)     // If this is a subordinate DNSServiceOp, just send a 'stop' command
+    {
+        DNSServiceOp **p = &sdRef->primary->next;
+        while (*p && *p != sdRef) p = &(*p)->next;
+        if (*p)
+        {
+            char *ptr;
+            size_t len = 0;
+            ipc_msg_hdr *hdr = create_hdr(cancel_request, &len, &ptr, 0, sdRef);
+            if (hdr)
+            {
+                ConvertHeaderBytes(hdr);
+                write_all(sdRef->sockfd, (char *)hdr, len);
+                free(hdr);
+            }
+            *p = sdRef->next;
+            FreeDNSServiceOp(sdRef);
+        }
+    }
+    else                    // else, make sure to terminate all subordinates as well
+    {
+#if _DNS_SD_LIBDISPATCH
+        // The cancel handler will close the fd if a dispatch source has been set
+        if (sdRef->disp_source)
+        {
+            // By setting the ProcessReply to NULL, we make sure that we never call
+            // the application callbacks ever, after returning from this function. We
+            // assume that DNSServiceRefDeallocate is called from the serial queue
+            // that was passed to DNSServiceSetDispatchQueue. Hence, dispatch_source_cancel
+            // should cancel all the blocks on the queue and hence there should be no more
+            // callbacks when we return from this function. Setting ProcessReply to NULL
+            // provides extra protection.
+            sdRef->ProcessReply = NULL;
+            dispatch_source_cancel(sdRef->disp_source);
+            dispatch_release(sdRef->disp_source);
+            sdRef->disp_source = NULL;
+        }
+        // if disp_queue is set, it means it used the DNSServiceSetDispatchQueue API. In that case,
+        // when the source was cancelled, the fd was closed in the handler. Currently the source
+        // is cancelled only when the mDNSResponder daemon dies
+        else if (!sdRef->disp_queue) dnssd_close(sdRef->sockfd);
+#else
+        dnssd_close(sdRef->sockfd);
+#endif
+        // Free DNSRecords added in DNSRegisterRecord if they have not
+        // been freed in DNSRemoveRecord
+        while (sdRef)
+        {
+            DNSServiceOp *p = sdRef;
+            sdRef = sdRef->next;
+            // When there is an error reading from the daemon e.g., bad fd, CallbackWithError
+            // is called which sets moreptr. It might set the moreptr on a subordinate sdRef
+            // but the application might call DNSServiceRefDeallocate with the main sdRef from
+            // the callback. Hence, when we loop through the subordinate sdRefs, we need
+            // to clear the moreptr so that CallbackWithError can terminate itself instead of
+            // walking through the freed sdRefs.
+            if (p->moreptr) *(p->moreptr) = 0;
+            FreeDNSServiceOp(p);
+        }
+    }
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceGetProperty(const char *property, void *result, uint32_t *size)
+{
+    char *ptr;
+    size_t len = strlen(property) + 1;
+    ipc_msg_hdr *hdr;
+    DNSServiceOp *tmp;
+    uint32_t actualsize;
+
+    DNSServiceErrorType err = ConnectToServer(&tmp, 0, getproperty_request, NULL, NULL, NULL);
+    if (err) return err;
+
+    hdr = create_hdr(getproperty_request, &len, &ptr, 0, tmp);
+    if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
+
+    put_string(property, &ptr);
+    err = deliver_request(hdr, tmp);        // Will free hdr for us
+    if (read_all(tmp->sockfd, (char*)&actualsize, (int)sizeof(actualsize)) < 0)
+    { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; }
+
+    actualsize = ntohl(actualsize);
+    if (read_all(tmp->sockfd, (char*)result, actualsize < *size ? actualsize : *size) < 0)
+    { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; }
+    DNSServiceRefDeallocate(tmp);
+
+    // Swap version result back to local process byte order
+    if (!strcmp(property, kDNSServiceProperty_DaemonVersion) && *size >= 4)
+        *(uint32_t*)result = ntohl(*(uint32_t*)result);
+
+    *size = actualsize;
+    return kDNSServiceErr_NoError;
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceGetPID(const uint16_t srcport, int32_t *pid)
+{
+    char *ptr;
+    ipc_msg_hdr *hdr;
+    DNSServiceOp *tmp;
+    size_t len = sizeof(int32_t);
+
+    DNSServiceErrorType err = ConnectToServer(&tmp, 0, getpid_request, NULL, NULL, NULL);
+    if (err)
+        return err;
+
+    hdr = create_hdr(getpid_request, &len, &ptr, 0, tmp);
+    if (!hdr)
+    {
+        DNSServiceRefDeallocate(tmp);
+        return kDNSServiceErr_NoMemory;
+    }
+
+    put_uint16(srcport, &ptr);
+    err = deliver_request(hdr, tmp);        // Will free hdr for us
+
+    if (read_all(tmp->sockfd, (char*)pid, sizeof(int32_t)) < 0)
+    {
+        DNSServiceRefDeallocate(tmp);
+        return kDNSServiceErr_ServiceNotRunning;
+    }
+
+    DNSServiceRefDeallocate(tmp);
+    return kDNSServiceErr_NoError;
+}
+
+static void handle_resolve_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *end)
+{
+    char fullname[kDNSServiceMaxDomainName];
+    char target[kDNSServiceMaxDomainName];
+    uint16_t txtlen;
+    union { uint16_t s; u_char b[2]; } port;
+    unsigned char *txtrecord;
+
+    get_string(&data, end, fullname, kDNSServiceMaxDomainName);
+    get_string(&data, end, target,   kDNSServiceMaxDomainName);
+    if (!data || data + 2 > end) goto fail;
+
+    port.b[0] = *data++;
+    port.b[1] = *data++;
+    txtlen = get_uint16(&data, end);
+    txtrecord = (unsigned char *)get_rdata(&data, end, txtlen);
+
+    if (!data) goto fail;
+    ((DNSServiceResolveReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, fullname, target, port.s, txtlen, txtrecord, sdr->AppContext);
+    return;
+    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
+fail:
+    syslog(LOG_WARNING, "dnssd_clientstub handle_resolve_response: error reading result from daemon");
+}
+
+#if TARGET_OS_EMBEDDED
+
+static int32_t libSystemVersion = 0;
+
+// Return true if the iOS application linked against a version of libsystem where P2P
+// interfaces were included by default when using kDNSServiceInterfaceIndexAny.
+// Using 160.0.0 == 0xa00000 as the version threshold.
+static int includeP2PWithIndexAny()
+{
+    if (libSystemVersion == 0)
+        libSystemVersion = NSVersionOfLinkTimeLibrary("System");
+
+    if (libSystemVersion < 0xa00000)
+        return 1;
+    else
+        return 0;
+}
+
+#else   // TARGET_OS_EMBEDDED
+
+// always return false for non iOS platforms
+static int includeP2PWithIndexAny()
+{
+    return 0;
+}
+
+#endif  // TARGET_OS_EMBEDDED
+
+DNSServiceErrorType DNSSD_API DNSServiceResolve
+(
+    DNSServiceRef                 *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    const char                    *name,
+    const char                    *regtype,
+    const char                    *domain,
+    DNSServiceResolveReply callBack,
+    void                          *context
+)
+{
+    char *ptr;
+    size_t len;
+    ipc_msg_hdr *hdr;
+    DNSServiceErrorType err;
+
+    if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam;
+
+    // Need a real InterfaceID for WakeOnResolve
+    if ((flags & kDNSServiceFlagsWakeOnResolve) != 0 &&
+        ((interfaceIndex == kDNSServiceInterfaceIndexAny) ||
+         (interfaceIndex == kDNSServiceInterfaceIndexLocalOnly) ||
+         (interfaceIndex == kDNSServiceInterfaceIndexUnicast) ||
+         (interfaceIndex == kDNSServiceInterfaceIndexP2P)))
+    {
+        return kDNSServiceErr_BadParam;
+    }
+
+    if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
+        flags |= kDNSServiceFlagsIncludeP2P;
+
+    err = ConnectToServer(sdRef, flags, resolve_request, handle_resolve_response, callBack, context);
+    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
+
+    // Calculate total message length
+    len = sizeof(flags);
+    len += sizeof(interfaceIndex);
+    len += strlen(name) + 1;
+    len += strlen(regtype) + 1;
+    len += strlen(domain) + 1;
+
+    hdr = create_hdr(resolve_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
+    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
+
+    put_flags(flags, &ptr);
+    put_uint32(interfaceIndex, &ptr);
+    put_string(name, &ptr);
+    put_string(regtype, &ptr);
+    put_string(domain, &ptr);
+
+    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
+    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
+    return err;
+}
+
+static void handle_query_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
+{
+    uint32_t ttl;
+    char name[kDNSServiceMaxDomainName];
+    uint16_t rrtype, rrclass, rdlen;
+    const char *rdata;
+
+    get_string(&data, end, name, kDNSServiceMaxDomainName);
+    rrtype  = get_uint16(&data, end);
+    rrclass = get_uint16(&data, end);
+    rdlen   = get_uint16(&data, end);
+    rdata   = get_rdata(&data, end, rdlen);
+    ttl     = get_uint32(&data, end);
+
+    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_query_response: error reading result from daemon");
+    else ((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, name, rrtype, rrclass, rdlen, rdata, ttl, sdr->AppContext);
+    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
+(
+    DNSServiceRef              *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    const char                 *name,
+    uint16_t rrtype,
+    uint16_t rrclass,
+    DNSServiceQueryRecordReply callBack,
+    void                       *context
+)
+{
+    char *ptr;
+    size_t len;
+    ipc_msg_hdr *hdr;
+    DNSServiceErrorType err;
+
+    if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
+        flags |= kDNSServiceFlagsIncludeP2P;
+
+    err = ConnectToServer(sdRef, flags, query_request, handle_query_response, callBack, context);
+    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
+
+    if (!name) name = "\0";
+
+    // Calculate total message length
+    len = sizeof(flags);
+    len += sizeof(uint32_t);  // interfaceIndex
+    len += strlen(name) + 1;
+    len += 2 * sizeof(uint16_t);  // rrtype, rrclass
+
+    hdr = create_hdr(query_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
+    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
+
+    put_flags(flags, &ptr);
+    put_uint32(interfaceIndex, &ptr);
+    put_string(name, &ptr);
+    put_uint16(rrtype, &ptr);
+    put_uint16(rrclass, &ptr);
+
+    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
+    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
+    return err;
+}
+
+static void handle_addrinfo_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
+{
+    char hostname[kDNSServiceMaxDomainName];
+    uint16_t rrtype, rrclass, rdlen;
+    const char *rdata;
+    uint32_t ttl;
+
+    get_string(&data, end, hostname, kDNSServiceMaxDomainName);
+    rrtype  = get_uint16(&data, end);
+    rrclass = get_uint16(&data, end);
+    rdlen   = get_uint16(&data, end);
+    rdata   = get_rdata (&data, end, rdlen);
+    ttl     = get_uint32(&data, end);
+
+    // We only generate client callbacks for A and AAAA results (including NXDOMAIN results for
+    // those types, if the client has requested those with the kDNSServiceFlagsReturnIntermediates).
+    // Other result types, specifically CNAME referrals, are not communicated to the client, because
+    // the DNSServiceGetAddrInfoReply interface doesn't have any meaningful way to communiate CNAME referrals.
+    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_addrinfo_response: error reading result from daemon");
+    else if (rrtype == kDNSServiceType_A || rrtype == kDNSServiceType_AAAA)
+    {
+        struct sockaddr_in sa4;
+        struct sockaddr_in6 sa6;
+        const struct sockaddr *const sa = (rrtype == kDNSServiceType_A) ? (struct sockaddr*)&sa4 : (struct sockaddr*)&sa6;
+        if (rrtype == kDNSServiceType_A)
+        {
+            memset(&sa4, 0, sizeof(sa4));
+            #ifndef NOT_HAVE_SA_LEN
+            sa4.sin_len = sizeof(struct sockaddr_in);
+            #endif
+            sa4.sin_family = AF_INET;
+            //  sin_port   = 0;
+            if (!cbh->cb_err) memcpy(&sa4.sin_addr, rdata, rdlen);
+        }
+        else
+        {
+            memset(&sa6, 0, sizeof(sa6));
+            #ifndef NOT_HAVE_SA_LEN
+            sa6.sin6_len = sizeof(struct sockaddr_in6);
+            #endif
+            sa6.sin6_family     = AF_INET6;
+            //  sin6_port     = 0;
+            //  sin6_flowinfo = 0;
+            //  sin6_scope_id = 0;
+            if (!cbh->cb_err)
+            {
+                memcpy(&sa6.sin6_addr, rdata, rdlen);
+                if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr)) sa6.sin6_scope_id = cbh->cb_interface;
+            }
+        }
+        // Validation results are always delivered separately from the actual results of the
+        // DNSServiceGetAddrInfo. Set the "addr" to NULL as per the documentation.
+        //
+        // Note: If we deliver validation results along with the "addr" in the future, we need
+        // a way to differentiate the negative response from validation-only response as both
+        // has zero address.
+        if (!(cbh->cb_flags & kDNSServiceFlagsValidate))
+            ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, hostname, sa, ttl, sdr->AppContext);
+        else
+            ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, hostname, NULL, 0, sdr->AppContext);
+        // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
+    }
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo
+(
+    DNSServiceRef                    *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    uint32_t protocol,
+    const char                       *hostname,
+    DNSServiceGetAddrInfoReply callBack,
+    void                             *context          /* may be NULL */
+)
+{
+    char *ptr;
+    size_t len;
+    ipc_msg_hdr *hdr;
+    DNSServiceErrorType err;
+
+    if (!hostname) return kDNSServiceErr_BadParam;
+
+    err = ConnectToServer(sdRef, flags, addrinfo_request, handle_addrinfo_response, callBack, context);
+    if (err)
+    {
+         return err;    // On error ConnectToServer leaves *sdRef set to NULL
+    }
+
+    // Calculate total message length
+    len = sizeof(flags);
+    len += sizeof(uint32_t);      // interfaceIndex
+    len += sizeof(uint32_t);      // protocol
+    len += strlen(hostname) + 1;
+
+    hdr = create_hdr(addrinfo_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
+    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
+
+    put_flags(flags, &ptr);
+    put_uint32(interfaceIndex, &ptr);
+    put_uint32(protocol, &ptr);
+    put_string(hostname, &ptr);
+
+    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
+    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
+    return err;
+}
+
+static void handle_browse_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
+{
+    char replyName[256], replyType[kDNSServiceMaxDomainName], replyDomain[kDNSServiceMaxDomainName];
+    get_string(&data, end, replyName, 256);
+    get_string(&data, end, replyType, kDNSServiceMaxDomainName);
+    get_string(&data, end, replyDomain, kDNSServiceMaxDomainName);
+    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_browse_response: error reading result from daemon");
+    else ((DNSServiceBrowseReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, replyName, replyType, replyDomain, sdr->AppContext);
+    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceBrowse
+(
+    DNSServiceRef         *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    const char            *regtype,
+    const char            *domain,
+    DNSServiceBrowseReply callBack,
+    void                  *context
+)
+{
+    char *ptr;
+    size_t len;
+    ipc_msg_hdr *hdr;
+    DNSServiceErrorType err;
+
+    if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
+        flags |= kDNSServiceFlagsIncludeP2P;
+
+    err = ConnectToServer(sdRef, flags, browse_request, handle_browse_response, callBack, context);
+    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
+
+    if (!domain) domain = "";
+    len = sizeof(flags);
+    len += sizeof(interfaceIndex);
+    len += strlen(regtype) + 1;
+    len += strlen(domain) + 1;
+
+    hdr = create_hdr(browse_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
+    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
+
+    put_flags(flags, &ptr);
+    put_uint32(interfaceIndex, &ptr);
+    put_string(regtype, &ptr);
+    put_string(domain, &ptr);
+
+    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
+    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
+    return err;
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain);
+DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain)
+{
+    DNSServiceOp *tmp;
+    char *ptr;
+    size_t len = sizeof(flags) + strlen(domain) + 1;
+    ipc_msg_hdr *hdr;
+    DNSServiceErrorType err = ConnectToServer(&tmp, 0, setdomain_request, NULL, NULL, NULL);
+    if (err) return err;
+
+    hdr = create_hdr(setdomain_request, &len, &ptr, 0, tmp);
+    if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
+
+    put_flags(flags, &ptr);
+    put_string(domain, &ptr);
+    err = deliver_request(hdr, tmp);        // Will free hdr for us
+    DNSServiceRefDeallocate(tmp);
+    return err;
+}
+
+static void handle_regservice_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
+{
+    char name[256], regtype[kDNSServiceMaxDomainName], domain[kDNSServiceMaxDomainName];
+    get_string(&data, end, name, 256);
+    get_string(&data, end, regtype, kDNSServiceMaxDomainName);
+    get_string(&data, end, domain,  kDNSServiceMaxDomainName);
+    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_regservice_response: error reading result from daemon");
+    else ((DNSServiceRegisterReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_err, name, regtype, domain, sdr->AppContext);
+    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceRegister
+(
+    DNSServiceRef                       *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    const char                          *name,
+    const char                          *regtype,
+    const char                          *domain,
+    const char                          *host,
+    uint16_t PortInNetworkByteOrder,
+    uint16_t txtLen,
+    const void                          *txtRecord,
+    DNSServiceRegisterReply callBack,
+    void                                *context
+)
+{
+    char *ptr;
+    size_t len;
+    ipc_msg_hdr *hdr;
+    DNSServiceErrorType err;
+    union { uint16_t s; u_char b[2]; } port = { PortInNetworkByteOrder };
+
+    if (!name) name = "";
+    if (!regtype) return kDNSServiceErr_BadParam;
+    if (!domain) domain = "";
+    if (!host) host = "";
+    if (!txtRecord) txtRecord = (void*)"";
+
+    // No callback must have auto-rename
+    if (!callBack && (flags & kDNSServiceFlagsNoAutoRename)) return kDNSServiceErr_BadParam;
+
+    if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
+        flags |= kDNSServiceFlagsIncludeP2P;
+
+    err = ConnectToServer(sdRef, flags, reg_service_request, callBack ? handle_regservice_response : NULL, callBack, context);
+    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
+
+    len = sizeof(DNSServiceFlags);
+    len += sizeof(uint32_t);  // interfaceIndex
+    len += strlen(name) + strlen(regtype) + strlen(domain) + strlen(host) + 4;
+    len += 2 * sizeof(uint16_t);  // port, txtLen
+    len += txtLen;
+
+    hdr = create_hdr(reg_service_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
+    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
+
+    // If it is going over a shared connection, then don't set the IPC_FLAGS_NOREPLY
+    // as it affects all the operations over the shared connection. This is not
+    // a normal case and hence receiving the response back from the daemon and
+    // discarding it in ConnectionResponse is okay.
+
+    if (!(flags & kDNSServiceFlagsShareConnection) && !callBack) hdr->ipc_flags |= IPC_FLAGS_NOREPLY;
+
+    put_flags(flags, &ptr);
+    put_uint32(interfaceIndex, &ptr);
+    put_string(name, &ptr);
+    put_string(regtype, &ptr);
+    put_string(domain, &ptr);
+    put_string(host, &ptr);
+    *ptr++ = port.b[0];
+    *ptr++ = port.b[1];
+    put_uint16(txtLen, &ptr);
+    put_rdata(txtLen, txtRecord, &ptr);
+
+    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
+    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
+    return err;
+}
+
+static void handle_enumeration_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
+{
+    char domain[kDNSServiceMaxDomainName];
+    get_string(&data, end, domain, kDNSServiceMaxDomainName);
+    if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_enumeration_response: error reading result from daemon");
+    else ((DNSServiceDomainEnumReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, domain, sdr->AppContext);
+    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
+(
+    DNSServiceRef             *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    DNSServiceDomainEnumReply callBack,
+    void                      *context
+)
+{
+    char *ptr;
+    size_t len;
+    ipc_msg_hdr *hdr;
+    DNSServiceErrorType err;
+
+    int f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0;
+    int f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0;
+    if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
+
+    err = ConnectToServer(sdRef, flags, enumeration_request, handle_enumeration_response, callBack, context);
+    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
+
+    len = sizeof(DNSServiceFlags);
+    len += sizeof(uint32_t);
+
+    hdr = create_hdr(enumeration_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
+    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
+
+    put_flags(flags, &ptr);
+    put_uint32(interfaceIndex, &ptr);
+
+    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
+    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
+    return err;
+}
+
+static void ConnectionResponse(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *const data, const char *const end)
+{
+    (void)data; // Unused
+
+    //printf("ConnectionResponse got %d\n", cbh->ipc_hdr.op);
+    if (cbh->ipc_hdr.op != reg_record_reply_op)
+    {
+        // When using kDNSServiceFlagsShareConnection, need to search the list of associated DNSServiceOps
+        // to find the one this response is intended for, and then call through to its ProcessReply handler.
+        // We start with our first subordinate DNSServiceRef -- don't want to accidentally match the parent DNSServiceRef.
+        DNSServiceOp *op = sdr->next;
+        while (op && (op->uid.u32[0] != cbh->ipc_hdr.client_context.u32[0] || op->uid.u32[1] != cbh->ipc_hdr.client_context.u32[1]))
+            op = op->next;
+        // Note: We may sometimes not find a matching DNSServiceOp, in the case where the client has
+        // cancelled the subordinate DNSServiceOp, but there are still messages in the pipeline from the daemon
+        if (op && op->ProcessReply) op->ProcessReply(op, cbh, data, end);
+        // WARNING: Don't touch op or sdr after this -- client may have called DNSServiceRefDeallocate
+        return;
+    }
+    else
+    {
+        DNSRecordRef rec;
+        for (rec = sdr->rec; rec; rec = rec->recnext)
+        {
+            if (rec->uid.u32[0] == cbh->ipc_hdr.client_context.u32[0] && rec->uid.u32[1] == cbh->ipc_hdr.client_context.u32[1])
+                break;
+        }
+        // The record might have been freed already and hence not an
+        // error if the record is not found.
+        if (!rec)
+        {
+            syslog(LOG_INFO, "ConnectionResponse: Record not found");
+            return;
+        }
+        if (rec->sdr != sdr)
+        {
+            syslog(LOG_WARNING, "ConnectionResponse: Record sdr mismatch: rec %p sdr %p", rec->sdr, sdr);
+            return;
+        }
+
+        if (sdr->op == connection_request || sdr->op == connection_delegate_request)
+        {
+            rec->AppCallback(rec->sdr, rec, cbh->cb_flags, cbh->cb_err, rec->AppContext);
+        }
+        else
+        {
+            syslog(LOG_WARNING, "dnssd_clientstub ConnectionResponse: sdr->op != connection_request");
+            rec->AppCallback(rec->sdr, rec, 0, kDNSServiceErr_Unknown, rec->AppContext);
+        }
+        // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
+    }
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef)
+{
+    char *ptr;
+    size_t len = 0;
+    ipc_msg_hdr *hdr;
+    DNSServiceErrorType err = ConnectToServer(sdRef, 0, connection_request, ConnectionResponse, NULL, NULL);
+    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
+
+    hdr = create_hdr(connection_request, &len, &ptr, 0, *sdRef);
+    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
+
+    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
+    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
+    return err;
+}
+
+#if APPLE_OSX_mDNSResponder && !TARGET_IPHONE_SIMULATOR
+DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid)
+{
+    char *ptr;
+    size_t len = 0;
+    ipc_msg_hdr *hdr;
+
+    DNSServiceErrorType err = ConnectToServer(sdRef, 0, connection_delegate_request, ConnectionResponse, NULL, NULL);
+    if (err)
+    {
+         return err;    // On error ConnectToServer leaves *sdRef set to NULL
+    }
+
+    // Only one of the two options can be set. If pid is zero, uuid is used. 
+    // If both are specified only pid will be used. We send across the pid
+    // so that the daemon knows what to read from the socket.
+
+    len += sizeof(int32_t);
+
+    hdr = create_hdr(connection_delegate_request, &len, &ptr, 0, *sdRef);
+    if (!hdr)
+    {
+        DNSServiceRefDeallocate(*sdRef);
+        *sdRef = NULL;
+        return kDNSServiceErr_NoMemory;
+    }
+
+    if (pid && setsockopt((*sdRef)->sockfd, SOL_SOCKET, SO_DELEGATED, &pid, sizeof(pid)) == -1)
+    { 
+        syslog(LOG_WARNING, "dnssdclientstub: Could not setsockopt() for PID[%d], no entitlements or process(pid) invalid errno:%d (%s)", pid, errno, strerror(errno)); 
+        // Free the hdr in case we return before calling deliver_request() 
+        if (hdr)
+            free(hdr);
+        DNSServiceRefDeallocate(*sdRef);
+        *sdRef = NULL;
+        return kDNSServiceErr_NoAuth;
+    }
+
+    if (!pid && setsockopt((*sdRef)->sockfd, SOL_SOCKET, SO_DELEGATED_UUID, uuid, sizeof(uuid_t)) == -1)
+    {
+        syslog(LOG_WARNING, "dnssdclientstub: Could not setsockopt() for UUID, no entitlements or process(uuid) invalid errno:%d (%s) ", errno, strerror(errno));
+        // Free the hdr in case we return before calling deliver_request()
+        if (hdr)
+            free(hdr);
+        DNSServiceRefDeallocate(*sdRef);
+        *sdRef = NULL;
+        return kDNSServiceErr_NoAuth;
+    }
+
+    put_uint32(pid, &ptr);
+
+    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
+    if (err)
+    {
+        DNSServiceRefDeallocate(*sdRef);
+        *sdRef = NULL;
+    }
+    return err;
+}
+#elif TARGET_IPHONE_SIMULATOR // This hack is for Simulator platform only
+DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid)
+{
+    (void) pid;
+    (void) uuid;
+    return DNSServiceCreateConnection(sdRef);
+}
+#endif
+
+DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
+(
+    DNSServiceRef sdRef,
+    DNSRecordRef                  *RecordRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    const char                    *fullname,
+    uint16_t rrtype,
+    uint16_t rrclass,
+    uint16_t rdlen,
+    const void                    *rdata,
+    uint32_t ttl,
+    DNSServiceRegisterRecordReply callBack,
+    void                          *context
+)
+{
+    char *ptr;
+    size_t len;
+    ipc_msg_hdr *hdr = NULL;
+    DNSRecordRef rref = NULL;
+    DNSRecord **p;
+    int f1 = (flags & kDNSServiceFlagsShared) != 0;
+    int f2 = (flags & kDNSServiceFlagsUnique) != 0;
+    if (f1 + f2 != 1) return kDNSServiceErr_BadParam;
+
+    if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny())
+        flags |= kDNSServiceFlagsIncludeP2P;
+
+    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
+
+    if (!DNSServiceRefValid(sdRef))
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
+        return kDNSServiceErr_BadReference;
+    }
+
+    if (sdRef->op != connection_request && sdRef->op != connection_delegate_request)
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with non-DNSServiceCreateConnection DNSServiceRef %p %d", sdRef, sdRef->op);
+        return kDNSServiceErr_BadReference;
+    }
+
+    *RecordRef = NULL;
+
+    len = sizeof(DNSServiceFlags);
+    len += 2 * sizeof(uint32_t);  // interfaceIndex, ttl
+    len += 3 * sizeof(uint16_t);  // rrtype, rrclass, rdlen
+    len += strlen(fullname) + 1;
+    len += rdlen;
+
+    // Bump up the uid. Normally for shared operations (kDNSServiceFlagsShareConnection), this
+    // is done in ConnectToServer. For DNSServiceRegisterRecord, ConnectToServer has already
+    // been called. As multiple DNSServiceRegisterRecords can be multiplexed over a single
+    // connection, we need a way to demultiplex the response so that the callback corresponding
+    // to the right DNSServiceRegisterRecord instance can be called. Use the same mechanism that
+    // is used by kDNSServiceFlagsShareConnection. create_hdr copies the uid value to ipc
+    // hdr->client_context which will be returned in the ipc response.
+    if (++sdRef->uid.u32[0] == 0)
+        ++sdRef->uid.u32[1];
+    hdr = create_hdr(reg_record_request, &len, &ptr, 1, sdRef);
+    if (!hdr) return kDNSServiceErr_NoMemory;
+
+    put_flags(flags, &ptr);
+    put_uint32(interfaceIndex, &ptr);
+    put_string(fullname, &ptr);
+    put_uint16(rrtype, &ptr);
+    put_uint16(rrclass, &ptr);
+    put_uint16(rdlen, &ptr);
+    put_rdata(rdlen, rdata, &ptr);
+    put_uint32(ttl, &ptr);
+
+    rref = malloc(sizeof(DNSRecord));
+    if (!rref) { free(hdr); return kDNSServiceErr_NoMemory; }
+    rref->AppContext = context;
+    rref->AppCallback = callBack;
+    rref->record_index = sdRef->max_index++;
+    rref->sdr = sdRef;
+    rref->recnext = NULL;
+    *RecordRef = rref;
+    // Remember the uid that we are sending across so that we can match
+    // when the response comes back.
+    rref->uid = sdRef->uid;
+    hdr->reg_index = rref->record_index;
+
+    p = &(sdRef)->rec;
+    while (*p) p = &(*p)->recnext;
+    *p = rref;
+
+    return deliver_request(hdr, sdRef);     // Will free hdr for us
+}
+
+// sdRef returned by DNSServiceRegister()
+DNSServiceErrorType DNSSD_API DNSServiceAddRecord
+(
+    DNSServiceRef sdRef,
+    DNSRecordRef    *RecordRef,
+    DNSServiceFlags flags,
+    uint16_t rrtype,
+    uint16_t rdlen,
+    const void      *rdata,
+    uint32_t ttl
+)
+{
+    ipc_msg_hdr *hdr;
+    size_t len = 0;
+    char *ptr;
+    DNSRecordRef rref;
+    DNSRecord **p;
+
+    if (!sdRef)     { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSServiceRef");        return kDNSServiceErr_BadParam; }
+    if (!RecordRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSRecordRef pointer"); return kDNSServiceErr_BadParam; }
+    if (sdRef->op != reg_service_request)
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with non-DNSServiceRegister DNSServiceRef %p %d", sdRef, sdRef->op);
+        return kDNSServiceErr_BadReference;
+    }
+
+    if (!DNSServiceRefValid(sdRef))
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
+        return kDNSServiceErr_BadReference;
+    }
+
+    *RecordRef = NULL;
+
+    len += 2 * sizeof(uint16_t);  // rrtype, rdlen
+    len += rdlen;
+    len += sizeof(uint32_t);
+    len += sizeof(DNSServiceFlags);
+
+    hdr = create_hdr(add_record_request, &len, &ptr, 1, sdRef);
+    if (!hdr) return kDNSServiceErr_NoMemory;
+    put_flags(flags, &ptr);
+    put_uint16(rrtype, &ptr);
+    put_uint16(rdlen, &ptr);
+    put_rdata(rdlen, rdata, &ptr);
+    put_uint32(ttl, &ptr);
+
+    rref = malloc(sizeof(DNSRecord));
+    if (!rref) { free(hdr); return kDNSServiceErr_NoMemory; }
+    rref->AppContext = NULL;
+    rref->AppCallback = NULL;
+    rref->record_index = sdRef->max_index++;
+    rref->sdr = sdRef;
+    rref->recnext = NULL;
+    *RecordRef = rref;
+    hdr->reg_index = rref->record_index;
+
+    p = &(sdRef)->rec;
+    while (*p) p = &(*p)->recnext;
+    *p = rref;
+
+    return deliver_request(hdr, sdRef);     // Will free hdr for us
+}
+
+// DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord
+DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
+(
+    DNSServiceRef sdRef,
+    DNSRecordRef RecordRef,
+    DNSServiceFlags flags,
+    uint16_t rdlen,
+    const void      *rdata,
+    uint32_t ttl
+)
+{
+    ipc_msg_hdr *hdr;
+    size_t len = 0;
+    char *ptr;
+
+    if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
+
+    if (!DNSServiceRefValid(sdRef))
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
+        return kDNSServiceErr_BadReference;
+    }
+
+    // Note: RecordRef is allowed to be NULL
+
+    len += sizeof(uint16_t);
+    len += rdlen;
+    len += sizeof(uint32_t);
+    len += sizeof(DNSServiceFlags);
+
+    hdr = create_hdr(update_record_request, &len, &ptr, 1, sdRef);
+    if (!hdr) return kDNSServiceErr_NoMemory;
+    hdr->reg_index = RecordRef ? RecordRef->record_index : TXT_RECORD_INDEX;
+    put_flags(flags, &ptr);
+    put_uint16(rdlen, &ptr);
+    put_rdata(rdlen, rdata, &ptr);
+    put_uint32(ttl, &ptr);
+    return deliver_request(hdr, sdRef);     // Will free hdr for us
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
+(
+    DNSServiceRef sdRef,
+    DNSRecordRef RecordRef,
+    DNSServiceFlags flags
+)
+{
+    ipc_msg_hdr *hdr;
+    size_t len = 0;
+    char *ptr;
+    DNSServiceErrorType err;
+
+    if (!sdRef)            { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; }
+    if (!RecordRef)        { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with NULL DNSRecordRef");  return kDNSServiceErr_BadParam; }
+    if (!sdRef->max_index) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with bad DNSServiceRef");  return kDNSServiceErr_BadReference; }
+
+    if (!DNSServiceRefValid(sdRef))
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator);
+        return kDNSServiceErr_BadReference;
+    }
+
+    len += sizeof(flags);
+    hdr = create_hdr(remove_record_request, &len, &ptr, 1, sdRef);
+    if (!hdr) return kDNSServiceErr_NoMemory;
+    hdr->reg_index = RecordRef->record_index;
+    put_flags(flags, &ptr);
+    err = deliver_request(hdr, sdRef);      // Will free hdr for us
+    if (!err)
+    {
+        // This RecordRef could have been allocated in DNSServiceRegisterRecord or DNSServiceAddRecord.
+        // If so, delink from the list before freeing
+        DNSRecord **p = &sdRef->rec;
+        while (*p && *p != RecordRef) p = &(*p)->recnext;
+        if (*p) *p = RecordRef->recnext;
+        free(RecordRef);
+    }
+    return err;
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
+(
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    const char      *fullname,
+    uint16_t rrtype,
+    uint16_t rrclass,
+    uint16_t rdlen,
+    const void      *rdata
+)
+{
+    char *ptr;
+    size_t len;
+    ipc_msg_hdr *hdr;
+    DNSServiceOp *tmp;
+
+    DNSServiceErrorType err = ConnectToServer(&tmp, flags, reconfirm_record_request, NULL, NULL, NULL);
+    if (err) return err;
+
+    len = sizeof(DNSServiceFlags);
+    len += sizeof(uint32_t);
+    len += strlen(fullname) + 1;
+    len += 3 * sizeof(uint16_t);
+    len += rdlen;
+    hdr = create_hdr(reconfirm_record_request, &len, &ptr, 0, tmp);
+    if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; }
+
+    put_flags(flags, &ptr);
+    put_uint32(interfaceIndex, &ptr);
+    put_string(fullname, &ptr);
+    put_uint16(rrtype, &ptr);
+    put_uint16(rrclass, &ptr);
+    put_uint16(rdlen, &ptr);
+    put_rdata(rdlen, rdata, &ptr);
+
+    err = deliver_request(hdr, tmp);        // Will free hdr for us
+    DNSServiceRefDeallocate(tmp);
+    return err;
+}
+
+
+static void handle_port_mapping_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end)
+{
+    union { uint32_t l; u_char b[4]; } addr;
+    uint8_t protocol;
+    union { uint16_t s; u_char b[2]; } internalPort;
+    union { uint16_t s; u_char b[2]; } externalPort;
+    uint32_t ttl;
+
+    if (!data || data + 13 > end) goto fail;
+
+    addr.b[0] = *data++;
+    addr.b[1] = *data++;
+    addr.b[2] = *data++;
+    addr.b[3] = *data++;
+    protocol          = *data++;
+    internalPort.b[0] = *data++;
+    internalPort.b[1] = *data++;
+    externalPort.b[0] = *data++;
+    externalPort.b[1] = *data++;
+    ttl               = get_uint32(&data, end);
+    if (!data) goto fail;
+
+    ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, addr.l, protocol, internalPort.s, externalPort.s, ttl, sdr->AppContext);
+    return;
+    // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function
+
+    fail :
+    syslog(LOG_WARNING, "dnssd_clientstub handle_port_mapping_response: error reading result from daemon");
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
+(
+    DNSServiceRef                       *sdRef,
+    DNSServiceFlags flags,
+    uint32_t interfaceIndex,
+    uint32_t protocol,                                /* TCP and/or UDP */
+    uint16_t internalPortInNetworkByteOrder,
+    uint16_t externalPortInNetworkByteOrder,
+    uint32_t ttl,                                     /* time to live in seconds */
+    DNSServiceNATPortMappingReply callBack,
+    void                                *context      /* may be NULL */
+)
+{
+    char *ptr;
+    size_t len;
+    ipc_msg_hdr *hdr;
+    union { uint16_t s; u_char b[2]; } internalPort = { internalPortInNetworkByteOrder };
+    union { uint16_t s; u_char b[2]; } externalPort = { externalPortInNetworkByteOrder };
+
+    DNSServiceErrorType err = ConnectToServer(sdRef, flags, port_mapping_request, handle_port_mapping_response, callBack, context);
+    if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
+
+    len = sizeof(flags);
+    len += sizeof(interfaceIndex);
+    len += sizeof(protocol);
+    len += sizeof(internalPort);
+    len += sizeof(externalPort);
+    len += sizeof(ttl);
+
+    hdr = create_hdr(port_mapping_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef);
+    if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; }
+
+    put_flags(flags, &ptr);
+    put_uint32(interfaceIndex, &ptr);
+    put_uint32(protocol, &ptr);
+    *ptr++ = internalPort.b[0];
+    *ptr++ = internalPort.b[1];
+    *ptr++ = externalPort.b[0];
+    *ptr++ = externalPort.b[1];
+    put_uint32(ttl, &ptr);
+
+    err = deliver_request(hdr, *sdRef);     // Will free hdr for us
+    if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; }
+    return err;
+}
+
+#if _DNS_SD_LIBDISPATCH
+DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue
+(
+    DNSServiceRef service,
+    dispatch_queue_t queue
+)
+{
+    int dnssd_fd  = DNSServiceRefSockFD(service);
+    if (dnssd_fd == dnssd_InvalidSocket) return kDNSServiceErr_BadParam;
+    if (!queue)
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub: DNSServiceSetDispatchQueue dispatch queue NULL");
+        return kDNSServiceErr_BadParam;
+    }
+    if (service->disp_queue)
+    {
+        syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSetDispatchQueue dispatch queue set already");
+        return kDNSServiceErr_BadParam;
+    }
+    if (service->disp_source)
+    {
+        syslog(LOG_WARNING, "DNSServiceSetDispatchQueue dispatch source set already");
+        return kDNSServiceErr_BadParam;
+    }
+    service->disp_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, dnssd_fd, 0, queue);
+    if (!service->disp_source)
+    {
+        syslog(LOG_WARNING, "DNSServiceSetDispatchQueue dispatch_source_create failed");
+        return kDNSServiceErr_NoMemory;
+    }
+    service->disp_queue = queue;
+    dispatch_source_set_event_handler(service->disp_source, ^{DNSServiceProcessResult(service);});
+    dispatch_source_set_cancel_handler(service->disp_source, ^{dnssd_close(dnssd_fd);});
+    dispatch_resume(service->disp_source);
+    return kDNSServiceErr_NoError;
+}
+#endif // _DNS_SD_LIBDISPATCH
+
+#if !defined(_WIN32)
+
+static void DNSSD_API SleepKeepaliveCallback(DNSServiceRef sdRef, DNSRecordRef rec, const DNSServiceFlags flags,
+                                             DNSServiceErrorType errorCode, void *context)
+{
+    SleepKAContext *ka = (SleepKAContext *)context;
+    (void)rec;      // Unused
+    (void)flags;    // Unused
+
+    if (sdRef->kacontext != context)
+        syslog(LOG_WARNING, "SleepKeepaliveCallback context mismatch");
+
+    if (ka->AppCallback)
+        ((DNSServiceSleepKeepaliveReply)ka->AppCallback)(sdRef, errorCode, ka->AppContext);
+}
+
+DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive
+(
+    DNSServiceRef                       *sdRef,
+    DNSServiceFlags flags,
+    int fd,
+    unsigned int timeout,
+    DNSServiceSleepKeepaliveReply callBack,
+    void                                *context
+)
+{
+    char source_str[INET6_ADDRSTRLEN];
+    char target_str[INET6_ADDRSTRLEN];
+    struct sockaddr_storage lss;
+    struct sockaddr_storage rss;
+    socklen_t len1, len2;
+    unsigned int len, proxyreclen;
+    char buf[256];
+    DNSServiceErrorType err;
+    DNSRecordRef record = NULL;
+    char name[10];
+    char recname[128];
+    SleepKAContext *ka;
+    unsigned int i, unique;
+
+
+    (void) flags; //unused
+    if (!timeout) return kDNSServiceErr_BadParam;
+
+
+    len1 = sizeof(lss);
+    if (getsockname(fd, (struct sockaddr *)&lss, &len1) < 0)
+    {
+        syslog(LOG_WARNING, "DNSServiceSleepKeepalive: getsockname %d\n", errno);
+        return kDNSServiceErr_BadParam;
+    }
+
+    len2 = sizeof(rss);
+    if (getpeername(fd, (struct sockaddr *)&rss, &len2) < 0)
+    {
+        syslog(LOG_WARNING, "DNSServiceSleepKeepalive: getpeername %d\n", errno);
+        return kDNSServiceErr_BadParam;
+    }
+
+    if (len1 != len2)
+    {
+        syslog(LOG_WARNING, "DNSServiceSleepKeepalive local/remote info not same");
+        return kDNSServiceErr_Unknown;
+    }
+
+    unique = 0;
+    if (lss.ss_family == AF_INET)
+    {
+        struct sockaddr_in *sl = (struct sockaddr_in *)&lss;
+        struct sockaddr_in *sr = (struct sockaddr_in *)&rss;
+        unsigned char *ptr = (unsigned char *)&sl->sin_addr;
+
+        if (!inet_ntop(AF_INET, (const void *)&sr->sin_addr, target_str, sizeof (target_str)))
+        {
+            syslog(LOG_WARNING, "DNSServiceSleepKeepalive remote info failed %d", errno);
+            return kDNSServiceErr_Unknown;
+        }
+        if (!inet_ntop(AF_INET, (const void *)&sl->sin_addr, source_str, sizeof (source_str)))
+        {
+            syslog(LOG_WARNING, "DNSServiceSleepKeepalive local info failed %d", errno);
+            return kDNSServiceErr_Unknown;
+        }
+        // Sum of all bytes in the local address and port should result in a unique
+        // number in the local network
+        for (i = 0; i < sizeof(struct in_addr); i++)
+            unique += ptr[i];
+        unique += sl->sin_port;
+        len = snprintf(buf+1, sizeof(buf) - 1, "t=%u h=%s d=%s l=%u r=%u", timeout, source_str, target_str, ntohs(sl->sin_port), ntohs(sr->sin_port));
+    }
+    else
+    {
+        struct sockaddr_in6 *sl6 = (struct sockaddr_in6 *)&lss;
+        struct sockaddr_in6 *sr6 = (struct sockaddr_in6 *)&rss;
+        unsigned char *ptr = (unsigned char *)&sl6->sin6_addr;
+
+        if (!inet_ntop(AF_INET6, (const void *)&sr6->sin6_addr, target_str, sizeof (target_str)))
+        {
+            syslog(LOG_WARNING, "DNSServiceSleepKeepalive remote6 info failed %d", errno);
+            return kDNSServiceErr_Unknown;
+        }
+        if (!inet_ntop(AF_INET6, (const void *)&sl6->sin6_addr, source_str, sizeof (source_str)))
+        {
+            syslog(LOG_WARNING, "DNSServiceSleepKeepalive local6 info failed %d", errno);
+            return kDNSServiceErr_Unknown;
+        }
+        for (i = 0; i < sizeof(struct in6_addr); i++)
+            unique += ptr[i];
+        unique += sl6->sin6_port;
+        len = snprintf(buf+1, sizeof(buf) - 1, "t=%u H=%s D=%s l=%u r=%u", timeout, source_str, target_str, ntohs(sl6->sin6_port), ntohs(sr6->sin6_port));
+    }
+
+    if (len >= (sizeof(buf) - 1))
+    {
+        syslog(LOG_WARNING, "DNSServiceSleepKeepalive could not fit local/remote info");
+        return kDNSServiceErr_Unknown;
+    }
+    // Include the NULL byte also in the first byte. The total length of the record includes the
+    // first byte also.
+    buf[0] = len + 1;
+    proxyreclen = len + 2;
+
+    len = snprintf(name, sizeof(name), "%u", unique);
+    if (len >= sizeof(name))
+    {
+        syslog(LOG_WARNING, "DNSServiceSleepKeepalive could not fit unique");
+        return kDNSServiceErr_Unknown;
+    }
+
+    len = snprintf(recname, sizeof(recname), "%s.%s", name, "_keepalive._dns-sd._udp.local");
+    if (len >= sizeof(recname))
+    {
+        syslog(LOG_WARNING, "DNSServiceSleepKeepalive could not fit name");
+        return kDNSServiceErr_Unknown;
+    }
+
+    ka = malloc(sizeof(SleepKAContext));
+    if (!ka) return kDNSServiceErr_NoMemory;
+    ka->AppCallback = callBack;
+    ka->AppContext = context;
+
+    err = DNSServiceCreateConnection(sdRef);
+    if (err)
+    {
+        syslog(LOG_WARNING, "DNSServiceSleepKeepalive cannot create connection");
+        free(ka);
+        return err;
+    }
+
+    // we don't care about the "record". When sdRef gets deallocated later, it will be freed too
+    err = DNSServiceRegisterRecord(*sdRef, &record, kDNSServiceFlagsUnique, 0, recname,
+                                   kDNSServiceType_NULL,  kDNSServiceClass_IN, proxyreclen, buf,  kDNSServiceInterfaceIndexAny, SleepKeepaliveCallback, ka);
+    if (err)
+    {
+        syslog(LOG_WARNING, "DNSServiceSleepKeepalive cannot create connection");
+        free(ka);
+        return err;
+    }
+    (*sdRef)->kacontext = ka;
+    return kDNSServiceErr_NoError;
+}
+#endif

Deleted: vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_ipc.h
===================================================================
--- vendor/apple/mDNSResponder/dist/mDNSShared/dnssd_ipc.h	2014-06-30 23:58:12 UTC (rev 6706)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_ipc.h	2015-03-20 01:14:52 UTC (rev 6985)
@@ -1,221 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1.  Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
- *     contributors may be used to endorse or promote products derived from this
- *     software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DNSSD_IPC_H
-#define DNSSD_IPC_H
-
-#include "dns_sd.h"
-
-//
-// Common cross platform services
-//
-#if defined(WIN32)
-#   include <winsock2.h>
-#   define dnssd_InvalidSocket  INVALID_SOCKET
-#   define dnssd_SocketValid(s) ((s) != INVALID_SOCKET)
-#   define dnssd_EWOULDBLOCK    WSAEWOULDBLOCK
-#   define dnssd_EINTR          WSAEINTR
-#   define dnssd_ECONNRESET     WSAECONNRESET
-#   define dnssd_sock_t         SOCKET
-#   define dnssd_socklen_t      int
-#   define dnssd_close(sock)    closesocket(sock)
-#   define dnssd_errno          WSAGetLastError()
-#   define dnssd_strerror(X)    win32_strerror(X)
-#   define ssize_t              int
-#   define getpid               _getpid
-#   define unlink               _unlink
-extern char *win32_strerror(int inErrorCode);
-#else
-#   include <sys/types.h>
-#   include <unistd.h>
-#   include <sys/un.h>
-#   include <string.h>
-#   include <stdio.h>
-#   include <stdlib.h>
-#   include <sys/stat.h>
-#   include <sys/socket.h>
-#   include <netinet/in.h>
-#   include <arpa/inet.h>
-#   define dnssd_InvalidSocket  -1
-#   define dnssd_SocketValid(s) ((s) >= 0)
-#   define dnssd_EWOULDBLOCK    EWOULDBLOCK
-#   define dnssd_EINTR          EINTR
-#   define dnssd_ECONNRESET     ECONNRESET
-#   define dnssd_EPIPE          EPIPE
-#   define dnssd_sock_t         int
-#   define dnssd_socklen_t      unsigned int
-#   define dnssd_close(sock)    close(sock)
-#   define dnssd_errno          errno
-#   define dnssd_strerror(X)    strerror(X)
-#endif
-
-#if defined(USE_TCP_LOOPBACK)
-#   define AF_DNSSD             AF_INET
-#   define MDNS_TCP_SERVERADDR  "127.0.0.1"
-#   define MDNS_TCP_SERVERPORT  5354
-#   define LISTENQ              5
-#   define dnssd_sockaddr_t     struct sockaddr_in
-#else
-#   define AF_DNSSD             AF_LOCAL
-#   ifndef MDNS_UDS_SERVERPATH
-#       define MDNS_UDS_SERVERPATH  "/var/run/mDNSResponder"
-#   endif
-#   define LISTENQ              100
-// longest legal control path length
-#   define MAX_CTLPATH          256
-#   define dnssd_sockaddr_t     struct sockaddr_un
-#endif
-
-// Compatibility workaround
-#ifndef AF_LOCAL
-#define AF_LOCAL    AF_UNIX
-#endif
-
-// General UDS constants
-#define TXT_RECORD_INDEX ((uint32_t)(-1))   // record index for default text record
-
-// IPC data encoding constants and types
-#define VERSION 1
-#define IPC_FLAGS_NOREPLY 1 // set flag if no asynchronous replies are to be sent to client
-
-// Structure packing macro. If we're not using GNUC, it's not fatal. Most compilers naturally pack the on-the-wire
-// structures correctly anyway, so a plain "struct" is usually fine. In the event that structures are not packed
-// correctly, our compile-time assertion checks will catch it and prevent inadvertent generation of non-working code.
-#ifndef packedstruct
- #if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
-  #define packedstruct struct __attribute__((__packed__))
-  #define packedunion  union  __attribute__((__packed__))
- #else
-  #define packedstruct struct
-  #define packedunion  union
- #endif
-#endif
-
-typedef enum
-{
-    request_op_none = 0,    // No request yet received on this connection
-    connection_request = 1, // connected socket via DNSServiceConnect()
-    reg_record_request,     // reg/remove record only valid for connected sockets
-    remove_record_request,
-    enumeration_request,
-    reg_service_request,
-    browse_request,
-    resolve_request,
-    query_request,
-    reconfirm_record_request,
-    add_record_request,
-    update_record_request,
-    setdomain_request,      // Up to here is in Tiger and B4W 1.0.3
-    getproperty_request,    // New in B4W 1.0.4
-    port_mapping_request,   // New in Leopard and B4W 2.0
-    addrinfo_request,
-    send_bpf,               // New in SL
-    getpid_request,
-    release_request,
-    connection_delegate_request,
-
-    cancel_request = 63
-} request_op_t;
-
-typedef enum
-{
-    enumeration_reply_op = 64,
-    reg_service_reply_op,
-    browse_reply_op,
-    resolve_reply_op,
-    query_reply_op,
-    reg_record_reply_op,    // Up to here is in Tiger and B4W 1.0.3
-    getproperty_reply_op,   // New in B4W 1.0.4
-    port_mapping_reply_op,  // New in Leopard and B4W 2.0
-    addrinfo_reply_op
-} reply_op_t;
-
-#if defined(_WIN64)
-#   pragma pack(push,4)
-#endif
-
-// Define context object big enough to hold a 64-bit pointer,
-// to accomodate 64-bit clients communicating with 32-bit daemon.
-// There's no reason for the daemon to ever be a 64-bit process, but its clients might be
-typedef packedunion
-{
-    void *context;
-    uint32_t u32[2];
-} client_context_t;
-
-typedef packedstruct
-{
-    uint32_t version;
-    uint32_t datalen;
-    uint32_t ipc_flags;
-    uint32_t op;        // request_op_t or reply_op_t
-    client_context_t client_context; // context passed from client, returned by server in corresponding reply
-    uint32_t reg_index;            // identifier for a record registered via DNSServiceRegisterRecord() on a
-    // socket connected by DNSServiceCreateConnection().  Must be unique in the scope of the connection, such that and
-    // index/socket pair uniquely identifies a record.  (Used to select records for removal by DNSServiceRemoveRecord())
-} ipc_msg_hdr;
-
-#if defined(_WIN64)
-#   pragma pack(pop)
-#endif
-
-// routines to write to and extract data from message buffers.
-// caller responsible for bounds checking.
-// ptr is the address of the pointer to the start of the field.
-// it is advanced to point to the next field, or the end of the message
-
-void put_uint32(const uint32_t l, char **ptr);
-uint32_t get_uint32(const char **ptr, const char *end);
-
-void put_uint16(uint16_t s, char **ptr);
-uint16_t get_uint16(const char **ptr, const char *end);
-
-#define put_flags put_uint32
-#define get_flags get_uint32
-
-#define put_error_code put_uint32
-#define get_error_code get_uint32
-
-int put_string(const char *str, char **ptr);
-int get_string(const char **ptr, const char *const end, char *buffer, int buflen);
-
-void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr);
-const char *get_rdata(const char **ptr, const char *end, int rdlen);  // return value is rdata pointed to by *ptr -
-// rdata is not copied from buffer.
-
-void ConvertHeaderBytes(ipc_msg_hdr *hdr);
-
-struct CompileTimeAssertionChecks_dnssd_ipc
-{
-    // Check that the compiler generated our on-the-wire packet format structure definitions
-    // properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries.
-    char assert0[(sizeof(client_context_t) ==  8) ? 1 : -1];
-    char assert1[(sizeof(ipc_msg_hdr)      == 28) ? 1 : -1];
-};
-
-#endif // DNSSD_IPC_H

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_ipc.h (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSShared/dnssd_ipc.h)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_ipc.h	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSShared/dnssd_ipc.h	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,222 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
+ *     contributors may be used to endorse or promote products derived from this
+ *     software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DNSSD_IPC_H
+#define DNSSD_IPC_H
+
+#include "dns_sd.h"
+
+//
+// Common cross platform services
+//
+#if defined(WIN32)
+#   include <winsock2.h>
+#   define dnssd_InvalidSocket  INVALID_SOCKET
+#   define dnssd_SocketValid(s) ((s) != INVALID_SOCKET)
+#   define dnssd_EWOULDBLOCK    WSAEWOULDBLOCK
+#   define dnssd_EINTR          WSAEINTR
+#   define dnssd_ECONNRESET     WSAECONNRESET
+#   define dnssd_sock_t         SOCKET
+#   define dnssd_socklen_t      int
+#   define dnssd_close(sock)    closesocket(sock)
+#   define dnssd_errno          WSAGetLastError()
+#   define dnssd_strerror(X)    win32_strerror(X)
+#   define ssize_t              int
+#   define getpid               _getpid
+#   define unlink               _unlink
+extern char *win32_strerror(int inErrorCode);
+#else
+#   include <sys/types.h>
+#   include <unistd.h>
+#   include <sys/un.h>
+#   include <string.h>
+#   include <stdio.h>
+#   include <stdlib.h>
+#   include <sys/stat.h>
+#   include <sys/socket.h>
+#   include <netinet/in.h>
+#   include <arpa/inet.h>
+#   define dnssd_InvalidSocket  -1
+#   define dnssd_SocketValid(s) ((s) >= 0)
+#   define dnssd_EWOULDBLOCK    EWOULDBLOCK
+#   define dnssd_EINTR          EINTR
+#   define dnssd_ECONNRESET     ECONNRESET
+#   define dnssd_EPIPE          EPIPE
+#   define dnssd_sock_t         int
+#   define dnssd_socklen_t      unsigned int
+#   define dnssd_close(sock)    close(sock)
+#   define dnssd_errno          errno
+#   define dnssd_strerror(X)    strerror(X)
+#endif
+
+#if defined(USE_TCP_LOOPBACK)
+#   define AF_DNSSD             AF_INET
+#   define MDNS_TCP_SERVERADDR  "127.0.0.1"
+#   define MDNS_TCP_SERVERPORT  5354
+#   define LISTENQ              5
+#   define dnssd_sockaddr_t     struct sockaddr_in
+#else
+#   define AF_DNSSD             AF_LOCAL
+#   ifndef MDNS_UDS_SERVERPATH
+#       define MDNS_UDS_SERVERPATH  "/var/run/mDNSResponder"
+#   endif
+#   define MDNS_UDS_SERVERPATH_ENVVAR "DNSSD_UDS_PATH"
+#   define LISTENQ              100
+// longest legal control path length
+#   define MAX_CTLPATH          256
+#   define dnssd_sockaddr_t     struct sockaddr_un
+#endif
+
+// Compatibility workaround
+#ifndef AF_LOCAL
+#define AF_LOCAL    AF_UNIX
+#endif
+
+// General UDS constants
+#define TXT_RECORD_INDEX ((uint32_t)(-1))   // record index for default text record
+
+// IPC data encoding constants and types
+#define VERSION 1
+#define IPC_FLAGS_NOREPLY 1 // set flag if no asynchronous replies are to be sent to client
+
+// Structure packing macro. If we're not using GNUC, it's not fatal. Most compilers naturally pack the on-the-wire
+// structures correctly anyway, so a plain "struct" is usually fine. In the event that structures are not packed
+// correctly, our compile-time assertion checks will catch it and prevent inadvertent generation of non-working code.
+#ifndef packedstruct
+ #if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
+  #define packedstruct struct __attribute__((__packed__))
+  #define packedunion  union  __attribute__((__packed__))
+ #else
+  #define packedstruct struct
+  #define packedunion  union
+ #endif
+#endif
+
+typedef enum
+{
+    request_op_none = 0,    // No request yet received on this connection
+    connection_request = 1, // connected socket via DNSServiceConnect()
+    reg_record_request,     // reg/remove record only valid for connected sockets
+    remove_record_request,
+    enumeration_request,
+    reg_service_request,
+    browse_request,
+    resolve_request,
+    query_request,
+    reconfirm_record_request,
+    add_record_request,
+    update_record_request,
+    setdomain_request,      // Up to here is in Tiger and B4W 1.0.3
+    getproperty_request,    // New in B4W 1.0.4
+    port_mapping_request,   // New in Leopard and B4W 2.0
+    addrinfo_request,
+    send_bpf,               // New in SL
+    getpid_request,
+    release_request,
+    connection_delegate_request,
+
+    cancel_request = 63
+} request_op_t;
+
+typedef enum
+{
+    enumeration_reply_op = 64,
+    reg_service_reply_op,
+    browse_reply_op,
+    resolve_reply_op,
+    query_reply_op,
+    reg_record_reply_op,    // Up to here is in Tiger and B4W 1.0.3
+    getproperty_reply_op,   // New in B4W 1.0.4
+    port_mapping_reply_op,  // New in Leopard and B4W 2.0
+    addrinfo_reply_op
+} reply_op_t;
+
+#if defined(_WIN64)
+#   pragma pack(push,4)
+#endif
+
+// Define context object big enough to hold a 64-bit pointer,
+// to accomodate 64-bit clients communicating with 32-bit daemon.
+// There's no reason for the daemon to ever be a 64-bit process, but its clients might be
+typedef packedunion
+{
+    void *context;
+    uint32_t u32[2];
+} client_context_t;
+
+typedef packedstruct
+{
+    uint32_t version;
+    uint32_t datalen;
+    uint32_t ipc_flags;
+    uint32_t op;        // request_op_t or reply_op_t
+    client_context_t client_context; // context passed from client, returned by server in corresponding reply
+    uint32_t reg_index;            // identifier for a record registered via DNSServiceRegisterRecord() on a
+    // socket connected by DNSServiceCreateConnection().  Must be unique in the scope of the connection, such that and
+    // index/socket pair uniquely identifies a record.  (Used to select records for removal by DNSServiceRemoveRecord())
+} ipc_msg_hdr;
+
+#if defined(_WIN64)
+#   pragma pack(pop)
+#endif
+
+// routines to write to and extract data from message buffers.
+// caller responsible for bounds checking.
+// ptr is the address of the pointer to the start of the field.
+// it is advanced to point to the next field, or the end of the message
+
+void put_uint32(const uint32_t l, char **ptr);
+uint32_t get_uint32(const char **ptr, const char *end);
+
+void put_uint16(uint16_t s, char **ptr);
+uint16_t get_uint16(const char **ptr, const char *end);
+
+#define put_flags put_uint32
+#define get_flags get_uint32
+
+#define put_error_code put_uint32
+#define get_error_code get_uint32
+
+int put_string(const char *str, char **ptr);
+int get_string(const char **ptr, const char *const end, char *buffer, int buflen);
+
+void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr);
+const char *get_rdata(const char **ptr, const char *end, int rdlen);  // return value is rdata pointed to by *ptr -
+// rdata is not copied from buffer.
+
+void ConvertHeaderBytes(ipc_msg_hdr *hdr);
+
+struct CompileTimeAssertionChecks_dnssd_ipc
+{
+    // Check that the compiler generated our on-the-wire packet format structure definitions
+    // properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries.
+    char assert0[(sizeof(client_context_t) ==  8) ? 1 : -1];
+    char assert1[(sizeof(ipc_msg_hdr)      == 28) ? 1 : -1];
+};
+
+#endif // DNSSD_IPC_H

Deleted: vendor/apple/mDNSResponder/561.1.1/mDNSWindows/mDNSWin32.c
===================================================================
--- vendor/apple/mDNSResponder/dist/mDNSWindows/mDNSWin32.c	2014-06-30 23:58:12 UTC (rev 6706)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSWindows/mDNSWin32.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -1,5197 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2013 Apple Computer, 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.
-
-	To Do:
-	
-	- Get unicode name of machine for nice name instead of just the host name.
-	- Use the IPv6 Internet Connection Firewall API to allow IPv6 mDNS without manually changing the firewall.
-	- Get DNS server address(es) from Windows and provide them to the uDNS layer.
-	- Implement TCP support for truncated packets (only stubs now).	
-
-*/
-
-#define _CRT_RAND_S
-
-#include	<stdarg.h>
-#include	<stddef.h>
-#include	<stdio.h>
-#include	<stdlib.h>
-#include	<crtdbg.h>
-#include	<string.h>
-
-#include	"Poll.h"
-#include	"CommonServices.h"
-#include	"DebugServices.h"
-#include	"Firewall.h"
-#include	"RegNames.h"
-#include	"Secret.h"
-#include	<dns_sd.h>
-
-#include	<Iphlpapi.h>
-#include	<mswsock.h>
-#include	<process.h>
-#include	<ntsecapi.h>
-#include	<lm.h>
-#include	<winioctl.h>
-#include	<ntddndis.h>        // This defines the IOCTL constants.
-
-#include	"mDNSEmbeddedAPI.h"
-#include	"GenLinkedList.h"
-#include	"DNSCommon.h"
-#include	"mDNSWin32.h"
-#include    "dnssec.h"
-#include    "nsec.h"
-
-#if 0
-#pragma mark == Constants ==
-#endif
-
-//===========================================================================================================================
-//	Constants
-//===========================================================================================================================
-
-#define	DEBUG_NAME									"[mDNSWin32] "
-
-#define	MDNS_WINDOWS_USE_IPV6_IF_ADDRS				1
-#define	MDNS_WINDOWS_ENABLE_IPV4					1
-#define	MDNS_WINDOWS_ENABLE_IPV6					1
-#define	MDNS_FIX_IPHLPAPI_PREFIX_BUG				1
-#define MDNS_SET_HINFO_STRINGS						0
-
-#define	kMDNSDefaultName							"My Computer"
-
-#define	kWinSockMajorMin							2
-#define	kWinSockMinorMin							2
-
-#define kRegistryMaxKeyLength						255
-#define kRegistryMaxValueName						16383
-
-static GUID											kWSARecvMsgGUID = WSAID_WSARECVMSG;
-
-#define kIPv6IfIndexBase							(10000000L)
-#define SMBPortAsNumber								445
-#define DEVICE_PREFIX								"\\\\.\\"
-
-#if 0
-#pragma mark == Prototypes ==
-#endif
-
-//===========================================================================================================================
-//	Prototypes
-//===========================================================================================================================
-
-mDNSlocal mStatus			SetupNiceName( mDNS * const inMDNS );
-mDNSlocal mStatus			SetupHostName( mDNS * const inMDNS );
-mDNSlocal mStatus			SetupName( mDNS * const inMDNS );
-mDNSlocal mStatus			SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD );
-mDNSlocal mStatus			TearDownInterface( mDNS * const inMDNS, mDNSInterfaceData *inIFD );
-mDNSlocal void CALLBACK		FreeInterface( mDNSInterfaceData *inIFD );
-mDNSlocal mStatus			SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAddr, mDNSIPPort port, SocketRef *outSocketRef  );
-mDNSlocal mStatus			SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP, mDNSIPPort *outPort );
-mDNSlocal OSStatus			GetWindowsVersionString( char *inBuffer, size_t inBufferSize );
-mDNSlocal int				getifaddrs( struct ifaddrs **outAddrs );
-mDNSlocal void				freeifaddrs( struct ifaddrs *inAddrs );
-
-
-
-// Platform Accessors
-
-#ifdef	__cplusplus
-	extern "C" {
-#endif
-
-typedef struct mDNSPlatformInterfaceInfo	mDNSPlatformInterfaceInfo;
-struct	mDNSPlatformInterfaceInfo
-{
-	const char *		name;
-	mDNSAddr			ip;
-};
-
-
-mDNSexport mStatus	mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID );
-mDNSexport mStatus	mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo );
-
-
-// Wakeup Structs
-
-#define kUnicastWakeupNumTries				( 1 )
-#define kUnicastWakeupSleepBetweenTries		( 0 )
-#define kMulticastWakeupNumTries			( 18 )
-#define kMulticastWakeupSleepBetweenTries	( 100 )
-
-typedef struct MulticastWakeupStruct
-{
-	mDNS					*inMDNS;
-	struct sockaddr_in		addr;
-	INT						addrLen;
-	unsigned char			data[ 102 ];
-	INT						dataLen;
-	INT						numTries;
-	INT						msecSleep;
-} MulticastWakeupStruct;
-
-
-// Utilities
-
-#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
-	mDNSlocal int	getifaddrs_ipv6( struct ifaddrs **outAddrs );
-#endif
-
-mDNSlocal int getifaddrs_ipv4( struct ifaddrs **outAddrs );
-
-
-mDNSlocal DWORD				GetPrimaryInterface();
-mDNSlocal mStatus			AddressToIndexAndMask( struct sockaddr * address, uint32_t * index, struct sockaddr * mask );
-mDNSlocal mDNSBool			CanReceiveUnicast( void );
-mDNSlocal mDNSBool			IsPointToPoint( IP_ADAPTER_UNICAST_ADDRESS * addr );
-
-mDNSlocal mStatus			StringToAddress( mDNSAddr * ip, LPSTR string );
-mDNSlocal mStatus			RegQueryString( HKEY key, LPCSTR param, LPSTR * string, DWORD * stringLen, DWORD * enabled );
-mDNSlocal struct ifaddrs*	myGetIfAddrs(int refresh);
-mDNSlocal OSStatus			TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize );
-mDNSlocal OSStatus			WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize );
-mDNSlocal void CALLBACK		TCPSocketNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context );
-mDNSlocal void				TCPCloseSocket( TCPSocket * socket );
-mDNSlocal void CALLBACK		UDPSocketNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context );
-mDNSlocal void				UDPCloseSocket( UDPSocket * sock );
-mDNSlocal mStatus           SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa);
-mDNSlocal void				GetDDNSFQDN( domainname *const fqdn );
-#ifdef UNICODE
-mDNSlocal void				GetDDNSDomains( DNameListElem ** domains, LPCWSTR lpSubKey );
-#else
-mDNSlocal void				GetDDNSDomains( DNameListElem ** domains, LPCSTR lpSubKey );
-#endif
-mDNSlocal void				SetDomainSecrets( mDNS * const inMDNS );
-mDNSlocal void				SetDomainSecret( mDNS * const m, const domainname * inDomain );
-mDNSlocal VOID CALLBACK		CheckFileSharesProc( LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue );
-mDNSlocal void				CheckFileShares( mDNS * const inMDNS );
-mDNSlocal void				SMBCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus result);
-mDNSlocal mDNSu8			IsWOMPEnabledForAdapter( const char * adapterName );
-mDNSlocal void				SendWakeupPacket( mDNS * const inMDNS, LPSOCKADDR addr, INT addrlen, const char * buf, INT buflen, INT numTries, INT msecSleep );
-mDNSlocal void _cdecl		SendMulticastWakeupPacket( void *arg );
-
-#ifdef	__cplusplus
-	}
-#endif
-
-#if 0
-#pragma mark == Globals ==
-#endif
-
-//===========================================================================================================================
-//	Globals
-//===========================================================================================================================
-
-mDNSlocal mDNS_PlatformSupport	gMDNSPlatformSupport;
-mDNSs32							mDNSPlatformOneSecond	= 0;
-mDNSlocal UDPSocket		*		gUDPSockets				= NULL;
-mDNSlocal int					gUDPNumSockets			= 0;
-mDNSlocal BOOL					gEnableIPv6				= TRUE;
-
-#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
-
-	typedef DWORD
-		( WINAPI * GetAdaptersAddressesFunctionPtr )( 
-			ULONG 					inFamily, 
-			DWORD 					inFlags, 
-			PVOID 					inReserved, 
-			PIP_ADAPTER_ADDRESSES 	inAdapter, 
-			PULONG					outBufferSize );
-
-	mDNSlocal HMODULE								gIPHelperLibraryInstance			= NULL;
-	mDNSlocal GetAdaptersAddressesFunctionPtr		gGetAdaptersAddressesFunctionPtr	= NULL;
-
-#endif
-
-
-#ifndef HCRYPTPROV
-   typedef ULONG_PTR HCRYPTPROV;    // WinCrypt.h, line 249
-#endif
-
-
-#ifndef CRYPT_MACHINE_KEYSET
-#	define CRYPT_MACHINE_KEYSET    0x00000020
-#endif
-
-#ifndef CRYPT_NEWKEYSET
-#	define CRYPT_NEWKEYSET         0x00000008
-#endif
-
-#ifndef PROV_RSA_FULL
-#  define PROV_RSA_FULL 1
-#endif
-
-typedef BOOL (__stdcall *fnCryptGenRandom)( HCRYPTPROV, DWORD, BYTE* ); 
-typedef BOOL (__stdcall *fnCryptAcquireContext)( HCRYPTPROV*, LPCTSTR, LPCTSTR, DWORD, DWORD);
-typedef BOOL (__stdcall *fnCryptReleaseContext)(HCRYPTPROV, DWORD);
-
-static fnCryptAcquireContext g_lpCryptAcquireContext 	= NULL;
-static fnCryptReleaseContext g_lpCryptReleaseContext 	= NULL;
-static fnCryptGenRandom		 g_lpCryptGenRandom 		= NULL;
-static HINSTANCE			 g_hAAPI32 					= NULL;
-static HCRYPTPROV			 g_hProvider 				= ( ULONG_PTR ) NULL;
-
-
-typedef DNSServiceErrorType ( DNSSD_API *DNSServiceRegisterFunc )
-    (
-    DNSServiceRef                       *sdRef,
-    DNSServiceFlags                     flags,
-    uint32_t                            interfaceIndex,
-    const char                          *name,         /* may be NULL */
-    const char                          *regtype,
-    const char                          *domain,       /* may be NULL */
-    const char                          *host,         /* may be NULL */
-    uint16_t                            port,
-    uint16_t                            txtLen,
-    const void                          *txtRecord,    /* may be NULL */
-    DNSServiceRegisterReply             callBack,      /* may be NULL */
-    void                                *context       /* may be NULL */
-    );
-
-
-typedef void ( DNSSD_API *DNSServiceRefDeallocateFunc )( DNSServiceRef sdRef );
-
-mDNSlocal HMODULE					gDNSSDLibrary				= NULL;
-mDNSlocal DNSServiceRegisterFunc	gDNSServiceRegister			= NULL;
-mDNSlocal DNSServiceRefDeallocateFunc gDNSServiceRefDeallocate	= NULL;
-mDNSlocal HANDLE					gSMBThread					= NULL;
-mDNSlocal HANDLE					gSMBThreadRegisterEvent		= NULL;
-mDNSlocal HANDLE					gSMBThreadDeregisterEvent	= NULL;
-mDNSlocal HANDLE					gSMBThreadStopEvent			= NULL;
-mDNSlocal HANDLE					gSMBThreadQuitEvent			= NULL;
-
-#define	kSMBStopEvent				( WAIT_OBJECT_0 + 0 )
-#define	kSMBRegisterEvent			( WAIT_OBJECT_0 + 1 )
-#define kSMBDeregisterEvent			( WAIT_OBJECT_0 + 2 )
-
-
-#if 0
-#pragma mark -
-#pragma mark == Platform Support ==
-#endif
-
-//===========================================================================================================================
-//	mDNSPlatformInit
-//===========================================================================================================================
-
-mDNSexport mStatus	mDNSPlatformInit( mDNS * const inMDNS )
-{
-	mStatus		err;
-	OSVERSIONINFO osInfo;
-	BOOL ok;
-	WSADATA		wsaData;
-	int			supported;
-	struct sockaddr_in	sa4;
-	struct sockaddr_in6 sa6;
-	int					sa4len;
-	int					sa6len;
-	DWORD				size;
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "platform init\n" );
-	
-	// Initialize variables. If the PlatformSupport pointer is not null then just assume that a non-Apple client is 
-	// calling mDNS_Init and wants to provide its own storage for the platform-specific data so do not overwrite it.
-	
-	mDNSPlatformMemZero( &gMDNSPlatformSupport, sizeof( gMDNSPlatformSupport ) );
-	if( !inMDNS->p ) inMDNS->p				= &gMDNSPlatformSupport;
-	inMDNS->p->mainThread					= OpenThread( THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId() );
-	require_action( inMDNS->p->mainThread, exit, err = mStatus_UnknownErr );
-	inMDNS->p->checkFileSharesTimer = CreateWaitableTimer( NULL, FALSE, NULL );
-	require_action( inMDNS->p->checkFileSharesTimer, exit, err = mStatus_UnknownErr );
-	inMDNS->p->checkFileSharesTimeout		= 10;		// Retry time for CheckFileShares() in seconds
-	mDNSPlatformOneSecond 					= 1000;		// Use milliseconds as the quantum of time
-	
-	// Get OS version info
-	
-	osInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
-	ok = GetVersionEx( &osInfo );
-	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	inMDNS->p->osMajorVersion = osInfo.dwMajorVersion;
-	inMDNS->p->osMinorVersion = osInfo.dwMinorVersion;
-	
-	// Don't enable IPv6 on anything less recent than Windows Vista
-
-	if ( inMDNS->p->osMajorVersion < 6 )
-	{
-		gEnableIPv6 = FALSE;
-	}
-
-	// Startup WinSock 2.2 or later.
-	
-	err = WSAStartup( MAKEWORD( kWinSockMajorMin, kWinSockMinorMin ), &wsaData );
-	require_noerr( err, exit );
-	
-	supported = ( ( LOBYTE( wsaData.wVersion ) == kWinSockMajorMin ) && ( HIBYTE( wsaData.wVersion ) == kWinSockMinorMin ) );
-	require_action( supported, exit, err = mStatus_UnsupportedErr );
-	
-	inMDNS->CanReceiveUnicastOn5353 = CanReceiveUnicast();
-	
-	// Setup the HINFO HW strings.
-	//<rdar://problem/7245119> device-info should have model=Windows
-
-	strcpy_s( ( char* ) &inMDNS->HIHardware.c[ 1 ], sizeof( inMDNS->HIHardware.c ) - 2, "Windows" );
-	inMDNS->HIHardware.c[ 0 ] = ( mDNSu8 ) mDNSPlatformStrLen( &inMDNS->HIHardware.c[ 1 ] );
-	dlog( kDebugLevelInfo, DEBUG_NAME "HIHardware: %#s\n", inMDNS->HIHardware.c );
-
-	// Setup the HINFO SW strings.
-#if ( MDNS_SET_HINFO_STRINGS )
-	mDNS_snprintf( (char *) &inMDNS->HISoftware.c[ 1 ], sizeof( inMDNS->HISoftware.c ) - 2, 
-		"mDNSResponder (%s %s)", __DATE__, __TIME__ );
-	inMDNS->HISoftware.c[ 0 ] = (mDNSu8) mDNSPlatformStrLen( &inMDNS->HISoftware.c[ 1 ] );
-	dlog( kDebugLevelInfo, DEBUG_NAME "HISoftware: %#s\n", inMDNS->HISoftware.c );
-#endif
-
-	// Set up the IPv4 unicast socket
-
-	inMDNS->p->unicastSock4.fd			= INVALID_SOCKET;
-	inMDNS->p->unicastSock4.recvMsgPtr	= NULL;
-	inMDNS->p->unicastSock4.ifd			= NULL;
-	inMDNS->p->unicastSock4.next		= NULL;
-	inMDNS->p->unicastSock4.m			= inMDNS;
-
-#if ( MDNS_WINDOWS_ENABLE_IPV4 )
-
-	sa4.sin_family		= AF_INET;
-	sa4.sin_addr.s_addr = INADDR_ANY;
-	err = SetupSocket( inMDNS, (const struct sockaddr*) &sa4, zeroIPPort, &inMDNS->p->unicastSock4.fd );
-	check_noerr( err );
-	sa4len = sizeof( sa4 );
-	err = getsockname( inMDNS->p->unicastSock4.fd, (struct sockaddr*) &sa4, &sa4len );
-	require_noerr( err, exit );
-	inMDNS->p->unicastSock4.port.NotAnInteger = sa4.sin_port;
-	inMDNS->UnicastPort4 = inMDNS->p->unicastSock4.port;
-	err = WSAIoctl( inMDNS->p->unicastSock4.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock4.recvMsgPtr, sizeof( inMDNS->p->unicastSock4.recvMsgPtr ), &size, NULL, NULL );
-		
-	if ( err )
-	{
-		inMDNS->p->unicastSock4.recvMsgPtr = NULL;
-	}
-
-	err = mDNSPollRegisterSocket( inMDNS->p->unicastSock4.fd, FD_READ, UDPSocketNotification, &inMDNS->p->unicastSock4 );
-	require_noerr( err, exit ); 
-
-#endif
-
-	// Set up the IPv6 unicast socket
-
-	inMDNS->p->unicastSock6.fd			= INVALID_SOCKET;
-	inMDNS->p->unicastSock6.recvMsgPtr	= NULL;
-	inMDNS->p->unicastSock6.ifd			= NULL;
-	inMDNS->p->unicastSock6.next		= NULL;
-	inMDNS->p->unicastSock6.m			= inMDNS;
-
-#if ( MDNS_WINDOWS_ENABLE_IPV6 )
-
-	if ( gEnableIPv6 )
-	{
-		sa6.sin6_family		= AF_INET6;
-		sa6.sin6_addr		= in6addr_any;
-		sa6.sin6_scope_id	= 0;
-
-		// This call will fail if the machine hasn't installed IPv6.  In that case,
-		// the error will be WSAEAFNOSUPPORT.
-
-		err = SetupSocket( inMDNS, (const struct sockaddr*) &sa6, zeroIPPort, &inMDNS->p->unicastSock6.fd );
-		require_action( !err || ( err == WSAEAFNOSUPPORT ), exit, err = (mStatus) WSAGetLastError() );
-		err = kNoErr;
-		
-		// If we weren't able to create the socket (because IPv6 hasn't been installed) don't do this
-
-		if ( inMDNS->p->unicastSock6.fd != INVALID_SOCKET )
-		{
-			sa6len = sizeof( sa6 );
-			err = getsockname( inMDNS->p->unicastSock6.fd, (struct sockaddr*) &sa6, &sa6len );
-			require_noerr( err, exit );
-			inMDNS->p->unicastSock6.port.NotAnInteger = sa6.sin6_port;
-			inMDNS->UnicastPort6 = inMDNS->p->unicastSock6.port;
-
-			err = WSAIoctl( inMDNS->p->unicastSock6.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock6.recvMsgPtr, sizeof( inMDNS->p->unicastSock6.recvMsgPtr ), &size, NULL, NULL );
-			
-			if ( err != 0 )
-			{
-				inMDNS->p->unicastSock6.recvMsgPtr = NULL;
-			}
-
-			err = mDNSPollRegisterSocket( inMDNS->p->unicastSock6.fd, FD_READ, UDPSocketNotification, &inMDNS->p->unicastSock6 );
-			require_noerr( err, exit );
-		}
-	}
-
-#endif
-
-	// Notify core of domain secret keys
-
-	SetDomainSecrets( inMDNS );
-	
-	// Success!
-
-	mDNSCoreInitComplete( inMDNS, err );
-
-	
-exit:
-
-	if ( err )
-	{
-		mDNSPlatformClose( inMDNS );
-	}
-
-	dlog( kDebugLevelTrace, DEBUG_NAME "platform init done (err=%d %m)\n", err, err );
-	return( err );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformClose
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformClose( mDNS * const inMDNS )
-{
-	mStatus		err;
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "platform close\n" );
-	check( inMDNS );
-
-	if ( gSMBThread != NULL )
-	{
-		dlog( kDebugLevelTrace, DEBUG_NAME "tearing down smb registration thread\n" );
-		SetEvent( gSMBThreadStopEvent );
-		
-		if ( WaitForSingleObject( gSMBThreadQuitEvent, 5 * 1000 ) == WAIT_OBJECT_0 )
-		{
-			if ( gSMBThreadQuitEvent )
-			{
-				CloseHandle( gSMBThreadQuitEvent );
-				gSMBThreadQuitEvent = NULL;
-			}
-
-			if ( gSMBThreadStopEvent )
-			{
-				CloseHandle( gSMBThreadStopEvent );
-				gSMBThreadStopEvent = NULL;
-			}
-
-			if ( gSMBThreadDeregisterEvent )
-			{
-				CloseHandle( gSMBThreadDeregisterEvent );
-				gSMBThreadDeregisterEvent = NULL;
-			}
-
-			if ( gSMBThreadRegisterEvent )
-			{
-				CloseHandle( gSMBThreadRegisterEvent );
-				gSMBThreadRegisterEvent = NULL;
-			}
-
-			if ( gDNSSDLibrary )
-			{
-				FreeLibrary( gDNSSDLibrary );
-				gDNSSDLibrary = NULL;
-			}	
-		}
-		else
-		{
-			LogMsg( "Unable to stop SMBThread" );
-		}
-
-		inMDNS->p->smbFileSharing = mDNSfalse;
-		inMDNS->p->smbPrintSharing = mDNSfalse;
-	}
-
-	// Tear everything down in reverse order to how it was set up.
-	
-	err = TearDownInterfaceList( inMDNS );
-	check_noerr( err );
-	check( !inMDNS->p->inactiveInterfaceList );
-
-#if ( MDNS_WINDOWS_ENABLE_IPV4 )
-
-	UDPCloseSocket( &inMDNS->p->unicastSock4 );
-
-#endif
-	
-#if ( MDNS_WINDOWS_ENABLE_IPV6 )
-
-	if ( gEnableIPv6 )
-	{
-		UDPCloseSocket( &inMDNS->p->unicastSock6 );
-	}
-
-#endif
-
-	// Free the DLL needed for IPv6 support.
-	
-#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
-	if( gIPHelperLibraryInstance )
-	{
-		gGetAdaptersAddressesFunctionPtr = NULL;
-		
-		FreeLibrary( gIPHelperLibraryInstance );
-		gIPHelperLibraryInstance = NULL;
-	}
-#endif
-
-	if ( g_hAAPI32 )
-	{
-		// Release any resources
-
-		if ( g_hProvider && g_lpCryptReleaseContext )
-		{
-			( g_lpCryptReleaseContext )( g_hProvider, 0 );
-		}
-
-		// Free the AdvApi32.dll
-
-		FreeLibrary( g_hAAPI32 );
-
-		// And reset all the data
-
-		g_lpCryptAcquireContext = NULL;
-		g_lpCryptReleaseContext = NULL;
-		g_lpCryptGenRandom 		= NULL;
-		g_hProvider 			= ( ULONG_PTR ) NULL;
-		g_hAAPI32				= NULL;
-	}
-
-	WSACleanup();
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "platform close done\n" );
-}
-
-
-//===========================================================================================================================
-//	mDNSPlatformLock
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformLock( const mDNS * const inMDNS )
-{
-	( void ) inMDNS;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformUnlock
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformUnlock( const mDNS * const inMDNS )
-{
-	( void ) inMDNS;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformStrCopy
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformStrCopy( void *inDst, const void *inSrc )
-{
-	check( inSrc );
-	check( inDst );
-	
-	strcpy( (char *) inDst, (const char*) inSrc );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformStrLen
-//===========================================================================================================================
-
-mDNSexport mDNSu32	mDNSPlatformStrLen( const void *inSrc )
-{
-	check( inSrc );
-	
-	return( (mDNSu32) strlen( (const char *) inSrc ) );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemCopy
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformMemCopy( void *inDst, const void *inSrc, mDNSu32 inSize )
-{
-	check( inSrc );
-	check( inDst );
-	
-	memcpy( inDst, inSrc, inSize );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemSame
-//===========================================================================================================================
-
-mDNSexport mDNSBool	mDNSPlatformMemSame( const void *inDst, const void *inSrc, mDNSu32 inSize )
-{
-	check( inSrc );
-	check( inDst );
-	
-	return( (mDNSBool)( memcmp( inSrc, inDst, inSize ) == 0 ) );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemCmp
-//===========================================================================================================================
-
-mDNSexport int	mDNSPlatformMemCmp( const void *inDst, const void *inSrc, mDNSu32 inSize )
-{
-	check( inSrc );
-	check( inDst );
-	
-	return( memcmp( inSrc, inDst, inSize ) );
-}
-
-mDNSexport void mDNSPlatformQsort(void *base, int nel, int width, int (*compar)(const void *, const void *))
-{
-	(void)base;
-	(void)nel;
-	(void)width;
-	(void)compar;
-}
-
-// DNSSEC stub functions
-mDNSexport void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *q)
-	{
-	(void)m;
-	(void)dv;
-	(void)q;
-	}
-
-mDNSexport mDNSBool AddNSECSForCacheRecord(mDNS *const m, CacheRecord *crlist, CacheRecord *negcr, mDNSu8 rcode)
-	{
-	(void)m;
-	(void)crlist;
-	(void)negcr;
-	(void)rcode;
-	return mDNSfalse;
-	}
-
-mDNSexport void BumpDNSSECStats(mDNS *const m, DNSSECStatsAction action, DNSSECStatsType type, mDNSu32 value)
-    {
-    (void)m;
-    (void)action;
-    (void)type;
-    (void)value;
-    }
-
-// Proxy stub functions
-mDNSexport mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit)
-{
-    (void) q;
-    (void) h;
-    (void) msg;
-    (void) ptr;
-    (void) limit;
-
-    return ptr;
-}
-
-mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[], mDNSu32 OpIf)
-{
-    (void) m;
-    (void) IpIfArr;
-    (void) OpIf;
-}
-
-mDNSexport void DNSProxyTerminate(mDNS *const m)
-{
-    (void) m;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemZero
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformMemZero( void *inDst, mDNSu32 inSize )
-{
-	check( inDst );
-	
-	memset( inDst, 0, inSize );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemAllocate
-//===========================================================================================================================
-
-mDNSexport void *	mDNSPlatformMemAllocate( mDNSu32 inSize )
-{
-	void *		mem;
-	
-	check( inSize > 0 );
-	
-	mem = malloc( inSize );
-	check( mem );
-	
-	return( mem );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformMemFree
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformMemFree( void *inMem )
-{
-	check( inMem );
-	
-	free( inMem );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformRandomNumber
-//===========================================================================================================================
-
-mDNSexport mDNSu32 mDNSPlatformRandomNumber(void)
-{
-	unsigned int	randomNumber;
-	errno_t			err;
-
-	err = rand_s( &randomNumber );
-	require_noerr( err, exit );
-
-exit:
-
-	if ( err )
-	{
-		randomNumber = rand();
-	}
-
-	return ( mDNSu32 ) randomNumber;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformTimeInit
-//===========================================================================================================================
-
-mDNSexport mStatus	mDNSPlatformTimeInit( void )
-{
-	// No special setup is required on Windows -- we just use GetTickCount().
-	return( mStatus_NoError );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformRawTime
-//===========================================================================================================================
-
-mDNSexport mDNSs32	mDNSPlatformRawTime( void )
-{
-	return( (mDNSs32) GetTickCount() );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformUTC
-//===========================================================================================================================
-
-mDNSexport mDNSs32	mDNSPlatformUTC( void )
-{
-	return ( mDNSs32 ) time( NULL );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformInterfaceNameToID
-//===========================================================================================================================
-
-mDNSexport mStatus	mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID )
-{
-	mStatus					err;
-	mDNSInterfaceData *		ifd;
-	
-	check( inMDNS );
-	check( inMDNS->p );
-	check( inName );
-	
-	// Search for an interface with the specified name,
-	
-	for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
-	{
-		if( strcmp( ifd->name, inName ) == 0 )
-		{
-			break;
-		}
-	}
-	require_action_quiet( ifd, exit, err = mStatus_NoSuchNameErr );
-	
-	// Success!
-	
-	if( outID )
-	{
-		*outID = (mDNSInterfaceID) ifd;
-	}
-	err = mStatus_NoError;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformInterfaceIDToInfo
-//===========================================================================================================================
-
-mDNSexport mStatus	mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo )
-{
-	mStatus					err;
-	mDNSInterfaceData *		ifd;
-	
-	check( inMDNS );
-	check( inID );
-	check( outInfo );
-	
-	// Search for an interface with the specified ID,
-	
-	for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
-	{
-		if( ifd == (mDNSInterfaceData *) inID )
-		{
-			break;
-		}
-	}
-	require_action_quiet( ifd, exit, err = mStatus_NoSuchNameErr );
-	
-	// Success!
-	
-	outInfo->name 	= ifd->name;
-	outInfo->ip 	= ifd->interfaceInfo.ip;
-	err 			= mStatus_NoError;
-	
-exit:
-	return( err );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformInterfaceIDfromInterfaceIndex
-//===========================================================================================================================
-
-mDNSexport mDNSInterfaceID	mDNSPlatformInterfaceIDfromInterfaceIndex( mDNS * const inMDNS, mDNSu32 inIndex )
-{
-	mDNSInterfaceID		id;
-	
-	id = mDNSNULL;
-	if( inIndex == kDNSServiceInterfaceIndexLocalOnly )
-	{
-		id = mDNSInterface_LocalOnly;
-	}
-	else if( inIndex != 0 )
-	{
-		mDNSInterfaceData *		ifd;
-		
-		for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
-		{
-			if( ( ifd->scopeID == inIndex ) && ifd->interfaceInfo.InterfaceActive )
-			{
-				id = ifd->interfaceInfo.InterfaceID;
-				break;
-			}
-		}
-		check( ifd );
-	}
-	return( id );
-}
-
-//===========================================================================================================================
-//	mDNSPlatformInterfaceIndexfromInterfaceID
-//===========================================================================================================================
-	
-mDNSexport mDNSu32	mDNSPlatformInterfaceIndexfromInterfaceID( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSBool suppressNetworkChange )
-{
-	mDNSu32		index;
-	
-	(void) suppressNetworkChange;
-
-	index = 0;
-	if( inID == mDNSInterface_LocalOnly )
-	{
-		index = (mDNSu32) kDNSServiceInterfaceIndexLocalOnly;
-	}
-	else if( inID )
-	{
-		mDNSInterfaceData *		ifd;
-		
-		// Search active interfaces.
-		for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
-		{
-			if( (mDNSInterfaceID) ifd == inID )
-			{
-				index = ifd->scopeID;
-				break;
-			}
-		}
-		
-		// Search inactive interfaces too so remove events for inactive interfaces report the old interface index.
-		
-		if( !ifd )
-		{
-			for( ifd = inMDNS->p->inactiveInterfaceList; ifd; ifd = ifd->next )
-			{
-				if( (mDNSInterfaceID) ifd == inID )
-				{
-					index = ifd->scopeID;
-					break;
-				}
-			}
-		}
-		check( ifd );
-	}
-	return( index );
-}
-
-
-//===========================================================================================================================
-//	mDNSPlatformTCPSocket
-//===========================================================================================================================
-
-TCPSocket *
-mDNSPlatformTCPSocket
-	(
-	mDNS			* const m,
-	TCPSocketFlags		flags,
-	mDNSIPPort			*	port, 
-	mDNSBool			useBackgroundTrafficClass
-	)
-{
-	TCPSocket *		sock    = NULL;
-	u_long				on		= 1;  // "on" for setsockopt
-	struct sockaddr_in	saddr;
-	int					len;
-	mStatus				err		= mStatus_NoError;
-
-	DEBUG_UNUSED( m );
-	DEBUG_UNUSED( useBackgroundTrafficClass );
-
-	require_action( flags == 0, exit, err = mStatus_UnsupportedErr );
-
-	// Setup connection data object
-
-	sock = (TCPSocket *) malloc( sizeof( TCPSocket ) );
-	require_action( sock, exit, err = mStatus_NoMemoryErr );
-	mDNSPlatformMemZero( sock, sizeof( TCPSocket ) );
-	sock->fd		= INVALID_SOCKET;
-	sock->flags		= flags;
-	sock->m			= m;
-
-	mDNSPlatformMemZero(&saddr, sizeof(saddr));
-	saddr.sin_family		= AF_INET;
-	saddr.sin_addr.s_addr	= htonl( INADDR_ANY );
-	saddr.sin_port			= port->NotAnInteger;
-	
-	// Create the socket
-
-	sock->fd = socket(AF_INET, SOCK_STREAM, 0);
-	err = translate_errno( sock->fd != INVALID_SOCKET, WSAGetLastError(), mStatus_UnknownErr );
-	require_noerr( err, exit );
-
-	// bind
-
-	err = bind( sock->fd, ( struct sockaddr* ) &saddr, sizeof( saddr )  );
-	err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
-	require_noerr( err, exit );
-
-	// Set it to be non-blocking
-
-	err = ioctlsocket( sock->fd, FIONBIO, &on );
-	err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
-	require_noerr( err, exit );
-
-	// Get port number
-
-	mDNSPlatformMemZero( &saddr, sizeof( saddr ) );
-	len = sizeof( saddr );
-
-	err = getsockname( sock->fd, ( struct sockaddr* ) &saddr, &len );
-	err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
-	require_noerr( err, exit );
-
-	port->NotAnInteger = saddr.sin_port;
-
-exit:
-
-	if ( err && sock )
-	{
-		TCPCloseSocket( sock );
-		free( sock );
-		sock = mDNSNULL;
-	}
-
-	return sock;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformTCPConnect
-//===========================================================================================================================
-
-mStatus
-mDNSPlatformTCPConnect
-	(
-	TCPSocket			*	sock,
-	const mDNSAddr		*	inDstIP, 
-	mDNSOpaque16 			inDstPort, 
-	domainname			*	hostname,
-	mDNSInterfaceID			inInterfaceID,
-	TCPConnectionCallback	inCallback, 
-	void *					inContext
-	)
-{
-	struct sockaddr_in	saddr;
-	mStatus				err		= mStatus_NoError;
-
-	DEBUG_UNUSED( hostname );
-	DEBUG_UNUSED( inInterfaceID );
-
-	if ( inDstIP->type != mDNSAddrType_IPv4 )
-	{
-		LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: operation not supported");
-		return mStatus_UnknownErr;
-	}
-
-	// Setup connection data object
-
-	sock->userCallback	= inCallback;
-	sock->userContext	= inContext;
-
-	mDNSPlatformMemZero(&saddr, sizeof(saddr));
-	saddr.sin_family	= AF_INET;
-	saddr.sin_port		= inDstPort.NotAnInteger;
-	memcpy(&saddr.sin_addr, &inDstIP->ip.v4.NotAnInteger, sizeof(saddr.sin_addr));
-
-	// Try and do connect
-
-	err = connect( sock->fd, ( struct sockaddr* ) &saddr, sizeof( saddr ) );
-	require_action( !err || ( WSAGetLastError() == WSAEWOULDBLOCK ), exit, err = mStatus_ConnFailed );
-	sock->connected	= !err ? TRUE : FALSE;
-
-	err = mDNSPollRegisterSocket( sock->fd, FD_CONNECT | FD_READ | FD_CLOSE, TCPSocketNotification, sock );
-	require_noerr( err, exit );
-
-exit:
-
-	if ( !err )
-	{
-		err = sock->connected ? mStatus_ConnEstablished : mStatus_ConnPending;
-	}
-
-	return err;
-}
-
-
-//===========================================================================================================================
-//	mDNSPlatformTCPAccept
-//===========================================================================================================================
-
-mDNSexport 
-mDNSexport TCPSocket *mDNSPlatformTCPAccept( TCPSocketFlags flags, int fd )
-	{
-	TCPSocket	*	sock = NULL;
-	mStatus							err = mStatus_NoError;
-
-	require_action( !flags, exit, err = mStatus_UnsupportedErr );
-
-	sock = malloc( sizeof( TCPSocket ) );
-	require_action( sock, exit, err = mStatus_NoMemoryErr );
-	
-	mDNSPlatformMemZero( sock, sizeof( *sock ) );
-
-	sock->fd	= fd;
-	sock->flags = flags;
-
-exit:
-
-	if ( err && sock )
-	{
-		free( sock );
-		sock = NULL;
-	}
-
-	return sock;
-	}
-
-
-//===========================================================================================================================
-//	mDNSPlatformTCPCloseConnection
-//===========================================================================================================================
-
-mDNSexport void	mDNSPlatformTCPCloseConnection( TCPSocket *sock )
-{
-	check( sock );
-
-	if ( sock )
-	{
-		dlog( kDebugLevelChatty, DEBUG_NAME "mDNSPlatformTCPCloseConnection 0x%x:%d\n", sock, sock->fd );
-
-		if ( sock->fd != INVALID_SOCKET )
-		{
-			mDNSPollUnregisterSocket( sock->fd );
-			closesocket( sock->fd );
-			sock->fd = INVALID_SOCKET;
-		}
-
-		free( sock );
-	}
-}
-
-
-//===========================================================================================================================
-//	mDNSPlatformReadTCP
-//===========================================================================================================================
-
-mDNSexport long	mDNSPlatformReadTCP( TCPSocket *sock, void *inBuffer, unsigned long inBufferSize, mDNSBool * closed )
-{
-	int			nread;
-    OSStatus    err;
-
-	*closed = mDNSfalse;
-    nread = recv( sock->fd, inBuffer, inBufferSize, 0 );
-    err = translate_errno( ( nread >= 0 ), WSAGetLastError(), mStatus_UnknownErr );
-	
-	if ( nread > 0 )
-	{
-		dlog( kDebugLevelChatty, DEBUG_NAME "mDNSPlatformReadTCP: 0x%x:%d read %d bytes\n", sock, sock->fd, nread );
-	}
-	else if ( !nread )
-	{
-		*closed = mDNStrue;
-	}
-	else if ( err == WSAECONNRESET )
-	{
-		*closed = mDNStrue;
-		nread = 0;
-	}
-	else if ( err == WSAEWOULDBLOCK )
-	{
-		nread = 0;
-	}
-	else
-	{
-		LogMsg( "ERROR: mDNSPlatformReadTCP - recv: %d\n", err );
-		nread = -1;
-	}
-
-    return nread;
-}
-
-
-//===========================================================================================================================
-//	mDNSPlatformWriteTCP
-//===========================================================================================================================
-
-mDNSexport long	mDNSPlatformWriteTCP( TCPSocket *sock, const char *inMsg, unsigned long inMsgSize )
-{
-	int			nsent;
-	OSStatus	err;
-
-	nsent = send( sock->fd, inMsg, inMsgSize, 0 );
-
-	err = translate_errno( ( nsent >= 0 ) || ( WSAGetLastError() == WSAEWOULDBLOCK ), WSAGetLastError(), mStatus_UnknownErr );
-	require_noerr( err, exit );
-
-	if ( nsent < 0)
-	{
-		nsent = 0;
-	}
-		
-exit:
-
-	return nsent;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformTCPGetFD
-//===========================================================================================================================
-
-mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock )
-{
-	return ( int ) sock->fd;
-}
-
-
-
-//===========================================================================================================================
-//	TCPSocketNotification
-//===========================================================================================================================
-
-mDNSlocal void CALLBACK
-TCPSocketNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context )
-{
-	TCPSocket				*tcpSock = ( TCPSocket* ) context;
-	TCPConnectionCallback	callback;
-	int						err;
-
-	DEBUG_UNUSED( sock );
-
-	require_action( tcpSock, exit, err = mStatus_BadParamErr );
-	callback = ( TCPConnectionCallback ) tcpSock->userCallback;
-	require_action( callback, exit, err = mStatus_BadParamErr );
-
-	if ( event && ( event->lNetworkEvents & FD_CONNECT ) )
-	{
-		if ( event->iErrorCode[ FD_CONNECT_BIT ] == 0 )
-		{
-			callback( tcpSock, tcpSock->userContext, mDNStrue, 0 );
-			tcpSock->connected = mDNStrue;
-		}
-		else
-		{
-			callback( tcpSock, tcpSock->userContext, mDNSfalse, event->iErrorCode[ FD_CONNECT_BIT ] );
-		}
-	}
-	else
-	{
-		callback( tcpSock, tcpSock->userContext, mDNSfalse, 0 );
-	}
-
-exit:
-
-	return;
-}
-
-
-
-//===========================================================================================================================
-//	mDNSPlatformUDPSocket
-//===========================================================================================================================
-
-mDNSexport UDPSocket* mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
-{
-	UDPSocket*	sock	= NULL;
-	mDNSIPPort	port	= requestedport;
-	mStatus		err		= mStatus_NoError;
-	unsigned	i;
-
-	// Setup connection data object
-
-	sock = ( UDPSocket* ) malloc(sizeof( UDPSocket ) );
-	require_action( sock, exit, err = mStatus_NoMemoryErr );
-	memset( sock, 0, sizeof( UDPSocket ) );
-
-	// Create the socket
-
-	sock->fd			= INVALID_SOCKET;
-	sock->recvMsgPtr	= m->p->unicastSock4.recvMsgPtr;
-	sock->addr			= m->p->unicastSock4.addr;
-	sock->ifd			= NULL;
-	sock->m				= m;
-
-	// Try at most 10000 times to get a unique random port
-
-	for (i=0; i<10000; i++)
-	{
-		struct sockaddr_in saddr;
-
-		saddr.sin_family		= AF_INET;
-		saddr.sin_addr.s_addr	= 0;
-
-		// The kernel doesn't do cryptographically strong random port
-		// allocation, so we do it ourselves here
-
-        if (mDNSIPPortIsZero(requestedport))
-		{
-			port = mDNSOpaque16fromIntVal( ( mDNSu16 ) ( 0xC000 + mDNSRandom(0x3FFF) ) );
-		}
-
-		saddr.sin_port = port.NotAnInteger;
-
-        err = SetupSocket(m, ( struct sockaddr* ) &saddr, port, &sock->fd );
-        if (!err) break;
-	}
-
-	require_noerr( err, exit );
-
-	// Set the port
-
-	sock->port = port;
-
-	// Arm the completion routine
-
-	err = mDNSPollRegisterSocket( sock->fd, FD_READ, UDPSocketNotification, sock );
-	require_noerr( err, exit ); 
-
-	// Bookkeeping
-
-	sock->next		= gUDPSockets;
-	gUDPSockets		= sock;
-	gUDPNumSockets++;
-
-exit:
-
-	if ( err && sock )
-	{
-		UDPCloseSocket( sock );
-		free( sock );
-		sock = NULL;
-	}
-
-	return sock;
-}
-	
-//===========================================================================================================================
-//	mDNSPlatformUDPClose
-//===========================================================================================================================
-	
-mDNSexport void mDNSPlatformUDPClose( UDPSocket *sock )
-{
-	UDPSocket	*	current  = gUDPSockets;
-	UDPSocket	*	last = NULL;
-
-	while ( current )
-	{
-		if ( current == sock )
-		{
-			if ( last == NULL )
-			{
-				gUDPSockets = sock->next;
-			}
-			else
-			{
-				last->next = sock->next;
-			}
-
-			UDPCloseSocket( sock );
-			free( sock );
-
-			gUDPNumSockets--;
-
-			break;
-		}
-
-		last	= current;
-		current	= current->next;
-	}
-}
-
-
-//===========================================================================================================================
-//	mDNSPlatformSendUDP
-//===========================================================================================================================
-
-mDNSexport mStatus
-	mDNSPlatformSendUDP( 
-		const mDNS * const			inMDNS, 
-		const void * const	        inMsg, 
-		const mDNSu8 * const		inMsgEnd, 
-		mDNSInterfaceID 			inInterfaceID, 
-		UDPSocket *					inSrcSocket,
-		const mDNSAddr *			inDstIP, 
-		mDNSIPPort 					inDstPort,
-		mDNSBool 					useBackgroundTrafficClass )
-{
-	SOCKET						sendingsocket = INVALID_SOCKET;
-	mStatus						err = mStatus_NoError;
-	mDNSInterfaceData *			ifd = (mDNSInterfaceData*) inInterfaceID;
-	struct sockaddr_storage		addr;
-	int							n;
-	
-	DEBUG_USE_ONLY( inMDNS );
-	DEBUG_USE_ONLY( useBackgroundTrafficClass );
-	
-	n = (int)( inMsgEnd - ( (const mDNSu8 * const) inMsg ) );
-	check( inMDNS );
-	check( inMsg );
-	check( inMsgEnd );
-	check( inDstIP );
-	
-	dlog( kDebugLevelChatty, DEBUG_NAME "platform send %d bytes to %#a:%u\n", n, inDstIP, ntohs( inDstPort.NotAnInteger ) );
-	
-	if( inDstIP->type == mDNSAddrType_IPv4 )
-	{
-		struct sockaddr_in *		sa4;
-		
-		sa4						= (struct sockaddr_in *) &addr;
-		sa4->sin_family			= AF_INET;
-		sa4->sin_port			= inDstPort.NotAnInteger;
-		sa4->sin_addr.s_addr	= inDstIP->ip.v4.NotAnInteger;
-		sendingsocket           = ifd ? ifd->sock.fd : inMDNS->p->unicastSock4.fd;
-
-		if (inSrcSocket) { sendingsocket = inSrcSocket->fd; debugf("mDNSPlatformSendUDP using port %d, static port %d, sock %d", mDNSVal16(inSrcSocket->port), inMDNS->p->unicastSock4.fd, sendingsocket); }
-	}
-	else if( inDstIP->type == mDNSAddrType_IPv6 )
-	{
-		struct sockaddr_in6 *		sa6;
-		
-		sa6					= (struct sockaddr_in6 *) &addr;
-		sa6->sin6_family	= AF_INET6;
-		sa6->sin6_port		= inDstPort.NotAnInteger;
-		sa6->sin6_flowinfo	= 0;
-		sa6->sin6_addr		= *( (struct in6_addr *) &inDstIP->ip.v6 );
-		sa6->sin6_scope_id	= 0;	// Windows requires the scope ID to be zero. IPV6_MULTICAST_IF specifies interface.
-		sendingsocket		= ifd ? ifd->sock.fd : inMDNS->p->unicastSock6.fd;
-	}
-	else
-	{
-		dlog( kDebugLevelError, DEBUG_NAME "%s: dst is not an IPv4 or IPv6 address (type=%d)\n", __ROUTINE__, inDstIP->type );
-		err = mStatus_BadParamErr;
-		goto exit;
-	}
-	
-	if (IsValidSocket(sendingsocket))
-	{
-		n = sendto( sendingsocket, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) );
-		err = translate_errno( n > 0, errno_compat(), kWriteErr );
-
-		if ( err )
-		{
-			// Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
-
-			if ( !mDNSAddressIsAllDNSLinkGroup( inDstIP ) && ( WSAGetLastError() == WSAEHOSTDOWN || WSAGetLastError() == WSAENETDOWN || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAENETUNREACH ) )
-			{
-				err = mStatus_TransientErr;
-			}
-			else
-			{
-				require_noerr( err, exit );
-			}
-		}
-	}
-	
-exit:
-	return( err );
-}
-
-
-mDNSexport mDNSBool mDNSPlatformPeekUDP(mDNS *const m, UDPSocket *src)
-{
-	DEBUG_UNUSED( m );
-	DEBUG_UNUSED( src );
-	return mDNSfalse;
-}
-
-mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
-	{
-	DEBUG_UNUSED( m );
-	DEBUG_UNUSED( InterfaceID );
-	}
-
-
-mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason)
-	{
-	DEBUG_UNUSED( m );
-	DEBUG_UNUSED( allowSleep );
-	DEBUG_UNUSED( reason );
-	}
-
-//===========================================================================================================================
-//	mDNSPlatformSendRawPacket
-//===========================================================================================================================
-
-mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *ethaddr, char *ipaddr, int iteration)
-{
-	unsigned char			mac[ 6 ];
-	unsigned char			buf[ 102 ];
-	char					hex[ 3 ] = { 0 };
-	unsigned char			*bufPtr = buf;
-	struct sockaddr_storage	saddr;
-	INT						len = sizeof( saddr );
-	mDNSBool				unicast = mDNSfalse;
-	MulticastWakeupStruct	*info;
-	int						i;
-	mStatus					err;
-
-	(void) InterfaceID;
-
-	require_action( ethaddr, exit, err = mStatus_BadParamErr );
-
-	for ( i = 0; i < 6; i++ )
-	{
-		memcpy( hex, ethaddr + ( i * 3 ), 2 );
-		mac[ i ] = ( unsigned char ) strtoul( hex, NULL, 16 );
-	}
-
-	memset( buf, 0, sizeof( buf ) );
-
-	for ( i = 0; i < 6; i++ )
-	{
-		*bufPtr++ = 0xff;
-	}
-	
-	for ( i = 0; i < 16; i++ )
-	{
-		memcpy( bufPtr, mac, sizeof( mac ) );
-		bufPtr += sizeof( mac );
-	}
-
-	if ( ipaddr )
-	{
-		if ( WSAStringToAddressA( ipaddr, AF_INET, NULL, ( LPSOCKADDR ) &saddr, &len ) == 0 )
-		{
-			struct sockaddr_in * saddr4 = ( struct sockaddr_in* ) &saddr;
-			saddr4->sin_port = htons( 9 );
-			len = sizeof( *saddr4 );
-
-			if ( saddr4->sin_addr.s_addr != htonl( INADDR_ANY ) )
-			{
-				unicast = mDNStrue;
-			}
-		}
-		else if ( WSAStringToAddressA( ipaddr, AF_INET6, NULL, ( LPSOCKADDR ) &saddr, &len ) == 0 )
-		{
-			mDNSInterfaceData *ifd = ( mDNSInterfaceData* ) InterfaceID;
-			struct sockaddr_in6 * saddr6 = ( struct sockaddr_in6* ) &saddr;
-			saddr6->sin6_port = htons( 9 );
-
-			if ( ifd != NULL )
-			{
-				saddr6->sin6_scope_id = ifd->scopeID;
-			}
-
-			len = sizeof( *saddr6 );
-
-			if ( memcmp( &saddr6->sin6_addr, &in6addr_any, sizeof( IN6_ADDR ) ) != 0 )
-			{
-				unicast = mDNStrue;
-			}
-		}
-	}
-
-	if ( ( iteration < 2 ) && ( unicast ) )
-	{
-		SendWakeupPacket( m, ( LPSOCKADDR ) &saddr, len, ( const char* ) buf, sizeof( buf ), kUnicastWakeupNumTries, kUnicastWakeupSleepBetweenTries );
-	}		
-
-	info = ( MulticastWakeupStruct* ) malloc( sizeof( MulticastWakeupStruct ) );
-	require_action( info, exit, err = mStatus_NoMemoryErr );
-	info->inMDNS = m;
-	memset( &info->addr, 0, sizeof( info->addr ) );
-	info->addr.sin_family = AF_INET;
-	info->addr.sin_addr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
-	info->addr.sin_port = htons( 9 );
-	info->addrLen = sizeof( info->addr );
-	memcpy( info->data, buf, sizeof( buf ) );
-	info->dataLen = sizeof( buf );
-	info->numTries  = kMulticastWakeupNumTries;
-	info->msecSleep = kMulticastWakeupSleepBetweenTries;
-
-	_beginthread( SendMulticastWakeupPacket, 0, ( void* ) info );
-
-exit:
-
-	return;
-}
-
-
-mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf)
-{
-	DEBUG_UNUSED( rr );
-	DEBUG_UNUSED( intf );
-
-	return mDNStrue;
-}
- 
-mDNSexport mDNSBool mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf)
-{
-	DEBUG_UNUSED( q );
-	DEBUG_UNUSED( intf );
-
-	return mDNStrue;
-}
- 
-mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
-	{
-	DEBUG_UNUSED( msg );
-	DEBUG_UNUSED( end );
-	DEBUG_UNUSED( InterfaceID );
-	}
-
-// Used for debugging purposes. For now, just set the buffer to zero
-mDNSexport void mDNSPlatformFormatTime(unsigned long te, mDNSu8 *buf, int bufsize)
-	{
-	DEBUG_UNUSED( te );
-	if (bufsize) buf[0] = 0;
-	}
-
-
-mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
-	{
-	DEBUG_UNUSED( m );
-	DEBUG_UNUSED( tpa );
-	DEBUG_UNUSED( tha );
-	DEBUG_UNUSED( InterfaceID );
-	}
-
-
-mDNSexport void mDNSPlatformReceiveRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
-	{
-	DEBUG_UNUSED( msg );
-	DEBUG_UNUSED( end );
-	DEBUG_UNUSED( InterfaceID );
-	}
-
-mDNSexport void mDNSPlatformSetLocalARP( const mDNSv4Addr * const tpa, const mDNSEthAddr * const tha, mDNSInterfaceID InterfaceID )
-	{
-	DEBUG_UNUSED( tpa );
-	DEBUG_UNUSED( tha );
-	DEBUG_UNUSED( InterfaceID );
-	}
-
-mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
-	{
-	dlog( kDebugLevelInfo, "%s\n", msg );
-	}
-
-mDNSexport void mDNSPlatformWriteLogMsg( const char * ident, const char * msg, mDNSLogLevel_t loglevel )
-	{
-	extern mDNS mDNSStorage;
-	int type;
-	
-	DEBUG_UNUSED( ident );
-
-	type = EVENTLOG_ERROR_TYPE;
-
-	switch (loglevel) 
-	{
-		case MDNS_LOG_MSG:       type = EVENTLOG_ERROR_TYPE;		break;
-		case MDNS_LOG_OPERATION: type = EVENTLOG_WARNING_TYPE;		break;
-		case MDNS_LOG_SPS:       type = EVENTLOG_INFORMATION_TYPE;  break;
-		case MDNS_LOG_INFO:      type = EVENTLOG_INFORMATION_TYPE;	break;
-		case MDNS_LOG_DEBUG:     type = EVENTLOG_INFORMATION_TYPE;	break;
-		default:
-			fprintf(stderr, "Unknown loglevel %d, assuming LOG_ERR\n", loglevel);
-			fflush(stderr);
-			}
-
-	mDNSStorage.p->reportStatusFunc( type, msg );
-	dlog( kDebugLevelInfo, "%s\n", msg );
-	}
-
-mDNSexport void mDNSPlatformSourceAddrForDest( mDNSAddr * const src, const mDNSAddr * const dst )
-	{
-	DEBUG_UNUSED( src );
-	DEBUG_UNUSED( dst );
-	}
-
-//===========================================================================================================================
-//	mDNSPlatformTLSSetupCerts
-//===========================================================================================================================
-
-mDNSexport mStatus
-mDNSPlatformTLSSetupCerts(void)
-{
-	return mStatus_UnsupportedErr;
-}
-
-//===========================================================================================================================
-//	mDNSPlatformTLSTearDownCerts
-//===========================================================================================================================
-
-mDNSexport void
-mDNSPlatformTLSTearDownCerts(void)
-{
-}
-
-//===========================================================================================================================
-//	mDNSPlatformSetDNSConfig
-//===========================================================================================================================
-
-mDNSlocal void SetDNSServers( mDNS *const m );
-mDNSlocal void SetSearchDomainList( void );
-
-mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **regDomains, DNameListElem **browseDomains, mDNSBool ackConfig)
-{
-	(void) ackConfig;
-
-	if (setservers) SetDNSServers(m);
-	if (setsearch) SetSearchDomainList();
-	
-	if ( fqdn )
-	{
-		GetDDNSFQDN( fqdn );
-	}
-
-	if ( browseDomains )
-	{
-		GetDDNSDomains( browseDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSBrowseDomains );
-	}
-
-	if ( regDomains )
-	{
-		GetDDNSDomains( regDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains );
-	}
-    return mDNStrue;
-}
-
-
-//===========================================================================================================================
-//	mDNSPlatformDynDNSHostNameStatusChanged
-//===========================================================================================================================
-
-mDNSexport void
-mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
-{
-	char		uname[MAX_ESCAPED_DOMAIN_NAME];
-	BYTE		bStatus;
-	LPCTSTR		name;
-	HKEY		key = NULL;
-	mStatus		err;
-	char	*	p;
-	
-	ConvertDomainNameToCString(dname, uname);
-	
-	p = uname;
-
-	while (*p)
-	{
-		*p = (char) tolower(*p);
-		if (!(*(p+1)) && *p == '.') *p = 0; // if last character, strip trailing dot
-		p++;
-	}
-
-	check( strlen( p ) <= MAX_ESCAPED_DOMAIN_NAME );
-	name = kServiceParametersNode TEXT("\\DynDNS\\State\\HostNames");
-	err = RegCreateKey( HKEY_LOCAL_MACHINE, name, &key );
-	require_noerr( err, exit );
-
-	bStatus = ( status ) ? 0 : 1;
-	err = RegSetValueEx( key, kServiceDynDNSStatus, 0, REG_DWORD, (const LPBYTE) &bStatus, sizeof(DWORD) );
-	require_noerr( err, exit );
-
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-
-	return;
-}
-
-
-//===========================================================================================================================
-//	SetDomainSecrets
-//===========================================================================================================================
-
-// This routine needs to be called whenever the system secrets database changes.
-// We call it from DynDNSConfigDidChange and mDNSPlatformInit
-
-void
-SetDomainSecrets( mDNS * const m )
-{
-	DomainAuthInfo *ptr;
-	domainname		fqdn;
-	DNameListElem * regDomains = NULL;
-
-	// Rather than immediately deleting all keys now, we mark them for deletion in ten seconds.
-	// In the case where the user simultaneously removes their DDNS host name and the key
-	// for it, this gives mDNSResponder ten seconds to gracefully delete the name from the
-	// server before it loses access to the necessary key. Otherwise, we'd leave orphaned
-	// address records behind that we no longer have permission to delete.
-	
-	for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
-		ptr->deltime = NonZeroTime(m->timenow + mDNSPlatformOneSecond*10);
-
-	GetDDNSFQDN( &fqdn );
-
-	if ( fqdn.c[ 0 ] )
-	{
-		SetDomainSecret( m, &fqdn );
-	}
-
-	GetDDNSDomains( &regDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains );
-
-	while ( regDomains )
-	{
-		DNameListElem * current = regDomains;
-		SetDomainSecret( m, &current->name );
-		regDomains = regDomains->next;
-		free( current );
-	}
-}
-
-
-//===========================================================================================================================
-//	SetSearchDomainList
-//===========================================================================================================================
-
-mDNSlocal void SetDomainFromDHCP( void );
-mDNSlocal void SetReverseMapSearchDomainList( void );
-
-mDNSlocal void
-SetSearchDomainList( void )
-{
-	char			*	searchList	= NULL;
-	DWORD				searchListLen;
-	//DNameListElem	*	head = NULL;
-	//DNameListElem	*	current = NULL;
-	char			*	tok;
-	HKEY				key;
-	mStatus				err;
-
-	err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &key );
-	require_noerr( err, exit );
-
-	err = RegQueryString( key, "SearchList", &searchList, &searchListLen, NULL );
-	require_noerr( err, exit );
-
-	// Windows separates the search domains with ','
-
-	tok = strtok( searchList, "," );
-	while ( tok )
-	{
-		if ( ( strcmp( tok, "" ) != 0 ) && ( strcmp( tok, "." ) != 0 ) )
-			mDNS_AddSearchDomain_CString(tok, mDNSNULL);
-		tok = strtok( NULL, "," );
-	}
-
-exit:
-
-	if ( searchList ) 
-	{
-		free( searchList );
-	}
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-
-	SetDomainFromDHCP();
-	SetReverseMapSearchDomainList();
-}
-
-
-//===========================================================================================================================
-//	SetReverseMapSearchDomainList
-//===========================================================================================================================
-
-mDNSlocal void
-SetReverseMapSearchDomainList( void )
-{
-	struct ifaddrs	*	ifa;
-
-	ifa = myGetIfAddrs( 1 );
-	while (ifa)
-	{
-		mDNSAddr addr;
-		
-		if (ifa->ifa_addr->sa_family == AF_INET && !SetupAddr(&addr, ifa->ifa_addr) && !(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_netmask)
-		{
-			mDNSAddr	netmask;
-			char		buffer[256];
-			
-			if (!SetupAddr(&netmask, ifa->ifa_netmask))
-			{
-				sprintf(buffer, "%d.%d.%d.%d.in-addr.arpa.", addr.ip.v4.b[3] & netmask.ip.v4.b[3],
-                                                             addr.ip.v4.b[2] & netmask.ip.v4.b[2],
-                                                             addr.ip.v4.b[1] & netmask.ip.v4.b[1],
-                                                             addr.ip.v4.b[0] & netmask.ip.v4.b[0]);
-				mDNS_AddSearchDomain_CString(buffer, mDNSNULL);
-			}
-		}
-	
-		ifa = ifa->ifa_next;
-	}
-
-	return;
-}
-
-
-//===========================================================================================================================
-//	SetDNSServers
-//===========================================================================================================================
-
-mDNSlocal void
-SetDNSServers( mDNS *const m )
-{
-	PIP_PER_ADAPTER_INFO	pAdapterInfo	=	NULL;
-	FIXED_INFO			*	fixedInfo	= NULL;
-	ULONG					bufLen		= 0;	
-	IP_ADDR_STRING		*	dnsServerList;
-	IP_ADDR_STRING		*	ipAddr;
-	DWORD					index;
-	int						i			= 0;
-	mStatus					err			= kUnknownErr;
-
-	// Get the primary interface.
-
-	index = GetPrimaryInterface();
-
-	// This should have the interface index of the primary index.  Fall back in cases where
-	// it can't be determined.
-
-	if ( index )
-	{
-		bufLen = 0;
-
-		for ( i = 0; i < 100; i++ )
-		{
-			err = GetPerAdapterInfo( index, pAdapterInfo, &bufLen );
-
-			if ( err != ERROR_BUFFER_OVERFLOW )
-			{
-				break;
-			}
-
-			pAdapterInfo = (PIP_PER_ADAPTER_INFO) realloc( pAdapterInfo, bufLen );
-			require_action( pAdapterInfo, exit, err = mStatus_NoMemoryErr );
-		}
-
-		require_noerr( err, exit );
-
-		dnsServerList = &pAdapterInfo->DnsServerList;
-	}
-	else
-	{
-		bufLen = sizeof( FIXED_INFO );
-
-		for ( i = 0; i < 100; i++ )
-		{
-			if ( fixedInfo )
-			{
-				GlobalFree( fixedInfo );
-				fixedInfo = NULL;
-			}
-
-			fixedInfo = (FIXED_INFO*) GlobalAlloc( GPTR, bufLen );
-			require_action( fixedInfo, exit, err = mStatus_NoMemoryErr );
-	   
-			err = GetNetworkParams( fixedInfo, &bufLen );
-
-			if ( err != ERROR_BUFFER_OVERFLOW )
-			{
-				break;
-			}
-		}
-
-		require_noerr( err, exit );
-
-		dnsServerList = &fixedInfo->DnsServerList;
-	}
-
-	for ( ipAddr = dnsServerList; ipAddr; ipAddr = ipAddr->Next )
-	{
-		mDNSAddr addr;
-		err = StringToAddress( &addr, ipAddr->IpAddress.String );
-		if ( !err ) mDNS_AddDNSServer(m, mDNSNULL, mDNSInterface_Any, 0, &addr, UnicastDNSPort, kScopeNone, DEFAULT_UDNS_TIMEOUT, mDNSfalse, 0, mDNStrue, mDNStrue, mDNSfalse);
-	}
-
-exit:
-
-	if ( pAdapterInfo )
-	{
-		free( pAdapterInfo );
-	}
-
-	if ( fixedInfo )
-	{
-		GlobalFree( fixedInfo );
-	}
-}
-
-
-//===========================================================================================================================
-//	SetDomainFromDHCP
-//===========================================================================================================================
-
-mDNSlocal void
-SetDomainFromDHCP( void )
-{
-	int					i			= 0;
-	IP_ADAPTER_INFO *	pAdapterInfo;
-	IP_ADAPTER_INFO *	pAdapter;
-	DWORD				bufLen;
-	DWORD				index;
-	HKEY				key = NULL;
-	LPSTR				domain = NULL;
-	DWORD				dwSize;
-	mStatus				err = mStatus_NoError;
-
-	pAdapterInfo	= NULL;
-	
-	for ( i = 0; i < 100; i++ )
-	{
-		err = GetAdaptersInfo( pAdapterInfo, &bufLen);
-
-		if ( err != ERROR_BUFFER_OVERFLOW )
-		{
-			break;
-		}
-
-		pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
-		require_action( pAdapterInfo, exit, err = kNoMemoryErr );
-	}
-
-	require_noerr( err, exit );
-
-	index = GetPrimaryInterface();
-
-	for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
-	{
-		if ( pAdapter->IpAddressList.IpAddress.String &&
-		     pAdapter->IpAddressList.IpAddress.String[0] &&
-		     pAdapter->GatewayList.IpAddress.String &&
-		     pAdapter->GatewayList.IpAddress.String[0] &&
-		     ( !index || ( pAdapter->Index == index ) ) )
-		{
-			// Found one that will work
-
-			char keyName[1024];
-
-			_snprintf( keyName, 1024, "%s%s", "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\", pAdapter->AdapterName );
-
-			err = RegCreateKeyA( HKEY_LOCAL_MACHINE, keyName, &key );
-			require_noerr( err, exit );
-
-			err = RegQueryString( key, "Domain", &domain, &dwSize, NULL );
-			check_noerr( err );
-
-			if ( !domain || !domain[0] )
-			{
-				if ( domain )
-				{
-					free( domain );
-					domain = NULL;
-				}
-
-				err = RegQueryString( key, "DhcpDomain", &domain, &dwSize, NULL );
-				check_noerr( err );
-			}
-
-			if ( domain && domain[0] ) mDNS_AddSearchDomain_CString(domain, mDNSNULL);
-
-			break;
-		}
-	}
-
-exit:
-
-	if ( pAdapterInfo )
-	{
-		free( pAdapterInfo );
-	}
-
-	if ( domain )
-	{
-		free( domain );
-	}
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-}
-
-
-//===========================================================================================================================
-//	mDNSPlatformGetPrimaryInterface
-//===========================================================================================================================
-
-mDNSexport mStatus
-mDNSPlatformGetPrimaryInterface( mDNS * const m, mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router )
-{
-	IP_ADAPTER_INFO *	pAdapterInfo;
-	IP_ADAPTER_INFO *	pAdapter;
-	DWORD				bufLen;
-	int					i;
-	BOOL				found;
-	DWORD				index;
-	mStatus				err = mStatus_NoError;
-
-	DEBUG_UNUSED( m );
-
-	*v6 = zeroAddr;
-
-	pAdapterInfo	= NULL;
-	bufLen			= 0;
-	found			= FALSE;
-
-	for ( i = 0; i < 100; i++ )
-	{
-		err = GetAdaptersInfo( pAdapterInfo, &bufLen);
-
-		if ( err != ERROR_BUFFER_OVERFLOW )
-		{
-			break;
-		}
-
-		pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
-		require_action( pAdapterInfo, exit, err = kNoMemoryErr );
-	}
-
-	require_noerr( err, exit );
-
-	index = GetPrimaryInterface();
-
-	for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
-	{
-		if ( pAdapter->IpAddressList.IpAddress.String &&
-		     pAdapter->IpAddressList.IpAddress.String[0] &&
-		     pAdapter->GatewayList.IpAddress.String &&
-		     pAdapter->GatewayList.IpAddress.String[0] &&
-		     ( StringToAddress( v4, pAdapter->IpAddressList.IpAddress.String ) == mStatus_NoError ) &&
-		     ( StringToAddress( router, pAdapter->GatewayList.IpAddress.String ) == mStatus_NoError ) &&
-		     ( !index || ( pAdapter->Index == index ) ) )
-		{
-			// Found one that will work
-
-			if ( pAdapter->AddressLength == sizeof( m->PrimaryMAC ) )
-			{
-				memcpy( &m->PrimaryMAC, pAdapter->Address, pAdapter->AddressLength );
-			}
-
-			found = TRUE;
-			break;
-		}
-	}
-
-exit:
-
-	if ( pAdapterInfo )
-	{
-		free( pAdapterInfo );
-	}
-
-	return err;
-}
-
-mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win)
-	{
-	(void) sadd; 	// Unused
-	(void) dadd; 	// Unused
-	(void) lport; 	// Unused
-	(void) rport; 	// Unused
-	(void) seq; 	// Unused
-	(void) ack; 	// Unused
-	(void) win;		// Unused
-	}
-
-mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNSAddr *raddr, char *eth)
-	{
-	(void) raddr; // Unused
-	(void) eth;   // Unused
-	}
-
-mDNSexport  mStatus    mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname)
-	{
-	(void) spsaddr; // Unused
-	(void) ifname;  // Unused
-	}
-
-mDNSexport  mStatus    mDNSPlatformClearSPSMACAddr(void)
-	{
-	}
-
-mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti)
-	{
-	(void) m;       // Unused
-	(void) laddr; 	// Unused
-	(void) raddr; 	// Unused
-	(void) lport; 	// Unused
-	(void) rport; 	// Unused
-	(void) mti; 	// Unused
-	}
-
-mDNSexport mDNSBool mDNSPlatformAllowPID(mDNS *const m, DNSQuestion *q)
-    {
-    (void) m;
-    (void) q;
-    return mDNStrue;
-    }
-
-mDNSexport mDNSs32 mDNSPlatformGetServiceID(mDNS *const m, DNSQuestion *q)
-    {
-    (void) m;
-    (void) q;
-    return 0;
-    }
-
-mDNSexport void mDNSPlatformSetDelegatePID(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q)
-    {
-    (void) src;
-    (void) dst;
-    (void) q;
-    }
-
-mDNSexport mDNSs32 mDNSPlatformGetPID()
-    {
-    return 0;
-    }
-
-mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
-{
-	DEBUG_UNUSED( sock );
- 
-	return (mDNSu16)-1;
-}
-
-mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
-{
-	DEBUG_UNUSED( InterfaceID );
-    
-	return mDNSfalse;
-}
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	debugf_
-//===========================================================================================================================
-#if( MDNS_DEBUGMSGS )
-mDNSexport void	debugf_( const char *inFormat, ... )
-{
-	char		buffer[ 512 ];
-    va_list		args;
-    mDNSu32		length;
-	
-	va_start( args, inFormat );
-	length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
-	va_end( args );
-	
-	dlog( kDebugLevelInfo, "%s\n", buffer );
-}
-#endif
-
-//===========================================================================================================================
-//	verbosedebugf_
-//===========================================================================================================================
-
-#if( MDNS_DEBUGMSGS > 1 )
-mDNSexport void	verbosedebugf_( const char *inFormat, ... )
-{
-	char		buffer[ 512 ];
-    va_list		args;
-    mDNSu32		length;
-	
-	va_start( args, inFormat );
-	length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
-	va_end( args );
-	
-	dlog( kDebugLevelVerbose, "%s\n", buffer );
-}
-#endif
-
-
-#if 0
-#pragma mark -
-#pragma mark == Platform Internals  ==
-#endif
-
-
-//===========================================================================================================================
-//	SetupNiceName
-//===========================================================================================================================
-
-mStatus	SetupNiceName( mDNS * const inMDNS )
-{
-	HKEY		descKey = NULL;
-	char		utf8[ 256 ];
-	LPCTSTR		s;
-	LPWSTR		joinName;
-	NETSETUP_JOIN_STATUS joinStatus;
-	mStatus		err = 0;
-	DWORD		namelen;
-	BOOL		ok;
-	
-	check( inMDNS );
-	
-	// Set up the nice name.
-	utf8[0] = '\0';
-
-	// First try and open the registry key that contains the computer description value
-	s = TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters");
-	err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s, 0, KEY_READ, &descKey);
-	check_translated_errno( err == 0, errno_compat(), kNameErr );
-
-	if ( !err )
-	{
-		TCHAR	desc[256];
-		DWORD	descSize = sizeof( desc );
-
-		// look for the computer description
-		err = RegQueryValueEx( descKey, TEXT("srvcomment"), 0, NULL, (LPBYTE) &desc, &descSize);
-		
-		if ( !err )
-		{
-			err = TCHARtoUTF8( desc, utf8, sizeof( utf8 ) );
-		}
-
-		if ( err )
-		{
-			utf8[ 0 ] = '\0';
-		}
-	}
-
-	// if we can't find it in the registry, then use the hostname of the machine
-	if ( err || ( utf8[ 0 ] == '\0' ) )
-	{
-		TCHAR hostname[256];
-		
-		namelen = sizeof( hostname ) / sizeof( TCHAR );
-
-		ok = GetComputerNameExW( ComputerNamePhysicalDnsHostname, hostname, &namelen );
-		err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
-		check_noerr( err );
-		
-		if( !err )
-		{
-			err = TCHARtoUTF8( hostname, utf8, sizeof( utf8 ) );
-		}
-
-		if ( err )
-		{
-			utf8[ 0 ] = '\0';
-		}
-	}
-
-	// if we can't get the hostname
-	if ( err || ( utf8[ 0 ] == '\0' ) )
-	{
-		// Invalidate name so fall back to a default name.
-		
-		strcpy( utf8, kMDNSDefaultName );
-	}
-
-	utf8[ sizeof( utf8 ) - 1 ]	= '\0';	
-	inMDNS->nicelabel.c[ 0 ]	= (mDNSu8) (strlen( utf8 ) < MAX_DOMAIN_LABEL ? strlen( utf8 ) : MAX_DOMAIN_LABEL);
-	memcpy( &inMDNS->nicelabel.c[ 1 ], utf8, inMDNS->nicelabel.c[ 0 ] );
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "nice name \"%.*s\"\n", inMDNS->nicelabel.c[ 0 ], &inMDNS->nicelabel.c[ 1 ] );
-	
-	if ( descKey )
-	{
-		RegCloseKey( descKey );
-	}
-
-	ZeroMemory( inMDNS->p->nbname, sizeof( inMDNS->p->nbname ) );
-	ZeroMemory( inMDNS->p->nbdomain, sizeof( inMDNS->p->nbdomain ) );
-
-	namelen = sizeof( inMDNS->p->nbname );
-	ok = GetComputerNameExA( ComputerNamePhysicalNetBIOS, inMDNS->p->nbname, &namelen );
-	check( ok );
-	if ( ok ) dlog( kDebugLevelInfo, DEBUG_NAME "netbios name \"%s\"\n", inMDNS->p->nbname );
-
-	err = NetGetJoinInformation( NULL, &joinName, &joinStatus );
-	check ( err == NERR_Success );
-	if ( err == NERR_Success )
-	{
-		if ( ( joinStatus == NetSetupWorkgroupName ) || ( joinStatus == NetSetupDomainName ) )
-		{
-			err = TCHARtoUTF8( joinName, inMDNS->p->nbdomain, sizeof( inMDNS->p->nbdomain ) );
-			check( !err );
-			if ( !err ) dlog( kDebugLevelInfo, DEBUG_NAME "netbios domain/workgroup \"%s\"\n", inMDNS->p->nbdomain );
-		}
-
-		NetApiBufferFree( joinName );
-		joinName = NULL;
-	}
-
-	err = 0;
-
-	return( err );
-}
-
-//===========================================================================================================================
-//	SetupHostName
-//===========================================================================================================================
-
-mDNSlocal mStatus	SetupHostName( mDNS * const inMDNS )
-{
-	mStatus		err = 0;
-	char		tempString[ 256 ];
-	DWORD		tempStringLen;
-	domainlabel tempLabel;
-	BOOL		ok;
-	
-	check( inMDNS );
-
-	// Set up the nice name.
-	tempString[ 0 ] = '\0';
-
-	// use the hostname of the machine
-	tempStringLen = sizeof( tempString );
-	ok = GetComputerNameExA( ComputerNamePhysicalDnsHostname, tempString, &tempStringLen );
-	err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
-	check_noerr( err );
-
-	// if we can't get the hostname
-	if( err || ( tempString[ 0 ] == '\0' ) )
-	{
-		// Invalidate name so fall back to a default name.
-		
-		strcpy( tempString, kMDNSDefaultName );
-	}
-
-	tempString[ sizeof( tempString ) - 1 ] = '\0';
-	tempLabel.c[ 0 ] = (mDNSu8) (strlen( tempString ) < MAX_DOMAIN_LABEL ? strlen( tempString ) : MAX_DOMAIN_LABEL );
-	memcpy( &tempLabel.c[ 1 ], tempString, tempLabel.c[ 0 ] );
-	
-	// Set up the host name.
-	
-	ConvertUTF8PstringToRFC1034HostLabel( tempLabel.c, &inMDNS->hostlabel );
-	if( inMDNS->hostlabel.c[ 0 ] == 0 )
-	{
-		// Nice name has no characters that are representable as an RFC1034 name (e.g. Japanese) so use the default.
-		
-		MakeDomainLabelFromLiteralString( &inMDNS->hostlabel, kMDNSDefaultName );
-	}
-
-	check( inMDNS->hostlabel.c[ 0 ] != 0 );
-	
-	mDNS_SetFQDN( inMDNS );
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "host name \"%.*s\"\n", inMDNS->hostlabel.c[ 0 ], &inMDNS->hostlabel.c[ 1 ] );
-	
-	return( err );
-}
-
-//===========================================================================================================================
-//	SetupName
-//===========================================================================================================================
-
-mDNSlocal mStatus	SetupName( mDNS * const inMDNS )
-{
-	mStatus		err = 0;
-	
-	check( inMDNS );
-	
-	err = SetupNiceName( inMDNS );
-	check_noerr( err );
-
-	err = SetupHostName( inMDNS );
-	check_noerr( err );
-
-	return err;
-}
-
-
-//===========================================================================================================================
-//	SetupInterfaceList
-//===========================================================================================================================
-
-mStatus	SetupInterfaceList( mDNS * const inMDNS )
-{
-	mStatus						err;
-	mDNSInterfaceData **		next;
-	mDNSInterfaceData *			ifd;
-	struct ifaddrs *			addrs;
-	struct ifaddrs *			p;
-	struct ifaddrs *			loopbackv4;
-	struct ifaddrs *			loopbackv6;
-	u_int						flagMask;
-	u_int						flagTest;
-	mDNSBool					foundv4;
-	mDNSBool					foundv6;
-	mDNSBool					foundUnicastSock4DestAddr;
-	mDNSBool					foundUnicastSock6DestAddr;
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list\n" );
-	check( inMDNS );
-	check( inMDNS->p );
-	
-	inMDNS->p->registeredLoopback4	= mDNSfalse;
-	inMDNS->p->nextDHCPLeaseExpires = 0x7FFFFFFF;
-	addrs							= NULL;
-	foundv4							= mDNSfalse;
-	foundv6							= mDNSfalse;
-	foundUnicastSock4DestAddr		= mDNSfalse;
-	foundUnicastSock6DestAddr		= mDNSfalse;
-	
-	// Tear down any existing interfaces that may be set up.
-	
-	TearDownInterfaceList( inMDNS );
-
-	// Set up the name of this machine.
-	
-	err = SetupName( inMDNS );
-	check_noerr( err );
-
-	// Set up IPv4 interface(s). We have to set up IPv4 first so any IPv6 interface with an IPv4-routable address
-	// can refer to the IPv4 interface when it registers to allow DNS AAAA records over the IPv4 interface.
-	
-	err = getifaddrs( &addrs );
-	require_noerr( err, exit );
-	
-	loopbackv4	= NULL;
-	loopbackv6	= NULL;
-	next		= &inMDNS->p->interfaceList;
-
-	flagMask = IFF_UP | IFF_MULTICAST;
-	flagTest = IFF_UP | IFF_MULTICAST;
-	
-#if( MDNS_WINDOWS_ENABLE_IPV4 )
-	for( p = addrs; p; p = p->ifa_next )
-	{
-		if( !p->ifa_addr || ( p->ifa_addr->sa_family != AF_INET ) || ( ( p->ifa_flags & flagMask ) != flagTest ) )
-		{
-			continue;
-		}
-		if( p->ifa_flags & IFF_LOOPBACK )
-		{
-			if( !loopbackv4 )
-			{
-				loopbackv4 = p;
-			}
-			continue;
-		}
-		dlog( kDebugLevelVerbose, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
-			p->ifa_name ? p->ifa_name : "<null>", p->ifa_extra.index, p->ifa_addr );
-		
-		err = SetupInterface( inMDNS, p, &ifd );
-		require_noerr( err, exit );
-
-		// If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to
-		// register him, but we also want to note that we haven't found a v4 interface
-		// so that we register loopback so same host operations work
- 		
-		if ( ifd->interfaceInfo.McastTxRx == mDNStrue )
-		{
-			foundv4 = mDNStrue;
-		}
-
-		if ( p->ifa_dhcpEnabled && ( p->ifa_dhcpLeaseExpires < inMDNS->p->nextDHCPLeaseExpires ) )
-		{
-			inMDNS->p->nextDHCPLeaseExpires = p->ifa_dhcpLeaseExpires;
-		}
-
-		// If we're on a platform that doesn't have WSARecvMsg(), there's no way
-		// of determing the destination address of a packet that is sent to us.
-		// For multicast packets, that's easy to determine.  But for the unicast
-		// sockets, we'll fake it by taking the address of the first interface
-		// that is successfully setup.
-
-		if ( !foundUnicastSock4DestAddr )
-		{
-			inMDNS->p->unicastSock4.addr = ifd->interfaceInfo.ip;
-			foundUnicastSock4DestAddr = TRUE;
-		}
-			
-		*next = ifd;
-		next  = &ifd->next;
-		++inMDNS->p->interfaceCount;
-	}
-#endif
-	
-	// Set up IPv6 interface(s) after IPv4 is set up (see IPv4 notes above for reasoning).
-	
-#if( MDNS_WINDOWS_ENABLE_IPV6 )
-
-	if ( gEnableIPv6 )
-	{
-		for( p = addrs; p; p = p->ifa_next )
-		{
-			if( !p->ifa_addr || ( p->ifa_addr->sa_family != AF_INET6 ) || ( ( p->ifa_flags & flagMask ) != flagTest ) )
-			{
-				continue;
-			}
-			if( p->ifa_flags & IFF_LOOPBACK )
-			{
-				if( !loopbackv6 )
-				{
-					loopbackv6 = p;
-				}
-				continue;
-			}
-			dlog( kDebugLevelVerbose, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
-				p->ifa_name ? p->ifa_name : "<null>", p->ifa_extra.index, p->ifa_addr );
-			
-			err = SetupInterface( inMDNS, p, &ifd );
-			require_noerr( err, exit );
-					
-			// If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to
-			// register him, but we also want to note that we haven't found a v4 interface
-			// so that we register loopback so same host operations work
-	 		
-			if ( ifd->interfaceInfo.McastTxRx == mDNStrue )
-			{
-				foundv6 = mDNStrue;
-			}
-
-			// If we're on a platform that doesn't have WSARecvMsg(), there's no way
-			// of determing the destination address of a packet that is sent to us.
-			// For multicast packets, that's easy to determine.  But for the unicast
-			// sockets, we'll fake it by taking the address of the first interface
-			// that is successfully setup.
-
-			if ( !foundUnicastSock6DestAddr )
-			{
-				inMDNS->p->unicastSock6.addr = ifd->interfaceInfo.ip;
-				foundUnicastSock6DestAddr = TRUE;
-			}
-
-			*next = ifd;
-			next  = &ifd->next;
-			++inMDNS->p->interfaceCount;
-		}
-	}
-
-#endif
-
-	// If there are no real interfaces, but there is a loopback interface, use that so same-machine operations work.
-
-#if( !MDNS_WINDOWS_ENABLE_IPV4 && !MDNS_WINDOWS_ENABLE_IPV6 )
-	
-	flagMask |= IFF_LOOPBACK;
-	flagTest |= IFF_LOOPBACK;
-	
-	for( p = addrs; p; p = p->ifa_next )
-	{
-		if( !p->ifa_addr || ( ( p->ifa_flags & flagMask ) != flagTest ) )
-		{
-			continue;
-		}
-		if( ( p->ifa_addr->sa_family != AF_INET ) && ( p->ifa_addr->sa_family != AF_INET6 ) )
-		{
-			continue;
-		}
-		
-		v4loopback = p;
-		break;
-	}
-	
-#endif
-	
-	if ( !foundv4 && loopbackv4 )
-	{
-		dlog( kDebugLevelInfo, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
-			loopbackv4->ifa_name ? loopbackv4->ifa_name : "<null>", loopbackv4->ifa_extra.index, loopbackv4->ifa_addr );
-		
-		err = SetupInterface( inMDNS, loopbackv4, &ifd );
-		require_noerr( err, exit );
-
-		inMDNS->p->registeredLoopback4 = mDNStrue;
-		
-#if( MDNS_WINDOWS_ENABLE_IPV4 )
-
-		// If we're on a platform that doesn't have WSARecvMsg(), there's no way
-		// of determing the destination address of a packet that is sent to us.
-		// For multicast packets, that's easy to determine.  But for the unicast
-		// sockets, we'll fake it by taking the address of the first interface
-		// that is successfully setup.
-
-		if ( !foundUnicastSock4DestAddr )
-		{
-			inMDNS->p->unicastSock4.addr = ifd->sock.addr;
-			foundUnicastSock4DestAddr = TRUE;
-		}
-#endif
-
-		*next = ifd;
-		next  = &ifd->next;
-		++inMDNS->p->interfaceCount;
-	}
-
-	if ( !foundv6 && loopbackv6 )
-	{
-		dlog( kDebugLevelInfo, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
-			loopbackv6->ifa_name ? loopbackv6->ifa_name : "<null>", loopbackv6->ifa_extra.index, loopbackv6->ifa_addr );
-		
-		err = SetupInterface( inMDNS, loopbackv6, &ifd );
-		require_noerr( err, exit );
-		
-#if( MDNS_WINDOWS_ENABLE_IPV6 )
-
-		if ( gEnableIPv6 )
-		{
-			// If we're on a platform that doesn't have WSARecvMsg(), there's no way
-			// of determing the destination address of a packet that is sent to us.
-			// For multicast packets, that's easy to determine.  But for the unicast
-			// sockets, we'll fake it by taking the address of the first interface
-			// that is successfully setup.
-
-			if ( !foundUnicastSock6DestAddr )
-			{
-				inMDNS->p->unicastSock6.addr = ifd->sock.addr;
-				foundUnicastSock6DestAddr = TRUE;
-			}
-		}
-
-#endif
-
-		*next = ifd;
-		next  = &ifd->next;
-		++inMDNS->p->interfaceCount;
-	}
-
-	CheckFileShares( inMDNS );
-
-exit:
-	if( err )
-	{
-		TearDownInterfaceList( inMDNS );
-	}
-	if( addrs )
-	{
-		freeifaddrs( addrs );
-	}
-	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list done (err=%d %m)\n", err, err );
-	return( err );
-}
-
-//===========================================================================================================================
-//	TearDownInterfaceList
-//===========================================================================================================================
-
-mStatus	TearDownInterfaceList( mDNS * const inMDNS )
-{
-	mDNSInterfaceData **		p;
-	mDNSInterfaceData *		ifd;
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "tearing down interface list\n" );
-	check( inMDNS );
-	check( inMDNS->p );
-
-	// Free any interfaces that were previously marked inactive and are no longer referenced by the mDNS cache.
-	// Interfaces are marked inactive, but not deleted immediately if they were still referenced by the mDNS cache
-	// so that remove events that occur after an interface goes away can still report the correct interface.
-
-	p = &inMDNS->p->inactiveInterfaceList;
-	while( *p )
-	{
-		ifd = *p;
-		if( NumCacheRecordsForInterfaceID( inMDNS, (mDNSInterfaceID) ifd ) > 0 )
-		{
-			p = &ifd->next;
-			continue;
-		}
-		
-		dlog( kDebugLevelInfo, DEBUG_NAME "freeing unreferenced, inactive interface %#p %#a\n", ifd, &ifd->interfaceInfo.ip );
-		*p = ifd->next;
-
-		QueueUserAPC( ( PAPCFUNC ) FreeInterface, inMDNS->p->mainThread, ( ULONG_PTR ) ifd );
-	}
-
-	// Tear down all the interfaces.
-	
-	while( inMDNS->p->interfaceList )
-	{
-		ifd = inMDNS->p->interfaceList;
-		inMDNS->p->interfaceList = ifd->next;
-		
-		TearDownInterface( inMDNS, ifd );
-	}
-	inMDNS->p->interfaceCount = 0;
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "tearing down interface list done\n" );
-	return( mStatus_NoError );
-}
-
-//===========================================================================================================================
-//	SetupInterface
-//===========================================================================================================================
-
-mDNSlocal mStatus	SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD )
-{
-	mDNSInterfaceData	*	ifd;
-	mDNSInterfaceData	*	p;
-	mStatus					err;
-	
-	ifd = NULL;
-	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface\n" );
-	check( inMDNS );
-	check( inMDNS->p );
-	check( inIFA );
-	check( inIFA->ifa_addr );
-	check( outIFD );
-	
-	// Allocate memory for the interface and initialize it.
-	
-	ifd = (mDNSInterfaceData *) calloc( 1, sizeof( *ifd ) );
-	require_action( ifd, exit, err = mStatus_NoMemoryErr );
-	ifd->sock.fd	= kInvalidSocketRef;
-	ifd->sock.ifd	= ifd;
-	ifd->sock.next	= NULL;
-	ifd->sock.m		= inMDNS;
-	ifd->index		= inIFA->ifa_extra.index;
-	ifd->scopeID	= inIFA->ifa_extra.index;
-	check( strlen( inIFA->ifa_name ) < sizeof( ifd->name ) );
-	strncpy( ifd->name, inIFA->ifa_name, sizeof( ifd->name ) - 1 );
-	ifd->name[ sizeof( ifd->name ) - 1 ] = '\0';
-	
-	strncpy(ifd->interfaceInfo.ifname, inIFA->ifa_name, sizeof(ifd->interfaceInfo.ifname));
-	ifd->interfaceInfo.ifname[sizeof(ifd->interfaceInfo.ifname)-1] = 0;
-	
-	// We always send and receive using IPv4, but to reduce traffic, we send and receive using IPv6 only on interfaces 
-	// that have no routable IPv4 address. Having a routable IPv4 address assigned is a reasonable indicator of being 
-	// on a large configured network, which means there's a good chance that most or all the other devices on that 
-	// network should also have v4. By doing this we lose the ability to talk to true v6-only devices on that link, 
-	// but we cut the packet rate in half. At this time, reducing the packet rate is more important than v6-only 
-	// devices on a large configured network, so we are willing to make that sacrifice.
-	
-	ifd->interfaceInfo.McastTxRx   = ( ( inIFA->ifa_flags & IFF_MULTICAST ) && !( inIFA->ifa_flags & IFF_POINTTOPOINT ) ) ? mDNStrue : mDNSfalse;
-	ifd->interfaceInfo.InterfaceID = NULL;
-
-	for( p = inMDNS->p->interfaceList; p; p = p->next )
-	{
-		if ( strcmp( p->name, ifd->name ) == 0 )
-		{
-			if (!ifd->interfaceInfo.InterfaceID)
-			{
-				ifd->interfaceInfo.InterfaceID	= (mDNSInterfaceID) p;
-			}
-
-			if ( ( inIFA->ifa_addr->sa_family != AF_INET ) &&
-			     ( p->interfaceInfo.ip.type == mDNSAddrType_IPv4 ) &&
-			     ( p->interfaceInfo.ip.ip.v4.b[ 0 ] != 169 || p->interfaceInfo.ip.ip.v4.b[ 1 ] != 254 ) )
-			{
-				ifd->interfaceInfo.McastTxRx = mDNSfalse;
-			}
-
-			break;
-		}
-	}
-
-	if ( !ifd->interfaceInfo.InterfaceID )
-	{
-		ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) ifd;
-	}
-
-	// Set up a socket for this interface (if needed).
-	
-	if( ifd->interfaceInfo.McastTxRx )
-	{
-		DWORD size;
-			
-		err = SetupSocket( inMDNS, inIFA->ifa_addr, MulticastDNSPort, &ifd->sock.fd );
-		require_noerr( err, exit );
-		ifd->sock.addr = ( inIFA->ifa_addr->sa_family == AF_INET6 ) ? AllDNSLinkGroup_v6 : AllDNSLinkGroup_v4;
-		ifd->sock.port = MulticastDNSPort;
-		
-		// Get a ptr to the WSARecvMsg function, if supported. Otherwise, we'll fallback to recvfrom.
-
-		err = WSAIoctl( ifd->sock.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &ifd->sock.recvMsgPtr, sizeof( ifd->sock.recvMsgPtr ), &size, NULL, NULL );
-
-		if ( err )
-		{
-			ifd->sock.recvMsgPtr = NULL;
-		}
-	}
-
-	if ( inIFA->ifa_dhcpEnabled && ( inIFA->ifa_dhcpLeaseExpires < inMDNS->p->nextDHCPLeaseExpires ) )
-	{
-		inMDNS->p->nextDHCPLeaseExpires = inIFA->ifa_dhcpLeaseExpires;
-	}
-
-	ifd->interfaceInfo.NetWake = inIFA->ifa_womp;
-
-	// Register this interface with mDNS.
-	
-	err = SockAddrToMDNSAddr( inIFA->ifa_addr, &ifd->interfaceInfo.ip, NULL );
-	require_noerr( err, exit );
-	
-	err = SockAddrToMDNSAddr( inIFA->ifa_netmask, &ifd->interfaceInfo.mask, NULL );
-	require_noerr( err, exit );
-
-	memcpy( ifd->interfaceInfo.MAC.b, inIFA->ifa_physaddr, sizeof( ifd->interfaceInfo.MAC.b ) );
-	
-	ifd->interfaceInfo.Advertise = ( mDNSu8 ) inMDNS->AdvertiseLocalAddresses;
-
-	if ( ifd->sock.fd != kInvalidSocketRef )
-	{
-		err = mDNSPollRegisterSocket( ifd->sock.fd, FD_READ, UDPSocketNotification, &ifd->sock );
-		require_noerr( err, exit );
-	}
-
-    // If interface is a direct link, address record will be marked as kDNSRecordTypeKnownUnique
-    // and skip the probe phase of the probe/announce packet sequence.
-    ifd->interfaceInfo.DirectLink = mDNSfalse;
-
-	err = mDNS_RegisterInterface( inMDNS, &ifd->interfaceInfo, mDNSfalse );
-	require_noerr( err, exit );
-	ifd->hostRegistered = mDNStrue;
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "Registered interface %##a with mDNS\n", inIFA->ifa_addr );
-	
-	// Success!
-	
-	*outIFD = ifd;
-	ifd = NULL;
-	
-exit:
-
-	if( ifd )
-	{
-		TearDownInterface( inMDNS, ifd );
-	}
-	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface done (err=%d %m)\n", err, err );
-	return( err );
-}
-
-//===========================================================================================================================
-//	TearDownInterface
-//===========================================================================================================================
-
-mDNSlocal mStatus	TearDownInterface( mDNS * const inMDNS, mDNSInterfaceData *inIFD )
-{	
-	check( inMDNS );
-	check( inIFD );
-	
-	// Deregister this interface with mDNS.
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "Deregistering interface %#a with mDNS\n", &inIFD->interfaceInfo.ip );
-	
-	if( inIFD->hostRegistered )
-	{
-		inIFD->hostRegistered = mDNSfalse;
-		mDNS_DeregisterInterface( inMDNS, &inIFD->interfaceInfo, mDNSfalse );
-	}
-	
-	// Tear down the multicast socket.
-	
-	UDPCloseSocket( &inIFD->sock );
-
-	// If the interface is still referenced by items in the mDNS cache then put it on the inactive list. This keeps 
-	// the InterfaceID valid so remove events report the correct interface. If it is no longer referenced, free it.
-
-	if( NumCacheRecordsForInterfaceID( inMDNS, (mDNSInterfaceID) inIFD ) > 0 )
-	{
-		inIFD->next = inMDNS->p->inactiveInterfaceList;
-		inMDNS->p->inactiveInterfaceList = inIFD;
-		dlog( kDebugLevelInfo, DEBUG_NAME "deferring free of interface %#p %#a\n", inIFD, &inIFD->interfaceInfo.ip );
-	}
-	else
-	{
-		dlog( kDebugLevelInfo, DEBUG_NAME "freeing interface %#p %#a immediately\n", inIFD, &inIFD->interfaceInfo.ip );
-		QueueUserAPC( ( PAPCFUNC ) FreeInterface, inMDNS->p->mainThread, ( ULONG_PTR ) inIFD );
-	}
-
-	return( mStatus_NoError );
-}
-
-mDNSlocal void CALLBACK FreeInterface( mDNSInterfaceData *inIFD )
-{
-	free( inIFD );
-}
-
-//===========================================================================================================================
-//	SetupSocket
-//===========================================================================================================================
-
-mDNSlocal mStatus	SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAddr, mDNSIPPort port, SocketRef *outSocketRef  )
-{
-	mStatus			err;
-	SocketRef		sock;
-	int				option;
-	DWORD			bytesReturned = 0;
-	BOOL			behavior = FALSE;
-	
-	DEBUG_UNUSED( inMDNS );
-	
-	dlog( kDebugLevelTrace, DEBUG_NAME "setting up socket %##a\n", inAddr );
-	check( inMDNS );
-	check( outSocketRef );
-	
-	// Set up an IPv4 or IPv6 UDP socket.
-	
-	sock = socket( inAddr->sa_family, SOCK_DGRAM, IPPROTO_UDP );
-	err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-		
-	// Turn on reuse address option so multiple servers can listen for Multicast DNS packets,
-	// if we're creating a multicast socket
-	
-	if ( !mDNSIPPortIsZero( port ) )
-	{
-		option = 1;
-		err = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-	}
-
-	// <rdar://problem/7894393> Bonjour for Windows broken on Windows XP
-	//
-	// Not sure why, but the default behavior for sockets is to behave incorrectly
-	// when using them in Overlapped I/O mode on XP. According to MSDN:
-	//
-	// SIO_UDP_CONNRESET (opcode setting: I, T==3)
-	//     Windows XP:  Controls whether UDP PORT_UNREACHABLE messages are reported. Set to TRUE to enable reporting.
-	//     Set to FALSE to disable reporting.
-	//
-	// Packet traces from misbehaving Bonjour installations showed that ICMP port unreachable
-	// messages were being sent to us after we sent out packets to a multicast address. This is clearly
-	// incorrect behavior, but should be harmless. However, after receiving a port unreachable error, WinSock
-	// will no longer receive any packets from that socket, which is not harmless. This behavior is only
-	// seen on XP.
-	//
-	// So we turn off port unreachable reporting to make sure our sockets that are reading
-	// multicast packets function correctly under all circumstances.
-
-	err = WSAIoctl( sock, SIO_UDP_CONNRESET, &behavior, sizeof(behavior), NULL, 0, &bytesReturned, NULL, NULL );
-	check_translated_errno( err == 0, errno_compat(), kOptionErr );
-
-	if( inAddr->sa_family == AF_INET )
-	{
-		mDNSv4Addr				ipv4;
-		struct sockaddr_in		sa4;
-		struct ip_mreq			mreqv4;
-		
-		// Bind the socket to the desired port
-		
-		ipv4.NotAnInteger 	= ( (const struct sockaddr_in *) inAddr )->sin_addr.s_addr;
-		mDNSPlatformMemZero( &sa4, sizeof( sa4 ) );
-		sa4.sin_family 		= AF_INET;
-		sa4.sin_port 		= port.NotAnInteger;
-		sa4.sin_addr.s_addr	= ipv4.NotAnInteger;
-		
-		err = bind( sock, (struct sockaddr *) &sa4, sizeof( sa4 ) );
-		check_translated_errno( err == 0, errno_compat(), kUnknownErr );
-		
-		// Turn on option to receive destination addresses and receiving interface.
-		
-		option = 1;
-		err = setsockopt( sock, IPPROTO_IP, IP_PKTINFO, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		
-		if ( !mDNSIPPortIsZero( port ) )
-		{
-			// Join the all-DNS multicast group so we receive Multicast DNS packets
-
-			mreqv4.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
-			mreqv4.imr_interface.s_addr = ipv4.NotAnInteger;
-			err = setsockopt( sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreqv4, sizeof( mreqv4 ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		
-			// Specify the interface to send multicast packets on this socket.
-		
-			sa4.sin_addr.s_addr = ipv4.NotAnInteger;
-			err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_IF, (char *) &sa4.sin_addr, sizeof( sa4.sin_addr ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		
-			// Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
-		
-			option = 1;
-			err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		}
-
-		// Send unicast packets with TTL 255 (helps against spoofing).
-		
-		option = 255;
-		err = setsockopt( sock, IPPROTO_IP, IP_TTL, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-
-		// Send multicast packets with TTL 255 (helps against spoofing).
-		
-		option = 255;
-		err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-
-	}
-	else if( inAddr->sa_family == AF_INET6 )
-	{
-		struct sockaddr_in6 *		sa6p;
-		struct sockaddr_in6			sa6;
-		struct ipv6_mreq			mreqv6;
-		
-		sa6p = (struct sockaddr_in6 *) inAddr;
-		
-		// Bind the socket to the desired port
-		
-		mDNSPlatformMemZero( &sa6, sizeof( sa6 ) );
-		sa6.sin6_family		= AF_INET6;
-		sa6.sin6_port		= port.NotAnInteger;
-		sa6.sin6_flowinfo	= 0;
-		sa6.sin6_addr		= sa6p->sin6_addr;
-		sa6.sin6_scope_id	= sa6p->sin6_scope_id;
-		
-		err = bind( sock, (struct sockaddr *) &sa6, sizeof( sa6 ) );
-		check_translated_errno( err == 0, errno_compat(), kUnknownErr );
-		
-		// Turn on option to receive destination addresses and receiving interface.
-		
-		option = 1;
-		err = setsockopt( sock, IPPROTO_IPV6, IPV6_PKTINFO, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		
-		// We only want to receive IPv6 packets (not IPv4-mapped IPv6 addresses) because we have a separate socket 
-		// for IPv4, but the IPv6 stack in Windows currently doesn't support IPv4-mapped IPv6 addresses and doesn't
-		// support the IPV6_V6ONLY socket option so the following code would typically not be executed (or needed).
-		
-		#if( defined( IPV6_V6ONLY ) )
-			option = 1;
-			err = setsockopt( sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &option, sizeof( option ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );		
-		#endif
-		
-		if ( !mDNSIPPortIsZero( port ) )
-		{
-			// Join the all-DNS multicast group so we receive Multicast DNS packets.
-		
-			mreqv6.ipv6mr_multiaddr = *( (struct in6_addr *) &AllDNSLinkGroup_v6.ip.v6 );
-			mreqv6.ipv6mr_interface = sa6p->sin6_scope_id;
-			err = setsockopt( sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &mreqv6, sizeof( mreqv6 ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		
-			// Specify the interface to send multicast packets on this socket.
-		
-			option = (int) sa6p->sin6_scope_id;
-			err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &option, sizeof( option ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		
-			// Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
-			
-			option = 1;
-			err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
-			check_translated_errno( err == 0, errno_compat(), kOptionErr );
-		}
-
-		// Send unicast packets with TTL 255 (helps against spoofing).
-		
-		option = 255;
-		err = setsockopt( sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-
-		// Send multicast packets with TTL 255 (helps against spoofing).
-			
-		option = 255;
-		err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &option, sizeof( option ) );
-		check_translated_errno( err == 0, errno_compat(), kOptionErr );
-	}
-	else
-	{
-		dlog( kDebugLevelError, DEBUG_NAME "%s: unsupport socket family (%d)\n", __ROUTINE__, inAddr->sa_family );
-		err = kUnsupportedErr;
-		goto exit;
-	}
-	
-	// Success!
-	
-	*outSocketRef = sock;
-	sock = kInvalidSocketRef;
-	err = mStatus_NoError;
-	
-exit:
-	if( IsValidSocket( sock ) )
-	{
-		close_compat( sock );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	SetupSocket
-//===========================================================================================================================
-
-mDNSlocal mStatus	SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP, mDNSIPPort *outPort )
-{
-	mStatus		err;
-	
-	check( inSA );
-	check( outIP );
-	
-	if( inSA->sa_family == AF_INET )
-	{
-		struct sockaddr_in *		sa4;
-		
-		sa4 						= (struct sockaddr_in *) inSA;
-		outIP->type 				= mDNSAddrType_IPv4;
-		outIP->ip.v4.NotAnInteger	= sa4->sin_addr.s_addr;
-		if( outPort )
-		{
-			outPort->NotAnInteger	= sa4->sin_port;
-		}
-		err = mStatus_NoError;
-	}
-	else if( inSA->sa_family == AF_INET6 )
-	{
-		struct sockaddr_in6 *		sa6;
-		
-		sa6 			= (struct sockaddr_in6 *) inSA;
-		outIP->type 	= mDNSAddrType_IPv6;
-		outIP->ip.v6 	= *( (mDNSv6Addr *) &sa6->sin6_addr );
-		if( IN6_IS_ADDR_LINKLOCAL( &sa6->sin6_addr ) )
-		{
-			outIP->ip.v6.w[ 1 ] = 0;
-		}
-		if( outPort )
-		{
-			outPort->NotAnInteger = sa6->sin6_port;
-		}
-		err = mStatus_NoError;
-	}
-	else
-	{
-		dlog( kDebugLevelError, DEBUG_NAME "%s: invalid sa_family %d", __ROUTINE__, inSA->sa_family );
-		err = mStatus_BadParamErr;
-	}
-	return( err );
-}
-
-
-#if 0
-#pragma mark -
-#endif
-
-//===========================================================================================================================
-//	UDPSocketNotification
-//===========================================================================================================================
-
-mDNSlocal void CALLBACK
-UDPSocketNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context )
-{
-	UDPSocket				*udpSock = ( UDPSocket* ) context;
-	WSAMSG					wmsg;
-	WSABUF					wbuf;
-	struct sockaddr_storage	sockSrcAddr;		// This is filled in by the WSARecv* function
-	INT						sockSrcAddrLen;		// See above
-	mDNSAddr				srcAddr;
-	mDNSInterfaceID			iid;
-	mDNSIPPort				srcPort;
-	mDNSAddr				dstAddr;
-	mDNSIPPort				dstPort;
-	uint8_t					controlBuffer[ 128 ];
-	mDNSu8				*	end;
-	int						num;
-	DWORD					numTries;
-	mStatus					err;
-
-	DEBUG_UNUSED( sock );
-	DEBUG_UNUSED( event );
-
-	require_action( udpSock != NULL, exit, err = mStatus_BadStateErr );
-
-	dlog( kDebugLevelChatty, DEBUG_NAME "%s: sock = %d\n", __ROUTINE__, udpSock->fd );
-	
-	// Initialize the buffer structure
-
-	wbuf.buf		= (char *) &udpSock->packet;
-	wbuf.len		= (u_long) sizeof( udpSock->packet );
-	sockSrcAddrLen	= sizeof( sockSrcAddr );
-
-	numTries = 0;
-
-	do
-	{
-		if ( udpSock->recvMsgPtr )
-		{
-			DWORD size;
-
-			wmsg.name			= ( LPSOCKADDR ) &sockSrcAddr;
-			wmsg.namelen		= sockSrcAddrLen;
-			wmsg.lpBuffers		= &wbuf;
-			wmsg.dwBufferCount	= 1;
-			wmsg.Control.buf	= ( CHAR* ) controlBuffer;
-			wmsg.Control.len	= sizeof( controlBuffer );
-			wmsg.dwFlags		= 0;
-
-			err = udpSock->recvMsgPtr( udpSock->fd, &wmsg, &size, NULL, NULL );
-			err = translate_errno( ( err == 0 ), (OSStatus) WSAGetLastError(), kUnknownErr ); 
-			num = ( int ) size;
-
-			// <rdar://problem/7824093> iTunes 9.1 fails to install with Bonjour service on Windows 7 Ultimate
-			//
-			// There seems to be a bug in some network device drivers that involves calling WSARecvMsg().
-			// Although all the parameters to WSARecvMsg() are correct, it returns a
-			// WSAEFAULT error code when there is no actual error. We have found experientially that falling
-			// back to using WSARecvFrom() when this happens will work correctly.
-
-			if ( err == WSAEFAULT ) udpSock->recvMsgPtr = NULL;
-		}
-		else
-		{
-			DWORD flags = 0;
-
-			num = WSARecvFrom( udpSock->fd, &wbuf, 1, NULL, &flags, ( LPSOCKADDR ) &sockSrcAddr, &sockSrcAddrLen, NULL, NULL );
-			err = translate_errno( ( num >= 0 ), ( OSStatus ) WSAGetLastError(), kUnknownErr );
-		}
-
-		// According to MSDN <http://msdn.microsoft.com/en-us/library/ms741687(VS.85).aspx>:
-		//
-		// "WSAECONNRESET: For a UDP datagram socket, this error would indicate that a previous
-		//                 send operation resulted in an ICMP "Port Unreachable" message."
-		//
-		// Because this is the case, we want to ignore this error and try again.  Just in case
-		// this is some kind of pathological condition, we'll break out of the retry loop 
-		// after 100 iterations
-
-		require_action( !err || ( err == WSAECONNRESET ) || ( err == WSAEFAULT ), exit, err = WSAGetLastError() );
-	}
-	while ( ( ( err == WSAECONNRESET ) || ( err == WSAEFAULT ) ) && ( numTries++ < 100 ) );
-	
-	require_noerr( err, exit );
-	
-	// Translate the source of this packet into mDNS data types
-
-	SockAddrToMDNSAddr( (struct sockaddr* ) &sockSrcAddr, &srcAddr, &srcPort );
-	
-	// Initialize the destination of this packet. Just in case
-	// we can't determine this info because we couldn't call
-	// WSARecvMsg (recvMsgPtr)
-
-	dstAddr = udpSock->addr;
-	dstPort = udpSock->port;
-
-	if ( udpSock->recvMsgPtr )
-	{
-		LPWSACMSGHDR	header;
-		LPWSACMSGHDR	last = NULL;
-		int				count = 0;
-		
-		// Parse the control information. Reject packets received on the wrong interface.
-		
-		// <rdar://problem/7832196> INSTALL: Bonjour 2.0 on Windows can not start / stop
-		// 
-		// There seems to be an interaction between Bullguard and this next bit of code.
-		// When a user's machine is running Bullguard, the control information that is
-		// returned is corrupted, and the code would go into an infinite loop. We'll add
-		// two bits of defensive coding here. The first will check that each pointer to
-		// the LPWSACMSGHDR that is returned in the for loop is different than the last.
-		// This fixes the problem with Bullguard. The second will break out of this loop
-		// after 100 iterations, just in case the corruption isn't caught by the first
-		// check.
-
-		for ( header = WSA_CMSG_FIRSTHDR( &wmsg ); header; header = WSA_CMSG_NXTHDR( &wmsg, header ) )
-		{
-			if ( ( header != last ) && ( ++count < 100 ) )
-			{
-				last = header;
-					
-				if ( ( header->cmsg_level == IPPROTO_IP ) && ( header->cmsg_type == IP_PKTINFO ) )
-				{
-					IN_PKTINFO * ipv4PacketInfo;
-					
-					ipv4PacketInfo = (IN_PKTINFO *) WSA_CMSG_DATA( header );
-
-					if ( udpSock->ifd != NULL )
-					{
-						require_action( ipv4PacketInfo->ipi_ifindex == udpSock->ifd->index, exit, err = ( DWORD ) kMismatchErr );
-					}
-
-					dstAddr.type 				= mDNSAddrType_IPv4;
-					dstAddr.ip.v4.NotAnInteger	= ipv4PacketInfo->ipi_addr.s_addr;
-				}
-				else if( ( header->cmsg_level == IPPROTO_IPV6 ) && ( header->cmsg_type == IPV6_PKTINFO ) )
-				{
-					IN6_PKTINFO * ipv6PacketInfo;
-						
-					ipv6PacketInfo = (IN6_PKTINFO *) WSA_CMSG_DATA( header );
-		
-					if ( udpSock->ifd != NULL )
-					{
-						require_action( ipv6PacketInfo->ipi6_ifindex == ( udpSock->ifd->index - kIPv6IfIndexBase ), exit, err = ( DWORD ) kMismatchErr );
-					}
-
-					dstAddr.type	= mDNSAddrType_IPv6;
-					dstAddr.ip.v6	= *( (mDNSv6Addr *) &ipv6PacketInfo->ipi6_addr );
-				}
-			}
-			else
-			{
-				static BOOL loggedMessage = FALSE;
-
-				if ( !loggedMessage )
-				{
-					LogMsg( "UDPEndRecv: WSARecvMsg control information error." );
-					loggedMessage = TRUE;
-				}
-
-				break;
-			}
-		}
-	}
-
-	dlog( kDebugLevelChatty, DEBUG_NAME "packet received\n" );
-	dlog( kDebugLevelChatty, DEBUG_NAME "    size      = %d\n", num );
-	dlog( kDebugLevelChatty, DEBUG_NAME "    src       = %#a:%u\n", &srcAddr, ntohs( srcPort.NotAnInteger ) );
-	dlog( kDebugLevelChatty, DEBUG_NAME "    dst       = %#a:%u\n", &dstAddr, ntohs( dstPort.NotAnInteger ) );
-	
-	if ( udpSock->ifd != NULL )
-	{
-		dlog( kDebugLevelChatty, DEBUG_NAME "    interface = %#a (index=0x%08X)\n", &udpSock->ifd->interfaceInfo.ip, udpSock->ifd->index );
-	}
-
-	dlog( kDebugLevelChatty, DEBUG_NAME "\n" );
-
-	iid = udpSock->ifd ? udpSock->ifd->interfaceInfo.InterfaceID : NULL;
-	end = ( (mDNSu8 *) &udpSock->packet ) + num;
-
-	mDNSCoreReceive( udpSock->m, &udpSock->packet, end, &srcAddr, srcPort, &dstAddr, dstPort, iid );
-
-exit:
-
-	return;
-}
-
-
-//===========================================================================================================================
-//	InterfaceListDidChange
-//===========================================================================================================================
-void InterfaceListDidChange( mDNS * const inMDNS )
-{
-	mStatus err;
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "interface list changed\n" );
-	check( inMDNS );
-	
-	// Tear down the existing interfaces and set up new ones using the new IP info.
-	
-	err = TearDownInterfaceList( inMDNS );
-	check_noerr( err );
-	
-	err = SetupInterfaceList( inMDNS );
-	check_noerr( err );
-		
-	err = uDNS_SetupDNSConfig( inMDNS );
-	check_noerr( err );
-	
-	// Inform clients of the change.
-	
-	mDNS_ConfigChanged(inMDNS);
-	
-	// Force mDNS to update.
-	
-	mDNSCoreMachineSleep( inMDNS, mDNSfalse ); // What is this for? Mac OS X does not do this
-}
-
-
-//===========================================================================================================================
-//	ComputerDescriptionDidChange
-//===========================================================================================================================
-void ComputerDescriptionDidChange( mDNS * const inMDNS )
-{	
-	dlog( kDebugLevelInfo, DEBUG_NAME "computer description has changed\n" );
-	check( inMDNS );
-
-	// redo the names
-	SetupNiceName( inMDNS );
-}
-
-
-//===========================================================================================================================
-//	TCPIPConfigDidChange
-//===========================================================================================================================
-void TCPIPConfigDidChange( mDNS * const inMDNS )
-{
-	mStatus		err;
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "TCP/IP config has changed\n" );
-	check( inMDNS );
-
-	err = uDNS_SetupDNSConfig( inMDNS );
-	check_noerr( err );
-}
-
-
-//===========================================================================================================================
-//	DynDNSConfigDidChange
-//===========================================================================================================================
-void DynDNSConfigDidChange( mDNS * const inMDNS )
-{
-	mStatus		err;
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "DynDNS config has changed\n" );
-	check( inMDNS );
-
-	SetDomainSecrets( inMDNS );
-
-	err = uDNS_SetupDNSConfig( inMDNS );
-	check_noerr( err );
-}
-
-
-//===========================================================================================================================
-//	FileSharingDidChange
-//===========================================================================================================================
-void FileSharingDidChange( mDNS * const inMDNS )
-{	
-	dlog( kDebugLevelInfo, DEBUG_NAME "File shares has changed\n" );
-	check( inMDNS );
-
-	CheckFileShares( inMDNS );
-}
-
-
-//===========================================================================================================================
-//	FilewallDidChange
-//===========================================================================================================================
-void FirewallDidChange( mDNS * const inMDNS )
-{	
-	dlog( kDebugLevelInfo, DEBUG_NAME "Firewall has changed\n" );
-	check( inMDNS );
-
-	CheckFileShares( inMDNS );
-}
-
-
-#if 0
-#pragma mark -
-#pragma mark == Utilities ==
-#endif
-
-//===========================================================================================================================
-//	getifaddrs
-//===========================================================================================================================
-
-mDNSlocal int	getifaddrs( struct ifaddrs **outAddrs )
-{
-	int		err;
-	
-#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
-	
-	// Try to the load the GetAdaptersAddresses function from the IP Helpers DLL. This API is only available on Windows
-	// XP or later. Looking up the symbol at runtime allows the code to still work on older systems without that API.
-	
-	if( !gIPHelperLibraryInstance )
-	{
-		gIPHelperLibraryInstance = LoadLibrary( TEXT( "Iphlpapi" ) );
-		if( gIPHelperLibraryInstance )
-		{
-			gGetAdaptersAddressesFunctionPtr = 
-				(GetAdaptersAddressesFunctionPtr) GetProcAddress( gIPHelperLibraryInstance, "GetAdaptersAddresses" );
-			if( !gGetAdaptersAddressesFunctionPtr )
-			{
-				BOOL		ok;
-				
-				ok = FreeLibrary( gIPHelperLibraryInstance );
-				check_translated_errno( ok, GetLastError(), kUnknownErr );
-				gIPHelperLibraryInstance = NULL;
-			}
-		}
-	}
-	
-	// Use the new IPv6-capable routine if supported. Otherwise, fall back to the old and compatible IPv4-only code.
-	// <rdar://problem/4278934>  Fall back to using getifaddrs_ipv4 if getifaddrs_ipv6 fails
-	// <rdar://problem/6145913>  Fall back to using getifaddrs_ipv4 if getifaddrs_ipv6 returns no addrs
-
-	if( !gGetAdaptersAddressesFunctionPtr || ( ( ( err = getifaddrs_ipv6( outAddrs ) ) != mStatus_NoError ) || ( ( outAddrs != NULL ) && ( *outAddrs == NULL ) ) ) )
-	{
-		err = getifaddrs_ipv4( outAddrs );
-		require_noerr( err, exit );
-	}
-	
-#else
-
-	err = getifaddrs_ipv4( outAddrs );
-	require_noerr( err, exit );
-
-#endif
-
-exit:
-	return( err );
-}
-
-#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
-//===========================================================================================================================
-//	getifaddrs_ipv6
-//===========================================================================================================================
-
-mDNSlocal int	getifaddrs_ipv6( struct ifaddrs **outAddrs )
-{
-	DWORD						err;
-	int							i;
-	DWORD						flags;
-	struct ifaddrs *			head;
-	struct ifaddrs **			next;
-	IP_ADAPTER_ADDRESSES *		iaaList;
-	ULONG						iaaListSize;
-	IP_ADAPTER_ADDRESSES *		iaa;
-	size_t						size;
-	struct ifaddrs *			ifa;
-	
-	check( gGetAdaptersAddressesFunctionPtr );
-	
-	head	= NULL;
-	next	= &head;
-	iaaList	= NULL;
-	
-	// Get the list of interfaces. The first call gets the size and the second call gets the actual data.
-	// This loops to handle the case where the interface changes in the window after getting the size, but before the
-	// second call completes. A limit of 100 retries is enforced to prevent infinite loops if something else is wrong.
-	
-	flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
-	i = 0;
-	for( ;; )
-	{
-		iaaListSize = 0;
-		err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, NULL, &iaaListSize );
-		check( err == ERROR_BUFFER_OVERFLOW );
-		check( iaaListSize >= sizeof( IP_ADAPTER_ADDRESSES ) );
-		
-		iaaList = (IP_ADAPTER_ADDRESSES *) malloc( iaaListSize );
-		require_action( iaaList, exit, err = ERROR_NOT_ENOUGH_MEMORY );
-		
-		err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, iaaList, &iaaListSize );
-		if( err == ERROR_SUCCESS ) break;
-		
-		free( iaaList );
-		iaaList = NULL;
-		++i;
-		require( i < 100, exit );
-		dlog( kDebugLevelWarning, "%s: retrying GetAdaptersAddresses after %d failure(s) (%d %m)\n", __ROUTINE__, i, err, err );
-	}
-	
-	for( iaa = iaaList; iaa; iaa = iaa->Next )
-	{
-		int								addrIndex;
-		IP_ADAPTER_UNICAST_ADDRESS	*	addr;
-		DWORD							ipv6IfIndex;
-		IP_ADAPTER_PREFIX			*	firstPrefix;
-
-		if( iaa->IfIndex > 0xFFFFFF )
-		{
-			dlog( kDebugLevelAlert, DEBUG_NAME "%s: IPv4 ifindex out-of-range (0x%08X)\n", __ROUTINE__, iaa->IfIndex );
-		}
-		if( iaa->Ipv6IfIndex > 0xFF )
-		{
-			dlog( kDebugLevelAlert, DEBUG_NAME "%s: IPv6 ifindex out-of-range (0x%08X)\n", __ROUTINE__, iaa->Ipv6IfIndex );
-		}
-
-		// For IPv4 interfaces, there seems to be a bug in iphlpapi.dll that causes the 
-		// following code to crash when iterating through the prefix list.  This seems
-		// to occur when iaa->Ipv6IfIndex != 0 when IPv6 is not installed on the host.
-		// This shouldn't happen according to Microsoft docs which states:
-		//
-		//     "Ipv6IfIndex contains 0 if IPv6 is not available on the interface."
-		//
-		// So the data structure seems to be corrupted when we return from
-		// GetAdaptersAddresses(). The bug seems to occur when iaa->Length <
-		// sizeof(IP_ADAPTER_ADDRESSES), so when that happens, we'll manually
-		// modify iaa to have the correct values.
-
-		if ( iaa->Length >= sizeof( IP_ADAPTER_ADDRESSES ) )
-		{
-			ipv6IfIndex = iaa->Ipv6IfIndex;
-			firstPrefix = iaa->FirstPrefix;
-		}
-		else
-		{
-			ipv6IfIndex	= 0;
-			firstPrefix = NULL;
-		}
-
-		// Skip pseudo and tunnel interfaces.
-		
-		if( ( ( ipv6IfIndex == 1 ) && ( iaa->IfType != IF_TYPE_SOFTWARE_LOOPBACK ) ) || ( iaa->IfType == IF_TYPE_TUNNEL ) )
-		{
-			continue;
-		}
-		
-		// Add each address as a separate interface to emulate the way getifaddrs works.
-		
-		for( addrIndex = 0, addr = iaa->FirstUnicastAddress; addr; ++addrIndex, addr = addr->Next )
-		{			
-			int						family;
-			IP_ADAPTER_PREFIX *		prefix;
-			uint32_t				ipv4Index;
-			struct sockaddr_in		ipv4Netmask;
-
-			family = addr->Address.lpSockaddr->sa_family;
-			if( ( family != AF_INET ) && ( family != AF_INET6 ) ) continue;
-			
-			// <rdar://problem/6220642> iTunes 8: Bonjour doesn't work after upgrading iTunes 8
-			// Seems as if the problem here is a buggy implementation of some network interface
-			// driver. It is reporting that is has a link-local address when it is actually
-			// disconnected. This was causing a problem in AddressToIndexAndMask.
-			// The solution is to call AddressToIndexAndMask first, and if unable to lookup
-			// the address, to ignore that address.
-
-			ipv4Index = 0;
-			memset( &ipv4Netmask, 0, sizeof( ipv4Netmask ) );
-			
-			if ( family == AF_INET )
-			{
-				err = AddressToIndexAndMask( addr->Address.lpSockaddr, &ipv4Index, ( struct sockaddr* ) &ipv4Netmask );
-				
-				if ( err )
-				{
-					err = 0;
-					continue;
-				}
-			}
-
-			ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
-			require_action( ifa, exit, err = WSAENOBUFS );
-			
-			*next = ifa;
-			next  = &ifa->ifa_next;
-			
-			// Get the name.
-			
-			size = strlen( iaa->AdapterName ) + 1;
-			ifa->ifa_name = (char *) malloc( size );
-			require_action( ifa->ifa_name, exit, err = WSAENOBUFS );
-			memcpy( ifa->ifa_name, iaa->AdapterName, size );
-			
-			// Get interface flags.
-			
-			ifa->ifa_flags = 0;
-			if( iaa->OperStatus == IfOperStatusUp ) 		ifa->ifa_flags |= IFF_UP;
-			if( iaa->IfType == IF_TYPE_SOFTWARE_LOOPBACK )	ifa->ifa_flags |= IFF_LOOPBACK;
-			else if ( IsPointToPoint( addr ) )				ifa->ifa_flags |= IFF_POINTTOPOINT;
-			if( !( iaa->Flags & IP_ADAPTER_NO_MULTICAST ) )	ifa->ifa_flags |= IFF_MULTICAST;
-
-			
-			// <rdar://problem/4045657> Interface index being returned is 512
-			//
-			// Windows does not have a uniform scheme for IPv4 and IPv6 interface indexes.
-			// This code used to shift the IPv4 index up to ensure uniqueness between
-			// it and IPv6 indexes.  Although this worked, it was somewhat confusing to developers, who
-			// then see interface indexes passed back that don't correspond to anything
-			// that is seen in Win32 APIs or command line tools like "route".  As a relatively
-			// small percentage of developers are actively using IPv6, it seems to 
-			// make sense to make our use of IPv4 as confusion free as possible.
-			// So now, IPv6 interface indexes will be shifted up by a
-			// constant value which will serve to uniquely identify them, and we will
-			// leave IPv4 interface indexes unmodified.
-			
-			switch( family )
-			{
-				case AF_INET:  ifa->ifa_extra.index = iaa->IfIndex; break;
-				case AF_INET6: ifa->ifa_extra.index = ipv6IfIndex + kIPv6IfIndexBase;	 break;
-				default: break;
-			}
-
-			// Get lease lifetime
-
-			if ( ( iaa->IfType != IF_TYPE_SOFTWARE_LOOPBACK ) && ( addr->LeaseLifetime != 0 ) && ( addr->ValidLifetime != 0xFFFFFFFF ) )
-			{
-				ifa->ifa_dhcpEnabled		= TRUE;
-				ifa->ifa_dhcpLeaseExpires	= time( NULL ) + addr->ValidLifetime;
-			}
-			else
-			{
-				ifa->ifa_dhcpEnabled		= FALSE;
-				ifa->ifa_dhcpLeaseExpires	= 0;
-			}
-
-			if ( iaa->PhysicalAddressLength == sizeof( ifa->ifa_physaddr ) )
-			{
-				memcpy( ifa->ifa_physaddr, iaa->PhysicalAddress, iaa->PhysicalAddressLength );
-			}
-
-			// Because we don't get notified of womp changes, we're going to just assume
-			// that all wired interfaces have it enabled. Before we go to sleep, we'll check
-			// if the interface actually supports it, and update mDNS->SystemWakeOnLANEnabled
-			// accordingly
-
-			ifa->ifa_womp = ( iaa->IfType == IF_TYPE_ETHERNET_CSMACD ) ? mDNStrue : mDNSfalse;
-			
-			// Get address.
-			
-			switch( family )
-			{
-				case AF_INET:
-				case AF_INET6:
-					ifa->ifa_addr = (struct sockaddr *) calloc( 1, (size_t) addr->Address.iSockaddrLength );
-					require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
-					memcpy( ifa->ifa_addr, addr->Address.lpSockaddr, (size_t) addr->Address.iSockaddrLength );
-					break;
-				
-				default:
-					break;
-			}
-			check( ifa->ifa_addr );
-			
-			// Get subnet mask (IPv4)/link prefix (IPv6). It is specified as a bit length (e.g. 24 for 255.255.255.0).
-
-			switch ( family )
-			{
-				case AF_INET:
-				{
-					struct sockaddr_in * sa4;
-					
-					sa4 = (struct sockaddr_in *) calloc( 1, sizeof( *sa4 ) );
-					require_action( sa4, exit, err = WSAENOBUFS );
-					sa4->sin_family = AF_INET;
-					sa4->sin_addr.s_addr = ipv4Netmask.sin_addr.s_addr;
-
-					dlog( kDebugLevelInfo, DEBUG_NAME "%s: IPv4 mask = %s\n", __ROUTINE__, inet_ntoa( sa4->sin_addr ) );
-					ifa->ifa_netmask = (struct sockaddr *) sa4;
-					break;
-				}
-
-				case AF_INET6:
-				{
-					struct sockaddr_in6 *sa6;
-					char buf[ 256 ] = { 0 };
-					DWORD buflen = sizeof( buf );
-
-					sa6 = (struct sockaddr_in6 *) calloc( 1, sizeof( *sa6 ) );
-					require_action( sa6, exit, err = WSAENOBUFS );
-					sa6->sin6_family = AF_INET6;
-					memset( sa6->sin6_addr.s6_addr, 0xFF, sizeof( sa6->sin6_addr.s6_addr ) );
-					ifa->ifa_netmask = (struct sockaddr *) sa6;
-
-					for ( prefix = firstPrefix; prefix; prefix = prefix->Next )
-					{
-						IN6_ADDR	mask;
-						IN6_ADDR	maskedAddr;
-						int			maskIndex;
-						DWORD		len;
-
-						// According to MSDN:
-						// "On Windows Vista and later, the linked IP_ADAPTER_PREFIX structures pointed to by the FirstPrefix member
-						// include three IP adapter prefixes for each IP address assigned to the adapter. These include the host IP address prefix,
-						// the subnet IP address prefix, and the subnet broadcast IP address prefix.
-						// In addition, for each adapter there is a multicast address prefix and a broadcast address prefix.
-						// On Windows XP with SP1 and later prior to Windows Vista, the linked IP_ADAPTER_PREFIX structures pointed to by the FirstPrefix member
-						// include only a single IP adapter prefix for each IP address assigned to the adapter."
-						
-						// We're only interested in the subnet IP address prefix.  We'll determine if the prefix is the
-						// subnet prefix by masking our address with a mask (computed from the prefix length) and see if that is the same
-						// as the prefix address.
-
-						if ( ( prefix->PrefixLength == 0 ) ||
-						     ( prefix->PrefixLength > 128 ) ||
-						     ( addr->Address.iSockaddrLength != prefix->Address.iSockaddrLength ) ||
-							 ( memcmp( addr->Address.lpSockaddr, prefix->Address.lpSockaddr, addr->Address.iSockaddrLength ) == 0 ) )
-						{
-							continue;
-						}
-
-						// Compute the mask
-
-						memset( mask.s6_addr, 0, sizeof( mask.s6_addr ) );
-
-						for ( len = (int) prefix->PrefixLength, maskIndex = 0; len > 0; len -= 8 )
-						{
-							uint8_t maskByte = ( len >= 8 ) ? 0xFF : (uint8_t)( ( 0xFFU << ( 8 - len ) ) & 0xFFU );
-							mask.s6_addr[ maskIndex++ ] = maskByte;
-						}
-
-						// Apply the mask
-
-						for ( i = 0; i < 16; i++ )
-						{
-							maskedAddr.s6_addr[ i ] = ( ( struct sockaddr_in6* ) addr->Address.lpSockaddr )->sin6_addr.s6_addr[ i ] & mask.s6_addr[ i ];
-						}
-
-						// Compare
-
-						if ( memcmp( ( ( struct sockaddr_in6* ) prefix->Address.lpSockaddr )->sin6_addr.s6_addr, maskedAddr.s6_addr, sizeof( maskedAddr.s6_addr ) ) == 0 )
-						{
-							memcpy( sa6->sin6_addr.s6_addr, mask.s6_addr, sizeof( mask.s6_addr ) );
-							break;
-						}
-					}
-
-					WSAAddressToStringA( ( LPSOCKADDR ) sa6, sizeof( struct sockaddr_in6 ), NULL, buf, &buflen );
-					dlog( kDebugLevelInfo, DEBUG_NAME "%s: IPv6 mask = %s\n", __ROUTINE__, buf );				
-
-					break;
-				}
-				
-				default:
-					break;
-			}
-		}
-	}
-	
-	// Success!
-	
-	if( outAddrs )
-	{
-		*outAddrs = head;
-		head = NULL;
-	}
-	err = ERROR_SUCCESS;
-	
-exit:
-	if( head )
-	{
-		freeifaddrs( head );
-	}
-	if( iaaList )
-	{
-		free( iaaList );
-	}
-	return( (int) err );
-}
-
-#endif	// MDNS_WINDOWS_USE_IPV6_IF_ADDRS
-
-//===========================================================================================================================
-//	getifaddrs_ipv4
-//===========================================================================================================================
-
-mDNSlocal int	getifaddrs_ipv4( struct ifaddrs **outAddrs )
-{
-	int						err;
-	SOCKET					sock;
-	DWORD					size;
-	DWORD					actualSize;
-	INTERFACE_INFO *		buffer;
-	INTERFACE_INFO *		tempBuffer;
-	INTERFACE_INFO *		ifInfo;
-	int						n;
-	int						i;
-	struct ifaddrs *		head;
-	struct ifaddrs **		next;
-	struct ifaddrs *		ifa;
-	
-	sock	= INVALID_SOCKET;
-	buffer	= NULL;
-	head	= NULL;
-	next	= &head;
-	
-	// Get the interface list. WSAIoctl is called with SIO_GET_INTERFACE_LIST, but since this does not provide a 
-	// way to determine the size of the interface list beforehand, we have to start with an initial size guess and
-	// call WSAIoctl repeatedly with increasing buffer sizes until it succeeds. Limit this to 100 tries for safety.
-	
-	sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
-	err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-		
-	n = 0;
-	size = 16 * sizeof( INTERFACE_INFO );
-	for( ;; )
-	{
-		tempBuffer = (INTERFACE_INFO *) realloc( buffer, size );
-		require_action( tempBuffer, exit, err = WSAENOBUFS );
-		buffer = tempBuffer;
-		
-		err = WSAIoctl( sock, SIO_GET_INTERFACE_LIST, NULL, 0, buffer, size, &actualSize, NULL, NULL );
-		if( err == 0 )
-		{
-			break;
-		}
-		
-		++n;
-		require_action( n < 100, exit, err = WSAEADDRNOTAVAIL );
-		
-		size += ( 16 * sizeof( INTERFACE_INFO ) );
-	}
-	check( actualSize <= size );
-	check( ( actualSize % sizeof( INTERFACE_INFO ) ) == 0 );
-	n = (int)( actualSize / sizeof( INTERFACE_INFO ) );
-	
-	// Process the raw interface list and build a linked list of IPv4 interfaces.
-	
-	for( i = 0; i < n; ++i )
-	{
-		uint32_t ifIndex;
-		struct sockaddr_in netmask;
-		
-		ifInfo = &buffer[ i ];
-		if( ifInfo->iiAddress.Address.sa_family != AF_INET )
-		{
-			continue;
-		}
-		
-		// <rdar://problem/6220642> iTunes 8: Bonjour doesn't work after upgrading iTunes 8
-		// See comment in getifaddrs_ipv6
-
-		ifIndex = 0;
-		memset( &netmask, 0, sizeof( netmask ) );
-		err = AddressToIndexAndMask( ( struct sockaddr* ) &ifInfo->iiAddress.AddressIn, &ifIndex, ( struct sockaddr* ) &netmask );
-
-		if ( err )
-		{
-			continue;
-		}
-
-		ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
-		require_action( ifa, exit, err = WSAENOBUFS );
-		
-		*next = ifa;
-		next  = &ifa->ifa_next;
-		
-		// Get the name.
-		
-		ifa->ifa_name = (char *) malloc( 16 );
-		require_action( ifa->ifa_name, exit, err = WSAENOBUFS );
-		sprintf( ifa->ifa_name, "%d", i + 1 );
-		
-		// Get interface flags.
-		
-		ifa->ifa_flags = (u_int) ifInfo->iiFlags;
-		
-		// Get addresses.
-		
-		if ( ifInfo->iiAddress.Address.sa_family == AF_INET )
-		{
-			struct sockaddr_in *		sa4;
-			
-			sa4 = &ifInfo->iiAddress.AddressIn;
-			ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( *sa4 ) );
-			require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
-			memcpy( ifa->ifa_addr, sa4, sizeof( *sa4 ) );
-
-			ifa->ifa_netmask = (struct sockaddr*) calloc(1, sizeof( *sa4 ) );
-			require_action( ifa->ifa_netmask, exit, err = WSAENOBUFS );
-
-			// <rdar://problem/4076478> Service won't start on Win2K. The address
-			// family field was not being initialized.
-
-			ifa->ifa_netmask->sa_family = AF_INET;
-			( ( struct sockaddr_in* ) ifa->ifa_netmask )->sin_addr = netmask.sin_addr;
-			ifa->ifa_extra.index = ifIndex;
-		}
-		else
-		{
-			// Emulate an interface index.
-		
-			ifa->ifa_extra.index = (uint32_t)( i + 1 );
-		}
-	}
-	
-	// Success!
-	
-	if( outAddrs )
-	{
-		*outAddrs = head;
-		head = NULL;
-	}
-	err = 0;
-	
-exit:
-
-	if( head )
-	{
-		freeifaddrs( head );
-	}
-	if( buffer )
-	{
-		free( buffer );
-	}
-	if( sock != INVALID_SOCKET )
-	{
-		closesocket( sock );
-	}
-	return( err );
-}
-
-//===========================================================================================================================
-//	freeifaddrs
-//===========================================================================================================================
-
-mDNSlocal void	freeifaddrs( struct ifaddrs *inIFAs )
-{
-	struct ifaddrs *		p;
-	struct ifaddrs *		q;
-	
-	// Free each piece of the structure. Set to null after freeing to handle macro-aliased fields.
-	
-	for( p = inIFAs; p; p = q )
-	{
-		q = p->ifa_next;
-		
-		if( p->ifa_name )
-		{
-			free( p->ifa_name );
-			p->ifa_name = NULL;
-		}
-		if( p->ifa_addr )
-		{
-			free( p->ifa_addr );
-			p->ifa_addr = NULL;
-		}
-		if( p->ifa_netmask )
-		{
-			free( p->ifa_netmask );
-			p->ifa_netmask = NULL;
-		}
-		if( p->ifa_broadaddr )
-		{
-			free( p->ifa_broadaddr );
-			p->ifa_broadaddr = NULL;
-		}
-		if( p->ifa_dstaddr )
-		{
-			free( p->ifa_dstaddr );
-			p->ifa_dstaddr = NULL;
-		}
-		if( p->ifa_data )
-		{
-			free( p->ifa_data );
-			p->ifa_data = NULL;
-		}
-		free( p );
-	}
-}
-
-
-//===========================================================================================================================
-//	GetPrimaryInterface
-//===========================================================================================================================
-
-mDNSlocal DWORD
-GetPrimaryInterface()
-{
-	PMIB_IPFORWARDTABLE	pIpForwardTable	= NULL;
-	DWORD				dwSize			= 0;
-	BOOL				bOrder			= FALSE;
-	OSStatus			err;
-	DWORD				index			= 0;
-	DWORD				metric			= 0;
-	unsigned long int	i;
-
-	// Find out how big our buffer needs to be.
-
-	err = GetIpForwardTable(NULL, &dwSize, bOrder);
-	require_action( err == ERROR_INSUFFICIENT_BUFFER, exit, err = kUnknownErr );
-
-	// Allocate the memory for the table
-
-	pIpForwardTable = (PMIB_IPFORWARDTABLE) malloc( dwSize );
-	require_action( pIpForwardTable, exit, err = kNoMemoryErr );
-  
-	// Now get the table.
-
-	err = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
-	require_noerr( err, exit );
-
-
-	// Search for the row in the table we want.
-
-	for ( i = 0; i < pIpForwardTable->dwNumEntries; i++)
-	{
-		// Look for a default route
-
-		if ( pIpForwardTable->table[i].dwForwardDest == 0 )
-		{
-			if ( index && ( pIpForwardTable->table[i].dwForwardMetric1 >= metric ) )
-			{
-				continue;
-			}
-
-			index	= pIpForwardTable->table[i].dwForwardIfIndex;
-			metric	= pIpForwardTable->table[i].dwForwardMetric1;
-		}
-	}
-
-exit:
-
-	if ( pIpForwardTable != NULL )
-	{
-		free( pIpForwardTable );
-	}
-
-	return index;
-}
-
-
-//===========================================================================================================================
-//	AddressToIndexAndMask
-//===========================================================================================================================
-
-mDNSlocal mStatus
-AddressToIndexAndMask( struct sockaddr * addr, uint32_t * ifIndex, struct sockaddr * mask  )
-{
-	// Before calling AddIPAddress we use GetIpAddrTable to get
-	// an adapter to which we can add the IP.
-	
-	PMIB_IPADDRTABLE	pIPAddrTable	= NULL;
-	DWORD				dwSize			= 0;
-	mStatus				err				= mStatus_UnknownErr;
-	DWORD				i;
-
-	// For now, this is only for IPv4 addresses.  That is why we can safely cast
-	// addr's to sockaddr_in.
-
-	require_action( addr->sa_family == AF_INET, exit, err = mStatus_UnknownErr );
-
-	// Make an initial call to GetIpAddrTable to get the
-	// necessary size into the dwSize variable
-
-	for ( i = 0; i < 100; i++ )
-	{
-		err = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
-
-		if ( err != ERROR_INSUFFICIENT_BUFFER )
-		{
-			break;
-		}
-
-		pIPAddrTable = (MIB_IPADDRTABLE *) realloc( pIPAddrTable, dwSize );
-		require_action( pIPAddrTable, exit, err = WSAENOBUFS );
-	}
-
-	require_noerr( err, exit );
-	err = mStatus_UnknownErr;
-
-	for ( i = 0; i < pIPAddrTable->dwNumEntries; i++ )
-	{
-		if ( ( ( struct sockaddr_in* ) addr )->sin_addr.s_addr == pIPAddrTable->table[i].dwAddr )
-		{
-			*ifIndex											= pIPAddrTable->table[i].dwIndex;
-			( ( struct sockaddr_in*) mask )->sin_addr.s_addr	= pIPAddrTable->table[i].dwMask;
-			err													= mStatus_NoError;
-			break;
-		}
-	}
-
-exit:
-
-	if ( pIPAddrTable )
-	{
-		free( pIPAddrTable );
-	}
-
-	return err;
-}
-
-
-//===========================================================================================================================
-//	CanReceiveUnicast
-//===========================================================================================================================
-
-mDNSlocal mDNSBool	CanReceiveUnicast( void )
-{
-	mDNSBool				ok;
-	SocketRef				sock;
-	struct sockaddr_in		addr;
-	
-	// Try to bind to the port without the SO_REUSEADDR option to test if someone else has already bound to it.
-	
-	sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
-	check_translated_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
-	ok = IsValidSocket( sock );
-	if( ok )
-	{
-		mDNSPlatformMemZero( &addr, sizeof( addr ) );
-		addr.sin_family			= AF_INET;
-		addr.sin_port			= MulticastDNSPort.NotAnInteger;
-		addr.sin_addr.s_addr	= htonl( INADDR_ANY );
-		
-		ok = ( bind( sock, (struct sockaddr *) &addr, sizeof( addr ) ) == 0 );
-		close_compat( sock );
-	}
-	
-	dlog( kDebugLevelInfo, DEBUG_NAME "Unicast UDP responses %s\n", ok ? "okay" : "*not allowed*" );
-	return( ok );
-}
-
-
-//===========================================================================================================================
-//	IsPointToPoint
-//===========================================================================================================================
-
-mDNSlocal mDNSBool IsPointToPoint( IP_ADAPTER_UNICAST_ADDRESS * addr )
-{
-	struct ifaddrs	*	addrs	=	NULL;
-	struct ifaddrs	*	p		=	NULL;
-	OSStatus			err;
-	mDNSBool			ret		=	mDNSfalse;
-
-	// For now, only works for IPv4 interfaces
-
-	if ( addr->Address.lpSockaddr->sa_family == AF_INET )
-	{
-		// The getifaddrs_ipv4 call will give us correct information regarding IFF_POINTTOPOINT flags.
-
-		err = getifaddrs_ipv4( &addrs );
-		require_noerr( err, exit );
-
-		for ( p = addrs; p; p = p->ifa_next )
-		{
-			if ( ( addr->Address.lpSockaddr->sa_family == p->ifa_addr->sa_family ) &&
-			     ( ( ( struct sockaddr_in* ) addr->Address.lpSockaddr )->sin_addr.s_addr == ( ( struct sockaddr_in* ) p->ifa_addr )->sin_addr.s_addr ) )
-			{
-				ret = ( p->ifa_flags & IFF_POINTTOPOINT ) ? mDNStrue : mDNSfalse;
-				break;
-			}
-		}
-	}
-
-exit:
-
-	if ( addrs )
-	{
-		freeifaddrs( addrs );
-	}
-
-	return ret;
-}
-
-
-//===========================================================================================================================
-//	GetWindowsVersionString
-//===========================================================================================================================
-
-mDNSlocal OSStatus	GetWindowsVersionString( char *inBuffer, size_t inBufferSize )
-{
-#if( !defined( VER_PLATFORM_WIN32_CE ) )
-	#define VER_PLATFORM_WIN32_CE		3
-#endif
-
-	OSStatus				err;
-	OSVERSIONINFO			osInfo;
-	BOOL					ok;
-	const char *			versionString;
-	DWORD					platformID;
-	DWORD					majorVersion;
-	DWORD					minorVersion;
-	DWORD					buildNumber;
-	
-	versionString = "unknown Windows version";
-	
-	osInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
-	ok = GetVersionEx( &osInfo );
-	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
-	require_noerr( err, exit );
-	
-	platformID		= osInfo.dwPlatformId;
-	majorVersion	= osInfo.dwMajorVersion;
-	minorVersion	= osInfo.dwMinorVersion;
-	buildNumber		= osInfo.dwBuildNumber & 0xFFFF;
-	
-	if( ( platformID == VER_PLATFORM_WIN32_WINDOWS ) && ( majorVersion == 4 ) )
-	{
-		if( ( minorVersion < 10 ) && ( buildNumber == 950 ) )
-		{
-			versionString	= "Windows 95";
-		}
-		else if( ( minorVersion < 10 ) && ( ( buildNumber > 950 ) && ( buildNumber <= 1080 ) ) )
-		{
-			versionString	= "Windows 95 SP1";
-		}
-		else if( ( minorVersion < 10 ) && ( buildNumber > 1080 ) )
-		{
-			versionString	= "Windows 95 OSR2";
-		}
-		else if( ( minorVersion == 10 ) && ( buildNumber == 1998 ) )
-		{
-			versionString	= "Windows 98";
-		}
-		else if( ( minorVersion == 10 ) && ( ( buildNumber > 1998 ) && ( buildNumber < 2183 ) ) )
-		{
-			versionString	= "Windows 98 SP1";
-		}
-		else if( ( minorVersion == 10 ) && ( buildNumber >= 2183 ) )
-		{
-			versionString	= "Windows 98 SE";
-		}
-		else if( minorVersion == 90 )
-		{
-			versionString	= "Windows ME";
-		}
-	}
-	else if( platformID == VER_PLATFORM_WIN32_NT )
-	{
-		if( ( majorVersion == 3 ) && ( minorVersion == 51 ) )
-		{
-			versionString	= "Windows NT 3.51";
-		}
-		else if( ( majorVersion == 4 ) && ( minorVersion == 0 ) )
-		{
-			versionString	= "Windows NT 4";
-		}
-		else if( ( majorVersion == 5 ) && ( minorVersion == 0 ) )
-		{
-			versionString	= "Windows 2000";
-		}
-		else if( ( majorVersion == 5 ) && ( minorVersion == 1 ) )
-		{
-			versionString	= "Windows XP";
-		}
-		else if( ( majorVersion == 5 ) && ( minorVersion == 2 ) )
-		{
-			versionString	= "Windows Server 2003";
-		}
-	}
-	else if( platformID == VER_PLATFORM_WIN32_CE )
-	{
-		versionString		= "Windows CE";
-	}
-	
-exit:
-	if( inBuffer && ( inBufferSize > 0 ) )
-	{
-		inBufferSize -= 1;
-		strncpy( inBuffer, versionString, inBufferSize );
-		inBuffer[ inBufferSize ] = '\0';
-	}
-	return( err );
-}
-
-
-//===========================================================================================================================
-//	RegQueryString
-//===========================================================================================================================
-
-mDNSlocal mStatus
-RegQueryString( HKEY key, LPCSTR valueName, LPSTR * string, DWORD * stringLen, DWORD * enabled )
-{
-	DWORD	type;
-	int		i;
-	mStatus err;
-
-	*stringLen	= MAX_ESCAPED_DOMAIN_NAME;
-	*string		= NULL;
-	i			= 0;
-
-	do
-	{
-		if ( *string )
-		{
-			free( *string );
-		}
-
-		*string = (char*) malloc( *stringLen );
-		require_action( *string, exit, err = mStatus_NoMemoryErr );
-
-		err = RegQueryValueExA( key, valueName, 0, &type, (LPBYTE) *string, stringLen );
-
-		i++;
-	}
-	while ( ( err == ERROR_MORE_DATA ) && ( i < 100 ) );
-
-	require_noerr_quiet( err, exit );
-
-	if ( enabled )
-	{
-		DWORD dwSize = sizeof( DWORD );
-
-		err = RegQueryValueEx( key, TEXT("Enabled"), NULL, NULL, (LPBYTE) enabled, &dwSize );
-		check_noerr( err );
-
-		err = kNoErr;
-	}
-
-exit:
-
-	return err;
-}
-
-
-//===========================================================================================================================
-//	StringToAddress
-//===========================================================================================================================
-
-mDNSlocal mStatus StringToAddress( mDNSAddr * ip, LPSTR string )
-{
-	struct sockaddr_in6 sa6;
-	struct sockaddr_in	sa4;
-	INT					dwSize;
-	mStatus				err;
-
-	sa6.sin6_family	= AF_INET6;
-	dwSize			= sizeof( sa6 );
-
-	err = WSAStringToAddressA( string, AF_INET6, NULL, (struct sockaddr*) &sa6, &dwSize );
-
-	if ( err == mStatus_NoError )
-	{
-		err = SetupAddr( ip, (struct sockaddr*) &sa6 );
-		require_noerr( err, exit );
-	}
-	else
-	{
-		sa4.sin_family = AF_INET;
-		dwSize = sizeof( sa4 );
-
-		err = WSAStringToAddressA( string, AF_INET, NULL, (struct sockaddr*) &sa4, &dwSize );
-		err = translate_errno( err == 0, WSAGetLastError(), kUnknownErr );
-		require_noerr( err, exit );
-			
-		err = SetupAddr( ip, (struct sockaddr*) &sa4 );
-		require_noerr( err, exit );
-	}
-
-exit:
-
-	return err;
-}
-
-
-//===========================================================================================================================
-//	myGetIfAddrs
-//===========================================================================================================================
-
-mDNSlocal struct ifaddrs*
-myGetIfAddrs(int refresh)
-{
-	static struct ifaddrs *ifa = NULL;
-	
-	if (refresh && ifa)
-	{
-		freeifaddrs(ifa);
-		ifa = NULL;
-	}
-	
-	if (ifa == NULL)
-	{
-		getifaddrs(&ifa);
-	}
-	
-	return ifa;
-}
-
-
-//===========================================================================================================================
-//	TCHARtoUTF8
-//===========================================================================================================================
-
-mDNSlocal OSStatus
-TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize )
-{
-#if( defined( UNICODE ) || defined( _UNICODE ) )
-	OSStatus		err;
-	int				len;
-	
-	len = WideCharToMultiByte( CP_UTF8, 0, inString, -1, inBuffer, (int) inBufferSize, NULL, NULL );
-	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-	
-exit:
-	return( err );
-#else
-	return( WindowsLatin1toUTF8( inString, inBuffer, inBufferSize ) );
-#endif
-}
-
-
-//===========================================================================================================================
-//	WindowsLatin1toUTF8
-//===========================================================================================================================
-
-mDNSlocal OSStatus
-WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize )
-{
-	OSStatus		err;
-	WCHAR *			utf16;
-	int				len;
-	
-	utf16 = NULL;
-	
-	// Windows doesn't support going directly from Latin-1 to UTF-8 so we have to go from Latin-1 to UTF-16 first.
-	
-	len = MultiByteToWideChar( CP_ACP, 0, inString, -1, NULL, 0 );
-	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-	
-	utf16 = (WCHAR *) malloc( len * sizeof( *utf16 ) );
-	require_action( utf16, exit, err = kNoMemoryErr );
-	
-	len = MultiByteToWideChar( CP_ACP, 0, inString, -1, utf16, len );
-	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-	
-	// Now convert the temporary UTF-16 to UTF-8.
-	
-	len = WideCharToMultiByte( CP_UTF8, 0, utf16, -1, inBuffer, (int) inBufferSize, NULL, NULL );
-	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
-	require_noerr( err, exit );
-
-exit:
-	if( utf16 ) free( utf16 );
-	return( err );
-}
-
-
-//===========================================================================================================================
-//	TCPCloseSocket
-//===========================================================================================================================
-
-mDNSlocal void
-TCPCloseSocket( TCPSocket * sock )
-{
-	dlog( kDebugLevelChatty, DEBUG_NAME "closing TCPSocket 0x%x:%d\n", sock, sock->fd );
-
-	if ( sock->fd != INVALID_SOCKET )
-	{
-		closesocket( sock->fd );
-		sock->fd = INVALID_SOCKET;
-	}
-}
-
-
-//===========================================================================================================================
-//  UDPCloseSocket
-//===========================================================================================================================
-
-mDNSlocal void
-UDPCloseSocket( UDPSocket * sock )
-{
-	dlog( kDebugLevelChatty, DEBUG_NAME "closing UDPSocket %d\n", sock->fd );
-
-	if ( sock->fd != INVALID_SOCKET )
-	{
-		mDNSPollUnregisterSocket( sock->fd );
-		closesocket( sock->fd );
-		sock->fd = INVALID_SOCKET;
-	}
-}
-
-
-//===========================================================================================================================
-//	SetupAddr
-//===========================================================================================================================
-
-mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
-	{
-	if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
-
-	if (sa->sa_family == AF_INET)
-		{
-		struct sockaddr_in *ifa_addr = (struct sockaddr_in *)sa;
-		ip->type = mDNSAddrType_IPv4;
-		ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr;
-		return(mStatus_NoError);
-		}
-
-	if (sa->sa_family == AF_INET6)
-		{
-		struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
-		ip->type = mDNSAddrType_IPv6;
-		if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.u.Word[1] = 0;
-		ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
-		return(mStatus_NoError);
-		}
-
-	LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
-	return(mStatus_Invalid);
-	}
-
-
-mDNSlocal void GetDDNSFQDN( domainname *const fqdn )
-{
-	LPSTR		name = NULL;
-	DWORD		dwSize;
-	DWORD		enabled;
-	HKEY		key = NULL;
-	OSStatus	err;
-
-	check( fqdn );
-
-	// Initialize
-
-	fqdn->c[0] = '\0';
-
-	// Get info from Bonjour registry key
-
-	err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSHostNames, &key );
-	require_noerr( err, exit );
-
-	err = RegQueryString( key, "", &name, &dwSize, &enabled );
-	if ( !err && ( name[0] != '\0' ) && enabled )
-	{
-		if ( !MakeDomainNameFromDNSNameString( fqdn, name ) || !fqdn->c[0] )
-		{
-			dlog( kDebugLevelError, "bad DDNS host name in registry: %s", name[0] ? name : "(unknown)");
-		}
-	}
-
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-		key = NULL;
-	}
-
-	if ( name )
-	{
-		free( name );
-		name = NULL;
-	}
-}
-
-
-#ifdef UNICODE
-mDNSlocal void GetDDNSDomains( DNameListElem ** domains, LPCWSTR lpSubKey )
-#else
-mDNSlocal void GetDDNSConfig( DNameListElem ** domains, LPCSTR lpSubKey )
-#endif
-{
-	char		subKeyName[kRegistryMaxKeyLength + 1];
-	DWORD		cSubKeys = 0;
-	DWORD		cbMaxSubKey;
-	DWORD		cchMaxClass;
-	DWORD		dwSize;
-	HKEY		key = NULL;
-	HKEY		subKey = NULL;
-	domainname	dname;
-	DWORD		i;
-	OSStatus	err;
-
-	check( domains );
-
-	// Initialize
-
-	*domains = NULL;
-
-	err = RegCreateKey( HKEY_LOCAL_MACHINE, lpSubKey, &key );
-	require_noerr( err, exit );
-
-	// Get information about this node
-
-	err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
-	require_noerr( err, exit );
-
-	for ( i = 0; i < cSubKeys; i++)
-	{
-		DWORD enabled;
-
-		dwSize = kRegistryMaxKeyLength;
-        
-		err = RegEnumKeyExA( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
-
-		if ( !err )
-		{
-			err = RegOpenKeyExA( key, subKeyName, 0, KEY_READ, &subKey );
-			require_noerr( err, exit );
-
-			dwSize = sizeof( DWORD );
-			err = RegQueryValueExA( subKey, "Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
-
-			if ( !err && ( subKeyName[0] != '\0' ) && enabled )
-			{
-				if ( !MakeDomainNameFromDNSNameString( &dname, subKeyName ) || !dname.c[0] )
-				{
-					dlog( kDebugLevelError, "bad DDNS domain in registry: %s", subKeyName[0] ? subKeyName : "(unknown)");
-				}
-				else
-				{
-					DNameListElem * domain = (DNameListElem*) malloc( sizeof( DNameListElem ) );
-					require_action( domain, exit, err = mStatus_NoMemoryErr );
-					
-					AssignDomainName(&domain->name, &dname);
-					domain->next = *domains;
-
-					*domains = domain;
-				}
-			}
-
-			RegCloseKey( subKey );
-			subKey = NULL;
-		}
-	}
-
-exit:
-
-	if ( subKey )
-	{
-		RegCloseKey( subKey );
-	}
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-}
-
-
-mDNSlocal void SetDomainSecret( mDNS * const m, const domainname * inDomain )
-{
-	char					domainUTF8[ 256 ];
-	DomainAuthInfo			*foundInList;
-	DomainAuthInfo			*ptr;
-	char					outDomain[ 256 ];
-	char					outKey[ 256 ];
-	char					outSecret[ 256 ];
-	OSStatus				err;
-	
-	ConvertDomainNameToCString( inDomain, domainUTF8 );
-	
-	// If we're able to find a secret for this domain
-
-	if ( LsaGetSecret( domainUTF8, outDomain, sizeof( outDomain ), outKey, sizeof( outKey ), outSecret, sizeof( outSecret ) ) )
-	{
-		domainname domain;
-		domainname key;
-
-		// Tell the core about this secret
-
-		MakeDomainNameFromDNSNameString( &domain, outDomain );
-		MakeDomainNameFromDNSNameString( &key, outKey );
-
-		for (foundInList = m->AuthInfoList; foundInList; foundInList = foundInList->next)
-			if (SameDomainName(&foundInList->domain, &domain ) ) break;
-
-		ptr = foundInList;
-	
-		if (!ptr)
-		{
-			ptr = (DomainAuthInfo*)malloc(sizeof(DomainAuthInfo));
-			require_action( ptr, exit, err = mStatus_NoMemoryErr );
-		}
-
-		err = mDNS_SetSecretForDomain(m, ptr, &domain, &key, outSecret, NULL, NULL, FALSE );
-		require_action( err != mStatus_BadParamErr, exit, if (!foundInList ) mDNSPlatformMemFree( ptr ) );
-
-		debugf("Setting shared secret for zone %s with key %##s", outDomain, key.c);
-	}
-
-exit:
-
-	return;
-}
-
-
-mDNSlocal VOID CALLBACK
-CheckFileSharesProc( LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue )
-{
-	mDNS * const m = ( mDNS * const ) arg;
-
-	( void ) dwTimerLowValue;
-	( void ) dwTimerHighValue;
-
-	CheckFileShares( m );
-}
-
-
-mDNSlocal unsigned __stdcall 
-SMBRegistrationThread( void * arg )
-{
-	mDNS * const m = ( mDNS * const ) arg;
-	DNSServiceRef sref = NULL;
-	HANDLE		handles[ 3 ];
-	mDNSu8		txtBuf[ 256 ];
-	mDNSu8	*	txtPtr;
-	size_t		keyLen;
-	size_t		valLen;
-	mDNSIPPort	port = { { SMBPortAsNumber >> 8, SMBPortAsNumber & 0xFF } };
-	DNSServiceErrorType err;
-
-	DEBUG_UNUSED( arg );
-
-	handles[ 0 ] = gSMBThreadStopEvent;
-	handles[ 1 ] = gSMBThreadRegisterEvent;
-	handles[ 2 ] = gSMBThreadDeregisterEvent;
-
-	memset( txtBuf, 0, sizeof( txtBuf )  );
-	txtPtr = txtBuf;
-	keyLen = strlen( "netbios=" );
-	valLen = strlen( m->p->nbname );
-	require_action( valLen < 32, exit, err = kUnknownErr );	// This should never happen, but check to avoid further memory corruption
-	*txtPtr++ = ( mDNSu8 ) ( keyLen + valLen );
-	memcpy( txtPtr, "netbios=", keyLen );
-	txtPtr += keyLen;
-	if ( valLen ) { memcpy( txtPtr, m->p->nbname, valLen ); txtPtr += ( mDNSu8 ) valLen; }
-	keyLen = strlen( "domain=" );
-	valLen = strlen( m->p->nbdomain );
-	require_action( valLen < 32, exit, err = kUnknownErr );	// This should never happen, but check to avoid further memory corruption
-	*txtPtr++ = ( mDNSu8 )( keyLen + valLen );
-	memcpy( txtPtr, "domain=", keyLen );
-	txtPtr += keyLen;
-	if ( valLen ) { memcpy( txtPtr, m->p->nbdomain, valLen ); txtPtr += valLen; }
-	
-	for ( ;; )
-	{
-		DWORD ret;
-
-		ret = WaitForMultipleObjects( 3, handles, FALSE, INFINITE );
-
-		if ( ret != WAIT_FAILED )
-		{
-			if ( ret == kSMBStopEvent )
-			{
-				break;
-			}
-			else if ( ret == kSMBRegisterEvent )
-			{
-				err = gDNSServiceRegister( &sref, 0, 0, NULL, "_smb._tcp,_file", NULL, NULL, ( uint16_t ) port.NotAnInteger, ( mDNSu16 )( txtPtr - txtBuf ), txtBuf, NULL, NULL );
-
-				if ( err )
-				{
-					LogMsg( "SMBRegistrationThread: DNSServiceRegister returned %d\n", err );
-					sref = NULL;
-					break;
-				}
-			}
-			else if ( ret == kSMBDeregisterEvent )
-			{
-				if ( sref )
-				{
-					gDNSServiceRefDeallocate( sref );
-					sref = NULL;
-				}
-			}
-		}
-		else
-		{
-			LogMsg( "SMBRegistrationThread:  WaitForMultipleObjects returned %d\n", GetLastError() );
-			break;
-		}
-	}
-
-exit:
-
-	if ( sref != NULL )
-	{
-		gDNSServiceRefDeallocate( sref );
-		sref = NULL;
-	}
-
-	SetEvent( gSMBThreadQuitEvent );
-	_endthreadex( 0 );
-	return 0;
-}
-
-
-mDNSlocal void
-CheckFileShares( mDNS * const m )
-{
-	PSHARE_INFO_1	bufPtr = ( PSHARE_INFO_1 ) NULL;
-	DWORD			entriesRead = 0;
-	DWORD			totalEntries = 0;
-	DWORD			resume = 0;
-	mDNSBool		advertise = mDNSfalse;
-	mDNSBool		fileSharing = mDNSfalse;
-	mDNSBool		printSharing = mDNSfalse;
-	HKEY			key = NULL;
-	BOOL			retry = FALSE;
-	NET_API_STATUS  res;
-	mStatus			err;
-
-	check( m );
-
-	// Only do this if we're not shutting down
-
-	require_action_quiet( m->AdvertiseLocalAddresses && !m->ShutdownTime, exit, err = kNoErr );
-
-	err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Services\\SMB", &key );
-
-	if ( !err )
-	{
-		DWORD dwSize = sizeof( DWORD );
-		RegQueryValueEx( key, L"Advertise", NULL, NULL, (LPBYTE) &advertise, &dwSize );
-	}
-
-	if ( advertise && mDNSIsFileAndPrintSharingEnabled( &retry ) )
-	{
-		dlog( kDebugLevelTrace, DEBUG_NAME "Sharing is enabled\n" );
-
-		res = NetShareEnum( NULL, 1, ( LPBYTE* )&bufPtr, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resume );
-
-		if ( ( res == ERROR_SUCCESS ) || ( res == ERROR_MORE_DATA ) )
-		{
-			PSHARE_INFO_1 p = bufPtr;
-			DWORD i;
-
-			for( i = 0; i < entriesRead; i++ ) 
-			{
-				// We are only interested if the user is sharing anything other 
-				// than the built-in "print$" source
-
-				if ( ( p->shi1_type == STYPE_DISKTREE ) && ( wcscmp( p->shi1_netname, TEXT( "print$" ) ) != 0 ) )
-				{
-					fileSharing = mDNStrue;
-				}
-				else if ( p->shi1_type == STYPE_PRINTQ )
-				{
-					printSharing = mDNStrue;
-				}
-
-				p++;
-			}
-
-			NetApiBufferFree( bufPtr );
-			bufPtr = NULL;
-			retry = FALSE;
-		}
-		else if ( res == NERR_ServerNotStarted )
-		{
-			retry = TRUE;
-		}
-	}
-	
-	if ( retry )
-	{
-		__int64			qwTimeout;
-		LARGE_INTEGER   liTimeout;
-
-		qwTimeout = -m->p->checkFileSharesTimeout * 10000000;
-		liTimeout.LowPart  = ( DWORD )( qwTimeout & 0xFFFFFFFF );
-		liTimeout.HighPart = ( LONG )( qwTimeout >> 32 );
-
-		SetWaitableTimer( m->p->checkFileSharesTimer, &liTimeout, 0, CheckFileSharesProc, m, FALSE );
-	}
-
-	if ( !m->p->smbFileSharing && fileSharing )
-	{
-		if ( !gSMBThread )
-		{
-			if ( !gDNSSDLibrary )
-			{
-				gDNSSDLibrary = LoadLibrary( TEXT( "dnssd.dll" ) );
-				require_action( gDNSSDLibrary, exit, err = GetLastError() );
-			}
-
-			if ( !gDNSServiceRegister )
-			{
-				gDNSServiceRegister = ( DNSServiceRegisterFunc ) GetProcAddress( gDNSSDLibrary, "DNSServiceRegister" );
-				require_action( gDNSServiceRegister, exit, err = GetLastError() );
-			}
-
-			if ( !gDNSServiceRefDeallocate )
-			{
-				gDNSServiceRefDeallocate = ( DNSServiceRefDeallocateFunc ) GetProcAddress( gDNSSDLibrary, "DNSServiceRefDeallocate" );
-				require_action( gDNSServiceRefDeallocate, exit, err = GetLastError() );
-			}
-
-			if ( !gSMBThreadRegisterEvent )
-			{
-				gSMBThreadRegisterEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
-				require_action( gSMBThreadRegisterEvent != NULL, exit, err = GetLastError() );
-			}
-
-			if ( !gSMBThreadDeregisterEvent )
-			{
-				gSMBThreadDeregisterEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
-				require_action( gSMBThreadDeregisterEvent != NULL, exit, err = GetLastError() );
-			}
-
-			if ( !gSMBThreadStopEvent )
-			{
-				gSMBThreadStopEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
-				require_action( gSMBThreadStopEvent != NULL, exit, err = GetLastError() );
-			}
-
-			if ( !gSMBThreadQuitEvent )
-			{
-				gSMBThreadQuitEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
-				require_action( gSMBThreadQuitEvent != NULL, exit, err = GetLastError() );
-			}
-
-			gSMBThread = ( HANDLE ) _beginthreadex( NULL, 0, SMBRegistrationThread, m, 0, NULL );
-			require_action( gSMBThread != NULL, exit, err = GetLastError() );
-		}
-
-		SetEvent( gSMBThreadRegisterEvent );
-
-		m->p->smbFileSharing = mDNStrue;
-	}
-	else if ( m->p->smbFileSharing && !fileSharing )
-	{
-		dlog( kDebugLevelTrace, DEBUG_NAME "deregistering smb type\n" );
-
-		if ( gSMBThreadDeregisterEvent != NULL )
-		{
-			SetEvent( gSMBThreadDeregisterEvent );
-		}
-
-		m->p->smbFileSharing = mDNSfalse;
-	}
-
-exit:
-
-	if ( key )
-	{
-		RegCloseKey( key );
-	}
-}
-
-
-BOOL
-IsWOMPEnabled( mDNS * const m )
-{
-	BOOL enabled;
-
-	mDNSInterfaceData * ifd;
-
-	enabled = FALSE;
-
-	for( ifd = m->p->interfaceList; ifd; ifd = ifd->next )
-	{
-		if ( IsWOMPEnabledForAdapter( ifd->name ) )
-		{
-			enabled = TRUE;
-			break;
-		}
-	}
-
-	return enabled;
-}
-
-
-mDNSlocal mDNSu8
-IsWOMPEnabledForAdapter( const char * adapterName )
-{
-	char						fileName[80];
-	NDIS_OID					oid;
-    DWORD						count;
-    HANDLE						handle	= INVALID_HANDLE_VALUE;
-	NDIS_PNP_CAPABILITIES	*	pNPC	= NULL;
-	int							err;
-	mDNSu8						ok		= TRUE;
-
-	require_action( adapterName != NULL, exit, ok = FALSE );
-
-	dlog( kDebugLevelTrace, DEBUG_NAME "IsWOMPEnabledForAdapter: %s\n", adapterName );
-	
-    // Construct a device name to pass to CreateFile
-
-	strncpy_s( fileName, sizeof( fileName ), DEVICE_PREFIX, strlen( DEVICE_PREFIX ) );
-	strcat_s( fileName, sizeof( fileName ), adapterName );
-    handle = CreateFileA( fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, INVALID_HANDLE_VALUE );
-	require_action ( handle != INVALID_HANDLE_VALUE, exit, ok = FALSE );
-
-	// We successfully opened the driver, format the IOCTL to pass the driver.
-		
-	oid = OID_PNP_CAPABILITIES;
-	pNPC = ( NDIS_PNP_CAPABILITIES * ) malloc( sizeof( NDIS_PNP_CAPABILITIES ) );
-	require_action( pNPC != NULL, exit, ok = FALSE );
-	ok = ( mDNSu8 ) DeviceIoControl( handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof( oid ), pNPC, sizeof( NDIS_PNP_CAPABILITIES ), &count, NULL );
-	err = translate_errno( ok, GetLastError(), kUnknownErr );
-	require_action( !err, exit, ok = FALSE );
-	ok = ( mDNSu8 ) ( ( count == sizeof( NDIS_PNP_CAPABILITIES ) ) && ( pNPC->Flags & NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE ) );
-       
-exit:
-
-	if ( pNPC != NULL )
-	{
-		free( pNPC );
-	}
-
-    if ( handle != INVALID_HANDLE_VALUE )
-    {
-		CloseHandle( handle );
-    }
-
-	dlog( kDebugLevelTrace, DEBUG_NAME "IsWOMPEnabledForAdapter returns %s\n", ok ? "true" : "false" );
-
-	return ( mDNSu8 ) ok;
-}
-
-
-mDNSlocal void
-SendWakeupPacket( mDNS * const inMDNS, LPSOCKADDR addr, INT addrlen, const char * buf, INT buflen, INT numTries, INT msecSleep )
-{
-	mDNSBool	repeat = ( numTries == 1 ) ? mDNStrue : mDNSfalse;
-	SOCKET		sock;
-	int			num;
-	mStatus		err;
-
-	( void ) inMDNS;
-
-	sock = socket( addr->sa_family, SOCK_DGRAM, IPPROTO_UDP );
-	require_action( sock != INVALID_SOCKET, exit, err = mStatus_UnknownErr );
-
-	while ( numTries-- )
-	{
-		num = sendto( sock, ( const char* ) buf, buflen, 0, addr, addrlen );
-
-		if ( num != buflen )
-		{
-			LogMsg( "SendWakeupPacket error: sent %d bytes: %d\n", num, WSAGetLastError() );
-		}
-
-		if ( repeat )
-		{
-			num = sendto( sock, buf, buflen, 0, addr, addrlen );
-
-			if ( num != buflen )
-			{
-				LogMsg( "SendWakeupPacket error: sent %d bytes: %d\n", num, WSAGetLastError() );
-			}
-		}
-
-		if ( msecSleep )
-		{
-			Sleep( msecSleep );
-		}
-	}
-
-exit:
-
-	if ( sock != INVALID_SOCKET )
-	{
-		closesocket( sock );
-	}
-} 
-
-
-mDNSlocal void _cdecl
-SendMulticastWakeupPacket( void *arg )
-{
-	MulticastWakeupStruct *info = ( MulticastWakeupStruct* ) arg;
-	
-	if ( info )
-	{
-		SendWakeupPacket( info->inMDNS, ( LPSOCKADDR ) &info->addr, sizeof( info->addr ), ( const char* ) info->data, sizeof( info->data ), info->numTries, info->msecSleep );
-		free( info );
-	}
-
-	_endthread();
-}
-
-
-mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-	DEBUG_UNUSED( m );
-	DEBUG_UNUSED( rr );
-	DEBUG_UNUSED( result );
-}

Copied: vendor/apple/mDNSResponder/561.1.1/mDNSWindows/mDNSWin32.c (from rev 6984, vendor/apple/mDNSResponder/dist/mDNSWindows/mDNSWin32.c)
===================================================================
--- vendor/apple/mDNSResponder/561.1.1/mDNSWindows/mDNSWin32.c	                        (rev 0)
+++ vendor/apple/mDNSResponder/561.1.1/mDNSWindows/mDNSWin32.c	2015-03-20 01:14:52 UTC (rev 6985)
@@ -0,0 +1,5197 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2002-2013 Apple Computer, 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.
+
+	To Do:
+	
+	- Get unicode name of machine for nice name instead of just the host name.
+	- Use the IPv6 Internet Connection Firewall API to allow IPv6 mDNS without manually changing the firewall.
+	- Get DNS server address(es) from Windows and provide them to the uDNS layer.
+	- Implement TCP support for truncated packets (only stubs now).	
+
+*/
+
+#define _CRT_RAND_S
+
+#include	<stdarg.h>
+#include	<stddef.h>
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<crtdbg.h>
+#include	<string.h>
+
+#include	"Poll.h"
+#include	"CommonServices.h"
+#include	"DebugServices.h"
+#include	"Firewall.h"
+#include	"RegNames.h"
+#include	"Secret.h"
+#include	<dns_sd.h>
+
+#include	<Iphlpapi.h>
+#include	<mswsock.h>
+#include	<process.h>
+#include	<ntsecapi.h>
+#include	<lm.h>
+#include	<winioctl.h>
+#include	<ntddndis.h>        // This defines the IOCTL constants.
+
+#include	"mDNSEmbeddedAPI.h"
+#include	"GenLinkedList.h"
+#include	"DNSCommon.h"
+#include	"mDNSWin32.h"
+#include    "dnssec.h"
+#include    "nsec.h"
+
+#if 0
+#pragma mark == Constants ==
+#endif
+
+//===========================================================================================================================
+//	Constants
+//===========================================================================================================================
+
+#define	DEBUG_NAME									"[mDNSWin32] "
+
+#define	MDNS_WINDOWS_USE_IPV6_IF_ADDRS				1
+#define	MDNS_WINDOWS_ENABLE_IPV4					1
+#define	MDNS_WINDOWS_ENABLE_IPV6					1
+#define	MDNS_FIX_IPHLPAPI_PREFIX_BUG				1
+#define MDNS_SET_HINFO_STRINGS						0
+
+#define	kMDNSDefaultName							"My Computer"
+
+#define	kWinSockMajorMin							2
+#define	kWinSockMinorMin							2
+
+#define kRegistryMaxKeyLength						255
+#define kRegistryMaxValueName						16383
+
+static GUID											kWSARecvMsgGUID = WSAID_WSARECVMSG;
+
+#define kIPv6IfIndexBase							(10000000L)
+#define SMBPortAsNumber								445
+#define DEVICE_PREFIX								"\\\\.\\"
+
+#if 0
+#pragma mark == Prototypes ==
+#endif
+
+//===========================================================================================================================
+//	Prototypes
+//===========================================================================================================================
+
+mDNSlocal mStatus			SetupNiceName( mDNS * const inMDNS );
+mDNSlocal mStatus			SetupHostName( mDNS * const inMDNS );
+mDNSlocal mStatus			SetupName( mDNS * const inMDNS );
+mDNSlocal mStatus			SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD );
+mDNSlocal mStatus			TearDownInterface( mDNS * const inMDNS, mDNSInterfaceData *inIFD );
+mDNSlocal void CALLBACK		FreeInterface( mDNSInterfaceData *inIFD );
+mDNSlocal mStatus			SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAddr, mDNSIPPort port, SocketRef *outSocketRef  );
+mDNSlocal mStatus			SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP, mDNSIPPort *outPort );
+mDNSlocal OSStatus			GetWindowsVersionString( char *inBuffer, size_t inBufferSize );
+mDNSlocal int				getifaddrs( struct ifaddrs **outAddrs );
+mDNSlocal void				freeifaddrs( struct ifaddrs *inAddrs );
+
+
+
+// Platform Accessors
+
+#ifdef	__cplusplus
+	extern "C" {
+#endif
+
+typedef struct mDNSPlatformInterfaceInfo	mDNSPlatformInterfaceInfo;
+struct	mDNSPlatformInterfaceInfo
+{
+	const char *		name;
+	mDNSAddr			ip;
+};
+
+
+mDNSexport mStatus	mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID );
+mDNSexport mStatus	mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo );
+
+
+// Wakeup Structs
+
+#define kUnicastWakeupNumTries				( 1 )
+#define kUnicastWakeupSleepBetweenTries		( 0 )
+#define kMulticastWakeupNumTries			( 18 )
+#define kMulticastWakeupSleepBetweenTries	( 100 )
+
+typedef struct MulticastWakeupStruct
+{
+	mDNS					*inMDNS;
+	struct sockaddr_in		addr;
+	INT						addrLen;
+	unsigned char			data[ 102 ];
+	INT						dataLen;
+	INT						numTries;
+	INT						msecSleep;
+} MulticastWakeupStruct;
+
+
+// Utilities
+
+#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
+	mDNSlocal int	getifaddrs_ipv6( struct ifaddrs **outAddrs );
+#endif
+
+mDNSlocal int getifaddrs_ipv4( struct ifaddrs **outAddrs );
+
+
+mDNSlocal DWORD				GetPrimaryInterface();
+mDNSlocal mStatus			AddressToIndexAndMask( struct sockaddr * address, uint32_t * index, struct sockaddr * mask );
+mDNSlocal mDNSBool			CanReceiveUnicast( void );
+mDNSlocal mDNSBool			IsPointToPoint( IP_ADAPTER_UNICAST_ADDRESS * addr );
+
+mDNSlocal mStatus			StringToAddress( mDNSAddr * ip, LPSTR string );
+mDNSlocal mStatus			RegQueryString( HKEY key, LPCSTR param, LPSTR * string, DWORD * stringLen, DWORD * enabled );
+mDNSlocal struct ifaddrs*	myGetIfAddrs(int refresh);
+mDNSlocal OSStatus			TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize );
+mDNSlocal OSStatus			WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize );
+mDNSlocal void CALLBACK		TCPSocketNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context );
+mDNSlocal void				TCPCloseSocket( TCPSocket * socket );
+mDNSlocal void CALLBACK		UDPSocketNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context );
+mDNSlocal void				UDPCloseSocket( UDPSocket * sock );
+mDNSlocal mStatus           SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa);
+mDNSlocal void				GetDDNSFQDN( domainname *const fqdn );
+#ifdef UNICODE
+mDNSlocal void				GetDDNSDomains( DNameListElem ** domains, LPCWSTR lpSubKey );
+#else
+mDNSlocal void				GetDDNSDomains( DNameListElem ** domains, LPCSTR lpSubKey );
+#endif
+mDNSlocal void				SetDomainSecrets( mDNS * const inMDNS );
+mDNSlocal void				SetDomainSecret( mDNS * const m, const domainname * inDomain );
+mDNSlocal VOID CALLBACK		CheckFileSharesProc( LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue );
+mDNSlocal void				CheckFileShares( mDNS * const inMDNS );
+mDNSlocal void				SMBCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus result);
+mDNSlocal mDNSu8			IsWOMPEnabledForAdapter( const char * adapterName );
+mDNSlocal void				SendWakeupPacket( mDNS * const inMDNS, LPSOCKADDR addr, INT addrlen, const char * buf, INT buflen, INT numTries, INT msecSleep );
+mDNSlocal void _cdecl		SendMulticastWakeupPacket( void *arg );
+
+#ifdef	__cplusplus
+	}
+#endif
+
+#if 0
+#pragma mark == Globals ==
+#endif
+
+//===========================================================================================================================
+//	Globals
+//===========================================================================================================================
+
+mDNSlocal mDNS_PlatformSupport	gMDNSPlatformSupport;
+mDNSs32							mDNSPlatformOneSecond	= 0;
+mDNSlocal UDPSocket		*		gUDPSockets				= NULL;
+mDNSlocal int					gUDPNumSockets			= 0;
+mDNSlocal BOOL					gEnableIPv6				= TRUE;
+
+#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
+
+	typedef DWORD
+		( WINAPI * GetAdaptersAddressesFunctionPtr )( 
+			ULONG 					inFamily, 
+			DWORD 					inFlags, 
+			PVOID 					inReserved, 
+			PIP_ADAPTER_ADDRESSES 	inAdapter, 
+			PULONG					outBufferSize );
+
+	mDNSlocal HMODULE								gIPHelperLibraryInstance			= NULL;
+	mDNSlocal GetAdaptersAddressesFunctionPtr		gGetAdaptersAddressesFunctionPtr	= NULL;
+
+#endif
+
+
+#ifndef HCRYPTPROV
+   typedef ULONG_PTR HCRYPTPROV;    // WinCrypt.h, line 249
+#endif
+
+
+#ifndef CRYPT_MACHINE_KEYSET
+#	define CRYPT_MACHINE_KEYSET    0x00000020
+#endif
+
+#ifndef CRYPT_NEWKEYSET
+#	define CRYPT_NEWKEYSET         0x00000008
+#endif
+
+#ifndef PROV_RSA_FULL
+#  define PROV_RSA_FULL 1
+#endif
+
+typedef BOOL (__stdcall *fnCryptGenRandom)( HCRYPTPROV, DWORD, BYTE* ); 
+typedef BOOL (__stdcall *fnCryptAcquireContext)( HCRYPTPROV*, LPCTSTR, LPCTSTR, DWORD, DWORD);
+typedef BOOL (__stdcall *fnCryptReleaseContext)(HCRYPTPROV, DWORD);
+
+static fnCryptAcquireContext g_lpCryptAcquireContext 	= NULL;
+static fnCryptReleaseContext g_lpCryptReleaseContext 	= NULL;
+static fnCryptGenRandom		 g_lpCryptGenRandom 		= NULL;
+static HINSTANCE			 g_hAAPI32 					= NULL;
+static HCRYPTPROV			 g_hProvider 				= ( ULONG_PTR ) NULL;
+
+
+typedef DNSServiceErrorType ( DNSSD_API *DNSServiceRegisterFunc )
+    (
+    DNSServiceRef                       *sdRef,
+    DNSServiceFlags                     flags,
+    uint32_t                            interfaceIndex,
+    const char                          *name,         /* may be NULL */
+    const char                          *regtype,
+    const char                          *domain,       /* may be NULL */
+    const char                          *host,         /* may be NULL */
+    uint16_t                            port,
+    uint16_t                            txtLen,
+    const void                          *txtRecord,    /* may be NULL */
+    DNSServiceRegisterReply             callBack,      /* may be NULL */
+    void                                *context       /* may be NULL */
+    );
+
+
+typedef void ( DNSSD_API *DNSServiceRefDeallocateFunc )( DNSServiceRef sdRef );
+
+mDNSlocal HMODULE					gDNSSDLibrary				= NULL;
+mDNSlocal DNSServiceRegisterFunc	gDNSServiceRegister			= NULL;
+mDNSlocal DNSServiceRefDeallocateFunc gDNSServiceRefDeallocate	= NULL;
+mDNSlocal HANDLE					gSMBThread					= NULL;
+mDNSlocal HANDLE					gSMBThreadRegisterEvent		= NULL;
+mDNSlocal HANDLE					gSMBThreadDeregisterEvent	= NULL;
+mDNSlocal HANDLE					gSMBThreadStopEvent			= NULL;
+mDNSlocal HANDLE					gSMBThreadQuitEvent			= NULL;
+
+#define	kSMBStopEvent				( WAIT_OBJECT_0 + 0 )
+#define	kSMBRegisterEvent			( WAIT_OBJECT_0 + 1 )
+#define kSMBDeregisterEvent			( WAIT_OBJECT_0 + 2 )
+
+
+#if 0
+#pragma mark -
+#pragma mark == Platform Support ==
+#endif
+
+//===========================================================================================================================
+//	mDNSPlatformInit
+//===========================================================================================================================
+
+mDNSexport mStatus	mDNSPlatformInit( mDNS * const inMDNS )
+{
+	mStatus		err;
+	OSVERSIONINFO osInfo;
+	BOOL ok;
+	WSADATA		wsaData;
+	int			supported;
+	struct sockaddr_in	sa4;
+	struct sockaddr_in6 sa6;
+	int					sa4len;
+	int					sa6len;
+	DWORD				size;
+	
+	dlog( kDebugLevelTrace, DEBUG_NAME "platform init\n" );
+	
+	// Initialize variables. If the PlatformSupport pointer is not null then just assume that a non-Apple client is 
+	// calling mDNS_Init and wants to provide its own storage for the platform-specific data so do not overwrite it.
+	
+	mDNSPlatformMemZero( &gMDNSPlatformSupport, sizeof( gMDNSPlatformSupport ) );
+	if( !inMDNS->p ) inMDNS->p				= &gMDNSPlatformSupport;
+	inMDNS->p->mainThread					= OpenThread( THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId() );
+	require_action( inMDNS->p->mainThread, exit, err = mStatus_UnknownErr );
+	inMDNS->p->checkFileSharesTimer = CreateWaitableTimer( NULL, FALSE, NULL );
+	require_action( inMDNS->p->checkFileSharesTimer, exit, err = mStatus_UnknownErr );
+	inMDNS->p->checkFileSharesTimeout		= 10;		// Retry time for CheckFileShares() in seconds
+	mDNSPlatformOneSecond 					= 1000;		// Use milliseconds as the quantum of time
+	
+	// Get OS version info
+	
+	osInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+	ok = GetVersionEx( &osInfo );
+	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
+	require_noerr( err, exit );
+	inMDNS->p->osMajorVersion = osInfo.dwMajorVersion;
+	inMDNS->p->osMinorVersion = osInfo.dwMinorVersion;
+	
+	// Don't enable IPv6 on anything less recent than Windows Vista
+
+	if ( inMDNS->p->osMajorVersion < 6 )
+	{
+		gEnableIPv6 = FALSE;
+	}
+
+	// Startup WinSock 2.2 or later.
+	
+	err = WSAStartup( MAKEWORD( kWinSockMajorMin, kWinSockMinorMin ), &wsaData );
+	require_noerr( err, exit );
+	
+	supported = ( ( LOBYTE( wsaData.wVersion ) == kWinSockMajorMin ) && ( HIBYTE( wsaData.wVersion ) == kWinSockMinorMin ) );
+	require_action( supported, exit, err = mStatus_UnsupportedErr );
+	
+	inMDNS->CanReceiveUnicastOn5353 = CanReceiveUnicast();
+	
+	// Setup the HINFO HW strings.
+	//<rdar://problem/7245119> device-info should have model=Windows
+
+	strcpy_s( ( char* ) &inMDNS->HIHardware.c[ 1 ], sizeof( inMDNS->HIHardware.c ) - 2, "Windows" );
+	inMDNS->HIHardware.c[ 0 ] = ( mDNSu8 ) mDNSPlatformStrLen( &inMDNS->HIHardware.c[ 1 ] );
+	dlog( kDebugLevelInfo, DEBUG_NAME "HIHardware: %#s\n", inMDNS->HIHardware.c );
+
+	// Setup the HINFO SW strings.
+#if ( MDNS_SET_HINFO_STRINGS )
+	mDNS_snprintf( (char *) &inMDNS->HISoftware.c[ 1 ], sizeof( inMDNS->HISoftware.c ) - 2, 
+		"mDNSResponder (%s %s)", __DATE__, __TIME__ );
+	inMDNS->HISoftware.c[ 0 ] = (mDNSu8) mDNSPlatformStrLen( &inMDNS->HISoftware.c[ 1 ] );
+	dlog( kDebugLevelInfo, DEBUG_NAME "HISoftware: %#s\n", inMDNS->HISoftware.c );
+#endif
+
+	// Set up the IPv4 unicast socket
+
+	inMDNS->p->unicastSock4.fd			= INVALID_SOCKET;
+	inMDNS->p->unicastSock4.recvMsgPtr	= NULL;
+	inMDNS->p->unicastSock4.ifd			= NULL;
+	inMDNS->p->unicastSock4.next		= NULL;
+	inMDNS->p->unicastSock4.m			= inMDNS;
+
+#if ( MDNS_WINDOWS_ENABLE_IPV4 )
+
+	sa4.sin_family		= AF_INET;
+	sa4.sin_addr.s_addr = INADDR_ANY;
+	err = SetupSocket( inMDNS, (const struct sockaddr*) &sa4, zeroIPPort, &inMDNS->p->unicastSock4.fd );
+	check_noerr( err );
+	sa4len = sizeof( sa4 );
+	err = getsockname( inMDNS->p->unicastSock4.fd, (struct sockaddr*) &sa4, &sa4len );
+	require_noerr( err, exit );
+	inMDNS->p->unicastSock4.port.NotAnInteger = sa4.sin_port;
+	inMDNS->UnicastPort4 = inMDNS->p->unicastSock4.port;
+	err = WSAIoctl( inMDNS->p->unicastSock4.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock4.recvMsgPtr, sizeof( inMDNS->p->unicastSock4.recvMsgPtr ), &size, NULL, NULL );
+		
+	if ( err )
+	{
+		inMDNS->p->unicastSock4.recvMsgPtr = NULL;
+	}
+
+	err = mDNSPollRegisterSocket( inMDNS->p->unicastSock4.fd, FD_READ, UDPSocketNotification, &inMDNS->p->unicastSock4 );
+	require_noerr( err, exit ); 
+
+#endif
+
+	// Set up the IPv6 unicast socket
+
+	inMDNS->p->unicastSock6.fd			= INVALID_SOCKET;
+	inMDNS->p->unicastSock6.recvMsgPtr	= NULL;
+	inMDNS->p->unicastSock6.ifd			= NULL;
+	inMDNS->p->unicastSock6.next		= NULL;
+	inMDNS->p->unicastSock6.m			= inMDNS;
+
+#if ( MDNS_WINDOWS_ENABLE_IPV6 )
+
+	if ( gEnableIPv6 )
+	{
+		sa6.sin6_family		= AF_INET6;
+		sa6.sin6_addr		= in6addr_any;
+		sa6.sin6_scope_id	= 0;
+
+		// This call will fail if the machine hasn't installed IPv6.  In that case,
+		// the error will be WSAEAFNOSUPPORT.
+
+		err = SetupSocket( inMDNS, (const struct sockaddr*) &sa6, zeroIPPort, &inMDNS->p->unicastSock6.fd );
+		require_action( !err || ( err == WSAEAFNOSUPPORT ), exit, err = (mStatus) WSAGetLastError() );
+		err = kNoErr;
+		
+		// If we weren't able to create the socket (because IPv6 hasn't been installed) don't do this
+
+		if ( inMDNS->p->unicastSock6.fd != INVALID_SOCKET )
+		{
+			sa6len = sizeof( sa6 );
+			err = getsockname( inMDNS->p->unicastSock6.fd, (struct sockaddr*) &sa6, &sa6len );
+			require_noerr( err, exit );
+			inMDNS->p->unicastSock6.port.NotAnInteger = sa6.sin6_port;
+			inMDNS->UnicastPort6 = inMDNS->p->unicastSock6.port;
+
+			err = WSAIoctl( inMDNS->p->unicastSock6.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &inMDNS->p->unicastSock6.recvMsgPtr, sizeof( inMDNS->p->unicastSock6.recvMsgPtr ), &size, NULL, NULL );
+			
+			if ( err != 0 )
+			{
+				inMDNS->p->unicastSock6.recvMsgPtr = NULL;
+			}
+
+			err = mDNSPollRegisterSocket( inMDNS->p->unicastSock6.fd, FD_READ, UDPSocketNotification, &inMDNS->p->unicastSock6 );
+			require_noerr( err, exit );
+		}
+	}
+
+#endif
+
+	// Notify core of domain secret keys
+
+	SetDomainSecrets( inMDNS );
+	
+	// Success!
+
+	mDNSCoreInitComplete( inMDNS, err );
+
+	
+exit:
+
+	if ( err )
+	{
+		mDNSPlatformClose( inMDNS );
+	}
+
+	dlog( kDebugLevelTrace, DEBUG_NAME "platform init done (err=%d %m)\n", err, err );
+	return( err );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformClose
+//===========================================================================================================================
+
+mDNSexport void	mDNSPlatformClose( mDNS * const inMDNS )
+{
+	mStatus		err;
+	
+	dlog( kDebugLevelTrace, DEBUG_NAME "platform close\n" );
+	check( inMDNS );
+
+	if ( gSMBThread != NULL )
+	{
+		dlog( kDebugLevelTrace, DEBUG_NAME "tearing down smb registration thread\n" );
+		SetEvent( gSMBThreadStopEvent );
+		
+		if ( WaitForSingleObject( gSMBThreadQuitEvent, 5 * 1000 ) == WAIT_OBJECT_0 )
+		{
+			if ( gSMBThreadQuitEvent )
+			{
+				CloseHandle( gSMBThreadQuitEvent );
+				gSMBThreadQuitEvent = NULL;
+			}
+
+			if ( gSMBThreadStopEvent )
+			{
+				CloseHandle( gSMBThreadStopEvent );
+				gSMBThreadStopEvent = NULL;
+			}
+
+			if ( gSMBThreadDeregisterEvent )
+			{
+				CloseHandle( gSMBThreadDeregisterEvent );
+				gSMBThreadDeregisterEvent = NULL;
+			}
+
+			if ( gSMBThreadRegisterEvent )
+			{
+				CloseHandle( gSMBThreadRegisterEvent );
+				gSMBThreadRegisterEvent = NULL;
+			}
+
+			if ( gDNSSDLibrary )
+			{
+				FreeLibrary( gDNSSDLibrary );
+				gDNSSDLibrary = NULL;
+			}	
+		}
+		else
+		{
+			LogMsg( "Unable to stop SMBThread" );
+		}
+
+		inMDNS->p->smbFileSharing = mDNSfalse;
+		inMDNS->p->smbPrintSharing = mDNSfalse;
+	}
+
+	// Tear everything down in reverse order to how it was set up.
+	
+	err = TearDownInterfaceList( inMDNS );
+	check_noerr( err );
+	check( !inMDNS->p->inactiveInterfaceList );
+
+#if ( MDNS_WINDOWS_ENABLE_IPV4 )
+
+	UDPCloseSocket( &inMDNS->p->unicastSock4 );
+
+#endif
+	
+#if ( MDNS_WINDOWS_ENABLE_IPV6 )
+
+	if ( gEnableIPv6 )
+	{
+		UDPCloseSocket( &inMDNS->p->unicastSock6 );
+	}
+
+#endif
+
+	// Free the DLL needed for IPv6 support.
+	
+#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
+	if( gIPHelperLibraryInstance )
+	{
+		gGetAdaptersAddressesFunctionPtr = NULL;
+		
+		FreeLibrary( gIPHelperLibraryInstance );
+		gIPHelperLibraryInstance = NULL;
+	}
+#endif
+
+	if ( g_hAAPI32 )
+	{
+		// Release any resources
+
+		if ( g_hProvider && g_lpCryptReleaseContext )
+		{
+			( g_lpCryptReleaseContext )( g_hProvider, 0 );
+		}
+
+		// Free the AdvApi32.dll
+
+		FreeLibrary( g_hAAPI32 );
+
+		// And reset all the data
+
+		g_lpCryptAcquireContext = NULL;
+		g_lpCryptReleaseContext = NULL;
+		g_lpCryptGenRandom 		= NULL;
+		g_hProvider 			= ( ULONG_PTR ) NULL;
+		g_hAAPI32				= NULL;
+	}
+
+	WSACleanup();
+	
+	dlog( kDebugLevelTrace, DEBUG_NAME "platform close done\n" );
+}
+
+
+//===========================================================================================================================
+//	mDNSPlatformLock
+//===========================================================================================================================
+
+mDNSexport void	mDNSPlatformLock( const mDNS * const inMDNS )
+{
+	( void ) inMDNS;
+}
+
+//===========================================================================================================================
+//	mDNSPlatformUnlock
+//===========================================================================================================================
+
+mDNSexport void	mDNSPlatformUnlock( const mDNS * const inMDNS )
+{
+	( void ) inMDNS;
+}
+
+//===========================================================================================================================
+//	mDNSPlatformStrCopy
+//===========================================================================================================================
+
+mDNSexport void	mDNSPlatformStrCopy( void *inDst, const void *inSrc )
+{
+	check( inSrc );
+	check( inDst );
+	
+	strcpy( (char *) inDst, (const char*) inSrc );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformStrLen
+//===========================================================================================================================
+
+mDNSexport mDNSu32	mDNSPlatformStrLen( const void *inSrc )
+{
+	check( inSrc );
+	
+	return( (mDNSu32) strlen( (const char *) inSrc ) );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformMemCopy
+//===========================================================================================================================
+
+mDNSexport void	mDNSPlatformMemCopy( void *inDst, const void *inSrc, mDNSu32 inSize )
+{
+	check( inSrc );
+	check( inDst );
+	
+	memcpy( inDst, inSrc, inSize );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformMemSame
+//===========================================================================================================================
+
+mDNSexport mDNSBool	mDNSPlatformMemSame( const void *inDst, const void *inSrc, mDNSu32 inSize )
+{
+	check( inSrc );
+	check( inDst );
+	
+	return( (mDNSBool)( memcmp( inSrc, inDst, inSize ) == 0 ) );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformMemCmp
+//===========================================================================================================================
+
+mDNSexport int	mDNSPlatformMemCmp( const void *inDst, const void *inSrc, mDNSu32 inSize )
+{
+	check( inSrc );
+	check( inDst );
+	
+	return( memcmp( inSrc, inDst, inSize ) );
+}
+
+mDNSexport void mDNSPlatformQsort(void *base, int nel, int width, int (*compar)(const void *, const void *))
+{
+	(void)base;
+	(void)nel;
+	(void)width;
+	(void)compar;
+}
+
+// DNSSEC stub functions
+mDNSexport void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *q)
+	{
+	(void)m;
+	(void)dv;
+	(void)q;
+	}
+
+mDNSexport mDNSBool AddNSECSForCacheRecord(mDNS *const m, CacheRecord *crlist, CacheRecord *negcr, mDNSu8 rcode)
+	{
+	(void)m;
+	(void)crlist;
+	(void)negcr;
+	(void)rcode;
+	return mDNSfalse;
+	}
+
+mDNSexport void BumpDNSSECStats(mDNS *const m, DNSSECStatsAction action, DNSSECStatsType type, mDNSu32 value)
+    {
+    (void)m;
+    (void)action;
+    (void)type;
+    (void)value;
+    }
+
+// Proxy stub functions
+mDNSexport mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *limit)
+{
+    (void) q;
+    (void) h;
+    (void) msg;
+    (void) ptr;
+    (void) limit;
+
+    return ptr;
+}
+
+mDNSexport void DNSProxyInit(mDNS *const m, mDNSu32 IpIfArr[], mDNSu32 OpIf)
+{
+    (void) m;
+    (void) IpIfArr;
+    (void) OpIf;
+}
+
+mDNSexport void DNSProxyTerminate(mDNS *const m)
+{
+    (void) m;
+}
+
+//===========================================================================================================================
+//	mDNSPlatformMemZero
+//===========================================================================================================================
+
+mDNSexport void	mDNSPlatformMemZero( void *inDst, mDNSu32 inSize )
+{
+	check( inDst );
+	
+	memset( inDst, 0, inSize );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformMemAllocate
+//===========================================================================================================================
+
+mDNSexport void *	mDNSPlatformMemAllocate( mDNSu32 inSize )
+{
+	void *		mem;
+	
+	check( inSize > 0 );
+	
+	mem = malloc( inSize );
+	check( mem );
+	
+	return( mem );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformMemFree
+//===========================================================================================================================
+
+mDNSexport void	mDNSPlatformMemFree( void *inMem )
+{
+	check( inMem );
+	
+	free( inMem );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformRandomNumber
+//===========================================================================================================================
+
+mDNSexport mDNSu32 mDNSPlatformRandomNumber(void)
+{
+	unsigned int	randomNumber;
+	errno_t			err;
+
+	err = rand_s( &randomNumber );
+	require_noerr( err, exit );
+
+exit:
+
+	if ( err )
+	{
+		randomNumber = rand();
+	}
+
+	return ( mDNSu32 ) randomNumber;
+}
+
+//===========================================================================================================================
+//	mDNSPlatformTimeInit
+//===========================================================================================================================
+
+mDNSexport mStatus	mDNSPlatformTimeInit( void )
+{
+	// No special setup is required on Windows -- we just use GetTickCount().
+	return( mStatus_NoError );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformRawTime
+//===========================================================================================================================
+
+mDNSexport mDNSs32	mDNSPlatformRawTime( void )
+{
+	return( (mDNSs32) GetTickCount() );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformUTC
+//===========================================================================================================================
+
+mDNSexport mDNSs32	mDNSPlatformUTC( void )
+{
+	return ( mDNSs32 ) time( NULL );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformInterfaceNameToID
+//===========================================================================================================================
+
+mDNSexport mStatus	mDNSPlatformInterfaceNameToID( mDNS * const inMDNS, const char *inName, mDNSInterfaceID *outID )
+{
+	mStatus					err;
+	mDNSInterfaceData *		ifd;
+	
+	check( inMDNS );
+	check( inMDNS->p );
+	check( inName );
+	
+	// Search for an interface with the specified name,
+	
+	for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
+	{
+		if( strcmp( ifd->name, inName ) == 0 )
+		{
+			break;
+		}
+	}
+	require_action_quiet( ifd, exit, err = mStatus_NoSuchNameErr );
+	
+	// Success!
+	
+	if( outID )
+	{
+		*outID = (mDNSInterfaceID) ifd;
+	}
+	err = mStatus_NoError;
+	
+exit:
+	return( err );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformInterfaceIDToInfo
+//===========================================================================================================================
+
+mDNSexport mStatus	mDNSPlatformInterfaceIDToInfo( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSPlatformInterfaceInfo *outInfo )
+{
+	mStatus					err;
+	mDNSInterfaceData *		ifd;
+	
+	check( inMDNS );
+	check( inID );
+	check( outInfo );
+	
+	// Search for an interface with the specified ID,
+	
+	for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
+	{
+		if( ifd == (mDNSInterfaceData *) inID )
+		{
+			break;
+		}
+	}
+	require_action_quiet( ifd, exit, err = mStatus_NoSuchNameErr );
+	
+	// Success!
+	
+	outInfo->name 	= ifd->name;
+	outInfo->ip 	= ifd->interfaceInfo.ip;
+	err 			= mStatus_NoError;
+	
+exit:
+	return( err );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformInterfaceIDfromInterfaceIndex
+//===========================================================================================================================
+
+mDNSexport mDNSInterfaceID	mDNSPlatformInterfaceIDfromInterfaceIndex( mDNS * const inMDNS, mDNSu32 inIndex )
+{
+	mDNSInterfaceID		id;
+	
+	id = mDNSNULL;
+	if( inIndex == kDNSServiceInterfaceIndexLocalOnly )
+	{
+		id = mDNSInterface_LocalOnly;
+	}
+	else if( inIndex != 0 )
+	{
+		mDNSInterfaceData *		ifd;
+		
+		for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
+		{
+			if( ( ifd->scopeID == inIndex ) && ifd->interfaceInfo.InterfaceActive )
+			{
+				id = ifd->interfaceInfo.InterfaceID;
+				break;
+			}
+		}
+		check( ifd );
+	}
+	return( id );
+}
+
+//===========================================================================================================================
+//	mDNSPlatformInterfaceIndexfromInterfaceID
+//===========================================================================================================================
+	
+mDNSexport mDNSu32	mDNSPlatformInterfaceIndexfromInterfaceID( mDNS * const inMDNS, mDNSInterfaceID inID, mDNSBool suppressNetworkChange )
+{
+	mDNSu32		index;
+	
+	(void) suppressNetworkChange;
+
+	index = 0;
+	if( inID == mDNSInterface_LocalOnly )
+	{
+		index = (mDNSu32) kDNSServiceInterfaceIndexLocalOnly;
+	}
+	else if( inID )
+	{
+		mDNSInterfaceData *		ifd;
+		
+		// Search active interfaces.
+		for( ifd = inMDNS->p->interfaceList; ifd; ifd = ifd->next )
+		{
+			if( (mDNSInterfaceID) ifd == inID )
+			{
+				index = ifd->scopeID;
+				break;
+			}
+		}
+		
+		// Search inactive interfaces too so remove events for inactive interfaces report the old interface index.
+		
+		if( !ifd )
+		{
+			for( ifd = inMDNS->p->inactiveInterfaceList; ifd; ifd = ifd->next )
+			{
+				if( (mDNSInterfaceID) ifd == inID )
+				{
+					index = ifd->scopeID;
+					break;
+				}
+			}
+		}
+		check( ifd );
+	}
+	return( index );
+}
+
+
+//===========================================================================================================================
+//	mDNSPlatformTCPSocket
+//===========================================================================================================================
+
+TCPSocket *
+mDNSPlatformTCPSocket
+	(
+	mDNS			* const m,
+	TCPSocketFlags		flags,
+	mDNSIPPort			*	port, 
+	mDNSBool			useBackgroundTrafficClass
+	)
+{
+	TCPSocket *		sock    = NULL;
+	u_long				on		= 1;  // "on" for setsockopt
+	struct sockaddr_in	saddr;
+	int					len;
+	mStatus				err		= mStatus_NoError;
+
+	DEBUG_UNUSED( m );
+	DEBUG_UNUSED( useBackgroundTrafficClass );
+
+	require_action( flags == 0, exit, err = mStatus_UnsupportedErr );
+
+	// Setup connection data object
+
+	sock = (TCPSocket *) malloc( sizeof( TCPSocket ) );
+	require_action( sock, exit, err = mStatus_NoMemoryErr );
+	mDNSPlatformMemZero( sock, sizeof( TCPSocket ) );
+	sock->fd		= INVALID_SOCKET;
+	sock->flags		= flags;
+	sock->m			= m;
+
+	mDNSPlatformMemZero(&saddr, sizeof(saddr));
+	saddr.sin_family		= AF_INET;
+	saddr.sin_addr.s_addr	= htonl( INADDR_ANY );
+	saddr.sin_port			= port->NotAnInteger;
+	
+	// Create the socket
+
+	sock->fd = socket(AF_INET, SOCK_STREAM, 0);
+	err = translate_errno( sock->fd != INVALID_SOCKET, WSAGetLastError(), mStatus_UnknownErr );
+	require_noerr( err, exit );
+
+	// bind
+
+	err = bind( sock->fd, ( struct sockaddr* ) &saddr, sizeof( saddr )  );
+	err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
+	require_noerr( err, exit );
+
+	// Set it to be non-blocking
+
+	err = ioctlsocket( sock->fd, FIONBIO, &on );
+	err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
+	require_noerr( err, exit );
+
+	// Get port number
+
+	mDNSPlatformMemZero( &saddr, sizeof( saddr ) );
+	len = sizeof( saddr );
+
+	err = getsockname( sock->fd, ( struct sockaddr* ) &saddr, &len );
+	err = translate_errno( err == 0, WSAGetLastError(), mStatus_UnknownErr );
+	require_noerr( err, exit );
+
+	port->NotAnInteger = saddr.sin_port;
+
+exit:
+
+	if ( err && sock )
+	{
+		TCPCloseSocket( sock );
+		free( sock );
+		sock = mDNSNULL;
+	}
+
+	return sock;
+}
+
+//===========================================================================================================================
+//	mDNSPlatformTCPConnect
+//===========================================================================================================================
+
+mStatus
+mDNSPlatformTCPConnect
+	(
+	TCPSocket			*	sock,
+	const mDNSAddr		*	inDstIP, 
+	mDNSOpaque16 			inDstPort, 
+	domainname			*	hostname,
+	mDNSInterfaceID			inInterfaceID,
+	TCPConnectionCallback	inCallback, 
+	void *					inContext
+	)
+{
+	struct sockaddr_in	saddr;
+	mStatus				err		= mStatus_NoError;
+
+	DEBUG_UNUSED( hostname );
+	DEBUG_UNUSED( inInterfaceID );
+
+	if ( inDstIP->type != mDNSAddrType_IPv4 )
+	{
+		LogMsg("ERROR: mDNSPlatformTCPConnect - attempt to connect to an IPv6 address: operation not supported");
+		return mStatus_UnknownErr;
+	}
+
+	// Setup connection data object
+
+	sock->userCallback	= inCallback;
+	sock->userContext	= inContext;
+
+	mDNSPlatformMemZero(&saddr, sizeof(saddr));
+	saddr.sin_family	= AF_INET;
+	saddr.sin_port		= inDstPort.NotAnInteger;
+	memcpy(&saddr.sin_addr, &inDstIP->ip.v4.NotAnInteger, sizeof(saddr.sin_addr));
+
+	// Try and do connect
+
+	err = connect( sock->fd, ( struct sockaddr* ) &saddr, sizeof( saddr ) );
+	require_action( !err || ( WSAGetLastError() == WSAEWOULDBLOCK ), exit, err = mStatus_ConnFailed );
+	sock->connected	= !err ? TRUE : FALSE;
+
+	err = mDNSPollRegisterSocket( sock->fd, FD_CONNECT | FD_READ | FD_CLOSE, TCPSocketNotification, sock );
+	require_noerr( err, exit );
+
+exit:
+
+	if ( !err )
+	{
+		err = sock->connected ? mStatus_ConnEstablished : mStatus_ConnPending;
+	}
+
+	return err;
+}
+
+
+//===========================================================================================================================
+//	mDNSPlatformTCPAccept
+//===========================================================================================================================
+
+mDNSexport 
+mDNSexport TCPSocket *mDNSPlatformTCPAccept( TCPSocketFlags flags, int fd )
+	{
+	TCPSocket	*	sock = NULL;
+	mStatus							err = mStatus_NoError;
+
+	require_action( !flags, exit, err = mStatus_UnsupportedErr );
+
+	sock = malloc( sizeof( TCPSocket ) );
+	require_action( sock, exit, err = mStatus_NoMemoryErr );
+	
+	mDNSPlatformMemZero( sock, sizeof( *sock ) );
+
+	sock->fd	= fd;
+	sock->flags = flags;
+
+exit:
+
+	if ( err && sock )
+	{
+		free( sock );
+		sock = NULL;
+	}
+
+	return sock;
+	}
+
+
+//===========================================================================================================================
+//	mDNSPlatformTCPCloseConnection
+//===========================================================================================================================
+
+mDNSexport void	mDNSPlatformTCPCloseConnection( TCPSocket *sock )
+{
+	check( sock );
+
+	if ( sock )
+	{
+		dlog( kDebugLevelChatty, DEBUG_NAME "mDNSPlatformTCPCloseConnection 0x%x:%d\n", sock, sock->fd );
+
+		if ( sock->fd != INVALID_SOCKET )
+		{
+			mDNSPollUnregisterSocket( sock->fd );
+			closesocket( sock->fd );
+			sock->fd = INVALID_SOCKET;
+		}
+
+		free( sock );
+	}
+}
+
+
+//===========================================================================================================================
+//	mDNSPlatformReadTCP
+//===========================================================================================================================
+
+mDNSexport long	mDNSPlatformReadTCP( TCPSocket *sock, void *inBuffer, unsigned long inBufferSize, mDNSBool * closed )
+{
+	int			nread;
+    OSStatus    err;
+
+	*closed = mDNSfalse;
+    nread = recv( sock->fd, inBuffer, inBufferSize, 0 );
+    err = translate_errno( ( nread >= 0 ), WSAGetLastError(), mStatus_UnknownErr );
+	
+	if ( nread > 0 )
+	{
+		dlog( kDebugLevelChatty, DEBUG_NAME "mDNSPlatformReadTCP: 0x%x:%d read %d bytes\n", sock, sock->fd, nread );
+	}
+	else if ( !nread )
+	{
+		*closed = mDNStrue;
+	}
+	else if ( err == WSAECONNRESET )
+	{
+		*closed = mDNStrue;
+		nread = 0;
+	}
+	else if ( err == WSAEWOULDBLOCK )
+	{
+		nread = 0;
+	}
+	else
+	{
+		LogMsg( "ERROR: mDNSPlatformReadTCP - recv: %d\n", err );
+		nread = -1;
+	}
+
+    return nread;
+}
+
+
+//===========================================================================================================================
+//	mDNSPlatformWriteTCP
+//===========================================================================================================================
+
+mDNSexport long	mDNSPlatformWriteTCP( TCPSocket *sock, const char *inMsg, unsigned long inMsgSize )
+{
+	int			nsent;
+	OSStatus	err;
+
+	nsent = send( sock->fd, inMsg, inMsgSize, 0 );
+
+	err = translate_errno( ( nsent >= 0 ) || ( WSAGetLastError() == WSAEWOULDBLOCK ), WSAGetLastError(), mStatus_UnknownErr );
+	require_noerr( err, exit );
+
+	if ( nsent < 0)
+	{
+		nsent = 0;
+	}
+		
+exit:
+
+	return nsent;
+}
+
+//===========================================================================================================================
+//	mDNSPlatformTCPGetFD
+//===========================================================================================================================
+
+mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock )
+{
+	return ( int ) sock->fd;
+}
+
+
+
+//===========================================================================================================================
+//	TCPSocketNotification
+//===========================================================================================================================
+
+mDNSlocal void CALLBACK
+TCPSocketNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context )
+{
+	TCPSocket				*tcpSock = ( TCPSocket* ) context;
+	TCPConnectionCallback	callback;
+	int						err;
+
+	DEBUG_UNUSED( sock );
+
+	require_action( tcpSock, exit, err = mStatus_BadParamErr );
+	callback = ( TCPConnectionCallback ) tcpSock->userCallback;
+	require_action( callback, exit, err = mStatus_BadParamErr );
+
+	if ( event && ( event->lNetworkEvents & FD_CONNECT ) )
+	{
+		if ( event->iErrorCode[ FD_CONNECT_BIT ] == 0 )
+		{
+			callback( tcpSock, tcpSock->userContext, mDNStrue, 0 );
+			tcpSock->connected = mDNStrue;
+		}
+		else
+		{
+			callback( tcpSock, tcpSock->userContext, mDNSfalse, event->iErrorCode[ FD_CONNECT_BIT ] );
+		}
+	}
+	else
+	{
+		callback( tcpSock, tcpSock->userContext, mDNSfalse, 0 );
+	}
+
+exit:
+
+	return;
+}
+
+
+
+//===========================================================================================================================
+//	mDNSPlatformUDPSocket
+//===========================================================================================================================
+
+mDNSexport UDPSocket* mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport)
+{
+	UDPSocket*	sock	= NULL;
+	mDNSIPPort	port	= requestedport;
+	mStatus		err		= mStatus_NoError;
+	unsigned	i;
+
+	// Setup connection data object
+
+	sock = ( UDPSocket* ) malloc(sizeof( UDPSocket ) );
+	require_action( sock, exit, err = mStatus_NoMemoryErr );
+	memset( sock, 0, sizeof( UDPSocket ) );
+
+	// Create the socket
+
+	sock->fd			= INVALID_SOCKET;
+	sock->recvMsgPtr	= m->p->unicastSock4.recvMsgPtr;
+	sock->addr			= m->p->unicastSock4.addr;
+	sock->ifd			= NULL;
+	sock->m				= m;
+
+	// Try at most 10000 times to get a unique random port
+
+	for (i=0; i<10000; i++)
+	{
+		struct sockaddr_in saddr;
+
+		saddr.sin_family		= AF_INET;
+		saddr.sin_addr.s_addr	= 0;
+
+		// The kernel doesn't do cryptographically strong random port
+		// allocation, so we do it ourselves here
+
+        if (mDNSIPPortIsZero(requestedport))
+		{
+			port = mDNSOpaque16fromIntVal( ( mDNSu16 ) ( 0xC000 + mDNSRandom(0x3FFF) ) );
+		}
+
+		saddr.sin_port = port.NotAnInteger;
+
+        err = SetupSocket(m, ( struct sockaddr* ) &saddr, port, &sock->fd );
+        if (!err) break;
+	}
+
+	require_noerr( err, exit );
+
+	// Set the port
+
+	sock->port = port;
+
+	// Arm the completion routine
+
+	err = mDNSPollRegisterSocket( sock->fd, FD_READ, UDPSocketNotification, sock );
+	require_noerr( err, exit ); 
+
+	// Bookkeeping
+
+	sock->next		= gUDPSockets;
+	gUDPSockets		= sock;
+	gUDPNumSockets++;
+
+exit:
+
+	if ( err && sock )
+	{
+		UDPCloseSocket( sock );
+		free( sock );
+		sock = NULL;
+	}
+
+	return sock;
+}
+	
+//===========================================================================================================================
+//	mDNSPlatformUDPClose
+//===========================================================================================================================
+	
+mDNSexport void mDNSPlatformUDPClose( UDPSocket *sock )
+{
+	UDPSocket	*	current  = gUDPSockets;
+	UDPSocket	*	last = NULL;
+
+	while ( current )
+	{
+		if ( current == sock )
+		{
+			if ( last == NULL )
+			{
+				gUDPSockets = sock->next;
+			}
+			else
+			{
+				last->next = sock->next;
+			}
+
+			UDPCloseSocket( sock );
+			free( sock );
+
+			gUDPNumSockets--;
+
+			break;
+		}
+
+		last	= current;
+		current	= current->next;
+	}
+}
+
+
+//===========================================================================================================================
+//	mDNSPlatformSendUDP
+//===========================================================================================================================
+
+mDNSexport mStatus
+	mDNSPlatformSendUDP( 
+		const mDNS * const			inMDNS, 
+		const void * const	        inMsg, 
+		const mDNSu8 * const		inMsgEnd, 
+		mDNSInterfaceID 			inInterfaceID, 
+		UDPSocket *					inSrcSocket,
+		const mDNSAddr *			inDstIP, 
+		mDNSIPPort 					inDstPort,
+		mDNSBool 					useBackgroundTrafficClass )
+{
+	SOCKET						sendingsocket = INVALID_SOCKET;
+	mStatus						err = mStatus_NoError;
+	mDNSInterfaceData *			ifd = (mDNSInterfaceData*) inInterfaceID;
+	struct sockaddr_storage		addr;
+	int							n;
+	
+	DEBUG_USE_ONLY( inMDNS );
+	DEBUG_USE_ONLY( useBackgroundTrafficClass );
+	
+	n = (int)( inMsgEnd - ( (const mDNSu8 * const) inMsg ) );
+	check( inMDNS );
+	check( inMsg );
+	check( inMsgEnd );
+	check( inDstIP );
+	
+	dlog( kDebugLevelChatty, DEBUG_NAME "platform send %d bytes to %#a:%u\n", n, inDstIP, ntohs( inDstPort.NotAnInteger ) );
+	
+	if( inDstIP->type == mDNSAddrType_IPv4 )
+	{
+		struct sockaddr_in *		sa4;
+		
+		sa4						= (struct sockaddr_in *) &addr;
+		sa4->sin_family			= AF_INET;
+		sa4->sin_port			= inDstPort.NotAnInteger;
+		sa4->sin_addr.s_addr	= inDstIP->ip.v4.NotAnInteger;
+		sendingsocket           = ifd ? ifd->sock.fd : inMDNS->p->unicastSock4.fd;
+
+		if (inSrcSocket) { sendingsocket = inSrcSocket->fd; debugf("mDNSPlatformSendUDP using port %d, static port %d, sock %d", mDNSVal16(inSrcSocket->port), inMDNS->p->unicastSock4.fd, sendingsocket); }
+	}
+	else if( inDstIP->type == mDNSAddrType_IPv6 )
+	{
+		struct sockaddr_in6 *		sa6;
+		
+		sa6					= (struct sockaddr_in6 *) &addr;
+		sa6->sin6_family	= AF_INET6;
+		sa6->sin6_port		= inDstPort.NotAnInteger;
+		sa6->sin6_flowinfo	= 0;
+		sa6->sin6_addr		= *( (struct in6_addr *) &inDstIP->ip.v6 );
+		sa6->sin6_scope_id	= 0;	// Windows requires the scope ID to be zero. IPV6_MULTICAST_IF specifies interface.
+		sendingsocket		= ifd ? ifd->sock.fd : inMDNS->p->unicastSock6.fd;
+	}
+	else
+	{
+		dlog( kDebugLevelError, DEBUG_NAME "%s: dst is not an IPv4 or IPv6 address (type=%d)\n", __ROUTINE__, inDstIP->type );
+		err = mStatus_BadParamErr;
+		goto exit;
+	}
+	
+	if (IsValidSocket(sendingsocket))
+	{
+		n = sendto( sendingsocket, (char *) inMsg, n, 0, (struct sockaddr *) &addr, sizeof( addr ) );
+		err = translate_errno( n > 0, errno_compat(), kWriteErr );
+
+		if ( err )
+		{
+			// Don't report EHOSTDOWN (i.e. ARP failure), ENETDOWN, or no route to host for unicast destinations
+
+			if ( !mDNSAddressIsAllDNSLinkGroup( inDstIP ) && ( WSAGetLastError() == WSAEHOSTDOWN || WSAGetLastError() == WSAENETDOWN || WSAGetLastError() == WSAEHOSTUNREACH || WSAGetLastError() == WSAENETUNREACH ) )
+			{
+				err = mStatus_TransientErr;
+			}
+			else
+			{
+				require_noerr( err, exit );
+			}
+		}
+	}
+	
+exit:
+	return( err );
+}
+
+
+mDNSexport mDNSBool mDNSPlatformPeekUDP(mDNS *const m, UDPSocket *src)
+{
+	DEBUG_UNUSED( m );
+	DEBUG_UNUSED( src );
+	return mDNSfalse;
+}
+
+mDNSexport void mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID)
+	{
+	DEBUG_UNUSED( m );
+	DEBUG_UNUSED( InterfaceID );
+	}
+
+
+mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason)
+	{
+	DEBUG_UNUSED( m );
+	DEBUG_UNUSED( allowSleep );
+	DEBUG_UNUSED( reason );
+	}
+
+//===========================================================================================================================
+//	mDNSPlatformSendRawPacket
+//===========================================================================================================================
+
+mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *ethaddr, char *ipaddr, int iteration)
+{
+	unsigned char			mac[ 6 ];
+	unsigned char			buf[ 102 ];
+	char					hex[ 3 ] = { 0 };
+	unsigned char			*bufPtr = buf;
+	struct sockaddr_storage	saddr;
+	INT						len = sizeof( saddr );
+	mDNSBool				unicast = mDNSfalse;
+	MulticastWakeupStruct	*info;
+	int						i;
+	mStatus					err;
+
+	(void) InterfaceID;
+
+	require_action( ethaddr, exit, err = mStatus_BadParamErr );
+
+	for ( i = 0; i < 6; i++ )
+	{
+		memcpy( hex, ethaddr + ( i * 3 ), 2 );
+		mac[ i ] = ( unsigned char ) strtoul( hex, NULL, 16 );
+	}
+
+	memset( buf, 0, sizeof( buf ) );
+
+	for ( i = 0; i < 6; i++ )
+	{
+		*bufPtr++ = 0xff;
+	}
+	
+	for ( i = 0; i < 16; i++ )
+	{
+		memcpy( bufPtr, mac, sizeof( mac ) );
+		bufPtr += sizeof( mac );
+	}
+
+	if ( ipaddr )
+	{
+		if ( WSAStringToAddressA( ipaddr, AF_INET, NULL, ( LPSOCKADDR ) &saddr, &len ) == 0 )
+		{
+			struct sockaddr_in * saddr4 = ( struct sockaddr_in* ) &saddr;
+			saddr4->sin_port = htons( 9 );
+			len = sizeof( *saddr4 );
+
+			if ( saddr4->sin_addr.s_addr != htonl( INADDR_ANY ) )
+			{
+				unicast = mDNStrue;
+			}
+		}
+		else if ( WSAStringToAddressA( ipaddr, AF_INET6, NULL, ( LPSOCKADDR ) &saddr, &len ) == 0 )
+		{
+			mDNSInterfaceData *ifd = ( mDNSInterfaceData* ) InterfaceID;
+			struct sockaddr_in6 * saddr6 = ( struct sockaddr_in6* ) &saddr;
+			saddr6->sin6_port = htons( 9 );
+
+			if ( ifd != NULL )
+			{
+				saddr6->sin6_scope_id = ifd->scopeID;
+			}
+
+			len = sizeof( *saddr6 );
+
+			if ( memcmp( &saddr6->sin6_addr, &in6addr_any, sizeof( IN6_ADDR ) ) != 0 )
+			{
+				unicast = mDNStrue;
+			}
+		}
+	}
+
+	if ( ( iteration < 2 ) && ( unicast ) )
+	{
+		SendWakeupPacket( m, ( LPSOCKADDR ) &saddr, len, ( const char* ) buf, sizeof( buf ), kUnicastWakeupNumTries, kUnicastWakeupSleepBetweenTries );
+	}		
+
+	info = ( MulticastWakeupStruct* ) malloc( sizeof( MulticastWakeupStruct ) );
+	require_action( info, exit, err = mStatus_NoMemoryErr );
+	info->inMDNS = m;
+	memset( &info->addr, 0, sizeof( info->addr ) );
+	info->addr.sin_family = AF_INET;
+	info->addr.sin_addr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
+	info->addr.sin_port = htons( 9 );
+	info->addrLen = sizeof( info->addr );
+	memcpy( info->data, buf, sizeof( buf ) );
+	info->dataLen = sizeof( buf );
+	info->numTries  = kMulticastWakeupNumTries;
+	info->msecSleep = kMulticastWakeupSleepBetweenTries;
+
+	_beginthread( SendMulticastWakeupPacket, 0, ( void* ) info );
+
+exit:
+
+	return;
+}
+
+
+mDNSexport mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf)
+{
+	DEBUG_UNUSED( rr );
+	DEBUG_UNUSED( intf );
+
+	return mDNStrue;
+}
+ 
+mDNSexport mDNSBool mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf)
+{
+	DEBUG_UNUSED( q );
+	DEBUG_UNUSED( intf );
+
+	return mDNStrue;
+}
+ 
+mDNSexport void mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
+	{
+	DEBUG_UNUSED( msg );
+	DEBUG_UNUSED( end );
+	DEBUG_UNUSED( InterfaceID );
+	}
+
+// Used for debugging purposes. For now, just set the buffer to zero
+mDNSexport void mDNSPlatformFormatTime(unsigned long te, mDNSu8 *buf, int bufsize)
+	{
+	DEBUG_UNUSED( te );
+	if (bufsize) buf[0] = 0;
+	}
+
+
+mDNSexport void mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID)
+	{
+	DEBUG_UNUSED( m );
+	DEBUG_UNUSED( tpa );
+	DEBUG_UNUSED( tha );
+	DEBUG_UNUSED( InterfaceID );
+	}
+
+
+mDNSexport void mDNSPlatformReceiveRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID)
+	{
+	DEBUG_UNUSED( msg );
+	DEBUG_UNUSED( end );
+	DEBUG_UNUSED( InterfaceID );
+	}
+
+mDNSexport void mDNSPlatformSetLocalARP( const mDNSv4Addr * const tpa, const mDNSEthAddr * const tha, mDNSInterfaceID InterfaceID )
+	{
+	DEBUG_UNUSED( tpa );
+	DEBUG_UNUSED( tha );
+	DEBUG_UNUSED( InterfaceID );
+	}
+
+mDNSexport void mDNSPlatformWriteDebugMsg(const char *msg)
+	{
+	dlog( kDebugLevelInfo, "%s\n", msg );
+	}
+
+mDNSexport void mDNSPlatformWriteLogMsg( const char * ident, const char * msg, mDNSLogLevel_t loglevel )
+	{
+	extern mDNS mDNSStorage;
+	int type;
+	
+	DEBUG_UNUSED( ident );
+
+	type = EVENTLOG_ERROR_TYPE;
+
+	switch (loglevel) 
+	{
+		case MDNS_LOG_MSG:       type = EVENTLOG_ERROR_TYPE;		break;
+		case MDNS_LOG_OPERATION: type = EVENTLOG_WARNING_TYPE;		break;
+		case MDNS_LOG_SPS:       type = EVENTLOG_INFORMATION_TYPE;  break;
+		case MDNS_LOG_INFO:      type = EVENTLOG_INFORMATION_TYPE;	break;
+		case MDNS_LOG_DEBUG:     type = EVENTLOG_INFORMATION_TYPE;	break;
+		default:
+			fprintf(stderr, "Unknown loglevel %d, assuming LOG_ERR\n", loglevel);
+			fflush(stderr);
+			}
+
+	mDNSStorage.p->reportStatusFunc( type, msg );
+	dlog( kDebugLevelInfo, "%s\n", msg );
+	}
+
+mDNSexport void mDNSPlatformSourceAddrForDest( mDNSAddr * const src, const mDNSAddr * const dst )
+	{
+	DEBUG_UNUSED( src );
+	DEBUG_UNUSED( dst );
+	}
+
+//===========================================================================================================================
+//	mDNSPlatformTLSSetupCerts
+//===========================================================================================================================
+
+mDNSexport mStatus
+mDNSPlatformTLSSetupCerts(void)
+{
+	return mStatus_UnsupportedErr;
+}
+
+//===========================================================================================================================
+//	mDNSPlatformTLSTearDownCerts
+//===========================================================================================================================
+
+mDNSexport void
+mDNSPlatformTLSTearDownCerts(void)
+{
+}
+
+//===========================================================================================================================
+//	mDNSPlatformSetDNSConfig
+//===========================================================================================================================
+
+mDNSlocal void SetDNSServers( mDNS *const m );
+mDNSlocal void SetSearchDomainList( void );
+
+mDNSexport mDNSBool mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **regDomains, DNameListElem **browseDomains, mDNSBool ackConfig)
+{
+	(void) ackConfig;
+
+	if (setservers) SetDNSServers(m);
+	if (setsearch) SetSearchDomainList();
+	
+	if ( fqdn )
+	{
+		GetDDNSFQDN( fqdn );
+	}
+
+	if ( browseDomains )
+	{
+		GetDDNSDomains( browseDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSBrowseDomains );
+	}
+
+	if ( regDomains )
+	{
+		GetDDNSDomains( regDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains );
+	}
+    return mDNStrue;
+}
+
+
+//===========================================================================================================================
+//	mDNSPlatformDynDNSHostNameStatusChanged
+//===========================================================================================================================
+
+mDNSexport void
+mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status)
+{
+	char		uname[MAX_ESCAPED_DOMAIN_NAME];
+	BYTE		bStatus;
+	LPCTSTR		name;
+	HKEY		key = NULL;
+	mStatus		err;
+	char	*	p;
+	
+	ConvertDomainNameToCString(dname, uname);
+	
+	p = uname;
+
+	while (*p)
+	{
+		*p = (char) tolower(*p);
+		if (!(*(p+1)) && *p == '.') *p = 0; // if last character, strip trailing dot
+		p++;
+	}
+
+	check( strlen( p ) <= MAX_ESCAPED_DOMAIN_NAME );
+	name = kServiceParametersNode TEXT("\\DynDNS\\State\\HostNames");
+	err = RegCreateKey( HKEY_LOCAL_MACHINE, name, &key );
+	require_noerr( err, exit );
+
+	bStatus = ( status ) ? 0 : 1;
+	err = RegSetValueEx( key, kServiceDynDNSStatus, 0, REG_DWORD, (const LPBYTE) &bStatus, sizeof(DWORD) );
+	require_noerr( err, exit );
+
+exit:
+
+	if ( key )
+	{
+		RegCloseKey( key );
+	}
+
+	return;
+}
+
+
+//===========================================================================================================================
+//	SetDomainSecrets
+//===========================================================================================================================
+
+// This routine needs to be called whenever the system secrets database changes.
+// We call it from DynDNSConfigDidChange and mDNSPlatformInit
+
+void
+SetDomainSecrets( mDNS * const m )
+{
+	DomainAuthInfo *ptr;
+	domainname		fqdn;
+	DNameListElem * regDomains = NULL;
+
+	// Rather than immediately deleting all keys now, we mark them for deletion in ten seconds.
+	// In the case where the user simultaneously removes their DDNS host name and the key
+	// for it, this gives mDNSResponder ten seconds to gracefully delete the name from the
+	// server before it loses access to the necessary key. Otherwise, we'd leave orphaned
+	// address records behind that we no longer have permission to delete.
+	
+	for (ptr = m->AuthInfoList; ptr; ptr = ptr->next)
+		ptr->deltime = NonZeroTime(m->timenow + mDNSPlatformOneSecond*10);
+
+	GetDDNSFQDN( &fqdn );
+
+	if ( fqdn.c[ 0 ] )
+	{
+		SetDomainSecret( m, &fqdn );
+	}
+
+	GetDDNSDomains( &regDomains, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSRegistrationDomains );
+
+	while ( regDomains )
+	{
+		DNameListElem * current = regDomains;
+		SetDomainSecret( m, &current->name );
+		regDomains = regDomains->next;
+		free( current );
+	}
+}
+
+
+//===========================================================================================================================
+//	SetSearchDomainList
+//===========================================================================================================================
+
+mDNSlocal void SetDomainFromDHCP( void );
+mDNSlocal void SetReverseMapSearchDomainList( void );
+
+mDNSlocal void
+SetSearchDomainList( void )
+{
+	char			*	searchList	= NULL;
+	DWORD				searchListLen;
+	//DNameListElem	*	head = NULL;
+	//DNameListElem	*	current = NULL;
+	char			*	tok;
+	HKEY				key;
+	mStatus				err;
+
+	err = RegCreateKey( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &key );
+	require_noerr( err, exit );
+
+	err = RegQueryString( key, "SearchList", &searchList, &searchListLen, NULL );
+	require_noerr( err, exit );
+
+	// Windows separates the search domains with ','
+
+	tok = strtok( searchList, "," );
+	while ( tok )
+	{
+		if ( ( strcmp( tok, "" ) != 0 ) && ( strcmp( tok, "." ) != 0 ) )
+			mDNS_AddSearchDomain_CString(tok, mDNSNULL);
+		tok = strtok( NULL, "," );
+	}
+
+exit:
+
+	if ( searchList ) 
+	{
+		free( searchList );
+	}
+
+	if ( key )
+	{
+		RegCloseKey( key );
+	}
+
+	SetDomainFromDHCP();
+	SetReverseMapSearchDomainList();
+}
+
+
+//===========================================================================================================================
+//	SetReverseMapSearchDomainList
+//===========================================================================================================================
+
+mDNSlocal void
+SetReverseMapSearchDomainList( void )
+{
+	struct ifaddrs	*	ifa;
+
+	ifa = myGetIfAddrs( 1 );
+	while (ifa)
+	{
+		mDNSAddr addr;
+		
+		if (ifa->ifa_addr->sa_family == AF_INET && !SetupAddr(&addr, ifa->ifa_addr) && !(ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_netmask)
+		{
+			mDNSAddr	netmask;
+			char		buffer[256];
+			
+			if (!SetupAddr(&netmask, ifa->ifa_netmask))
+			{
+				sprintf(buffer, "%d.%d.%d.%d.in-addr.arpa.", addr.ip.v4.b[3] & netmask.ip.v4.b[3],
+                                                             addr.ip.v4.b[2] & netmask.ip.v4.b[2],
+                                                             addr.ip.v4.b[1] & netmask.ip.v4.b[1],
+                                                             addr.ip.v4.b[0] & netmask.ip.v4.b[0]);
+				mDNS_AddSearchDomain_CString(buffer, mDNSNULL);
+			}
+		}
+	
+		ifa = ifa->ifa_next;
+	}
+
+	return;
+}
+
+
+//===========================================================================================================================
+//	SetDNSServers
+//===========================================================================================================================
+
+mDNSlocal void
+SetDNSServers( mDNS *const m )
+{
+	PIP_PER_ADAPTER_INFO	pAdapterInfo	=	NULL;
+	FIXED_INFO			*	fixedInfo	= NULL;
+	ULONG					bufLen		= 0;	
+	IP_ADDR_STRING		*	dnsServerList;
+	IP_ADDR_STRING		*	ipAddr;
+	DWORD					index;
+	int						i			= 0;
+	mStatus					err			= kUnknownErr;
+
+	// Get the primary interface.
+
+	index = GetPrimaryInterface();
+
+	// This should have the interface index of the primary index.  Fall back in cases where
+	// it can't be determined.
+
+	if ( index )
+	{
+		bufLen = 0;
+
+		for ( i = 0; i < 100; i++ )
+		{
+			err = GetPerAdapterInfo( index, pAdapterInfo, &bufLen );
+
+			if ( err != ERROR_BUFFER_OVERFLOW )
+			{
+				break;
+			}
+
+			pAdapterInfo = (PIP_PER_ADAPTER_INFO) realloc( pAdapterInfo, bufLen );
+			require_action( pAdapterInfo, exit, err = mStatus_NoMemoryErr );
+		}
+
+		require_noerr( err, exit );
+
+		dnsServerList = &pAdapterInfo->DnsServerList;
+	}
+	else
+	{
+		bufLen = sizeof( FIXED_INFO );
+
+		for ( i = 0; i < 100; i++ )
+		{
+			if ( fixedInfo )
+			{
+				GlobalFree( fixedInfo );
+				fixedInfo = NULL;
+			}
+
+			fixedInfo = (FIXED_INFO*) GlobalAlloc( GPTR, bufLen );
+			require_action( fixedInfo, exit, err = mStatus_NoMemoryErr );
+	   
+			err = GetNetworkParams( fixedInfo, &bufLen );
+
+			if ( err != ERROR_BUFFER_OVERFLOW )
+			{
+				break;
+			}
+		}
+
+		require_noerr( err, exit );
+
+		dnsServerList = &fixedInfo->DnsServerList;
+	}
+
+	for ( ipAddr = dnsServerList; ipAddr; ipAddr = ipAddr->Next )
+	{
+		mDNSAddr addr;
+		err = StringToAddress( &addr, ipAddr->IpAddress.String );
+		if ( !err ) mDNS_AddDNSServer(m, mDNSNULL, mDNSInterface_Any, 0, &addr, UnicastDNSPort, kScopeNone, DEFAULT_UDNS_TIMEOUT, mDNSfalse, 0, mDNStrue, mDNStrue, mDNSfalse);
+	}
+
+exit:
+
+	if ( pAdapterInfo )
+	{
+		free( pAdapterInfo );
+	}
+
+	if ( fixedInfo )
+	{
+		GlobalFree( fixedInfo );
+	}
+}
+
+
+//===========================================================================================================================
+//	SetDomainFromDHCP
+//===========================================================================================================================
+
+mDNSlocal void
+SetDomainFromDHCP( void )
+{
+	int					i			= 0;
+	IP_ADAPTER_INFO *	pAdapterInfo;
+	IP_ADAPTER_INFO *	pAdapter;
+	DWORD				bufLen;
+	DWORD				index;
+	HKEY				key = NULL;
+	LPSTR				domain = NULL;
+	DWORD				dwSize;
+	mStatus				err = mStatus_NoError;
+
+	pAdapterInfo	= NULL;
+	
+	for ( i = 0; i < 100; i++ )
+	{
+		err = GetAdaptersInfo( pAdapterInfo, &bufLen);
+
+		if ( err != ERROR_BUFFER_OVERFLOW )
+		{
+			break;
+		}
+
+		pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
+		require_action( pAdapterInfo, exit, err = kNoMemoryErr );
+	}
+
+	require_noerr( err, exit );
+
+	index = GetPrimaryInterface();
+
+	for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
+	{
+		if ( pAdapter->IpAddressList.IpAddress.String &&
+		     pAdapter->IpAddressList.IpAddress.String[0] &&
+		     pAdapter->GatewayList.IpAddress.String &&
+		     pAdapter->GatewayList.IpAddress.String[0] &&
+		     ( !index || ( pAdapter->Index == index ) ) )
+		{
+			// Found one that will work
+
+			char keyName[1024];
+
+			_snprintf( keyName, 1024, "%s%s", "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\", pAdapter->AdapterName );
+
+			err = RegCreateKeyA( HKEY_LOCAL_MACHINE, keyName, &key );
+			require_noerr( err, exit );
+
+			err = RegQueryString( key, "Domain", &domain, &dwSize, NULL );
+			check_noerr( err );
+
+			if ( !domain || !domain[0] )
+			{
+				if ( domain )
+				{
+					free( domain );
+					domain = NULL;
+				}
+
+				err = RegQueryString( key, "DhcpDomain", &domain, &dwSize, NULL );
+				check_noerr( err );
+			}
+
+			if ( domain && domain[0] ) mDNS_AddSearchDomain_CString(domain, mDNSNULL);
+
+			break;
+		}
+	}
+
+exit:
+
+	if ( pAdapterInfo )
+	{
+		free( pAdapterInfo );
+	}
+
+	if ( domain )
+	{
+		free( domain );
+	}
+
+	if ( key )
+	{
+		RegCloseKey( key );
+	}
+}
+
+
+//===========================================================================================================================
+//	mDNSPlatformGetPrimaryInterface
+//===========================================================================================================================
+
+mDNSexport mStatus
+mDNSPlatformGetPrimaryInterface( mDNS * const m, mDNSAddr * v4, mDNSAddr * v6, mDNSAddr * router )
+{
+	IP_ADAPTER_INFO *	pAdapterInfo;
+	IP_ADAPTER_INFO *	pAdapter;
+	DWORD				bufLen;
+	int					i;
+	BOOL				found;
+	DWORD				index;
+	mStatus				err = mStatus_NoError;
+
+	DEBUG_UNUSED( m );
+
+	*v6 = zeroAddr;
+
+	pAdapterInfo	= NULL;
+	bufLen			= 0;
+	found			= FALSE;
+
+	for ( i = 0; i < 100; i++ )
+	{
+		err = GetAdaptersInfo( pAdapterInfo, &bufLen);
+
+		if ( err != ERROR_BUFFER_OVERFLOW )
+		{
+			break;
+		}
+
+		pAdapterInfo = (IP_ADAPTER_INFO*) realloc( pAdapterInfo, bufLen );
+		require_action( pAdapterInfo, exit, err = kNoMemoryErr );
+	}
+
+	require_noerr( err, exit );
+
+	index = GetPrimaryInterface();
+
+	for ( pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next )
+	{
+		if ( pAdapter->IpAddressList.IpAddress.String &&
+		     pAdapter->IpAddressList.IpAddress.String[0] &&
+		     pAdapter->GatewayList.IpAddress.String &&
+		     pAdapter->GatewayList.IpAddress.String[0] &&
+		     ( StringToAddress( v4, pAdapter->IpAddressList.IpAddress.String ) == mStatus_NoError ) &&
+		     ( StringToAddress( router, pAdapter->GatewayList.IpAddress.String ) == mStatus_NoError ) &&
+		     ( !index || ( pAdapter->Index == index ) ) )
+		{
+			// Found one that will work
+
+			if ( pAdapter->AddressLength == sizeof( m->PrimaryMAC ) )
+			{
+				memcpy( &m->PrimaryMAC, pAdapter->Address, pAdapter->AddressLength );
+			}
+
+			found = TRUE;
+			break;
+		}
+	}
+
+exit:
+
+	if ( pAdapterInfo )
+	{
+		free( pAdapterInfo );
+	}
+
+	return err;
+}
+
+mDNSexport void mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win)
+	{
+	(void) sadd; 	// Unused
+	(void) dadd; 	// Unused
+	(void) lport; 	// Unused
+	(void) rport; 	// Unused
+	(void) seq; 	// Unused
+	(void) ack; 	// Unused
+	(void) win;		// Unused
+	}
+
+mDNSexport mStatus mDNSPlatformGetRemoteMacAddr(mDNSAddr *raddr, char *eth)
+	{
+	(void) raddr; // Unused
+	(void) eth;   // Unused
+	}
+
+mDNSexport  mStatus    mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname)
+	{
+	(void) spsaddr; // Unused
+	(void) ifname;  // Unused
+	}
+
+mDNSexport  mStatus    mDNSPlatformClearSPSMACAddr(void)
+	{
+	}
+
+mDNSexport mStatus mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr, mDNSIPPort *rport, mDNSTCPInfo *mti)
+	{
+	(void) m;       // Unused
+	(void) laddr; 	// Unused
+	(void) raddr; 	// Unused
+	(void) lport; 	// Unused
+	(void) rport; 	// Unused
+	(void) mti; 	// Unused
+	}
+
+mDNSexport mDNSBool mDNSPlatformAllowPID(mDNS *const m, DNSQuestion *q)
+    {
+    (void) m;
+    (void) q;
+    return mDNStrue;
+    }
+
+mDNSexport mDNSs32 mDNSPlatformGetServiceID(mDNS *const m, DNSQuestion *q)
+    {
+    (void) m;
+    (void) q;
+    return -1;
+    }
+
+mDNSexport void mDNSPlatformSetDelegatePID(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q)
+    {
+    (void) src;
+    (void) dst;
+    (void) q;
+    }
+
+mDNSexport mDNSs32 mDNSPlatformGetPID()
+    {
+    return 0;
+    }
+
+mDNSexport mDNSu16 mDNSPlatformGetUDPPort(UDPSocket *sock)
+{
+	DEBUG_UNUSED( sock );
+ 
+	return (mDNSu16)-1;
+}
+
+mDNSexport mDNSBool mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID)
+{
+	DEBUG_UNUSED( InterfaceID );
+    
+	return mDNSfalse;
+}
+
+#if 0
+#pragma mark -
+#endif
+
+//===========================================================================================================================
+//	debugf_
+//===========================================================================================================================
+#if( MDNS_DEBUGMSGS )
+mDNSexport void	debugf_( const char *inFormat, ... )
+{
+	char		buffer[ 512 ];
+    va_list		args;
+    mDNSu32		length;
+	
+	va_start( args, inFormat );
+	length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
+	va_end( args );
+	
+	dlog( kDebugLevelInfo, "%s\n", buffer );
+}
+#endif
+
+//===========================================================================================================================
+//	verbosedebugf_
+//===========================================================================================================================
+
+#if( MDNS_DEBUGMSGS > 1 )
+mDNSexport void	verbosedebugf_( const char *inFormat, ... )
+{
+	char		buffer[ 512 ];
+    va_list		args;
+    mDNSu32		length;
+	
+	va_start( args, inFormat );
+	length = mDNS_vsnprintf( buffer, sizeof( buffer ), inFormat, args );
+	va_end( args );
+	
+	dlog( kDebugLevelVerbose, "%s\n", buffer );
+}
+#endif
+
+
+#if 0
+#pragma mark -
+#pragma mark == Platform Internals  ==
+#endif
+
+
+//===========================================================================================================================
+//	SetupNiceName
+//===========================================================================================================================
+
+mStatus	SetupNiceName( mDNS * const inMDNS )
+{
+	HKEY		descKey = NULL;
+	char		utf8[ 256 ];
+	LPCTSTR		s;
+	LPWSTR		joinName;
+	NETSETUP_JOIN_STATUS joinStatus;
+	mStatus		err = 0;
+	DWORD		namelen;
+	BOOL		ok;
+	
+	check( inMDNS );
+	
+	// Set up the nice name.
+	utf8[0] = '\0';
+
+	// First try and open the registry key that contains the computer description value
+	s = TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\parameters");
+	err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, s, 0, KEY_READ, &descKey);
+	check_translated_errno( err == 0, errno_compat(), kNameErr );
+
+	if ( !err )
+	{
+		TCHAR	desc[256];
+		DWORD	descSize = sizeof( desc );
+
+		// look for the computer description
+		err = RegQueryValueEx( descKey, TEXT("srvcomment"), 0, NULL, (LPBYTE) &desc, &descSize);
+		
+		if ( !err )
+		{
+			err = TCHARtoUTF8( desc, utf8, sizeof( utf8 ) );
+		}
+
+		if ( err )
+		{
+			utf8[ 0 ] = '\0';
+		}
+	}
+
+	// if we can't find it in the registry, then use the hostname of the machine
+	if ( err || ( utf8[ 0 ] == '\0' ) )
+	{
+		TCHAR hostname[256];
+		
+		namelen = sizeof( hostname ) / sizeof( TCHAR );
+
+		ok = GetComputerNameExW( ComputerNamePhysicalDnsHostname, hostname, &namelen );
+		err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
+		check_noerr( err );
+		
+		if( !err )
+		{
+			err = TCHARtoUTF8( hostname, utf8, sizeof( utf8 ) );
+		}
+
+		if ( err )
+		{
+			utf8[ 0 ] = '\0';
+		}
+	}
+
+	// if we can't get the hostname
+	if ( err || ( utf8[ 0 ] == '\0' ) )
+	{
+		// Invalidate name so fall back to a default name.
+		
+		strcpy( utf8, kMDNSDefaultName );
+	}
+
+	utf8[ sizeof( utf8 ) - 1 ]	= '\0';	
+	inMDNS->nicelabel.c[ 0 ]	= (mDNSu8) (strlen( utf8 ) < MAX_DOMAIN_LABEL ? strlen( utf8 ) : MAX_DOMAIN_LABEL);
+	memcpy( &inMDNS->nicelabel.c[ 1 ], utf8, inMDNS->nicelabel.c[ 0 ] );
+	
+	dlog( kDebugLevelInfo, DEBUG_NAME "nice name \"%.*s\"\n", inMDNS->nicelabel.c[ 0 ], &inMDNS->nicelabel.c[ 1 ] );
+	
+	if ( descKey )
+	{
+		RegCloseKey( descKey );
+	}
+
+	ZeroMemory( inMDNS->p->nbname, sizeof( inMDNS->p->nbname ) );
+	ZeroMemory( inMDNS->p->nbdomain, sizeof( inMDNS->p->nbdomain ) );
+
+	namelen = sizeof( inMDNS->p->nbname );
+	ok = GetComputerNameExA( ComputerNamePhysicalNetBIOS, inMDNS->p->nbname, &namelen );
+	check( ok );
+	if ( ok ) dlog( kDebugLevelInfo, DEBUG_NAME "netbios name \"%s\"\n", inMDNS->p->nbname );
+
+	err = NetGetJoinInformation( NULL, &joinName, &joinStatus );
+	check ( err == NERR_Success );
+	if ( err == NERR_Success )
+	{
+		if ( ( joinStatus == NetSetupWorkgroupName ) || ( joinStatus == NetSetupDomainName ) )
+		{
+			err = TCHARtoUTF8( joinName, inMDNS->p->nbdomain, sizeof( inMDNS->p->nbdomain ) );
+			check( !err );
+			if ( !err ) dlog( kDebugLevelInfo, DEBUG_NAME "netbios domain/workgroup \"%s\"\n", inMDNS->p->nbdomain );
+		}
+
+		NetApiBufferFree( joinName );
+		joinName = NULL;
+	}
+
+	err = 0;
+
+	return( err );
+}
+
+//===========================================================================================================================
+//	SetupHostName
+//===========================================================================================================================
+
+mDNSlocal mStatus	SetupHostName( mDNS * const inMDNS )
+{
+	mStatus		err = 0;
+	char		tempString[ 256 ];
+	DWORD		tempStringLen;
+	domainlabel tempLabel;
+	BOOL		ok;
+	
+	check( inMDNS );
+
+	// Set up the nice name.
+	tempString[ 0 ] = '\0';
+
+	// use the hostname of the machine
+	tempStringLen = sizeof( tempString );
+	ok = GetComputerNameExA( ComputerNamePhysicalDnsHostname, tempString, &tempStringLen );
+	err = translate_errno( ok, (mStatus) GetLastError(), kNameErr );
+	check_noerr( err );
+
+	// if we can't get the hostname
+	if( err || ( tempString[ 0 ] == '\0' ) )
+	{
+		// Invalidate name so fall back to a default name.
+		
+		strcpy( tempString, kMDNSDefaultName );
+	}
+
+	tempString[ sizeof( tempString ) - 1 ] = '\0';
+	tempLabel.c[ 0 ] = (mDNSu8) (strlen( tempString ) < MAX_DOMAIN_LABEL ? strlen( tempString ) : MAX_DOMAIN_LABEL );
+	memcpy( &tempLabel.c[ 1 ], tempString, tempLabel.c[ 0 ] );
+	
+	// Set up the host name.
+	
+	ConvertUTF8PstringToRFC1034HostLabel( tempLabel.c, &inMDNS->hostlabel );
+	if( inMDNS->hostlabel.c[ 0 ] == 0 )
+	{
+		// Nice name has no characters that are representable as an RFC1034 name (e.g. Japanese) so use the default.
+		
+		MakeDomainLabelFromLiteralString( &inMDNS->hostlabel, kMDNSDefaultName );
+	}
+
+	check( inMDNS->hostlabel.c[ 0 ] != 0 );
+	
+	mDNS_SetFQDN( inMDNS );
+	
+	dlog( kDebugLevelInfo, DEBUG_NAME "host name \"%.*s\"\n", inMDNS->hostlabel.c[ 0 ], &inMDNS->hostlabel.c[ 1 ] );
+	
+	return( err );
+}
+
+//===========================================================================================================================
+//	SetupName
+//===========================================================================================================================
+
+mDNSlocal mStatus	SetupName( mDNS * const inMDNS )
+{
+	mStatus		err = 0;
+	
+	check( inMDNS );
+	
+	err = SetupNiceName( inMDNS );
+	check_noerr( err );
+
+	err = SetupHostName( inMDNS );
+	check_noerr( err );
+
+	return err;
+}
+
+
+//===========================================================================================================================
+//	SetupInterfaceList
+//===========================================================================================================================
+
+mStatus	SetupInterfaceList( mDNS * const inMDNS )
+{
+	mStatus						err;
+	mDNSInterfaceData **		next;
+	mDNSInterfaceData *			ifd;
+	struct ifaddrs *			addrs;
+	struct ifaddrs *			p;
+	struct ifaddrs *			loopbackv4;
+	struct ifaddrs *			loopbackv6;
+	u_int						flagMask;
+	u_int						flagTest;
+	mDNSBool					foundv4;
+	mDNSBool					foundv6;
+	mDNSBool					foundUnicastSock4DestAddr;
+	mDNSBool					foundUnicastSock6DestAddr;
+	
+	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list\n" );
+	check( inMDNS );
+	check( inMDNS->p );
+	
+	inMDNS->p->registeredLoopback4	= mDNSfalse;
+	inMDNS->p->nextDHCPLeaseExpires = 0x7FFFFFFF;
+	addrs							= NULL;
+	foundv4							= mDNSfalse;
+	foundv6							= mDNSfalse;
+	foundUnicastSock4DestAddr		= mDNSfalse;
+	foundUnicastSock6DestAddr		= mDNSfalse;
+	
+	// Tear down any existing interfaces that may be set up.
+	
+	TearDownInterfaceList( inMDNS );
+
+	// Set up the name of this machine.
+	
+	err = SetupName( inMDNS );
+	check_noerr( err );
+
+	// Set up IPv4 interface(s). We have to set up IPv4 first so any IPv6 interface with an IPv4-routable address
+	// can refer to the IPv4 interface when it registers to allow DNS AAAA records over the IPv4 interface.
+	
+	err = getifaddrs( &addrs );
+	require_noerr( err, exit );
+	
+	loopbackv4	= NULL;
+	loopbackv6	= NULL;
+	next		= &inMDNS->p->interfaceList;
+
+	flagMask = IFF_UP | IFF_MULTICAST;
+	flagTest = IFF_UP | IFF_MULTICAST;
+	
+#if( MDNS_WINDOWS_ENABLE_IPV4 )
+	for( p = addrs; p; p = p->ifa_next )
+	{
+		if( !p->ifa_addr || ( p->ifa_addr->sa_family != AF_INET ) || ( ( p->ifa_flags & flagMask ) != flagTest ) )
+		{
+			continue;
+		}
+		if( p->ifa_flags & IFF_LOOPBACK )
+		{
+			if( !loopbackv4 )
+			{
+				loopbackv4 = p;
+			}
+			continue;
+		}
+		dlog( kDebugLevelVerbose, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
+			p->ifa_name ? p->ifa_name : "<null>", p->ifa_extra.index, p->ifa_addr );
+		
+		err = SetupInterface( inMDNS, p, &ifd );
+		require_noerr( err, exit );
+
+		// If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to
+		// register him, but we also want to note that we haven't found a v4 interface
+		// so that we register loopback so same host operations work
+ 		
+		if ( ifd->interfaceInfo.McastTxRx == mDNStrue )
+		{
+			foundv4 = mDNStrue;
+		}
+
+		if ( p->ifa_dhcpEnabled && ( p->ifa_dhcpLeaseExpires < inMDNS->p->nextDHCPLeaseExpires ) )
+		{
+			inMDNS->p->nextDHCPLeaseExpires = p->ifa_dhcpLeaseExpires;
+		}
+
+		// If we're on a platform that doesn't have WSARecvMsg(), there's no way
+		// of determing the destination address of a packet that is sent to us.
+		// For multicast packets, that's easy to determine.  But for the unicast
+		// sockets, we'll fake it by taking the address of the first interface
+		// that is successfully setup.
+
+		if ( !foundUnicastSock4DestAddr )
+		{
+			inMDNS->p->unicastSock4.addr = ifd->interfaceInfo.ip;
+			foundUnicastSock4DestAddr = TRUE;
+		}
+			
+		*next = ifd;
+		next  = &ifd->next;
+		++inMDNS->p->interfaceCount;
+	}
+#endif
+	
+	// Set up IPv6 interface(s) after IPv4 is set up (see IPv4 notes above for reasoning).
+	
+#if( MDNS_WINDOWS_ENABLE_IPV6 )
+
+	if ( gEnableIPv6 )
+	{
+		for( p = addrs; p; p = p->ifa_next )
+		{
+			if( !p->ifa_addr || ( p->ifa_addr->sa_family != AF_INET6 ) || ( ( p->ifa_flags & flagMask ) != flagTest ) )
+			{
+				continue;
+			}
+			if( p->ifa_flags & IFF_LOOPBACK )
+			{
+				if( !loopbackv6 )
+				{
+					loopbackv6 = p;
+				}
+				continue;
+			}
+			dlog( kDebugLevelVerbose, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
+				p->ifa_name ? p->ifa_name : "<null>", p->ifa_extra.index, p->ifa_addr );
+			
+			err = SetupInterface( inMDNS, p, &ifd );
+			require_noerr( err, exit );
+					
+			// If this guy is point-to-point (ifd->interfaceInfo.McastTxRx == 0 ) we still want to
+			// register him, but we also want to note that we haven't found a v4 interface
+			// so that we register loopback so same host operations work
+	 		
+			if ( ifd->interfaceInfo.McastTxRx == mDNStrue )
+			{
+				foundv6 = mDNStrue;
+			}
+
+			// If we're on a platform that doesn't have WSARecvMsg(), there's no way
+			// of determing the destination address of a packet that is sent to us.
+			// For multicast packets, that's easy to determine.  But for the unicast
+			// sockets, we'll fake it by taking the address of the first interface
+			// that is successfully setup.
+
+			if ( !foundUnicastSock6DestAddr )
+			{
+				inMDNS->p->unicastSock6.addr = ifd->interfaceInfo.ip;
+				foundUnicastSock6DestAddr = TRUE;
+			}
+
+			*next = ifd;
+			next  = &ifd->next;
+			++inMDNS->p->interfaceCount;
+		}
+	}
+
+#endif
+
+	// If there are no real interfaces, but there is a loopback interface, use that so same-machine operations work.
+
+#if( !MDNS_WINDOWS_ENABLE_IPV4 && !MDNS_WINDOWS_ENABLE_IPV6 )
+	
+	flagMask |= IFF_LOOPBACK;
+	flagTest |= IFF_LOOPBACK;
+	
+	for( p = addrs; p; p = p->ifa_next )
+	{
+		if( !p->ifa_addr || ( ( p->ifa_flags & flagMask ) != flagTest ) )
+		{
+			continue;
+		}
+		if( ( p->ifa_addr->sa_family != AF_INET ) && ( p->ifa_addr->sa_family != AF_INET6 ) )
+		{
+			continue;
+		}
+		
+		v4loopback = p;
+		break;
+	}
+	
+#endif
+	
+	if ( !foundv4 && loopbackv4 )
+	{
+		dlog( kDebugLevelInfo, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
+			loopbackv4->ifa_name ? loopbackv4->ifa_name : "<null>", loopbackv4->ifa_extra.index, loopbackv4->ifa_addr );
+		
+		err = SetupInterface( inMDNS, loopbackv4, &ifd );
+		require_noerr( err, exit );
+
+		inMDNS->p->registeredLoopback4 = mDNStrue;
+		
+#if( MDNS_WINDOWS_ENABLE_IPV4 )
+
+		// If we're on a platform that doesn't have WSARecvMsg(), there's no way
+		// of determing the destination address of a packet that is sent to us.
+		// For multicast packets, that's easy to determine.  But for the unicast
+		// sockets, we'll fake it by taking the address of the first interface
+		// that is successfully setup.
+
+		if ( !foundUnicastSock4DestAddr )
+		{
+			inMDNS->p->unicastSock4.addr = ifd->sock.addr;
+			foundUnicastSock4DestAddr = TRUE;
+		}
+#endif
+
+		*next = ifd;
+		next  = &ifd->next;
+		++inMDNS->p->interfaceCount;
+	}
+
+	if ( !foundv6 && loopbackv6 )
+	{
+		dlog( kDebugLevelInfo, DEBUG_NAME "Interface %40s (0x%08X) %##a\n", 
+			loopbackv6->ifa_name ? loopbackv6->ifa_name : "<null>", loopbackv6->ifa_extra.index, loopbackv6->ifa_addr );
+		
+		err = SetupInterface( inMDNS, loopbackv6, &ifd );
+		require_noerr( err, exit );
+		
+#if( MDNS_WINDOWS_ENABLE_IPV6 )
+
+		if ( gEnableIPv6 )
+		{
+			// If we're on a platform that doesn't have WSARecvMsg(), there's no way
+			// of determing the destination address of a packet that is sent to us.
+			// For multicast packets, that's easy to determine.  But for the unicast
+			// sockets, we'll fake it by taking the address of the first interface
+			// that is successfully setup.
+
+			if ( !foundUnicastSock6DestAddr )
+			{
+				inMDNS->p->unicastSock6.addr = ifd->sock.addr;
+				foundUnicastSock6DestAddr = TRUE;
+			}
+		}
+
+#endif
+
+		*next = ifd;
+		next  = &ifd->next;
+		++inMDNS->p->interfaceCount;
+	}
+
+	CheckFileShares( inMDNS );
+
+exit:
+	if( err )
+	{
+		TearDownInterfaceList( inMDNS );
+	}
+	if( addrs )
+	{
+		freeifaddrs( addrs );
+	}
+	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface list done (err=%d %m)\n", err, err );
+	return( err );
+}
+
+//===========================================================================================================================
+//	TearDownInterfaceList
+//===========================================================================================================================
+
+mStatus	TearDownInterfaceList( mDNS * const inMDNS )
+{
+	mDNSInterfaceData **		p;
+	mDNSInterfaceData *		ifd;
+	
+	dlog( kDebugLevelTrace, DEBUG_NAME "tearing down interface list\n" );
+	check( inMDNS );
+	check( inMDNS->p );
+
+	// Free any interfaces that were previously marked inactive and are no longer referenced by the mDNS cache.
+	// Interfaces are marked inactive, but not deleted immediately if they were still referenced by the mDNS cache
+	// so that remove events that occur after an interface goes away can still report the correct interface.
+
+	p = &inMDNS->p->inactiveInterfaceList;
+	while( *p )
+	{
+		ifd = *p;
+		if( NumCacheRecordsForInterfaceID( inMDNS, (mDNSInterfaceID) ifd ) > 0 )
+		{
+			p = &ifd->next;
+			continue;
+		}
+		
+		dlog( kDebugLevelInfo, DEBUG_NAME "freeing unreferenced, inactive interface %#p %#a\n", ifd, &ifd->interfaceInfo.ip );
+		*p = ifd->next;
+
+		QueueUserAPC( ( PAPCFUNC ) FreeInterface, inMDNS->p->mainThread, ( ULONG_PTR ) ifd );
+	}
+
+	// Tear down all the interfaces.
+	
+	while( inMDNS->p->interfaceList )
+	{
+		ifd = inMDNS->p->interfaceList;
+		inMDNS->p->interfaceList = ifd->next;
+		
+		TearDownInterface( inMDNS, ifd );
+	}
+	inMDNS->p->interfaceCount = 0;
+	
+	dlog( kDebugLevelTrace, DEBUG_NAME "tearing down interface list done\n" );
+	return( mStatus_NoError );
+}
+
+//===========================================================================================================================
+//	SetupInterface
+//===========================================================================================================================
+
+mDNSlocal mStatus	SetupInterface( mDNS * const inMDNS, const struct ifaddrs *inIFA, mDNSInterfaceData **outIFD )
+{
+	mDNSInterfaceData	*	ifd;
+	mDNSInterfaceData	*	p;
+	mStatus					err;
+	
+	ifd = NULL;
+	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface\n" );
+	check( inMDNS );
+	check( inMDNS->p );
+	check( inIFA );
+	check( inIFA->ifa_addr );
+	check( outIFD );
+	
+	// Allocate memory for the interface and initialize it.
+	
+	ifd = (mDNSInterfaceData *) calloc( 1, sizeof( *ifd ) );
+	require_action( ifd, exit, err = mStatus_NoMemoryErr );
+	ifd->sock.fd	= kInvalidSocketRef;
+	ifd->sock.ifd	= ifd;
+	ifd->sock.next	= NULL;
+	ifd->sock.m		= inMDNS;
+	ifd->index		= inIFA->ifa_extra.index;
+	ifd->scopeID	= inIFA->ifa_extra.index;
+	check( strlen( inIFA->ifa_name ) < sizeof( ifd->name ) );
+	strncpy( ifd->name, inIFA->ifa_name, sizeof( ifd->name ) - 1 );
+	ifd->name[ sizeof( ifd->name ) - 1 ] = '\0';
+	
+	strncpy(ifd->interfaceInfo.ifname, inIFA->ifa_name, sizeof(ifd->interfaceInfo.ifname));
+	ifd->interfaceInfo.ifname[sizeof(ifd->interfaceInfo.ifname)-1] = 0;
+	
+	// We always send and receive using IPv4, but to reduce traffic, we send and receive using IPv6 only on interfaces 
+	// that have no routable IPv4 address. Having a routable IPv4 address assigned is a reasonable indicator of being 
+	// on a large configured network, which means there's a good chance that most or all the other devices on that 
+	// network should also have v4. By doing this we lose the ability to talk to true v6-only devices on that link, 
+	// but we cut the packet rate in half. At this time, reducing the packet rate is more important than v6-only 
+	// devices on a large configured network, so we are willing to make that sacrifice.
+	
+	ifd->interfaceInfo.McastTxRx   = ( ( inIFA->ifa_flags & IFF_MULTICAST ) && !( inIFA->ifa_flags & IFF_POINTTOPOINT ) ) ? mDNStrue : mDNSfalse;
+	ifd->interfaceInfo.InterfaceID = NULL;
+
+	for( p = inMDNS->p->interfaceList; p; p = p->next )
+	{
+		if ( strcmp( p->name, ifd->name ) == 0 )
+		{
+			if (!ifd->interfaceInfo.InterfaceID)
+			{
+				ifd->interfaceInfo.InterfaceID	= (mDNSInterfaceID) p;
+			}
+
+			if ( ( inIFA->ifa_addr->sa_family != AF_INET ) &&
+			     ( p->interfaceInfo.ip.type == mDNSAddrType_IPv4 ) &&
+			     ( p->interfaceInfo.ip.ip.v4.b[ 0 ] != 169 || p->interfaceInfo.ip.ip.v4.b[ 1 ] != 254 ) )
+			{
+				ifd->interfaceInfo.McastTxRx = mDNSfalse;
+			}
+
+			break;
+		}
+	}
+
+	if ( !ifd->interfaceInfo.InterfaceID )
+	{
+		ifd->interfaceInfo.InterfaceID = (mDNSInterfaceID) ifd;
+	}
+
+	// Set up a socket for this interface (if needed).
+	
+	if( ifd->interfaceInfo.McastTxRx )
+	{
+		DWORD size;
+			
+		err = SetupSocket( inMDNS, inIFA->ifa_addr, MulticastDNSPort, &ifd->sock.fd );
+		require_noerr( err, exit );
+		ifd->sock.addr = ( inIFA->ifa_addr->sa_family == AF_INET6 ) ? AllDNSLinkGroup_v6 : AllDNSLinkGroup_v4;
+		ifd->sock.port = MulticastDNSPort;
+		
+		// Get a ptr to the WSARecvMsg function, if supported. Otherwise, we'll fallback to recvfrom.
+
+		err = WSAIoctl( ifd->sock.fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &kWSARecvMsgGUID, sizeof( kWSARecvMsgGUID ), &ifd->sock.recvMsgPtr, sizeof( ifd->sock.recvMsgPtr ), &size, NULL, NULL );
+
+		if ( err )
+		{
+			ifd->sock.recvMsgPtr = NULL;
+		}
+	}
+
+	if ( inIFA->ifa_dhcpEnabled && ( inIFA->ifa_dhcpLeaseExpires < inMDNS->p->nextDHCPLeaseExpires ) )
+	{
+		inMDNS->p->nextDHCPLeaseExpires = inIFA->ifa_dhcpLeaseExpires;
+	}
+
+	ifd->interfaceInfo.NetWake = inIFA->ifa_womp;
+
+	// Register this interface with mDNS.
+	
+	err = SockAddrToMDNSAddr( inIFA->ifa_addr, &ifd->interfaceInfo.ip, NULL );
+	require_noerr( err, exit );
+	
+	err = SockAddrToMDNSAddr( inIFA->ifa_netmask, &ifd->interfaceInfo.mask, NULL );
+	require_noerr( err, exit );
+
+	memcpy( ifd->interfaceInfo.MAC.b, inIFA->ifa_physaddr, sizeof( ifd->interfaceInfo.MAC.b ) );
+	
+	ifd->interfaceInfo.Advertise = ( mDNSu8 ) inMDNS->AdvertiseLocalAddresses;
+
+	if ( ifd->sock.fd != kInvalidSocketRef )
+	{
+		err = mDNSPollRegisterSocket( ifd->sock.fd, FD_READ, UDPSocketNotification, &ifd->sock );
+		require_noerr( err, exit );
+	}
+
+    // If interface is a direct link, address record will be marked as kDNSRecordTypeKnownUnique
+    // and skip the probe phase of the probe/announce packet sequence.
+    ifd->interfaceInfo.DirectLink = mDNSfalse;
+
+	err = mDNS_RegisterInterface( inMDNS, &ifd->interfaceInfo, mDNSfalse );
+	require_noerr( err, exit );
+	ifd->hostRegistered = mDNStrue;
+	
+	dlog( kDebugLevelInfo, DEBUG_NAME "Registered interface %##a with mDNS\n", inIFA->ifa_addr );
+	
+	// Success!
+	
+	*outIFD = ifd;
+	ifd = NULL;
+	
+exit:
+
+	if( ifd )
+	{
+		TearDownInterface( inMDNS, ifd );
+	}
+	dlog( kDebugLevelTrace, DEBUG_NAME "setting up interface done (err=%d %m)\n", err, err );
+	return( err );
+}
+
+//===========================================================================================================================
+//	TearDownInterface
+//===========================================================================================================================
+
+mDNSlocal mStatus	TearDownInterface( mDNS * const inMDNS, mDNSInterfaceData *inIFD )
+{	
+	check( inMDNS );
+	check( inIFD );
+	
+	// Deregister this interface with mDNS.
+	
+	dlog( kDebugLevelInfo, DEBUG_NAME "Deregistering interface %#a with mDNS\n", &inIFD->interfaceInfo.ip );
+	
+	if( inIFD->hostRegistered )
+	{
+		inIFD->hostRegistered = mDNSfalse;
+		mDNS_DeregisterInterface( inMDNS, &inIFD->interfaceInfo, mDNSfalse );
+	}
+	
+	// Tear down the multicast socket.
+	
+	UDPCloseSocket( &inIFD->sock );
+
+	// If the interface is still referenced by items in the mDNS cache then put it on the inactive list. This keeps 
+	// the InterfaceID valid so remove events report the correct interface. If it is no longer referenced, free it.
+
+	if( NumCacheRecordsForInterfaceID( inMDNS, (mDNSInterfaceID) inIFD ) > 0 )
+	{
+		inIFD->next = inMDNS->p->inactiveInterfaceList;
+		inMDNS->p->inactiveInterfaceList = inIFD;
+		dlog( kDebugLevelInfo, DEBUG_NAME "deferring free of interface %#p %#a\n", inIFD, &inIFD->interfaceInfo.ip );
+	}
+	else
+	{
+		dlog( kDebugLevelInfo, DEBUG_NAME "freeing interface %#p %#a immediately\n", inIFD, &inIFD->interfaceInfo.ip );
+		QueueUserAPC( ( PAPCFUNC ) FreeInterface, inMDNS->p->mainThread, ( ULONG_PTR ) inIFD );
+	}
+
+	return( mStatus_NoError );
+}
+
+mDNSlocal void CALLBACK FreeInterface( mDNSInterfaceData *inIFD )
+{
+	free( inIFD );
+}
+
+//===========================================================================================================================
+//	SetupSocket
+//===========================================================================================================================
+
+mDNSlocal mStatus	SetupSocket( mDNS * const inMDNS, const struct sockaddr *inAddr, mDNSIPPort port, SocketRef *outSocketRef  )
+{
+	mStatus			err;
+	SocketRef		sock;
+	int				option;
+	DWORD			bytesReturned = 0;
+	BOOL			behavior = FALSE;
+	
+	DEBUG_UNUSED( inMDNS );
+	
+	dlog( kDebugLevelTrace, DEBUG_NAME "setting up socket %##a\n", inAddr );
+	check( inMDNS );
+	check( outSocketRef );
+	
+	// Set up an IPv4 or IPv6 UDP socket.
+	
+	sock = socket( inAddr->sa_family, SOCK_DGRAM, IPPROTO_UDP );
+	err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
+	require_noerr( err, exit );
+		
+	// Turn on reuse address option so multiple servers can listen for Multicast DNS packets,
+	// if we're creating a multicast socket
+	
+	if ( !mDNSIPPortIsZero( port ) )
+	{
+		option = 1;
+		err = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof( option ) );
+		check_translated_errno( err == 0, errno_compat(), kOptionErr );
+	}
+
+	// <rdar://problem/7894393> Bonjour for Windows broken on Windows XP
+	//
+	// Not sure why, but the default behavior for sockets is to behave incorrectly
+	// when using them in Overlapped I/O mode on XP. According to MSDN:
+	//
+	// SIO_UDP_CONNRESET (opcode setting: I, T==3)
+	//     Windows XP:  Controls whether UDP PORT_UNREACHABLE messages are reported. Set to TRUE to enable reporting.
+	//     Set to FALSE to disable reporting.
+	//
+	// Packet traces from misbehaving Bonjour installations showed that ICMP port unreachable
+	// messages were being sent to us after we sent out packets to a multicast address. This is clearly
+	// incorrect behavior, but should be harmless. However, after receiving a port unreachable error, WinSock
+	// will no longer receive any packets from that socket, which is not harmless. This behavior is only
+	// seen on XP.
+	//
+	// So we turn off port unreachable reporting to make sure our sockets that are reading
+	// multicast packets function correctly under all circumstances.
+
+	err = WSAIoctl( sock, SIO_UDP_CONNRESET, &behavior, sizeof(behavior), NULL, 0, &bytesReturned, NULL, NULL );
+	check_translated_errno( err == 0, errno_compat(), kOptionErr );
+
+	if( inAddr->sa_family == AF_INET )
+	{
+		mDNSv4Addr				ipv4;
+		struct sockaddr_in		sa4;
+		struct ip_mreq			mreqv4;
+		
+		// Bind the socket to the desired port
+		
+		ipv4.NotAnInteger 	= ( (const struct sockaddr_in *) inAddr )->sin_addr.s_addr;
+		mDNSPlatformMemZero( &sa4, sizeof( sa4 ) );
+		sa4.sin_family 		= AF_INET;
+		sa4.sin_port 		= port.NotAnInteger;
+		sa4.sin_addr.s_addr	= ipv4.NotAnInteger;
+		
+		err = bind( sock, (struct sockaddr *) &sa4, sizeof( sa4 ) );
+		check_translated_errno( err == 0, errno_compat(), kUnknownErr );
+		
+		// Turn on option to receive destination addresses and receiving interface.
+		
+		option = 1;
+		err = setsockopt( sock, IPPROTO_IP, IP_PKTINFO, (char *) &option, sizeof( option ) );
+		check_translated_errno( err == 0, errno_compat(), kOptionErr );
+		
+		if ( !mDNSIPPortIsZero( port ) )
+		{
+			// Join the all-DNS multicast group so we receive Multicast DNS packets
+
+			mreqv4.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
+			mreqv4.imr_interface.s_addr = ipv4.NotAnInteger;
+			err = setsockopt( sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreqv4, sizeof( mreqv4 ) );
+			check_translated_errno( err == 0, errno_compat(), kOptionErr );
+		
+			// Specify the interface to send multicast packets on this socket.
+		
+			sa4.sin_addr.s_addr = ipv4.NotAnInteger;
+			err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_IF, (char *) &sa4.sin_addr, sizeof( sa4.sin_addr ) );
+			check_translated_errno( err == 0, errno_compat(), kOptionErr );
+		
+			// Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
+		
+			option = 1;
+			err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
+			check_translated_errno( err == 0, errno_compat(), kOptionErr );
+		}
+
+		// Send unicast packets with TTL 255 (helps against spoofing).
+		
+		option = 255;
+		err = setsockopt( sock, IPPROTO_IP, IP_TTL, (char *) &option, sizeof( option ) );
+		check_translated_errno( err == 0, errno_compat(), kOptionErr );
+
+		// Send multicast packets with TTL 255 (helps against spoofing).
+		
+		option = 255;
+		err = setsockopt( sock, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &option, sizeof( option ) );
+		check_translated_errno( err == 0, errno_compat(), kOptionErr );
+
+	}
+	else if( inAddr->sa_family == AF_INET6 )
+	{
+		struct sockaddr_in6 *		sa6p;
+		struct sockaddr_in6			sa6;
+		struct ipv6_mreq			mreqv6;
+		
+		sa6p = (struct sockaddr_in6 *) inAddr;
+		
+		// Bind the socket to the desired port
+		
+		mDNSPlatformMemZero( &sa6, sizeof( sa6 ) );
+		sa6.sin6_family		= AF_INET6;
+		sa6.sin6_port		= port.NotAnInteger;
+		sa6.sin6_flowinfo	= 0;
+		sa6.sin6_addr		= sa6p->sin6_addr;
+		sa6.sin6_scope_id	= sa6p->sin6_scope_id;
+		
+		err = bind( sock, (struct sockaddr *) &sa6, sizeof( sa6 ) );
+		check_translated_errno( err == 0, errno_compat(), kUnknownErr );
+		
+		// Turn on option to receive destination addresses and receiving interface.
+		
+		option = 1;
+		err = setsockopt( sock, IPPROTO_IPV6, IPV6_PKTINFO, (char *) &option, sizeof( option ) );
+		check_translated_errno( err == 0, errno_compat(), kOptionErr );
+		
+		// We only want to receive IPv6 packets (not IPv4-mapped IPv6 addresses) because we have a separate socket 
+		// for IPv4, but the IPv6 stack in Windows currently doesn't support IPv4-mapped IPv6 addresses and doesn't
+		// support the IPV6_V6ONLY socket option so the following code would typically not be executed (or needed).
+		
+		#if( defined( IPV6_V6ONLY ) )
+			option = 1;
+			err = setsockopt( sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &option, sizeof( option ) );
+			check_translated_errno( err == 0, errno_compat(), kOptionErr );		
+		#endif
+		
+		if ( !mDNSIPPortIsZero( port ) )
+		{
+			// Join the all-DNS multicast group so we receive Multicast DNS packets.
+		
+			mreqv6.ipv6mr_multiaddr = *( (struct in6_addr *) &AllDNSLinkGroup_v6.ip.v6 );
+			mreqv6.ipv6mr_interface = sa6p->sin6_scope_id;
+			err = setsockopt( sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &mreqv6, sizeof( mreqv6 ) );
+			check_translated_errno( err == 0, errno_compat(), kOptionErr );
+		
+			// Specify the interface to send multicast packets on this socket.
+		
+			option = (int) sa6p->sin6_scope_id;
+			err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &option, sizeof( option ) );
+			check_translated_errno( err == 0, errno_compat(), kOptionErr );
+		
+			// Enable multicast loopback so we receive multicast packets we send (for same-machine operations).
+			
+			option = 1;
+			err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *) &option, sizeof( option ) );
+			check_translated_errno( err == 0, errno_compat(), kOptionErr );
+		}
+
+		// Send unicast packets with TTL 255 (helps against spoofing).
+		
+		option = 255;
+		err = setsockopt( sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *) &option, sizeof( option ) );
+		check_translated_errno( err == 0, errno_compat(), kOptionErr );
+
+		// Send multicast packets with TTL 255 (helps against spoofing).
+			
+		option = 255;
+		err = setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *) &option, sizeof( option ) );
+		check_translated_errno( err == 0, errno_compat(), kOptionErr );
+	}
+	else
+	{
+		dlog( kDebugLevelError, DEBUG_NAME "%s: unsupport socket family (%d)\n", __ROUTINE__, inAddr->sa_family );
+		err = kUnsupportedErr;
+		goto exit;
+	}
+	
+	// Success!
+	
+	*outSocketRef = sock;
+	sock = kInvalidSocketRef;
+	err = mStatus_NoError;
+	
+exit:
+	if( IsValidSocket( sock ) )
+	{
+		close_compat( sock );
+	}
+	return( err );
+}
+
+//===========================================================================================================================
+//	SetupSocket
+//===========================================================================================================================
+
+mDNSlocal mStatus	SockAddrToMDNSAddr( const struct sockaddr * const inSA, mDNSAddr *outIP, mDNSIPPort *outPort )
+{
+	mStatus		err;
+	
+	check( inSA );
+	check( outIP );
+	
+	if( inSA->sa_family == AF_INET )
+	{
+		struct sockaddr_in *		sa4;
+		
+		sa4 						= (struct sockaddr_in *) inSA;
+		outIP->type 				= mDNSAddrType_IPv4;
+		outIP->ip.v4.NotAnInteger	= sa4->sin_addr.s_addr;
+		if( outPort )
+		{
+			outPort->NotAnInteger	= sa4->sin_port;
+		}
+		err = mStatus_NoError;
+	}
+	else if( inSA->sa_family == AF_INET6 )
+	{
+		struct sockaddr_in6 *		sa6;
+		
+		sa6 			= (struct sockaddr_in6 *) inSA;
+		outIP->type 	= mDNSAddrType_IPv6;
+		outIP->ip.v6 	= *( (mDNSv6Addr *) &sa6->sin6_addr );
+		if( IN6_IS_ADDR_LINKLOCAL( &sa6->sin6_addr ) )
+		{
+			outIP->ip.v6.w[ 1 ] = 0;
+		}
+		if( outPort )
+		{
+			outPort->NotAnInteger = sa6->sin6_port;
+		}
+		err = mStatus_NoError;
+	}
+	else
+	{
+		dlog( kDebugLevelError, DEBUG_NAME "%s: invalid sa_family %d", __ROUTINE__, inSA->sa_family );
+		err = mStatus_BadParamErr;
+	}
+	return( err );
+}
+
+
+#if 0
+#pragma mark -
+#endif
+
+//===========================================================================================================================
+//	UDPSocketNotification
+//===========================================================================================================================
+
+mDNSlocal void CALLBACK
+UDPSocketNotification( SOCKET sock, LPWSANETWORKEVENTS event, void *context )
+{
+	UDPSocket				*udpSock = ( UDPSocket* ) context;
+	WSAMSG					wmsg;
+	WSABUF					wbuf;
+	struct sockaddr_storage	sockSrcAddr;		// This is filled in by the WSARecv* function
+	INT						sockSrcAddrLen;		// See above
+	mDNSAddr				srcAddr;
+	mDNSInterfaceID			iid;
+	mDNSIPPort				srcPort;
+	mDNSAddr				dstAddr;
+	mDNSIPPort				dstPort;
+	uint8_t					controlBuffer[ 128 ];
+	mDNSu8				*	end;
+	int						num;
+	DWORD					numTries;
+	mStatus					err;
+
+	DEBUG_UNUSED( sock );
+	DEBUG_UNUSED( event );
+
+	require_action( udpSock != NULL, exit, err = mStatus_BadStateErr );
+
+	dlog( kDebugLevelChatty, DEBUG_NAME "%s: sock = %d\n", __ROUTINE__, udpSock->fd );
+	
+	// Initialize the buffer structure
+
+	wbuf.buf		= (char *) &udpSock->packet;
+	wbuf.len		= (u_long) sizeof( udpSock->packet );
+	sockSrcAddrLen	= sizeof( sockSrcAddr );
+
+	numTries = 0;
+
+	do
+	{
+		if ( udpSock->recvMsgPtr )
+		{
+			DWORD size;
+
+			wmsg.name			= ( LPSOCKADDR ) &sockSrcAddr;
+			wmsg.namelen		= sockSrcAddrLen;
+			wmsg.lpBuffers		= &wbuf;
+			wmsg.dwBufferCount	= 1;
+			wmsg.Control.buf	= ( CHAR* ) controlBuffer;
+			wmsg.Control.len	= sizeof( controlBuffer );
+			wmsg.dwFlags		= 0;
+
+			err = udpSock->recvMsgPtr( udpSock->fd, &wmsg, &size, NULL, NULL );
+			err = translate_errno( ( err == 0 ), (OSStatus) WSAGetLastError(), kUnknownErr ); 
+			num = ( int ) size;
+
+			// <rdar://problem/7824093> iTunes 9.1 fails to install with Bonjour service on Windows 7 Ultimate
+			//
+			// There seems to be a bug in some network device drivers that involves calling WSARecvMsg().
+			// Although all the parameters to WSARecvMsg() are correct, it returns a
+			// WSAEFAULT error code when there is no actual error. We have found experientially that falling
+			// back to using WSARecvFrom() when this happens will work correctly.
+
+			if ( err == WSAEFAULT ) udpSock->recvMsgPtr = NULL;
+		}
+		else
+		{
+			DWORD flags = 0;
+
+			num = WSARecvFrom( udpSock->fd, &wbuf, 1, NULL, &flags, ( LPSOCKADDR ) &sockSrcAddr, &sockSrcAddrLen, NULL, NULL );
+			err = translate_errno( ( num >= 0 ), ( OSStatus ) WSAGetLastError(), kUnknownErr );
+		}
+
+		// According to MSDN <http://msdn.microsoft.com/en-us/library/ms741687(VS.85).aspx>:
+		//
+		// "WSAECONNRESET: For a UDP datagram socket, this error would indicate that a previous
+		//                 send operation resulted in an ICMP "Port Unreachable" message."
+		//
+		// Because this is the case, we want to ignore this error and try again.  Just in case
+		// this is some kind of pathological condition, we'll break out of the retry loop 
+		// after 100 iterations
+
+		require_action( !err || ( err == WSAECONNRESET ) || ( err == WSAEFAULT ), exit, err = WSAGetLastError() );
+	}
+	while ( ( ( err == WSAECONNRESET ) || ( err == WSAEFAULT ) ) && ( numTries++ < 100 ) );
+	
+	require_noerr( err, exit );
+	
+	// Translate the source of this packet into mDNS data types
+
+	SockAddrToMDNSAddr( (struct sockaddr* ) &sockSrcAddr, &srcAddr, &srcPort );
+	
+	// Initialize the destination of this packet. Just in case
+	// we can't determine this info because we couldn't call
+	// WSARecvMsg (recvMsgPtr)
+
+	dstAddr = udpSock->addr;
+	dstPort = udpSock->port;
+
+	if ( udpSock->recvMsgPtr )
+	{
+		LPWSACMSGHDR	header;
+		LPWSACMSGHDR	last = NULL;
+		int				count = 0;
+		
+		// Parse the control information. Reject packets received on the wrong interface.
+		
+		// <rdar://problem/7832196> INSTALL: Bonjour 2.0 on Windows can not start / stop
+		// 
+		// There seems to be an interaction between Bullguard and this next bit of code.
+		// When a user's machine is running Bullguard, the control information that is
+		// returned is corrupted, and the code would go into an infinite loop. We'll add
+		// two bits of defensive coding here. The first will check that each pointer to
+		// the LPWSACMSGHDR that is returned in the for loop is different than the last.
+		// This fixes the problem with Bullguard. The second will break out of this loop
+		// after 100 iterations, just in case the corruption isn't caught by the first
+		// check.
+
+		for ( header = WSA_CMSG_FIRSTHDR( &wmsg ); header; header = WSA_CMSG_NXTHDR( &wmsg, header ) )
+		{
+			if ( ( header != last ) && ( ++count < 100 ) )
+			{
+				last = header;
+					
+				if ( ( header->cmsg_level == IPPROTO_IP ) && ( header->cmsg_type == IP_PKTINFO ) )
+				{
+					IN_PKTINFO * ipv4PacketInfo;
+					
+					ipv4PacketInfo = (IN_PKTINFO *) WSA_CMSG_DATA( header );
+
+					if ( udpSock->ifd != NULL )
+					{
+						require_action( ipv4PacketInfo->ipi_ifindex == udpSock->ifd->index, exit, err = ( DWORD ) kMismatchErr );
+					}
+
+					dstAddr.type 				= mDNSAddrType_IPv4;
+					dstAddr.ip.v4.NotAnInteger	= ipv4PacketInfo->ipi_addr.s_addr;
+				}
+				else if( ( header->cmsg_level == IPPROTO_IPV6 ) && ( header->cmsg_type == IPV6_PKTINFO ) )
+				{
+					IN6_PKTINFO * ipv6PacketInfo;
+						
+					ipv6PacketInfo = (IN6_PKTINFO *) WSA_CMSG_DATA( header );
+		
+					if ( udpSock->ifd != NULL )
+					{
+						require_action( ipv6PacketInfo->ipi6_ifindex == ( udpSock->ifd->index - kIPv6IfIndexBase ), exit, err = ( DWORD ) kMismatchErr );
+					}
+
+					dstAddr.type	= mDNSAddrType_IPv6;
+					dstAddr.ip.v6	= *( (mDNSv6Addr *) &ipv6PacketInfo->ipi6_addr );
+				}
+			}
+			else
+			{
+				static BOOL loggedMessage = FALSE;
+
+				if ( !loggedMessage )
+				{
+					LogMsg( "UDPEndRecv: WSARecvMsg control information error." );
+					loggedMessage = TRUE;
+				}
+
+				break;
+			}
+		}
+	}
+
+	dlog( kDebugLevelChatty, DEBUG_NAME "packet received\n" );
+	dlog( kDebugLevelChatty, DEBUG_NAME "    size      = %d\n", num );
+	dlog( kDebugLevelChatty, DEBUG_NAME "    src       = %#a:%u\n", &srcAddr, ntohs( srcPort.NotAnInteger ) );
+	dlog( kDebugLevelChatty, DEBUG_NAME "    dst       = %#a:%u\n", &dstAddr, ntohs( dstPort.NotAnInteger ) );
+	
+	if ( udpSock->ifd != NULL )
+	{
+		dlog( kDebugLevelChatty, DEBUG_NAME "    interface = %#a (index=0x%08X)\n", &udpSock->ifd->interfaceInfo.ip, udpSock->ifd->index );
+	}
+
+	dlog( kDebugLevelChatty, DEBUG_NAME "\n" );
+
+	iid = udpSock->ifd ? udpSock->ifd->interfaceInfo.InterfaceID : NULL;
+	end = ( (mDNSu8 *) &udpSock->packet ) + num;
+
+	mDNSCoreReceive( udpSock->m, &udpSock->packet, end, &srcAddr, srcPort, &dstAddr, dstPort, iid );
+
+exit:
+
+	return;
+}
+
+
+//===========================================================================================================================
+//	InterfaceListDidChange
+//===========================================================================================================================
+void InterfaceListDidChange( mDNS * const inMDNS )
+{
+	mStatus err;
+	
+	dlog( kDebugLevelInfo, DEBUG_NAME "interface list changed\n" );
+	check( inMDNS );
+	
+	// Tear down the existing interfaces and set up new ones using the new IP info.
+	
+	err = TearDownInterfaceList( inMDNS );
+	check_noerr( err );
+	
+	err = SetupInterfaceList( inMDNS );
+	check_noerr( err );
+		
+	err = uDNS_SetupDNSConfig( inMDNS );
+	check_noerr( err );
+	
+	// Inform clients of the change.
+	
+	mDNS_ConfigChanged(inMDNS);
+	
+	// Force mDNS to update.
+	
+	mDNSCoreMachineSleep( inMDNS, mDNSfalse ); // What is this for? Mac OS X does not do this
+}
+
+
+//===========================================================================================================================
+//	ComputerDescriptionDidChange
+//===========================================================================================================================
+void ComputerDescriptionDidChange( mDNS * const inMDNS )
+{	
+	dlog( kDebugLevelInfo, DEBUG_NAME "computer description has changed\n" );
+	check( inMDNS );
+
+	// redo the names
+	SetupNiceName( inMDNS );
+}
+
+
+//===========================================================================================================================
+//	TCPIPConfigDidChange
+//===========================================================================================================================
+void TCPIPConfigDidChange( mDNS * const inMDNS )
+{
+	mStatus		err;
+	
+	dlog( kDebugLevelInfo, DEBUG_NAME "TCP/IP config has changed\n" );
+	check( inMDNS );
+
+	err = uDNS_SetupDNSConfig( inMDNS );
+	check_noerr( err );
+}
+
+
+//===========================================================================================================================
+//	DynDNSConfigDidChange
+//===========================================================================================================================
+void DynDNSConfigDidChange( mDNS * const inMDNS )
+{
+	mStatus		err;
+	
+	dlog( kDebugLevelInfo, DEBUG_NAME "DynDNS config has changed\n" );
+	check( inMDNS );
+
+	SetDomainSecrets( inMDNS );
+
+	err = uDNS_SetupDNSConfig( inMDNS );
+	check_noerr( err );
+}
+
+
+//===========================================================================================================================
+//	FileSharingDidChange
+//===========================================================================================================================
+void FileSharingDidChange( mDNS * const inMDNS )
+{	
+	dlog( kDebugLevelInfo, DEBUG_NAME "File shares has changed\n" );
+	check( inMDNS );
+
+	CheckFileShares( inMDNS );
+}
+
+
+//===========================================================================================================================
+//	FilewallDidChange
+//===========================================================================================================================
+void FirewallDidChange( mDNS * const inMDNS )
+{	
+	dlog( kDebugLevelInfo, DEBUG_NAME "Firewall has changed\n" );
+	check( inMDNS );
+
+	CheckFileShares( inMDNS );
+}
+
+
+#if 0
+#pragma mark -
+#pragma mark == Utilities ==
+#endif
+
+//===========================================================================================================================
+//	getifaddrs
+//===========================================================================================================================
+
+mDNSlocal int	getifaddrs( struct ifaddrs **outAddrs )
+{
+	int		err;
+	
+#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
+	
+	// Try to the load the GetAdaptersAddresses function from the IP Helpers DLL. This API is only available on Windows
+	// XP or later. Looking up the symbol at runtime allows the code to still work on older systems without that API.
+	
+	if( !gIPHelperLibraryInstance )
+	{
+		gIPHelperLibraryInstance = LoadLibrary( TEXT( "Iphlpapi" ) );
+		if( gIPHelperLibraryInstance )
+		{
+			gGetAdaptersAddressesFunctionPtr = 
+				(GetAdaptersAddressesFunctionPtr) GetProcAddress( gIPHelperLibraryInstance, "GetAdaptersAddresses" );
+			if( !gGetAdaptersAddressesFunctionPtr )
+			{
+				BOOL		ok;
+				
+				ok = FreeLibrary( gIPHelperLibraryInstance );
+				check_translated_errno( ok, GetLastError(), kUnknownErr );
+				gIPHelperLibraryInstance = NULL;
+			}
+		}
+	}
+	
+	// Use the new IPv6-capable routine if supported. Otherwise, fall back to the old and compatible IPv4-only code.
+	// <rdar://problem/4278934>  Fall back to using getifaddrs_ipv4 if getifaddrs_ipv6 fails
+	// <rdar://problem/6145913>  Fall back to using getifaddrs_ipv4 if getifaddrs_ipv6 returns no addrs
+
+	if( !gGetAdaptersAddressesFunctionPtr || ( ( ( err = getifaddrs_ipv6( outAddrs ) ) != mStatus_NoError ) || ( ( outAddrs != NULL ) && ( *outAddrs == NULL ) ) ) )
+	{
+		err = getifaddrs_ipv4( outAddrs );
+		require_noerr( err, exit );
+	}
+	
+#else
+
+	err = getifaddrs_ipv4( outAddrs );
+	require_noerr( err, exit );
+
+#endif
+
+exit:
+	return( err );
+}
+
+#if( MDNS_WINDOWS_USE_IPV6_IF_ADDRS )
+//===========================================================================================================================
+//	getifaddrs_ipv6
+//===========================================================================================================================
+
+mDNSlocal int	getifaddrs_ipv6( struct ifaddrs **outAddrs )
+{
+	DWORD						err;
+	int							i;
+	DWORD						flags;
+	struct ifaddrs *			head;
+	struct ifaddrs **			next;
+	IP_ADAPTER_ADDRESSES *		iaaList;
+	ULONG						iaaListSize;
+	IP_ADAPTER_ADDRESSES *		iaa;
+	size_t						size;
+	struct ifaddrs *			ifa;
+	
+	check( gGetAdaptersAddressesFunctionPtr );
+	
+	head	= NULL;
+	next	= &head;
+	iaaList	= NULL;
+	
+	// Get the list of interfaces. The first call gets the size and the second call gets the actual data.
+	// This loops to handle the case where the interface changes in the window after getting the size, but before the
+	// second call completes. A limit of 100 retries is enforced to prevent infinite loops if something else is wrong.
+	
+	flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
+	i = 0;
+	for( ;; )
+	{
+		iaaListSize = 0;
+		err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, NULL, &iaaListSize );
+		check( err == ERROR_BUFFER_OVERFLOW );
+		check( iaaListSize >= sizeof( IP_ADAPTER_ADDRESSES ) );
+		
+		iaaList = (IP_ADAPTER_ADDRESSES *) malloc( iaaListSize );
+		require_action( iaaList, exit, err = ERROR_NOT_ENOUGH_MEMORY );
+		
+		err = gGetAdaptersAddressesFunctionPtr( AF_UNSPEC, flags, NULL, iaaList, &iaaListSize );
+		if( err == ERROR_SUCCESS ) break;
+		
+		free( iaaList );
+		iaaList = NULL;
+		++i;
+		require( i < 100, exit );
+		dlog( kDebugLevelWarning, "%s: retrying GetAdaptersAddresses after %d failure(s) (%d %m)\n", __ROUTINE__, i, err, err );
+	}
+	
+	for( iaa = iaaList; iaa; iaa = iaa->Next )
+	{
+		int								addrIndex;
+		IP_ADAPTER_UNICAST_ADDRESS	*	addr;
+		DWORD							ipv6IfIndex;
+		IP_ADAPTER_PREFIX			*	firstPrefix;
+
+		if( iaa->IfIndex > 0xFFFFFF )
+		{
+			dlog( kDebugLevelAlert, DEBUG_NAME "%s: IPv4 ifindex out-of-range (0x%08X)\n", __ROUTINE__, iaa->IfIndex );
+		}
+		if( iaa->Ipv6IfIndex > 0xFF )
+		{
+			dlog( kDebugLevelAlert, DEBUG_NAME "%s: IPv6 ifindex out-of-range (0x%08X)\n", __ROUTINE__, iaa->Ipv6IfIndex );
+		}
+
+		// For IPv4 interfaces, there seems to be a bug in iphlpapi.dll that causes the 
+		// following code to crash when iterating through the prefix list.  This seems
+		// to occur when iaa->Ipv6IfIndex != 0 when IPv6 is not installed on the host.
+		// This shouldn't happen according to Microsoft docs which states:
+		//
+		//     "Ipv6IfIndex contains 0 if IPv6 is not available on the interface."
+		//
+		// So the data structure seems to be corrupted when we return from
+		// GetAdaptersAddresses(). The bug seems to occur when iaa->Length <
+		// sizeof(IP_ADAPTER_ADDRESSES), so when that happens, we'll manually
+		// modify iaa to have the correct values.
+
+		if ( iaa->Length >= sizeof( IP_ADAPTER_ADDRESSES ) )
+		{
+			ipv6IfIndex = iaa->Ipv6IfIndex;
+			firstPrefix = iaa->FirstPrefix;
+		}
+		else
+		{
+			ipv6IfIndex	= 0;
+			firstPrefix = NULL;
+		}
+
+		// Skip pseudo and tunnel interfaces.
+		
+		if( ( ( ipv6IfIndex == 1 ) && ( iaa->IfType != IF_TYPE_SOFTWARE_LOOPBACK ) ) || ( iaa->IfType == IF_TYPE_TUNNEL ) )
+		{
+			continue;
+		}
+		
+		// Add each address as a separate interface to emulate the way getifaddrs works.
+		
+		for( addrIndex = 0, addr = iaa->FirstUnicastAddress; addr; ++addrIndex, addr = addr->Next )
+		{			
+			int						family;
+			IP_ADAPTER_PREFIX *		prefix;
+			uint32_t				ipv4Index;
+			struct sockaddr_in		ipv4Netmask;
+
+			family = addr->Address.lpSockaddr->sa_family;
+			if( ( family != AF_INET ) && ( family != AF_INET6 ) ) continue;
+			
+			// <rdar://problem/6220642> iTunes 8: Bonjour doesn't work after upgrading iTunes 8
+			// Seems as if the problem here is a buggy implementation of some network interface
+			// driver. It is reporting that is has a link-local address when it is actually
+			// disconnected. This was causing a problem in AddressToIndexAndMask.
+			// The solution is to call AddressToIndexAndMask first, and if unable to lookup
+			// the address, to ignore that address.
+
+			ipv4Index = 0;
+			memset( &ipv4Netmask, 0, sizeof( ipv4Netmask ) );
+			
+			if ( family == AF_INET )
+			{
+				err = AddressToIndexAndMask( addr->Address.lpSockaddr, &ipv4Index, ( struct sockaddr* ) &ipv4Netmask );
+				
+				if ( err )
+				{
+					err = 0;
+					continue;
+				}
+			}
+
+			ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
+			require_action( ifa, exit, err = WSAENOBUFS );
+			
+			*next = ifa;
+			next  = &ifa->ifa_next;
+			
+			// Get the name.
+			
+			size = strlen( iaa->AdapterName ) + 1;
+			ifa->ifa_name = (char *) malloc( size );
+			require_action( ifa->ifa_name, exit, err = WSAENOBUFS );
+			memcpy( ifa->ifa_name, iaa->AdapterName, size );
+			
+			// Get interface flags.
+			
+			ifa->ifa_flags = 0;
+			if( iaa->OperStatus == IfOperStatusUp ) 		ifa->ifa_flags |= IFF_UP;
+			if( iaa->IfType == IF_TYPE_SOFTWARE_LOOPBACK )	ifa->ifa_flags |= IFF_LOOPBACK;
+			else if ( IsPointToPoint( addr ) )				ifa->ifa_flags |= IFF_POINTTOPOINT;
+			if( !( iaa->Flags & IP_ADAPTER_NO_MULTICAST ) )	ifa->ifa_flags |= IFF_MULTICAST;
+
+			
+			// <rdar://problem/4045657> Interface index being returned is 512
+			//
+			// Windows does not have a uniform scheme for IPv4 and IPv6 interface indexes.
+			// This code used to shift the IPv4 index up to ensure uniqueness between
+			// it and IPv6 indexes.  Although this worked, it was somewhat confusing to developers, who
+			// then see interface indexes passed back that don't correspond to anything
+			// that is seen in Win32 APIs or command line tools like "route".  As a relatively
+			// small percentage of developers are actively using IPv6, it seems to 
+			// make sense to make our use of IPv4 as confusion free as possible.
+			// So now, IPv6 interface indexes will be shifted up by a
+			// constant value which will serve to uniquely identify them, and we will
+			// leave IPv4 interface indexes unmodified.
+			
+			switch( family )
+			{
+				case AF_INET:  ifa->ifa_extra.index = iaa->IfIndex; break;
+				case AF_INET6: ifa->ifa_extra.index = ipv6IfIndex + kIPv6IfIndexBase;	 break;
+				default: break;
+			}
+
+			// Get lease lifetime
+
+			if ( ( iaa->IfType != IF_TYPE_SOFTWARE_LOOPBACK ) && ( addr->LeaseLifetime != 0 ) && ( addr->ValidLifetime != 0xFFFFFFFF ) )
+			{
+				ifa->ifa_dhcpEnabled		= TRUE;
+				ifa->ifa_dhcpLeaseExpires	= time( NULL ) + addr->ValidLifetime;
+			}
+			else
+			{
+				ifa->ifa_dhcpEnabled		= FALSE;
+				ifa->ifa_dhcpLeaseExpires	= 0;
+			}
+
+			if ( iaa->PhysicalAddressLength == sizeof( ifa->ifa_physaddr ) )
+			{
+				memcpy( ifa->ifa_physaddr, iaa->PhysicalAddress, iaa->PhysicalAddressLength );
+			}
+
+			// Because we don't get notified of womp changes, we're going to just assume
+			// that all wired interfaces have it enabled. Before we go to sleep, we'll check
+			// if the interface actually supports it, and update mDNS->SystemWakeOnLANEnabled
+			// accordingly
+
+			ifa->ifa_womp = ( iaa->IfType == IF_TYPE_ETHERNET_CSMACD ) ? mDNStrue : mDNSfalse;
+			
+			// Get address.
+			
+			switch( family )
+			{
+				case AF_INET:
+				case AF_INET6:
+					ifa->ifa_addr = (struct sockaddr *) calloc( 1, (size_t) addr->Address.iSockaddrLength );
+					require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
+					memcpy( ifa->ifa_addr, addr->Address.lpSockaddr, (size_t) addr->Address.iSockaddrLength );
+					break;
+				
+				default:
+					break;
+			}
+			check( ifa->ifa_addr );
+			
+			// Get subnet mask (IPv4)/link prefix (IPv6). It is specified as a bit length (e.g. 24 for 255.255.255.0).
+
+			switch ( family )
+			{
+				case AF_INET:
+				{
+					struct sockaddr_in * sa4;
+					
+					sa4 = (struct sockaddr_in *) calloc( 1, sizeof( *sa4 ) );
+					require_action( sa4, exit, err = WSAENOBUFS );
+					sa4->sin_family = AF_INET;
+					sa4->sin_addr.s_addr = ipv4Netmask.sin_addr.s_addr;
+
+					dlog( kDebugLevelInfo, DEBUG_NAME "%s: IPv4 mask = %s\n", __ROUTINE__, inet_ntoa( sa4->sin_addr ) );
+					ifa->ifa_netmask = (struct sockaddr *) sa4;
+					break;
+				}
+
+				case AF_INET6:
+				{
+					struct sockaddr_in6 *sa6;
+					char buf[ 256 ] = { 0 };
+					DWORD buflen = sizeof( buf );
+
+					sa6 = (struct sockaddr_in6 *) calloc( 1, sizeof( *sa6 ) );
+					require_action( sa6, exit, err = WSAENOBUFS );
+					sa6->sin6_family = AF_INET6;
+					memset( sa6->sin6_addr.s6_addr, 0xFF, sizeof( sa6->sin6_addr.s6_addr ) );
+					ifa->ifa_netmask = (struct sockaddr *) sa6;
+
+					for ( prefix = firstPrefix; prefix; prefix = prefix->Next )
+					{
+						IN6_ADDR	mask;
+						IN6_ADDR	maskedAddr;
+						int			maskIndex;
+						DWORD		len;
+
+						// According to MSDN:
+						// "On Windows Vista and later, the linked IP_ADAPTER_PREFIX structures pointed to by the FirstPrefix member
+						// include three IP adapter prefixes for each IP address assigned to the adapter. These include the host IP address prefix,
+						// the subnet IP address prefix, and the subnet broadcast IP address prefix.
+						// In addition, for each adapter there is a multicast address prefix and a broadcast address prefix.
+						// On Windows XP with SP1 and later prior to Windows Vista, the linked IP_ADAPTER_PREFIX structures pointed to by the FirstPrefix member
+						// include only a single IP adapter prefix for each IP address assigned to the adapter."
+						
+						// We're only interested in the subnet IP address prefix.  We'll determine if the prefix is the
+						// subnet prefix by masking our address with a mask (computed from the prefix length) and see if that is the same
+						// as the prefix address.
+
+						if ( ( prefix->PrefixLength == 0 ) ||
+						     ( prefix->PrefixLength > 128 ) ||
+						     ( addr->Address.iSockaddrLength != prefix->Address.iSockaddrLength ) ||
+							 ( memcmp( addr->Address.lpSockaddr, prefix->Address.lpSockaddr, addr->Address.iSockaddrLength ) == 0 ) )
+						{
+							continue;
+						}
+
+						// Compute the mask
+
+						memset( mask.s6_addr, 0, sizeof( mask.s6_addr ) );
+
+						for ( len = (int) prefix->PrefixLength, maskIndex = 0; len > 0; len -= 8 )
+						{
+							uint8_t maskByte = ( len >= 8 ) ? 0xFF : (uint8_t)( ( 0xFFU << ( 8 - len ) ) & 0xFFU );
+							mask.s6_addr[ maskIndex++ ] = maskByte;
+						}
+
+						// Apply the mask
+
+						for ( i = 0; i < 16; i++ )
+						{
+							maskedAddr.s6_addr[ i ] = ( ( struct sockaddr_in6* ) addr->Address.lpSockaddr )->sin6_addr.s6_addr[ i ] & mask.s6_addr[ i ];
+						}
+
+						// Compare
+
+						if ( memcmp( ( ( struct sockaddr_in6* ) prefix->Address.lpSockaddr )->sin6_addr.s6_addr, maskedAddr.s6_addr, sizeof( maskedAddr.s6_addr ) ) == 0 )
+						{
+							memcpy( sa6->sin6_addr.s6_addr, mask.s6_addr, sizeof( mask.s6_addr ) );
+							break;
+						}
+					}
+
+					WSAAddressToStringA( ( LPSOCKADDR ) sa6, sizeof( struct sockaddr_in6 ), NULL, buf, &buflen );
+					dlog( kDebugLevelInfo, DEBUG_NAME "%s: IPv6 mask = %s\n", __ROUTINE__, buf );				
+
+					break;
+				}
+				
+				default:
+					break;
+			}
+		}
+	}
+	
+	// Success!
+	
+	if( outAddrs )
+	{
+		*outAddrs = head;
+		head = NULL;
+	}
+	err = ERROR_SUCCESS;
+	
+exit:
+	if( head )
+	{
+		freeifaddrs( head );
+	}
+	if( iaaList )
+	{
+		free( iaaList );
+	}
+	return( (int) err );
+}
+
+#endif	// MDNS_WINDOWS_USE_IPV6_IF_ADDRS
+
+//===========================================================================================================================
+//	getifaddrs_ipv4
+//===========================================================================================================================
+
+mDNSlocal int	getifaddrs_ipv4( struct ifaddrs **outAddrs )
+{
+	int						err;
+	SOCKET					sock;
+	DWORD					size;
+	DWORD					actualSize;
+	INTERFACE_INFO *		buffer;
+	INTERFACE_INFO *		tempBuffer;
+	INTERFACE_INFO *		ifInfo;
+	int						n;
+	int						i;
+	struct ifaddrs *		head;
+	struct ifaddrs **		next;
+	struct ifaddrs *		ifa;
+	
+	sock	= INVALID_SOCKET;
+	buffer	= NULL;
+	head	= NULL;
+	next	= &head;
+	
+	// Get the interface list. WSAIoctl is called with SIO_GET_INTERFACE_LIST, but since this does not provide a 
+	// way to determine the size of the interface list beforehand, we have to start with an initial size guess and
+	// call WSAIoctl repeatedly with increasing buffer sizes until it succeeds. Limit this to 100 tries for safety.
+	
+	sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
+	err = translate_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
+	require_noerr( err, exit );
+		
+	n = 0;
+	size = 16 * sizeof( INTERFACE_INFO );
+	for( ;; )
+	{
+		tempBuffer = (INTERFACE_INFO *) realloc( buffer, size );
+		require_action( tempBuffer, exit, err = WSAENOBUFS );
+		buffer = tempBuffer;
+		
+		err = WSAIoctl( sock, SIO_GET_INTERFACE_LIST, NULL, 0, buffer, size, &actualSize, NULL, NULL );
+		if( err == 0 )
+		{
+			break;
+		}
+		
+		++n;
+		require_action( n < 100, exit, err = WSAEADDRNOTAVAIL );
+		
+		size += ( 16 * sizeof( INTERFACE_INFO ) );
+	}
+	check( actualSize <= size );
+	check( ( actualSize % sizeof( INTERFACE_INFO ) ) == 0 );
+	n = (int)( actualSize / sizeof( INTERFACE_INFO ) );
+	
+	// Process the raw interface list and build a linked list of IPv4 interfaces.
+	
+	for( i = 0; i < n; ++i )
+	{
+		uint32_t ifIndex;
+		struct sockaddr_in netmask;
+		
+		ifInfo = &buffer[ i ];
+		if( ifInfo->iiAddress.Address.sa_family != AF_INET )
+		{
+			continue;
+		}
+		
+		// <rdar://problem/6220642> iTunes 8: Bonjour doesn't work after upgrading iTunes 8
+		// See comment in getifaddrs_ipv6
+
+		ifIndex = 0;
+		memset( &netmask, 0, sizeof( netmask ) );
+		err = AddressToIndexAndMask( ( struct sockaddr* ) &ifInfo->iiAddress.AddressIn, &ifIndex, ( struct sockaddr* ) &netmask );
+
+		if ( err )
+		{
+			continue;
+		}
+
+		ifa = (struct ifaddrs *) calloc( 1, sizeof( struct ifaddrs ) );
+		require_action( ifa, exit, err = WSAENOBUFS );
+		
+		*next = ifa;
+		next  = &ifa->ifa_next;
+		
+		// Get the name.
+		
+		ifa->ifa_name = (char *) malloc( 16 );
+		require_action( ifa->ifa_name, exit, err = WSAENOBUFS );
+		sprintf( ifa->ifa_name, "%d", i + 1 );
+		
+		// Get interface flags.
+		
+		ifa->ifa_flags = (u_int) ifInfo->iiFlags;
+		
+		// Get addresses.
+		
+		if ( ifInfo->iiAddress.Address.sa_family == AF_INET )
+		{
+			struct sockaddr_in *		sa4;
+			
+			sa4 = &ifInfo->iiAddress.AddressIn;
+			ifa->ifa_addr = (struct sockaddr *) calloc( 1, sizeof( *sa4 ) );
+			require_action( ifa->ifa_addr, exit, err = WSAENOBUFS );
+			memcpy( ifa->ifa_addr, sa4, sizeof( *sa4 ) );
+
+			ifa->ifa_netmask = (struct sockaddr*) calloc(1, sizeof( *sa4 ) );
+			require_action( ifa->ifa_netmask, exit, err = WSAENOBUFS );
+
+			// <rdar://problem/4076478> Service won't start on Win2K. The address
+			// family field was not being initialized.
+
+			ifa->ifa_netmask->sa_family = AF_INET;
+			( ( struct sockaddr_in* ) ifa->ifa_netmask )->sin_addr = netmask.sin_addr;
+			ifa->ifa_extra.index = ifIndex;
+		}
+		else
+		{
+			// Emulate an interface index.
+		
+			ifa->ifa_extra.index = (uint32_t)( i + 1 );
+		}
+	}
+	
+	// Success!
+	
+	if( outAddrs )
+	{
+		*outAddrs = head;
+		head = NULL;
+	}
+	err = 0;
+	
+exit:
+
+	if( head )
+	{
+		freeifaddrs( head );
+	}
+	if( buffer )
+	{
+		free( buffer );
+	}
+	if( sock != INVALID_SOCKET )
+	{
+		closesocket( sock );
+	}
+	return( err );
+}
+
+//===========================================================================================================================
+//	freeifaddrs
+//===========================================================================================================================
+
+mDNSlocal void	freeifaddrs( struct ifaddrs *inIFAs )
+{
+	struct ifaddrs *		p;
+	struct ifaddrs *		q;
+	
+	// Free each piece of the structure. Set to null after freeing to handle macro-aliased fields.
+	
+	for( p = inIFAs; p; p = q )
+	{
+		q = p->ifa_next;
+		
+		if( p->ifa_name )
+		{
+			free( p->ifa_name );
+			p->ifa_name = NULL;
+		}
+		if( p->ifa_addr )
+		{
+			free( p->ifa_addr );
+			p->ifa_addr = NULL;
+		}
+		if( p->ifa_netmask )
+		{
+			free( p->ifa_netmask );
+			p->ifa_netmask = NULL;
+		}
+		if( p->ifa_broadaddr )
+		{
+			free( p->ifa_broadaddr );
+			p->ifa_broadaddr = NULL;
+		}
+		if( p->ifa_dstaddr )
+		{
+			free( p->ifa_dstaddr );
+			p->ifa_dstaddr = NULL;
+		}
+		if( p->ifa_data )
+		{
+			free( p->ifa_data );
+			p->ifa_data = NULL;
+		}
+		free( p );
+	}
+}
+
+
+//===========================================================================================================================
+//	GetPrimaryInterface
+//===========================================================================================================================
+
+mDNSlocal DWORD
+GetPrimaryInterface()
+{
+	PMIB_IPFORWARDTABLE	pIpForwardTable	= NULL;
+	DWORD				dwSize			= 0;
+	BOOL				bOrder			= FALSE;
+	OSStatus			err;
+	DWORD				index			= 0;
+	DWORD				metric			= 0;
+	unsigned long int	i;
+
+	// Find out how big our buffer needs to be.
+
+	err = GetIpForwardTable(NULL, &dwSize, bOrder);
+	require_action( err == ERROR_INSUFFICIENT_BUFFER, exit, err = kUnknownErr );
+
+	// Allocate the memory for the table
+
+	pIpForwardTable = (PMIB_IPFORWARDTABLE) malloc( dwSize );
+	require_action( pIpForwardTable, exit, err = kNoMemoryErr );
+  
+	// Now get the table.
+
+	err = GetIpForwardTable(pIpForwardTable, &dwSize, bOrder);
+	require_noerr( err, exit );
+
+
+	// Search for the row in the table we want.
+
+	for ( i = 0; i < pIpForwardTable->dwNumEntries; i++)
+	{
+		// Look for a default route
+
+		if ( pIpForwardTable->table[i].dwForwardDest == 0 )
+		{
+			if ( index && ( pIpForwardTable->table[i].dwForwardMetric1 >= metric ) )
+			{
+				continue;
+			}
+
+			index	= pIpForwardTable->table[i].dwForwardIfIndex;
+			metric	= pIpForwardTable->table[i].dwForwardMetric1;
+		}
+	}
+
+exit:
+
+	if ( pIpForwardTable != NULL )
+	{
+		free( pIpForwardTable );
+	}
+
+	return index;
+}
+
+
+//===========================================================================================================================
+//	AddressToIndexAndMask
+//===========================================================================================================================
+
+mDNSlocal mStatus
+AddressToIndexAndMask( struct sockaddr * addr, uint32_t * ifIndex, struct sockaddr * mask  )
+{
+	// Before calling AddIPAddress we use GetIpAddrTable to get
+	// an adapter to which we can add the IP.
+	
+	PMIB_IPADDRTABLE	pIPAddrTable	= NULL;
+	DWORD				dwSize			= 0;
+	mStatus				err				= mStatus_UnknownErr;
+	DWORD				i;
+
+	// For now, this is only for IPv4 addresses.  That is why we can safely cast
+	// addr's to sockaddr_in.
+
+	require_action( addr->sa_family == AF_INET, exit, err = mStatus_UnknownErr );
+
+	// Make an initial call to GetIpAddrTable to get the
+	// necessary size into the dwSize variable
+
+	for ( i = 0; i < 100; i++ )
+	{
+		err = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
+
+		if ( err != ERROR_INSUFFICIENT_BUFFER )
+		{
+			break;
+		}
+
+		pIPAddrTable = (MIB_IPADDRTABLE *) realloc( pIPAddrTable, dwSize );
+		require_action( pIPAddrTable, exit, err = WSAENOBUFS );
+	}
+
+	require_noerr( err, exit );
+	err = mStatus_UnknownErr;
+
+	for ( i = 0; i < pIPAddrTable->dwNumEntries; i++ )
+	{
+		if ( ( ( struct sockaddr_in* ) addr )->sin_addr.s_addr == pIPAddrTable->table[i].dwAddr )
+		{
+			*ifIndex											= pIPAddrTable->table[i].dwIndex;
+			( ( struct sockaddr_in*) mask )->sin_addr.s_addr	= pIPAddrTable->table[i].dwMask;
+			err													= mStatus_NoError;
+			break;
+		}
+	}
+
+exit:
+
+	if ( pIPAddrTable )
+	{
+		free( pIPAddrTable );
+	}
+
+	return err;
+}
+
+
+//===========================================================================================================================
+//	CanReceiveUnicast
+//===========================================================================================================================
+
+mDNSlocal mDNSBool	CanReceiveUnicast( void )
+{
+	mDNSBool				ok;
+	SocketRef				sock;
+	struct sockaddr_in		addr;
+	
+	// Try to bind to the port without the SO_REUSEADDR option to test if someone else has already bound to it.
+	
+	sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
+	check_translated_errno( IsValidSocket( sock ), errno_compat(), kUnknownErr );
+	ok = IsValidSocket( sock );
+	if( ok )
+	{
+		mDNSPlatformMemZero( &addr, sizeof( addr ) );
+		addr.sin_family			= AF_INET;
+		addr.sin_port			= MulticastDNSPort.NotAnInteger;
+		addr.sin_addr.s_addr	= htonl( INADDR_ANY );
+		
+		ok = ( bind( sock, (struct sockaddr *) &addr, sizeof( addr ) ) == 0 );
+		close_compat( sock );
+	}
+	
+	dlog( kDebugLevelInfo, DEBUG_NAME "Unicast UDP responses %s\n", ok ? "okay" : "*not allowed*" );
+	return( ok );
+}
+
+
+//===========================================================================================================================
+//	IsPointToPoint
+//===========================================================================================================================
+
+mDNSlocal mDNSBool IsPointToPoint( IP_ADAPTER_UNICAST_ADDRESS * addr )
+{
+	struct ifaddrs	*	addrs	=	NULL;
+	struct ifaddrs	*	p		=	NULL;
+	OSStatus			err;
+	mDNSBool			ret		=	mDNSfalse;
+
+	// For now, only works for IPv4 interfaces
+
+	if ( addr->Address.lpSockaddr->sa_family == AF_INET )
+	{
+		// The getifaddrs_ipv4 call will give us correct information regarding IFF_POINTTOPOINT flags.
+
+		err = getifaddrs_ipv4( &addrs );
+		require_noerr( err, exit );
+
+		for ( p = addrs; p; p = p->ifa_next )
+		{
+			if ( ( addr->Address.lpSockaddr->sa_family == p->ifa_addr->sa_family ) &&
+			     ( ( ( struct sockaddr_in* ) addr->Address.lpSockaddr )->sin_addr.s_addr == ( ( struct sockaddr_in* ) p->ifa_addr )->sin_addr.s_addr ) )
+			{
+				ret = ( p->ifa_flags & IFF_POINTTOPOINT ) ? mDNStrue : mDNSfalse;
+				break;
+			}
+		}
+	}
+
+exit:
+
+	if ( addrs )
+	{
+		freeifaddrs( addrs );
+	}
+
+	return ret;
+}
+
+
+//===========================================================================================================================
+//	GetWindowsVersionString
+//===========================================================================================================================
+
+mDNSlocal OSStatus	GetWindowsVersionString( char *inBuffer, size_t inBufferSize )
+{
+#if( !defined( VER_PLATFORM_WIN32_CE ) )
+	#define VER_PLATFORM_WIN32_CE		3
+#endif
+
+	OSStatus				err;
+	OSVERSIONINFO			osInfo;
+	BOOL					ok;
+	const char *			versionString;
+	DWORD					platformID;
+	DWORD					majorVersion;
+	DWORD					minorVersion;
+	DWORD					buildNumber;
+	
+	versionString = "unknown Windows version";
+	
+	osInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+	ok = GetVersionEx( &osInfo );
+	err = translate_errno( ok, (OSStatus) GetLastError(), kUnknownErr );
+	require_noerr( err, exit );
+	
+	platformID		= osInfo.dwPlatformId;
+	majorVersion	= osInfo.dwMajorVersion;
+	minorVersion	= osInfo.dwMinorVersion;
+	buildNumber		= osInfo.dwBuildNumber & 0xFFFF;
+	
+	if( ( platformID == VER_PLATFORM_WIN32_WINDOWS ) && ( majorVersion == 4 ) )
+	{
+		if( ( minorVersion < 10 ) && ( buildNumber == 950 ) )
+		{
+			versionString	= "Windows 95";
+		}
+		else if( ( minorVersion < 10 ) && ( ( buildNumber > 950 ) && ( buildNumber <= 1080 ) ) )
+		{
+			versionString	= "Windows 95 SP1";
+		}
+		else if( ( minorVersion < 10 ) && ( buildNumber > 1080 ) )
+		{
+			versionString	= "Windows 95 OSR2";
+		}
+		else if( ( minorVersion == 10 ) && ( buildNumber == 1998 ) )
+		{
+			versionString	= "Windows 98";
+		}
+		else if( ( minorVersion == 10 ) && ( ( buildNumber > 1998 ) && ( buildNumber < 2183 ) ) )
+		{
+			versionString	= "Windows 98 SP1";
+		}
+		else if( ( minorVersion == 10 ) && ( buildNumber >= 2183 ) )
+		{
+			versionString	= "Windows 98 SE";
+		}
+		else if( minorVersion == 90 )
+		{
+			versionString	= "Windows ME";
+		}
+	}
+	else if( platformID == VER_PLATFORM_WIN32_NT )
+	{
+		if( ( majorVersion == 3 ) && ( minorVersion == 51 ) )
+		{
+			versionString	= "Windows NT 3.51";
+		}
+		else if( ( majorVersion == 4 ) && ( minorVersion == 0 ) )
+		{
+			versionString	= "Windows NT 4";
+		}
+		else if( ( majorVersion == 5 ) && ( minorVersion == 0 ) )
+		{
+			versionString	= "Windows 2000";
+		}
+		else if( ( majorVersion == 5 ) && ( minorVersion == 1 ) )
+		{
+			versionString	= "Windows XP";
+		}
+		else if( ( majorVersion == 5 ) && ( minorVersion == 2 ) )
+		{
+			versionString	= "Windows Server 2003";
+		}
+	}
+	else if( platformID == VER_PLATFORM_WIN32_CE )
+	{
+		versionString		= "Windows CE";
+	}
+	
+exit:
+	if( inBuffer && ( inBufferSize > 0 ) )
+	{
+		inBufferSize -= 1;
+		strncpy( inBuffer, versionString, inBufferSize );
+		inBuffer[ inBufferSize ] = '\0';
+	}
+	return( err );
+}
+
+
+//===========================================================================================================================
+//	RegQueryString
+//===========================================================================================================================
+
+mDNSlocal mStatus
+RegQueryString( HKEY key, LPCSTR valueName, LPSTR * string, DWORD * stringLen, DWORD * enabled )
+{
+	DWORD	type;
+	int		i;
+	mStatus err;
+
+	*stringLen	= MAX_ESCAPED_DOMAIN_NAME;
+	*string		= NULL;
+	i			= 0;
+
+	do
+	{
+		if ( *string )
+		{
+			free( *string );
+		}
+
+		*string = (char*) malloc( *stringLen );
+		require_action( *string, exit, err = mStatus_NoMemoryErr );
+
+		err = RegQueryValueExA( key, valueName, 0, &type, (LPBYTE) *string, stringLen );
+
+		i++;
+	}
+	while ( ( err == ERROR_MORE_DATA ) && ( i < 100 ) );
+
+	require_noerr_quiet( err, exit );
+
+	if ( enabled )
+	{
+		DWORD dwSize = sizeof( DWORD );
+
+		err = RegQueryValueEx( key, TEXT("Enabled"), NULL, NULL, (LPBYTE) enabled, &dwSize );
+		check_noerr( err );
+
+		err = kNoErr;
+	}
+
+exit:
+
+	return err;
+}
+
+
+//===========================================================================================================================
+//	StringToAddress
+//===========================================================================================================================
+
+mDNSlocal mStatus StringToAddress( mDNSAddr * ip, LPSTR string )
+{
+	struct sockaddr_in6 sa6;
+	struct sockaddr_in	sa4;
+	INT					dwSize;
+	mStatus				err;
+
+	sa6.sin6_family	= AF_INET6;
+	dwSize			= sizeof( sa6 );
+
+	err = WSAStringToAddressA( string, AF_INET6, NULL, (struct sockaddr*) &sa6, &dwSize );
+
+	if ( err == mStatus_NoError )
+	{
+		err = SetupAddr( ip, (struct sockaddr*) &sa6 );
+		require_noerr( err, exit );
+	}
+	else
+	{
+		sa4.sin_family = AF_INET;
+		dwSize = sizeof( sa4 );
+
+		err = WSAStringToAddressA( string, AF_INET, NULL, (struct sockaddr*) &sa4, &dwSize );
+		err = translate_errno( err == 0, WSAGetLastError(), kUnknownErr );
+		require_noerr( err, exit );
+			
+		err = SetupAddr( ip, (struct sockaddr*) &sa4 );
+		require_noerr( err, exit );
+	}
+
+exit:
+
+	return err;
+}
+
+
+//===========================================================================================================================
+//	myGetIfAddrs
+//===========================================================================================================================
+
+mDNSlocal struct ifaddrs*
+myGetIfAddrs(int refresh)
+{
+	static struct ifaddrs *ifa = NULL;
+	
+	if (refresh && ifa)
+	{
+		freeifaddrs(ifa);
+		ifa = NULL;
+	}
+	
+	if (ifa == NULL)
+	{
+		getifaddrs(&ifa);
+	}
+	
+	return ifa;
+}
+
+
+//===========================================================================================================================
+//	TCHARtoUTF8
+//===========================================================================================================================
+
+mDNSlocal OSStatus
+TCHARtoUTF8( const TCHAR *inString, char *inBuffer, size_t inBufferSize )
+{
+#if( defined( UNICODE ) || defined( _UNICODE ) )
+	OSStatus		err;
+	int				len;
+	
+	len = WideCharToMultiByte( CP_UTF8, 0, inString, -1, inBuffer, (int) inBufferSize, NULL, NULL );
+	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
+	require_noerr( err, exit );
+	
+exit:
+	return( err );
+#else
+	return( WindowsLatin1toUTF8( inString, inBuffer, inBufferSize ) );
+#endif
+}
+
+
+//===========================================================================================================================
+//	WindowsLatin1toUTF8
+//===========================================================================================================================
+
+mDNSlocal OSStatus
+WindowsLatin1toUTF8( const char *inString, char *inBuffer, size_t inBufferSize )
+{
+	OSStatus		err;
+	WCHAR *			utf16;
+	int				len;
+	
+	utf16 = NULL;
+	
+	// Windows doesn't support going directly from Latin-1 to UTF-8 so we have to go from Latin-1 to UTF-16 first.
+	
+	len = MultiByteToWideChar( CP_ACP, 0, inString, -1, NULL, 0 );
+	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
+	require_noerr( err, exit );
+	
+	utf16 = (WCHAR *) malloc( len * sizeof( *utf16 ) );
+	require_action( utf16, exit, err = kNoMemoryErr );
+	
+	len = MultiByteToWideChar( CP_ACP, 0, inString, -1, utf16, len );
+	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
+	require_noerr( err, exit );
+	
+	// Now convert the temporary UTF-16 to UTF-8.
+	
+	len = WideCharToMultiByte( CP_UTF8, 0, utf16, -1, inBuffer, (int) inBufferSize, NULL, NULL );
+	err = translate_errno( len > 0, errno_compat(), kUnknownErr );
+	require_noerr( err, exit );
+
+exit:
+	if( utf16 ) free( utf16 );
+	return( err );
+}
+
+
+//===========================================================================================================================
+//	TCPCloseSocket
+//===========================================================================================================================
+
+mDNSlocal void
+TCPCloseSocket( TCPSocket * sock )
+{
+	dlog( kDebugLevelChatty, DEBUG_NAME "closing TCPSocket 0x%x:%d\n", sock, sock->fd );
+
+	if ( sock->fd != INVALID_SOCKET )
+	{
+		closesocket( sock->fd );
+		sock->fd = INVALID_SOCKET;
+	}
+}
+
+
+//===========================================================================================================================
+//  UDPCloseSocket
+//===========================================================================================================================
+
+mDNSlocal void
+UDPCloseSocket( UDPSocket * sock )
+{
+	dlog( kDebugLevelChatty, DEBUG_NAME "closing UDPSocket %d\n", sock->fd );
+
+	if ( sock->fd != INVALID_SOCKET )
+	{
+		mDNSPollUnregisterSocket( sock->fd );
+		closesocket( sock->fd );
+		sock->fd = INVALID_SOCKET;
+	}
+}
+
+
+//===========================================================================================================================
+//	SetupAddr
+//===========================================================================================================================
+
+mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa)
+	{
+	if (!sa) { LogMsg("SetupAddr ERROR: NULL sockaddr"); return(mStatus_Invalid); }
+
+	if (sa->sa_family == AF_INET)
+		{
+		struct sockaddr_in *ifa_addr = (struct sockaddr_in *)sa;
+		ip->type = mDNSAddrType_IPv4;
+		ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr;
+		return(mStatus_NoError);
+		}
+
+	if (sa->sa_family == AF_INET6)
+		{
+		struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa;
+		ip->type = mDNSAddrType_IPv6;
+		if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.u.Word[1] = 0;
+		ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr;
+		return(mStatus_NoError);
+		}
+
+	LogMsg("SetupAddr invalid sa_family %d", sa->sa_family);
+	return(mStatus_Invalid);
+	}
+
+
+mDNSlocal void GetDDNSFQDN( domainname *const fqdn )
+{
+	LPSTR		name = NULL;
+	DWORD		dwSize;
+	DWORD		enabled;
+	HKEY		key = NULL;
+	OSStatus	err;
+
+	check( fqdn );
+
+	// Initialize
+
+	fqdn->c[0] = '\0';
+
+	// Get info from Bonjour registry key
+
+	err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode TEXT("\\DynDNS\\Setup\\") kServiceDynDNSHostNames, &key );
+	require_noerr( err, exit );
+
+	err = RegQueryString( key, "", &name, &dwSize, &enabled );
+	if ( !err && ( name[0] != '\0' ) && enabled )
+	{
+		if ( !MakeDomainNameFromDNSNameString( fqdn, name ) || !fqdn->c[0] )
+		{
+			dlog( kDebugLevelError, "bad DDNS host name in registry: %s", name[0] ? name : "(unknown)");
+		}
+	}
+
+exit:
+
+	if ( key )
+	{
+		RegCloseKey( key );
+		key = NULL;
+	}
+
+	if ( name )
+	{
+		free( name );
+		name = NULL;
+	}
+}
+
+
+#ifdef UNICODE
+mDNSlocal void GetDDNSDomains( DNameListElem ** domains, LPCWSTR lpSubKey )
+#else
+mDNSlocal void GetDDNSConfig( DNameListElem ** domains, LPCSTR lpSubKey )
+#endif
+{
+	char		subKeyName[kRegistryMaxKeyLength + 1];
+	DWORD		cSubKeys = 0;
+	DWORD		cbMaxSubKey;
+	DWORD		cchMaxClass;
+	DWORD		dwSize;
+	HKEY		key = NULL;
+	HKEY		subKey = NULL;
+	domainname	dname;
+	DWORD		i;
+	OSStatus	err;
+
+	check( domains );
+
+	// Initialize
+
+	*domains = NULL;
+
+	err = RegCreateKey( HKEY_LOCAL_MACHINE, lpSubKey, &key );
+	require_noerr( err, exit );
+
+	// Get information about this node
+
+	err = RegQueryInfoKey( key, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
+	require_noerr( err, exit );
+
+	for ( i = 0; i < cSubKeys; i++)
+	{
+		DWORD enabled;
+
+		dwSize = kRegistryMaxKeyLength;
+        
+		err = RegEnumKeyExA( key, i, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
+
+		if ( !err )
+		{
+			err = RegOpenKeyExA( key, subKeyName, 0, KEY_READ, &subKey );
+			require_noerr( err, exit );
+
+			dwSize = sizeof( DWORD );
+			err = RegQueryValueExA( subKey, "Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
+
+			if ( !err && ( subKeyName[0] != '\0' ) && enabled )
+			{
+				if ( !MakeDomainNameFromDNSNameString( &dname, subKeyName ) || !dname.c[0] )
+				{
+					dlog( kDebugLevelError, "bad DDNS domain in registry: %s", subKeyName[0] ? subKeyName : "(unknown)");
+				}
+				else
+				{
+					DNameListElem * domain = (DNameListElem*) malloc( sizeof( DNameListElem ) );
+					require_action( domain, exit, err = mStatus_NoMemoryErr );
+					
+					AssignDomainName(&domain->name, &dname);
+					domain->next = *domains;
+
+					*domains = domain;
+				}
+			}
+
+			RegCloseKey( subKey );
+			subKey = NULL;
+		}
+	}
+
+exit:
+
+	if ( subKey )
+	{
+		RegCloseKey( subKey );
+	}
+
+	if ( key )
+	{
+		RegCloseKey( key );
+	}
+}
+
+
+mDNSlocal void SetDomainSecret( mDNS * const m, const domainname * inDomain )
+{
+	char					domainUTF8[ 256 ];
+	DomainAuthInfo			*foundInList;
+	DomainAuthInfo			*ptr;
+	char					outDomain[ 256 ];
+	char					outKey[ 256 ];
+	char					outSecret[ 256 ];
+	OSStatus				err;
+	
+	ConvertDomainNameToCString( inDomain, domainUTF8 );
+	
+	// If we're able to find a secret for this domain
+
+	if ( LsaGetSecret( domainUTF8, outDomain, sizeof( outDomain ), outKey, sizeof( outKey ), outSecret, sizeof( outSecret ) ) )
+	{
+		domainname domain;
+		domainname key;
+
+		// Tell the core about this secret
+
+		MakeDomainNameFromDNSNameString( &domain, outDomain );
+		MakeDomainNameFromDNSNameString( &key, outKey );
+
+		for (foundInList = m->AuthInfoList; foundInList; foundInList = foundInList->next)
+			if (SameDomainName(&foundInList->domain, &domain ) ) break;
+
+		ptr = foundInList;
+	
+		if (!ptr)
+		{
+			ptr = (DomainAuthInfo*)malloc(sizeof(DomainAuthInfo));
+			require_action( ptr, exit, err = mStatus_NoMemoryErr );
+		}
+
+		err = mDNS_SetSecretForDomain(m, ptr, &domain, &key, outSecret, NULL, NULL, FALSE );
+		require_action( err != mStatus_BadParamErr, exit, if (!foundInList ) mDNSPlatformMemFree( ptr ) );
+
+		debugf("Setting shared secret for zone %s with key %##s", outDomain, key.c);
+	}
+
+exit:
+
+	return;
+}
+
+
+mDNSlocal VOID CALLBACK
+CheckFileSharesProc( LPVOID arg, DWORD dwTimerLowValue, DWORD dwTimerHighValue )
+{
+	mDNS * const m = ( mDNS * const ) arg;
+
+	( void ) dwTimerLowValue;
+	( void ) dwTimerHighValue;
+
+	CheckFileShares( m );
+}
+
+
+mDNSlocal unsigned __stdcall 
+SMBRegistrationThread( void * arg )
+{
+	mDNS * const m = ( mDNS * const ) arg;
+	DNSServiceRef sref = NULL;
+	HANDLE		handles[ 3 ];
+	mDNSu8		txtBuf[ 256 ];
+	mDNSu8	*	txtPtr;
+	size_t		keyLen;
+	size_t		valLen;
+	mDNSIPPort	port = { { SMBPortAsNumber >> 8, SMBPortAsNumber & 0xFF } };
+	DNSServiceErrorType err;
+
+	DEBUG_UNUSED( arg );
+
+	handles[ 0 ] = gSMBThreadStopEvent;
+	handles[ 1 ] = gSMBThreadRegisterEvent;
+	handles[ 2 ] = gSMBThreadDeregisterEvent;
+
+	memset( txtBuf, 0, sizeof( txtBuf )  );
+	txtPtr = txtBuf;
+	keyLen = strlen( "netbios=" );
+	valLen = strlen( m->p->nbname );
+	require_action( valLen < 32, exit, err = kUnknownErr );	// This should never happen, but check to avoid further memory corruption
+	*txtPtr++ = ( mDNSu8 ) ( keyLen + valLen );
+	memcpy( txtPtr, "netbios=", keyLen );
+	txtPtr += keyLen;
+	if ( valLen ) { memcpy( txtPtr, m->p->nbname, valLen ); txtPtr += ( mDNSu8 ) valLen; }
+	keyLen = strlen( "domain=" );
+	valLen = strlen( m->p->nbdomain );
+	require_action( valLen < 32, exit, err = kUnknownErr );	// This should never happen, but check to avoid further memory corruption
+	*txtPtr++ = ( mDNSu8 )( keyLen + valLen );
+	memcpy( txtPtr, "domain=", keyLen );
+	txtPtr += keyLen;
+	if ( valLen ) { memcpy( txtPtr, m->p->nbdomain, valLen ); txtPtr += valLen; }
+	
+	for ( ;; )
+	{
+		DWORD ret;
+
+		ret = WaitForMultipleObjects( 3, handles, FALSE, INFINITE );
+
+		if ( ret != WAIT_FAILED )
+		{
+			if ( ret == kSMBStopEvent )
+			{
+				break;
+			}
+			else if ( ret == kSMBRegisterEvent )
+			{
+				err = gDNSServiceRegister( &sref, 0, 0, NULL, "_smb._tcp,_file", NULL, NULL, ( uint16_t ) port.NotAnInteger, ( mDNSu16 )( txtPtr - txtBuf ), txtBuf, NULL, NULL );
+
+				if ( err )
+				{
+					LogMsg( "SMBRegistrationThread: DNSServiceRegister returned %d\n", err );
+					sref = NULL;
+					break;
+				}
+			}
+			else if ( ret == kSMBDeregisterEvent )
+			{
+				if ( sref )
+				{
+					gDNSServiceRefDeallocate( sref );
+					sref = NULL;
+				}
+			}
+		}
+		else
+		{
+			LogMsg( "SMBRegistrationThread:  WaitForMultipleObjects returned %d\n", GetLastError() );
+			break;
+		}
+	}
+
+exit:
+
+	if ( sref != NULL )
+	{
+		gDNSServiceRefDeallocate( sref );
+		sref = NULL;
+	}
+
+	SetEvent( gSMBThreadQuitEvent );
+	_endthreadex( 0 );
+	return 0;
+}
+
+
+mDNSlocal void
+CheckFileShares( mDNS * const m )
+{
+	PSHARE_INFO_1	bufPtr = ( PSHARE_INFO_1 ) NULL;
+	DWORD			entriesRead = 0;
+	DWORD			totalEntries = 0;
+	DWORD			resume = 0;
+	mDNSBool		advertise = mDNSfalse;
+	mDNSBool		fileSharing = mDNSfalse;
+	mDNSBool		printSharing = mDNSfalse;
+	HKEY			key = NULL;
+	BOOL			retry = FALSE;
+	NET_API_STATUS  res;
+	mStatus			err;
+
+	check( m );
+
+	// Only do this if we're not shutting down
+
+	require_action_quiet( m->AdvertiseLocalAddresses && !m->ShutdownTime, exit, err = kNoErr );
+
+	err = RegCreateKey( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\Services\\SMB", &key );
+
+	if ( !err )
+	{
+		DWORD dwSize = sizeof( DWORD );
+		RegQueryValueEx( key, L"Advertise", NULL, NULL, (LPBYTE) &advertise, &dwSize );
+	}
+
+	if ( advertise && mDNSIsFileAndPrintSharingEnabled( &retry ) )
+	{
+		dlog( kDebugLevelTrace, DEBUG_NAME "Sharing is enabled\n" );
+
+		res = NetShareEnum( NULL, 1, ( LPBYTE* )&bufPtr, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, &resume );
+
+		if ( ( res == ERROR_SUCCESS ) || ( res == ERROR_MORE_DATA ) )
+		{
+			PSHARE_INFO_1 p = bufPtr;
+			DWORD i;
+
+			for( i = 0; i < entriesRead; i++ ) 
+			{
+				// We are only interested if the user is sharing anything other 
+				// than the built-in "print$" source
+
+				if ( ( p->shi1_type == STYPE_DISKTREE ) && ( wcscmp( p->shi1_netname, TEXT( "print$" ) ) != 0 ) )
+				{
+					fileSharing = mDNStrue;
+				}
+				else if ( p->shi1_type == STYPE_PRINTQ )
+				{
+					printSharing = mDNStrue;
+				}
+
+				p++;
+			}
+
+			NetApiBufferFree( bufPtr );
+			bufPtr = NULL;
+			retry = FALSE;
+		}
+		else if ( res == NERR_ServerNotStarted )
+		{
+			retry = TRUE;
+		}
+	}
+	
+	if ( retry )
+	{
+		__int64			qwTimeout;
+		LARGE_INTEGER   liTimeout;
+
+		qwTimeout = -m->p->checkFileSharesTimeout * 10000000;
+		liTimeout.LowPart  = ( DWORD )( qwTimeout & 0xFFFFFFFF );
+		liTimeout.HighPart = ( LONG )( qwTimeout >> 32 );
+
+		SetWaitableTimer( m->p->checkFileSharesTimer, &liTimeout, 0, CheckFileSharesProc, m, FALSE );
+	}
+
+	if ( !m->p->smbFileSharing && fileSharing )
+	{
+		if ( !gSMBThread )
+		{
+			if ( !gDNSSDLibrary )
+			{
+				gDNSSDLibrary = LoadLibrary( TEXT( "dnssd.dll" ) );
+				require_action( gDNSSDLibrary, exit, err = GetLastError() );
+			}
+
+			if ( !gDNSServiceRegister )
+			{
+				gDNSServiceRegister = ( DNSServiceRegisterFunc ) GetProcAddress( gDNSSDLibrary, "DNSServiceRegister" );
+				require_action( gDNSServiceRegister, exit, err = GetLastError() );
+			}
+
+			if ( !gDNSServiceRefDeallocate )
+			{
+				gDNSServiceRefDeallocate = ( DNSServiceRefDeallocateFunc ) GetProcAddress( gDNSSDLibrary, "DNSServiceRefDeallocate" );
+				require_action( gDNSServiceRefDeallocate, exit, err = GetLastError() );
+			}
+
+			if ( !gSMBThreadRegisterEvent )
+			{
+				gSMBThreadRegisterEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+				require_action( gSMBThreadRegisterEvent != NULL, exit, err = GetLastError() );
+			}
+
+			if ( !gSMBThreadDeregisterEvent )
+			{
+				gSMBThreadDeregisterEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+				require_action( gSMBThreadDeregisterEvent != NULL, exit, err = GetLastError() );
+			}
+
+			if ( !gSMBThreadStopEvent )
+			{
+				gSMBThreadStopEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+				require_action( gSMBThreadStopEvent != NULL, exit, err = GetLastError() );
+			}
+
+			if ( !gSMBThreadQuitEvent )
+			{
+				gSMBThreadQuitEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+				require_action( gSMBThreadQuitEvent != NULL, exit, err = GetLastError() );
+			}
+
+			gSMBThread = ( HANDLE ) _beginthreadex( NULL, 0, SMBRegistrationThread, m, 0, NULL );
+			require_action( gSMBThread != NULL, exit, err = GetLastError() );
+		}
+
+		SetEvent( gSMBThreadRegisterEvent );
+
+		m->p->smbFileSharing = mDNStrue;
+	}
+	else if ( m->p->smbFileSharing && !fileSharing )
+	{
+		dlog( kDebugLevelTrace, DEBUG_NAME "deregistering smb type\n" );
+
+		if ( gSMBThreadDeregisterEvent != NULL )
+		{
+			SetEvent( gSMBThreadDeregisterEvent );
+		}
+
+		m->p->smbFileSharing = mDNSfalse;
+	}
+
+exit:
+
+	if ( key )
+	{
+		RegCloseKey( key );
+	}
+}
+
+
+BOOL
+IsWOMPEnabled( mDNS * const m )
+{
+	BOOL enabled;
+
+	mDNSInterfaceData * ifd;
+
+	enabled = FALSE;
+
+	for( ifd = m->p->interfaceList; ifd; ifd = ifd->next )
+	{
+		if ( IsWOMPEnabledForAdapter( ifd->name ) )
+		{
+			enabled = TRUE;
+			break;
+		}
+	}
+
+	return enabled;
+}
+
+
+mDNSlocal mDNSu8
+IsWOMPEnabledForAdapter( const char * adapterName )
+{
+	char						fileName[80];
+	NDIS_OID					oid;
+    DWORD						count;
+    HANDLE						handle	= INVALID_HANDLE_VALUE;
+	NDIS_PNP_CAPABILITIES	*	pNPC	= NULL;
+	int							err;
+	mDNSu8						ok		= TRUE;
+
+	require_action( adapterName != NULL, exit, ok = FALSE );
+
+	dlog( kDebugLevelTrace, DEBUG_NAME "IsWOMPEnabledForAdapter: %s\n", adapterName );
+	
+    // Construct a device name to pass to CreateFile
+
+	strncpy_s( fileName, sizeof( fileName ), DEVICE_PREFIX, strlen( DEVICE_PREFIX ) );
+	strcat_s( fileName, sizeof( fileName ), adapterName );
+    handle = CreateFileA( fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, INVALID_HANDLE_VALUE );
+	require_action ( handle != INVALID_HANDLE_VALUE, exit, ok = FALSE );
+
+	// We successfully opened the driver, format the IOCTL to pass the driver.
+		
+	oid = OID_PNP_CAPABILITIES;
+	pNPC = ( NDIS_PNP_CAPABILITIES * ) malloc( sizeof( NDIS_PNP_CAPABILITIES ) );
+	require_action( pNPC != NULL, exit, ok = FALSE );
+	ok = ( mDNSu8 ) DeviceIoControl( handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof( oid ), pNPC, sizeof( NDIS_PNP_CAPABILITIES ), &count, NULL );
+	err = translate_errno( ok, GetLastError(), kUnknownErr );
+	require_action( !err, exit, ok = FALSE );
+	ok = ( mDNSu8 ) ( ( count == sizeof( NDIS_PNP_CAPABILITIES ) ) && ( pNPC->Flags & NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE ) );
+       
+exit:
+
+	if ( pNPC != NULL )
+	{
+		free( pNPC );
+	}
+
+    if ( handle != INVALID_HANDLE_VALUE )
+    {
+		CloseHandle( handle );
+    }
+
+	dlog( kDebugLevelTrace, DEBUG_NAME "IsWOMPEnabledForAdapter returns %s\n", ok ? "true" : "false" );
+
+	return ( mDNSu8 ) ok;
+}
+
+
+mDNSlocal void
+SendWakeupPacket( mDNS * const inMDNS, LPSOCKADDR addr, INT addrlen, const char * buf, INT buflen, INT numTries, INT msecSleep )
+{
+	mDNSBool	repeat = ( numTries == 1 ) ? mDNStrue : mDNSfalse;
+	SOCKET		sock;
+	int			num;
+	mStatus		err;
+
+	( void ) inMDNS;
+
+	sock = socket( addr->sa_family, SOCK_DGRAM, IPPROTO_UDP );
+	require_action( sock != INVALID_SOCKET, exit, err = mStatus_UnknownErr );
+
+	while ( numTries-- )
+	{
+		num = sendto( sock, ( const char* ) buf, buflen, 0, addr, addrlen );
+
+		if ( num != buflen )
+		{
+			LogMsg( "SendWakeupPacket error: sent %d bytes: %d\n", num, WSAGetLastError() );
+		}
+
+		if ( repeat )
+		{
+			num = sendto( sock, buf, buflen, 0, addr, addrlen );
+
+			if ( num != buflen )
+			{
+				LogMsg( "SendWakeupPacket error: sent %d bytes: %d\n", num, WSAGetLastError() );
+			}
+		}
+
+		if ( msecSleep )
+		{
+			Sleep( msecSleep );
+		}
+	}
+
+exit:
+
+	if ( sock != INVALID_SOCKET )
+	{
+		closesocket( sock );
+	}
+} 
+
+
+mDNSlocal void _cdecl
+SendMulticastWakeupPacket( void *arg )
+{
+	MulticastWakeupStruct *info = ( MulticastWakeupStruct* ) arg;
+	
+	if ( info )
+	{
+		SendWakeupPacket( info->inMDNS, ( LPSOCKADDR ) &info->addr, sizeof( info->addr ), ( const char* ) info->data, sizeof( info->data ), info->numTries, info->msecSleep );
+		free( info );
+	}
+
+	_endthread();
+}
+
+
+mDNSexport void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result)
+{
+	DEBUG_UNUSED( m );
+	DEBUG_UNUSED( rr );
+	DEBUG_UNUSED( result );
+}



More information about the Midnightbsd-cvs mailing list